Skip to content

rogerguess/SnipMCP

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SnipMCP

A Docker-based MCP (Model Context Protocol) server that enables Claude Code to fetch and view screenshots from your Desktop using a simple #snip notation.

Overview

SnipMCP solves the friction of sharing screenshots with Claude Code. Instead of manually copying paths or dragging files, simply:

  1. Take a screenshot with macOS (Cmd+Shift+4 or Cmd+Shift+3)
  2. Reference it in your prompt with #snip
  3. Claude sees the image instantly
You: "Look at #snip - why is this CSS not centering?"
Claude: [views your screenshot] "The issue is..."

Features

  • Simple notation: #snip for latest, #snip0/#snip1/#snip2 for multiple
  • Native image support: Returns images Claude can view directly (not base64 text)
  • Docker-based: Isolated, reproducible, auto-restarts on boot
  • Fallback support: Works even if MCP server is down (via direct file read)
  • Health monitoring: Hook warns you if the server isn't running

Quick Start

1. Clone and start the server

cd ~/Documents/Github/SnipMCP
docker compose up -d

2. Register with Claude Code

claude mcp add --transport sse snip http://localhost:3001/sse --scope user

3. Add the hook (optional but recommended)

Add to ~/.claude/settings.json:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "matcher": "#snip",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/Documents/Github/SnipMCP/hooks/snip-check.sh"
          }
        ]
      }
    ]
  }
}

4. Update CLAUDE.md (optional)

Add to ~/.claude/CLAUDE.md for automatic recognition:

## Screenshot Reference System (#snip)

When you see `#snip` or `#snipN` in a prompt, use the SnipMCP server's
`screenshot` tool to fetch the referenced screenshot(s) from the Desktop.

- `#snip` = most recent screenshot
- `#snip0`, `#snip1`, `#snip2` = multiple screenshots (0=oldest, N=newest)

5. Use it!

tell me about #snip

The #snip Notation

Single Screenshot

Notation Meaning
#snip The most recent screenshot on Desktop

Multiple Screenshots

When you reference multiple screenshots in one prompt, they're numbered by age within that set:

Notation Meaning
#snip0 Oldest of the referenced screenshots
#snip1 Second oldest
#snip2 Third oldest (most recent if 3 total)

Example: If you take 3 screenshots and say:

"Compare #snip0 with #snip2"

  • #snip0 = first screenshot you took
  • #snip2 = last screenshot you took

MCP Tools

screenshot

Fetch screenshot(s) from the Desktop.

Parameters:

  • index (string, default: "latest"):
    • "latest" - most recent screenshot
    • "0" - single indexed screenshot
    • "0,1,2" - multiple screenshots

Returns: Image content that Claude can view directly.

Examples:

screenshot(index="latest")     # Most recent
screenshot(index="0")          # Oldest of set
screenshot(index="0,1,2")      # Three screenshots

list_screenshots

List available screenshots on the Desktop.

Parameters:

  • limit (int, default: 10): Maximum screenshots to list

Returns: Text listing of available screenshots with indices.

health

Check server health and screenshot availability.

Returns: Health status string.

Architecture

┌──────────────────────────────────────────────────────────────┐
│                        macOS Host                            │
│                                                              │
│  ~/Desktop/                                                  │
│  ├── Screenshot 2025-12-20 at 10.02.15 PM.png               │
│  ├── Screenshot 2025-12-20 at 10.02.22 PM.png               │
│  └── Screenshot 2025-12-20 at 10.02.31 PM.png               │
│         │                                                    │
│         │ (read-only volume mount)                           │
│         ▼                                                    │
│  ┌─────────────────────────────────────────────────────┐    │
│  │            Docker: snip-mcp                         │    │
│  │  ┌───────────────────────────────────────────────┐  │    │
│  │  │  Python MCP Server (FastMCP)                  │  │    │
│  │  │  - screenshot() tool                          │  │    │
│  │  │  - list_screenshots() tool                    │  │    │
│  │  │  - health() tool                              │  │    │
│  │  │  - SSE transport on 0.0.0.0:8000              │  │    │
│  │  └───────────────────────────────────────────────┘  │    │
│  │              │                                      │    │
│  │              │ :8000                                │    │
│  └──────────────┼──────────────────────────────────────┘    │
│                 │                                            │
│                 │ :3001 (port mapping)                       │
│                 ▼                                            │
│  ┌─────────────────────────────────────────────────────┐    │
│  │            Claude Code                              │    │
│  │  - MCP client connects via SSE                      │    │
│  │  - Receives native Image content                    │    │
│  │  - Falls back to Read tool if MCP unavailable       │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                              │
└──────────────────────────────────────────────────────────────┘

