# 📸 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 ```bash cd /home/alex/Projects/image-watch-mcp pip install -r requirements.txt ``` Or using a virtual environment (recommended): ```bash 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` ```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: ```json { "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: ```python # In image_watch_mcp.py WATCH_DIR = Path.home() / "Pictures" / "Incoming" ``` ### Archive Directory By default, archives to `~/Downloads/Processed/`. To change: ```python # 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": ```python # 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: ```bash 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`: ```bash 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: ```bash 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** 📸