Skip to main content
Glama

🖼️ vision-mcp

Selbst gehosteter multimodaler VLM-Bilderkennungs-MCP-Server

TUI-Terminal Bild einfügen → KI-Client erkennt automatisch und gibt zurück · Daten verlassen das Intranet nicht

MCP TypeScript Node Tests Build License: MIT Transport

Claude Code · Codex · OpenCode · jeder MCP-kompatible Client


✨ Warum es verwenden

Vorteil

Beschreibung

🔒

Privates Deployment, Daten verlassen das Netz nicht

Direkte Verbindung zu deinem selbst gehosteten VLM, Bilder passieren keine Drittanbieter-Cloud

🔌

OpenAI-kompatibel, Backend austauschbar

vLLM / Ollama / GLM-4V / Qwen-VL frei wählbar, nur base URL ändern, kein Code-Change

🖼️

TUI: Bild einfügen und los

Bild im Terminal einfügen, Client ruft automatisch das Tool auf, Erlebnis analog zum Zhipu-Bilderkennungs-MCP

🧩

Vier spezialisierte Tools

Allgemeines Verständnis / OCR / Diagrammverständnis / UI-zu-Code, jeweils mit voreingestelltem System-Prompt und strukturierter Ausgabe

📥

Drei Bild-Eingabemöglichkeiten

Lokaler Pfad · http(s) URL · data: URI, Client kann jede Variante senden

🛡️

Keine Fehler-Lecks

Fehlermeldungen nur statisch/Statuscodes, VLM-Antwortbody oder Stacktrace werden niemals an den Client weitergegeben

⚡

Leichtgewichtiger Einzelprozess

stdio, Client startet Unterprozess bei Bedarf, kein Daemon, kein Serverzustand

🔁

Eingebaute Resilienz

Automatischer Retry bei 5xx/Timeout, kein Retry bei 4xx, Request-Timeout, Bildgrößenlimit

✅

Volle TDD-Abdeckung

35 Tests + End-to-End-Roundtrip (Fake-VLM + InMemoryTransport)

Related MCP server: openai-vision-mcp-server

📐 Architektur

flowchart LR
    A["🖥️ TUI 客户端<br/>(Claude Code / Codex / OpenCode)"] -- stdio JSON-RPC --> B
    subgraph B["vision-mcp (Node, stdio)"]
        direction TB
        C["tools ×4<br/>analyze_image / extract_text /<br/>understand_diagram / ui_to_code"]
        C --> D["analyze()<br/>共享核心"]
        D --> E["imageSource<br/>路径/URL/data-URI → 归一化"]
        D --> F["vlmClient<br/>OpenAI 兼容 + 重试"]
    end
    F -- HTTPS chat/completions --> G["🧠 自托管 VLM<br/>(qwen-vl / glm-4v / ...)"]
    G -- JSON --> B
    B -- tool result --> A

🛠️ Tools

Alle teilen sich image_source (lokaler Pfad | http(s) URL | data: URI).

Tool

Eigene Parameter

Ausgabe

analyze_image

prompt (Pflicht)

Beschreibung in natürlicher Sprache / Q&A

extract_text

prompt?、programming_language?

OCR-Text (Code-Screenshots mit Sprachangabe)

understand_diagram

diagram_type? (weglassen oder auto)、prompt?

Strukturierte Beschreibung + mermaid/markdown-Nachbildung

ui_to_code

output_type (code/spec/description)、framework? (html/react-tailwind)、prompt?

Entsprechender code/spec/description

🚀 Schnellstart

Klonen und bauen

git clone https://github.com/skyone123/vision-mcp.git
cd vision-mcp
npm install
npm run build      # 产出 dist/index.js + dist/index.d.ts
npm test           # 可选:35/35 测试

Der Client nutzt nur dist/index.js — merke dir den absoluten Pfad (im Folgenden als $DIST bezeichnet), er wird in der Konfiguration benötigt.

Beispiel: Linux/macOS /home/you/vision-mcp/dist/index.js; Windows D:/git/vision-mcp/dist/index.js.

Umgebungsvariablen

Variable

Standard

Pflicht

Beschreibung

VLM_BASE_URL

—

✅

OpenAI-kompatible base, z. B. http://localhost:8000/v1 (mit /v1)

VLM_MODEL

qwen-vl-max

—

Modellname

VLM_API_KEY

""

—

Bearer-Token; nur ausfüllen, wenn das Backend Authentifizierung verlangt, sonst wird kein Authorization-Header gesendet

VLM_TIMEOUT_MS

60000

—

Timeout für einzelne Requests

VLM_MAX_IMAGE_BYTES

10485760

—

Bildlimit 10MB

VLM_MAX_TOKENS

2048

—

Token-Limit für Antworten

Fehlt VLM_BASE_URL, bricht der Start mit Fehler ab — kein stilles Scheitern.

🔧 Konfiguration

Schritt 1 · Prüfen, ob das Backend einen API-Key benötigt

curl http://localhost:8000/v1/models
  • 200 + Modellliste → kein Key nötig

  • 401/403 → Key nötig, mit Key erneut versuchen: curl http://localhost:8000/v1/models -H "Authorization: Bearer dein-token"