Configuration Files

Claude Code Settings (~/.claude/settings.json)

The hook configuration warns you if the MCP server isn't running:

{
  "hooks": {
    "UserPromptSubmit": [
      {
        "matcher": "#snip",
        "hooks": [
          {
            "type": "command",
            "command": "bash ~/Documents/Github/SnipMCP/hooks/snip-check.sh"
          }
        ]
      }
    ]
  }
}

MCP Server Registration (~/.claude.json)

Added automatically by claude mcp add:

{
  "mcpServers": {
    "snip": {
      "type": "sse",
      "url": "http://localhost:3001/sse"
    }
  }
}

Global Instructions (~/.claude/CLAUDE.md)

Teaches Claude to recognize #snip notation:

## Screenshot Reference System (#snip)

When the user mentions `#snip` or `#snipN` in their prompt,
use the SnipMCP server's `screenshot` tool.

- `#snip` = screenshot(index="latest")
- `#snip0`, `#snip1`, `#snip2` = screenshot(index="0,1,2")

Persistence Across Reboots

Docker Desktop Auto-Start

  1. Open Docker Desktop
  2. Go to SettingsGeneral
  3. Enable "Start Docker Desktop when you sign in"

Container Auto-Restart

The docker-compose.yml includes restart: always, so the container starts automatically when Docker starts.

File Structure

~/Documents/Github/SnipMCP/
├── Dockerfile              # Python 3.12 slim image
├── docker-compose.yml      # Container config with volume mount
├── server.py               # FastMCP server implementation
├── requirements.txt        # Python dependencies
├── hooks/
│   └── snip-check.sh       # Availability warning hook
├── README.md               # This file
└── .gitignore

How It Works

  1. Screenshot Detection: macOS saves screenshots to Desktop as Screenshot YYYY-MM-DD at H.MM.SS AM/PM.png

  2. Volume Mount: Docker mounts ~/Desktop read-only to /desktop inside the container

  3. File Discovery: Server uses glob to find Screenshot*.png files, sorted by modification time

  4. Image Return: Uses FastMCP's Image(data=bytes, format="png") to return native image content

  5. Claude Viewing: Claude Code receives the image and can analyze it directly (like the Read tool with images)

Troubleshooting

MCP server not connecting

# Check if container is running
docker compose ps

# Check container logs
docker logs snip-mcp

# Restart the container
docker compose restart

"Failed to connect" in claude mcp list

The server might not be bound to the right interface:

# Check the logs show 0.0.0.0:8000
docker logs snip-mcp | grep "Uvicorn running"
# Should show: Uvicorn running on http://0.0.0.0:8000

Screenshots not found

# Check if Desktop is mounted
docker compose exec snip-mcp ls /desktop

# Check screenshot pattern
docker compose exec snip-mcp ls /desktop/Screenshot*.png

Port 3001 already in use

# Find what's using the port
lsof -i :3001

# Change the port in docker-compose.yml
ports:
  - "3002:8000"  # Use a different host port

# Update MCP registration
claude mcp remove snip
claude mcp add --transport sse snip http://localhost:3002/sse --scope user

Image too large / token limit errors

This was fixed in v1.0. If you're seeing base64 JSON instead of images:

# Pull latest and rebuild
git pull
docker compose down
docker compose build --no-cache
docker compose up -d

Development

Local Testing (without Docker)

# Create virtual environment
python -m venv venv
source venv/bin/activate

# Install dependencies
pip install -r requirements.txt

# Set desktop path
export DESKTOP_PATH=~/Desktop

# Run server
python server.py

Modifying the Server

  1. Edit server.py
  2. Rebuild: docker compose build
  3. Restart: docker compose up -d

Adding New Screenshot Sources

Modify SCREENSHOT_PATTERN in server.py to match different file patterns:

# Include multiple patterns
SCREENSHOT_PATTERNS = ["Screenshot*.png", "CleanShot*.png", "Snagit*.png"]

Requirements

  • macOS (for screenshot integration)
  • Docker Desktop
  • Claude Code CLI

License

MIT

Credits

Built with:

  • FastMCP - Fast MCP server framework
  • MCP - Model Context Protocol
  • Claude Code - Anthropic's CLI for Claude

About

MCP server for Claude Code to fetch screenshots using #snip notation

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors