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 🦊
This commit is contained in:
325
README.md
Executable file
325
README.md
Executable file
@@ -0,0 +1,325 @@
|
||||
# 📸 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** 📸
|
||||
Reference in New Issue
Block a user