Files
image-watch-mcp/README.md
Alex Kazaiev 9198846405 Initial commit: Image Watch MCP
🖼️ MCP for monitoring and managing images
- get_latest_image: Get most recent image as inline display
- get_recent_images: Get multiple recent images
- list_pending_images: List without loading
- open_image_from_path: View any image file
- archive_processed_images: Clean up processed images

Built with love for the hardware dragon 🦊
2025-12-16 20:56:09 -06:00

7.4 KiB
Executable File

📸 Image Watch MCP Server

Local image watcher for Claude Desktop - AirDrop photos from your iPhone and discuss them with Claude instantly!

Features

  • 🔍 Automatic Detection - Watches ~/Downloads for new images in real-time
  • 📱 iPhone Support - Automatic HEIC → JPEG conversion for iPhone photos
  • 🗜️ Smart Compression - Adapts quality to fit Claude's 1MB limit while maintaining visual quality
  • 📦 Archive Management - Move processed images to ~/Downloads/Processed/ to keep Downloads clean
  • Multiple Workflows - Get latest image, batch of images, or list without loading

Supported Formats

  • JPEG / JPG
  • PNG
  • HEIC (iPhone photos)
  • GIF, BMP, WebP

Installation

1. Install Dependencies

cd /home/alex/Projects/image-watch-mcp
pip install -r requirements.txt

Or using a virtual environment (recommended):

python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install -r requirements.txt

2. Configure Claude Desktop

Add to your Claude Desktop config file:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

Linux: ~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "image-watch": {
      "command": "python3",
      "args": ["/home/alex/Projects/image-watch-mcp/image_watch_mcp.py"]
    }
  }
}

Note: If using a virtual environment, use the full path to the Python interpreter:

{
  "mcpServers": {
    "image-watch": {
      "command": "/home/alex/Projects/image-watch-mcp/venv/bin/python",
      "args": ["/home/alex/Projects/image-watch-mcp/image_watch_mcp.py"]
    }
  }
}

3. Restart Claude Desktop

Close and reopen Claude Desktop to load the MCP server.

Usage

Basic Workflow

  1. AirDrop photos from iPhone → Mac (they land in ~/Downloads)
  2. In Claude Desktop: "Show me the photos I just sent"
  3. Claude calls the MCP tools and displays images inline
  4. Discuss the images with Claude
  5. When done: "Archive those images" → Moved to ~/Downloads/Processed/

Available Tools

get_latest_image()

Get the most recent image added to Downloads.

Example:

Claude, show me the latest photo

Returns the newest unprocessed image, compressed to fit under 1MB.


get_recent_images(count, since_minutes)

Get multiple images at once.

Parameters:

  • count (default: 5) - Maximum number of images to return
  • since_minutes (default: 60) - Consider images from the last N minutes

Examples:

Show me the last 3 photos I took

Show me all photos from the last 10 minutes

Returns images in chronological order (oldest first).


list_pending_images()

List available images without loading them.

Example:

What images are pending?

Shows image names, sizes, formats, and timestamps. Useful for previewing what's available before loading large batches.


archive_processed_images()

Move viewed images to the archive folder.

Example:

Archive those images

Moves all processed images to ~/Downloads/Processed/ to keep Downloads clean. If a file with the same name exists, adds a timestamp suffix.

How It Works

Background Watcher

The MCP server starts a watchdog observer that monitors ~/Downloads for new image files. When an image is detected, it:

  1. Creates metadata (timestamp, size, format)
  2. Adds it to the pending queue
  3. Waits for you to request it

Smart Compression

Images larger than 1MB are automatically compressed using a multi-step strategy:

  1. Convert format - HEIC → JPEG, RGBA → RGB
  2. Quality reduction - Try 85% → 75% → 65% → 55%
  3. Resize if needed - Scale down 90% → 80% → 70%... until it fits
  4. Return best effort - Even if it exceeds 1MB slightly

This ensures maximum visual quality while meeting Claude's constraints.

State Tracking

Each image has three states:

  • Pending - Detected but not viewed
  • Processed - Viewed by Claude
  • Archived - Moved to archive folder

You can call archive_processed_images() anytime to clean up viewed photos.

Configuration

Watch Directory

By default, watches ~/Downloads. To change:

# In image_watch_mcp.py
WATCH_DIR = Path.home() / "Pictures" / "Incoming"

Archive Directory

By default, archives to ~/Downloads/Processed/. To change:

# In image_watch_mcp.py
ARCHIVE_DIR = Path.home() / "Pictures" / "Archive"

Recent Time Window

By default, considers images from the last 60 minutes as "recent":

# In image_watch_mcp.py
DEFAULT_RECENT_MINUTES = 60  # Change to your preference

Troubleshooting

Images not detected

  • Check that files are in ~/Downloads (not in subdirectories)
  • Verify file extensions are supported (.jpg, .png, .heic, etc.)
  • Check MCP server logs: /tmp/image_watch_mcp.log

HEIC not working

Install HEIC support:

pip install pillow-heif

Images too large

The MCP tries to compress images to fit under 1MB. If an image still won't load:

  • Original file might be corrupted
  • Extremely large dimensions (>10000px)
  • Check logs for compression errors

"No new images available"

This happens when:

  • No images in Downloads from the last 60 minutes
  • All images already processed

Try list_pending_images() to see what's available.

Logs

Server logs are written to /tmp/image_watch_mcp.log:

tail -f /tmp/image_watch_mcp.log

Shows:

  • Images detected
  • Compression results
  • Tools called
  • Errors and warnings

Development

Project Structure

image-watch-mcp/
├── image_watch_mcp.py       # Main MCP server
├── requirements.txt          # Python dependencies
├── README.md                 # This file
└── .gitignore               # Git ignores

Testing Locally

Run the server directly to see debug output:

python3 image_watch_mcp.py

The server will start and wait for MCP requests on stdin/stdout.

Adding Features

The code is organized for easy extension:

  • New image formats: Add to IMAGE_EXTENSIONS
  • Custom tools: Add @mcp.tool() decorated functions
  • Different compression: Modify smart_compress()
  • Additional metadata: Extend PendingImage dataclass

Example Conversations

Workflow 1: Single Photo

You: AirDrop photo from iPhone

You: "Claude, show me the latest photo"

Claude: [calls get_latest_image(), displays photo inline]

You: "What's in this photo?"

Claude: [analyzes the image and describes content]

You: "Archive it"

Claude: [calls archive_processed_images()] "Archived 1 image to ~/Downloads/Processed"


Workflow 2: Batch Photos

You: AirDrop 5 photos from iPhone

You: "Show me all the photos I just sent"

Claude: [calls get_recent_images(count=10)] [displays all 5 photos]

You: "Which one has the best composition?"

Claude: [analyzes all photos and provides feedback]


Workflow 3: Selective Loading

You: AirDrop many photos

You: "What images are pending?"

Claude: [calls list_pending_images()]

Pending images (12):
1. IMG_1234.heic (3.2MB, HEIC, 2m ago)
2. IMG_1235.heic (2.8MB, HEIC, 2m ago)
...

You: "Just show me the first 3"

Claude: [calls get_recent_images(count=3)] [displays 3 photos]

License

Part of the personal MCP toolkit for Claude Desktop.


Built with FastMCP + Watchdog + Pillow for seamless image workflows 📸