Modellnamen aus der Antwort auswählen, das visuelle Modell:

curl -s http://localhost:8000/v1/models | grep '"id"'

Visuelle Fähigkeit testen, ob Bilder verarbeitet werden (am wichtigsten):

curl http://localhost:8000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer 你的token" \
  -d '{
    "model": "qwen-vl-max",
    "messages": [{"role":"user","content":[
      {"type":"text","text":"一句话描述这张图"},
      {"type":"image_url","image_url":{"url":"https://upload.wikimedia.org/wikipedia/commons/thumb/4/47/PNG_transparency_demonstration_1.png/640px-PNG_transparency_demonstration_1.png"}}
    ]}]
  }'

Normale Textantwort → Endpoint nutzbar, diese Werte in env übernehmen.

Schritt 2 · In den Client eintragen

Ersetze $DIST unten durch den absoluten Pfad von dist/index.js aus dem vorherigen Schritt, command mit node.

claude mcp add vision-mcp --scope user \
  --env VLM_BASE_URL=http://localhost:8000/v1 \
  --env VLM_MODEL=qwen-vl-max \
  -- node "$DIST"

Mit Key eine weitere Zeile hinzufügen: --env VLM_API_KEY=dein-token.

{
  "command": "node",
  "args": ["/absolute/path/to/vision-mcp/dist/index.js"],
  "env": {
    "VLM_BASE_URL": "http://localhost:8000/v1",
    "VLM_MODEL": "qwen-vl-max"
  }
}

Mit Key in env ergänzen: "VLM_API_KEY": "dein-token".

{
  "mcpServers": {
    "vision-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/vision-mcp/dist/index.js"],
      "env": { "VLM_BASE_URL": "http://localhost:8000/v1", "VLM_MODEL": "qwen-vl-max" }
    }
  }
}
[mcp_servers.vision-mcp]
command = "node"
args = ["/absolute/path/to/vision-mcp/dist/index.js"]
env = { VLM_BASE_URL = "http://localhost:8000/v1", VLM_MODEL = "qwen-vl-max" }
{
  "mcp": {
    "vision-mcp": {
      "type": "local",
      "command": ["node", "/absolute/path/to/vision-mcp/dist/index.js"],
      "environment": {
        "VLM_BASE_URL": "http://localhost:8000/v1",
        "VLM_MODEL": "qwen-vl-max"
      }
    }
  }
}

Bei OpenCode können die Feldnamen je nach Version leicht abweichen; falls das Tool nicht erscheint, die offizielle MCP-Dokumentation vergleichen.

Schritt 3 · Verifizieren

claude mcp list          # 应看到 vision-mcp,状态 connected

Der MCP-Server muss nicht manuell als Daemon laufen — der Client startet den Unterprozess bei Bedarf. Dann im Chat ein Bild einfügen und fragen "Was ist auf dem Bild", der Client ruft automatisch analyze_image auf; oder explizit:

Nutze das analyze_image-Tool für dieses Bild: <Bild einfügen>

💻 Entwicklung

npm run dev              # tsx 直接跑源码(开发期)
npm run build            # tsup 打包 dist/index.js
npm test                 # vitest,35/35
npx tsc --noEmit         # 类型检查

Quellcode-Struktur:

src/
  config.ts          # env → VlmConfig
  imageSource.ts     # loadImage: 路径/URL/data-URI 归一化
  vlmClient.ts       # complete: 调 OpenAI 兼容端点 + 重试/超时
  analyze.ts         # 共享核心: loadImage + complete
  server.ts          # McpServer 注册 + stdio + main
  index.ts           # #!/usr/bin/env node 入口
  tools/
    analyzeImage.ts
    extractText.ts
    understandDiagram.ts
    uiToCode.ts

Jede Datei hat eine einzige Verantwortung und ist unabhängig testbar; die vier Tools sind dünne Wrapper um analyze(), jeweils mit eigenem System-Prompt.

🗺️ Roadmap (optionale Erweiterungen)

Aktueller Umfang: nur stdio · ein Backend · ein Bild · keine Persistenz. Folgende Erweiterungen bei Bedarf:

Kandidat

Wert

Empfehlung

Streaming-Ausgabe

ui_to_code-Ausgabe kann sehr lang sein, Streaming zeigt sie nach und nach

👍 Lohnenswert, bessere UX

Bildvorverarbeitung

Vor dem Senden nach langer Kante skalieren/komprimieren, spart Tokens, reduziert Timeouts

👍 Lohnenswert, Kostensenkung

Strukturierte Ausgabe

extract_text/understand_diagram geben JSON zurück

🤔 Je nach Szenario

HTTP/SSE-Transport

Mehrere Clients teilen, Remote-Deployment

🤔 Aktuell reicht stdio, bei Bedarf

Multi-Backend-Routing

Verschiedene Aufgaben an verschiedene VLMs routen

❌ YAGNI

Video/Multi-Bild-Batchverarbeitung

—

❌ Außerhalb der aktuellen Ausrichtung

Server-Caching

Gleiche Bilder wiederholt erkennen

❌ YAGNI

📄 Lizenz

MIT © 2026 luyuxin


Related MCP Connectors

Related MCP Servers