Content
# Tool List
A picture recognition server based on [Model Context Protocol](https://modelcontextprotocol.io/), which uniformly encapsulates three visual API backends, allowing Claude Desktop / Cursor / any MCP client to call image description, Q&A, and multi-image analysis capabilities.
> 📦 **npm package name: `@systemmin/image-mcp`** (bin command `image-mcp`), can be run directly with `npx @systemmin/image-mcp`, no need to clone the repository.
## ✨ Supported Visual Backends
| Provider | Service | Applicable Scenario |
|----------|------|----------|
| `anthropic` | Claude (Anthropic) API | User-mentioned "code plan API", most effective |
| `zhipu` | Zhipu API (GLM-4V, etc.) | Domestic visual model, stable domestic access |
| `ollama` | Ollama (local llava / llama3.2-vision) | Local offline operation, zero cost, good privacy |
All backends are dynamically switched at runtime through the unified `provider` parameter, without restarting.
## 🧰 Exposed MCP Tools
| Tool | Parameters | Description |
|------|------|------|
| `vision_describe` | `path`, `provider?` | Generate a detailed text description/recognition result for a single image |
| `vision_qa` | `path`, `question`, `provider?` | Ask questions about the image, and the model answers according to the image content (VQA) |
| `vision_analyze` | `paths[]`, `prompt`, `provider?` | Comprehensive analysis/comparison of multiple images |
- `provider` is optional; if not passed, it will automatically select the first configured backend according to the priority of `DEFAULT_PROVIDER` -> `anthropic` -> `zhipu` -> `ollama`.
- The return result will be marked with the actual provider used, for example, `[provider: zhipu]`.
## 📦 Installation
### Method 1: Directly use npx (recommended, no cloning)
```bash
npx @systemmin/image-mcp
```
Or install globally:
```bash
npm install -g @systemmin/image-mcp
image-mcp
```
### Method 2: Build from source
```bash
# Requires Node.js >= 20
git clone https://github.com/systemmin/image-mcp.git
cd image-mcp
npm install
npm run build
```
## ⚙️ Configuration
Copy `.env.example` to `.env` and fill in the keys:
```bash
cp .env.example .env
```
```ini
# Claude (Anthropic)
ANTHROPIC_API_KEY=sk-ant-xxx
ANTHROPIC_MODEL=claude-sonnet-4-5-20250929
# Zhipu
ZHIPU_API_KEY=xxx.xxx
ZHIPU_MODEL=glm-4v
# Ollama (local)
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llava
# Default backend
DEFAULT_PROVIDER=anthropic
```
> Only configure the keys for the backends you want to use, and leave the rest blank. Ollama does not require a key, but you need to pull the visual model with `ollama pull llava` and keep the service running.
## ⏱️ Tool Call Timeout (important)
`MCP_TOOL_TIMEOUT` is an environment variable on the **MCP client (Claude Code / Claude Desktop) side**, not a configuration for this server. Visual API processing large images is slow, and if the timeout is not adjusted, the client will often timeout and report an error before the tool returns (large images are prone to triggering).
Set it before starting the client (unit: milliseconds, the following example is 5 minutes):
```bash
# Windows CMD
set MCP_TOOL_TIMEOUT=300000
# PowerShell
$env:MCP_TOOL_TIMEOUT="300000"
# macOS / Linux
export MCP_TOOL_TIMEOUT=300000
```
Set it again before starting `claude` or Claude Desktop; you can also add it to the system environment variables to take effect permanently.
## 🔌 Access MCP Client
### Claude Code (command line, recommended)
Use the official command to add it with one click, no need to manually modify JSON:
```bash
# Only available for the current project (local scope, default)
claude mcp add image-mcp -- npx @systemmin/image-mcp
# Or globally available for all projects (user scope)
claude mcp add image-mcp --scope user -- npx @systemmin/image-mcp
```
If you need to pass API keys, use `-e` (can be used multiple times):
```bash
claude mcp add image-mcp --scope user -e ANTHROPIC_API_KEY=sk-ant-xxx -e DEFAULT_PROVIDER=anthropic -- npx @systemmin/image-mcp
```
> You can also not pass `-e`, but instead put a `.env` file in the directory where you run `claude` (dotenv will automatically load).
> Verify if the registration is successful: `claude mcp list`.
Or manually edit the configuration file `~/.claude.json` (Windows: `C:\Users\<username>\.claude.json`, note that the file name **has a leading dot**), and add it to the top-level `mcpServers`:
```json
{
"mcpServers": {
"image-mcp": {
"type": "stdio",
"command": "npx",
"args": ["@systemmin/image-mcp"],
"env": {
"ANTHROPIC_API_KEY": "sk-ant-xxx",
"DEFAULT_PROVIDER": "anthropic"
}
}
}
}
```
### Claude Desktop
Edit the configuration file (macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`, Windows: `%APPDATA%\Claude\claude_desktop_config.json`):
```json
{
"mcpServers": {
"image-mcp": {
"type": "stdio",
"command": "npx",
"args": ["@systemmin/image-mcp"],
"env": {
"ANTHROPIC_API_KEY": "sk-ant-xxx",
"ZHIPU_API_KEY": "xxx.xxx",
"DEFAULT_PROVIDER": "anthropic"
}
}
}
}
```
> You can also not write `env`, but instead put a `.env` file in the project directory (dotenv will automatically load). If running from the source code, replace `command/args` with `"command": "node", "args": ["/path/to/image-mcp/dist/index.js"]`.
### Cursor / Other MCP Clients
Add a stdio-type MCP server according to the corresponding client documentation, and the command is `npx @systemmin/image-mcp` (or directly use `image-mcp` after global installation).
## 🧪 Debugging
Interactively test with the official Inspector:
```bash
npm run inspector
```
A web interface will open, and you can manually call the three tools and view the request/response.
## 🏗️ Project Structure
```
src/
├── index.ts # MCP server entry, registering 3 tools
├── providers/
│ ├── index.ts # VisionProvider interface + getProvider factory
│ ├── anthropic.ts # Claude API adapter
│ ├── zhipu.ts # Zhipu API adapter
│ └── ollama.ts # Ollama API adapter
└── utils/
├── image.ts # Image reading + base64 encoding + MIME inference
└── config.ts # Environment variable loading + provider parsing
```
### Architecture Description
The three tools essentially call `VisionProvider.analyze(images, prompt)`, and the difference is only in the prompt:
- `vision_describe` -> fixed description prompt
- `vision_qa` -> user question as prompt
- `vision_analyze` -> multi-image + custom prompt
Adding a new visual backend only needs to implement the `VisionProvider` interface and register it in `getProvider`.
## 📜 Scripts
| Command | Effect |
|------|------|
| `npm run build` | TypeScript compilation to `dist/` |
| `npm start` | Run the compiled server |
| `npm run inspector` | Start MCP Inspector debugging |