pic-id-mcp
Local vision-capable MCP server that lets AI agents describe screenshots, UI, charts, and photos via vision and OCR tools, with support for multiple providers and automatic fallback.
README
pic-id-mcp
English | 中文
pic-id is first and foremost an MCP server for AI agents — 4 MCP tools (
vision/ocr/list_models/providers) describe screenshots, UI, charts, and photos through 14 preset providers with automatic fallback. The Tauri 2 desktop app is an optional add-on: a visual console for usage stats, call logs, provider/model testing, and convenient MCP configuration. Zero credentials in the repo.
Core: the MCP server
- 4 MCP tools: vision, ocr, list_models, providers — with automatic provider fallback (main fails → next enabled provider)
- 14 preset providers: OpenAI, Anthropic, Gemini, Kimi, Qwen, GLM, Z.AI, MiniMax, MiMo, SenseNova, Ollama — one-click setup
- Custom provider: any OpenAI / Anthropic / Ollama / Gemini compatible endpoint
- Transports: stdio (primary — the client manages the process lifecycle) + Streamable HTTP; plug into ZCode / Claude / Cursor
- Config hot-reload: config/secrets changes are picked up on the next tool call, no server restart needed
- Zero sensitive data in repo: credentials live in OS app-data, never committed
Optional: the desktop app
A tray-resident liquid-glass window parked at the bottom-right:
- Home: usage stats, token usage breakdown by provider/model, call logs (MCP + REST, paginated)
- Settings: manage providers, keys, models, MCP primary/fallback — saved and hot-applied
- Playground: real vision tests with the fallback trail
- Optional launch-at-startup; auto-updates via tauri-plugin-updater
Security
- REST binds to
127.0.0.1only, with a strict CORS allowlist (Tauri webview origins), Host-header validation (DNS rebinding defense), and optionalhttp_auth_token - Secrets are never returned by the REST API — only "configured" status; writes use server-side merge semantics
secrets.tomlis written with0600permissions on Unix- Call logs are whitelisted: image count/size and prompt preview (200 chars) only, never base64 or credentials
- Production builds ship with a strict CSP (
'nonce-{{nonce}}'is required so Tauri's IPC scripts are allowed)
Desktop architecture notes
- The app binary is named
pic-id.exe(unique — a sharedapp.exename would collide with other Tauri apps and breaktaskkill /IM app.exe) - Single-instance enforced (second launch focuses the existing window — prevents stray sidecars)
- The sidecar binds a port from a fixed pool
8100..=8300(chosen above Windows excluded port ranges, e.g. 7954-8053); the Tauri shell records the picked port in its state before spawning and exposes it to the UI via theserver_infocommand — no log parsing, no file polling
Quick Start
Prerequisites
- Rust 1.77+ (stable)
- Node.js 18+ / pnpm
- Windows / Linux / macOS
Install from source
git clone https://github.com/HaoyueQin/picture-identification-MCP.git
cd picture-identification-MCP
# 1. Build the core MCP server (headless)
cargo build --release -p picid-server
# → binary at target/release/pic-id-server.exe
# 2. Optionally build the desktop console (add-on)
pnpm install
pnpm tauri build
# → exe at src-tauri/target/release/pic-id.exe
Run
# MCP server (for agent integration)
.\target\release\pic-id-server --stdio
# Desktop console
.\src-tauri\target\release\pic-id.exe
# Test instance (isolated config)
$env:PIC_ID_HOME = ".\test-home"
.\src-tauri\target\release\pic-id.exe
Configure
-
Copy
config.example.tomlto your OS config directory:- Windows:
%APPDATA%/pic-id/config.toml - Linux:
~/.config/pic-id/config.toml - macOS:
~/Library/Application Support/pic-id/config.toml
- Windows:
-
Create
secrets.tomlin the same directory (never commit this file):
# OpenAI
[providers."openai"]
token = "sk-your-key-here"
# Anthropic
[providers."anthropic"]
token = "sk-ant-your-key-here"
Or use environment variables:
export PIC_ID__providers__openai__token="sk-..."
Run
# stdio mode (for agent integration)
./target/release/pic-id-server --stdio
# HTTP mode (for GUI + REST API)
./target/release/pic-id-server --http --http-port 8001
ZCode / Claude / Cursor Integration
Add to your MCP configuration:
{
"mcpServers": {
"pic-id": {
"command": "C:\\path\\to\\pic-id-server.exe",
"args": ["--stdio"]
}
}
}
Use the release binary (
cargo build --release -p picid-serveroutput, or the path shipped with an installer) — point at the debug build only for development.
Or for HTTP mode:
{
"mcpServers": {
"pic-id": {
"url": "http://127.0.0.1:8001/mcp"
}
}
}
Architecture
picture-identification-MCP/
├── crates/
│ ├── core/ # Shared library: config, provider adapters, logging
│ └── server/ # Headless MCP server (rmcp + axum)
├── src-tauri/ # Tauri 2 GUI shell
├── ui/ # Vue 3 + TypeScript frontend
└── docs/ # API reference, specs
Provider pipeline
ImageInput → normalize() → NormalizedImage → Provider.describe()
↓
mpsc::Receiver<VisionEvent>
↓
Delta | Thinking | Usage | Done
Config Reference
See config.example.toml for all options. Key fields:
| Field | Type | Default | Description |
|---|---|---|---|
server.http_port |
u16 | 8001 | HTTP bind port |
providers[].id |
string | — | Unique provider id |
providers[].kind |
enum | — | open_ai_compat / anthropic / ollama / gemini |
providers[].model |
string | "" | Default model (empty = auto-detect) |
providers[].enabled |
bool | true | Enable/disable |
REST API
When running in HTTP mode, the server also exposes a loopback REST API:
| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health check |
/api/config |
GET / PUT | Raw config read / write (TOML validated) |
/api/config/providers |
GET | List all providers from config (with key/active status) |
/api/config/providers |
POST | Add or update one provider (deduped by id) |
/api/config/providers/{id} |
DELETE | Remove a provider |
/api/secrets |
GET | {"configured": [ids]} — status only, never values |
/api/secrets |
PUT | Merge {"providers": {"id": {"token": "…"} | null}}; null removes |
/api/models |
GET | Detected models per provider |
/api/logs |
GET | Recent call logs |
/api/vision |
POST | Run vision with automatic fallback (same as MCP tool) |
/api/ocr |
POST | Run OCR with automatic fallback (same as MCP tool) |
Auth: if
[server].http_auth_tokenis set, every endpoint requiresAuthorization: Bearer <token>. The desktop UI sends it automatically via theserver_infoTauri command.
Auto-update
The desktop app uses tauri-plugin-updater
with GitHub Releases as the update source. The signing private key lives in
~/.tauri/pic-id.key (never in the repo); the public key is baked into
src-tauri/tauri.conf.json's plugins.updater.pubkey.
To publish an update:
-
Bump
versioninsrc-tauri/tauri.conf.json -
Build with the signing key:
$env:TAURI_SIGNING_PRIVATE_KEY = Get-Content "$HOME\.tauri\pic-id.key" -Raw $env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD = "" pnpm tauri build -
The NSIS bundle produces
pic-id_<version>_x64-setup.exeplus its.sig -
Create a GitHub Release
v<version>and upload the.exe, the.sigand a hand-writtenlatest.json(Tauri v2 does not generate it:signature= the.sigfile content,url= the release asset URL,pub_date= RFC 3339) -
The updater endpoint is
https://github.com/HaoyueQin/picture-identification-MCP/releases/latest/download/latest.json
Settings → Updates lets users check manually or on launch.
Acknowledgments
Reference projects — what we borrowed from each:
- esengine/DeepSeek-Reasonix (MIT) — the MCP model-level primary/fallback configuration (per-model
"provider/model"selection instead of provider-level) and the token usage dashboard layout (input cache-miss / cache-hit / output / hit-rate breakdown by provider and model) - HaoyueQin/DeepSeekMonitorWindows (MIT) — the liquid-glass UI style (frosted
backdrop-filter: blur()panels, inner-edge highlights, translucent border simulating glass thickness) and the tray-resident small-window pattern (480×700, parked bottom-right, skip taskbar) - JayHome137/DeepSeekMonitor & felikschu/deepseek-monitor — upstream projects that DeepSeekMonitorWindows adapts from; our usage-stats orientation follows their monitoring dashboard ideas
- Apple Human Interface Guidelines — visual inspiration for the liquid-glass design language (frosted surfaces, translucency, layering)
Core frameworks and libraries:
- rmcp — Rust MCP SDK (stdio + Streamable HTTP transports)
- Tauri — cross-platform desktop app framework (v2, with tray-icon, updater, single-instance, shell, log plugins)
- Vue 3 + Vite — frontend framework and build tool
- axum / tokio / reqwest — async HTTP stack
License
MIT © HaoyueQin
Presets
14 vision-capable providers are pre-configured. Need more? Open an issue and the maintainer will add the preset.
Image size limits: some preset providers restrict input image resolution. SenseNova (
sensenova) rejects images whose longer side exceeds ~256 px — real screenshots fail withinvalid image base64 content. Use a provider that supports large images (OpenAI / Gemini / Kimi / Qwen…) for screenshots.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。