Skip to main content
Glama

Vision MCP Server

A Model Context Protocol (MCP) server that gives vision understanding to agents connected to non-multimodal models (DeepSeek, older GPT-4, local small models, etc.): the agent hands an image to the MCP tool, the server calls a vision model, and returns text.

Supports major providers in China and the US plus any OpenAI-compatible endpoint. Official SDKs first, abstraction before implementation, zero-intrusion provider additions.

中文文档见 README.zh-CN.md

Features

  • 4 tools: analyze_image / describe_image / ocr_image / list_providers, all returning plain Markdown text

  • 13 built-in providers: OpenAI / Anthropic / Google Gemini / Qwen (DashScope) / Zhipu / Doubao (Volcengine) / ERNIE (Qianfan) / StepFun / Ollama / Alibaba Bailian / SiliconFlow / OpenRouter / custom OpenAI-compatible endpoint

  • Up to 9 images per call (configurable via VISION_MCP_MAX_IMAGES): local path / http(s) URL / base64 (data URI or raw base64), auto-sniffed, types mixable

  • Three-tier fallback chain: official SDK → OpenAI-compatible endpoint → native fetch (see SPEC §1)

  • Stateless: every call is independent; images and results are never cached; keys are read from environment variables only

Related MCP server: vision-mcp

Quick start

Option A: npx (published to npm, no repo needed)

npx -y @inferai/vision-mcp

Option B: local build

git clone <repo> && cd vision-mcp
pnpm install
pnpm build
node dist/index.js

MCP configuration examples (stdio)

The server speaks the stdio transport: the MCP client spawns the process and exchanges JSON-RPC messages over stdin/stdout. Configure it wherever your client defines MCP servers:

  • Claude Code: project-level .mcp.json or user-level ~/.claude.json (mcpServers key)

  • Claude Desktop: claude_desktop_config.json

  • Any MCP client (Cursor, self-built agents, etc.): same structure

Windows

On Windows npx resolves to npx.cmd, and MCP clients that spawn processes without a shell can't run it directly — wrap it in cmd /c:

{
  "mcpServers": {
    "vision-mcp": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@inferai/vision-mcp"],
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "DASHSCOPE_API_KEY": "sk-..."
      }
    }
  }
}

Local development (adjust the path; --env-file-if-exists=.env loads .env natively):

{
  "mcpServers": {
    "vision-mcp": {
      "command": "node",
      "args": [
        "--env-file-if-exists=.env",
        "C:\\path\\to\\vision-mcp\\dist\\index.js"
      ],
      "env": {
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}

Linux / macOS

npx runs directly:

{
  "mcpServers": {
    "vision-mcp": {
      "command": "npx",
      "args": ["-y", "@inferai/vision-mcp"],
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "DASHSCOPE_API_KEY": "sk-..."
      }
    }
  }
}

Local development (adjust the path; --env-file-if-exists=.env loads .env natively):

{
  "mcpServers": {
    "vision-mcp": {
      "command": "node",
      "args": [
        "--env-file-if-exists=.env",
        "/absolute/path/to/vision-mcp/dist/index.js"
      ],
      "env": {
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}

With startup arguments (override provider defaults via argv, see below; on Windows prefix the command/args with cmd /c):

{
  "mcpServers": {
    "vision-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@inferai/vision-mcp",
        "--default-provider=dashscope",
        "--siliconflow-api-key=sk-...",
        "--siliconflow-model=Qwen/Qwen2.5-VL-7B-Instruct"
      ],
      "env": {
        "DASHSCOPE_API_KEY": "sk-..."
      }
    }
  }
}

stdio notes:

  • stdout carries the MCP protocol only — the server never prints logs there; diagnostics go to stderr

  • the client manages the process lifecycle (spawn on start, kill on exit); no daemon needed

  • first npx run downloads the package and may take a few seconds

  • env variables can also come from the shell environment if the client inherits it (no env block needed)

Debug with MCP Inspector:

pnpm dlx @modelcontextprotocol/inspector node dist/index.js --xxx-api-key=xxx --xxx2-api-key=xxx

Setting variables

  1. MCP config env block (recommended, most reliable across platforms) — write the variables into the env object above

  2. .env file (local development) — copy .env.example to .env, fill it in, then node --env-file-if-exists=.env dist/index.js (Node 22 native, no dotenv needed)

  3. Shell export — export OPENAI_API_KEY=sk-xxx then run

Providers without keys show as unavailable in list_providers and report the missing variable when called.

Publishing (before npx works)

pnpm publish          # or pnpm release (changeset flow)

Environment variables

Every provider's API_KEY, BASE_URL, and MODEL support environment overrides (convention: <PROVIDER_PREFIX>_API_KEY / <PROVIDER_PREFIX>_BASE_URL / <PROVIDER_PREFIX>_MODEL):

Provider

Environment variables

Default model

OpenAI

OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL

gpt-4o

Anthropic

ANTHROPIC_API_KEY, ANTHROPIC_BASE_URL, ANTHROPIC_MODEL

claude-sonnet-4-5

Google Gemini

GEMINI_API_KEY, GEMINI_BASE_URL, GEMINI_MODEL

gemini-2.5-flash

Alibaba DashScope

DASHSCOPE_API_KEY, DASHSCOPE_BASE_URL, DASHSCOPE_MODEL

qwen-vl-max

Zhipu

ZHIPU_API_KEY, ZHIPU_BASE_URL, ZHIPU_MODEL

glm-4v-flash (free)

Volcengine Doubao

VOLCENGINE_ARK_API_KEY, VOLCENGINE_ARK_BASE_URL, VOLCENGINE_ARK_MODEL

doubao-1.5-vision-pro

Baidu Qianfan

QIANFAN_API_KEY, QIANFAN_SECRET_KEY, QIANFAN_BASE_URL, QIANFAN_MODEL

ernie-4.5-vl-8k

StepFun

STEPFUN_API_KEY, STEPFUN_BASE_URL, STEPFUN_MODEL

step-1v

Ollama (local)

OLLAMA_BASE_URL, OLLAMA_MODEL

— (no built-in default; endpoint and model must be set)

Alibaba Bailian

BAILIAN_API_KEY, BAILIAN_BASE_URL (default DashScope compatible mode), BAILIAN_MODEL

qwen-vl-max

SiliconFlow

SILICONFLOW_API_KEY, SILICONFLOW_BASE_URL (default https://api.siliconflow.cn/v1), SILICONFLOW_MODEL

Qwen/Qwen2.5-VL-72B-Instruct

OpenRouter

OPENROUTER_API_KEY, OPENROUTER_BASE_URL (default https://openrouter.ai/api/v1), OPENROUTER_MODEL

openai/gpt-4o

Custom compatible

OPENAI_COMPAT_BASE_URL, OPENAI_COMPAT_API_KEY?, OPENAI_COMPAT_MODEL

—

? = optional (has a built-in default); * = required.

Global configuration:

Environment variable

Default

Description

VISION_MCP_DEFAULT_PROVIDER

first available

Default provider

VISION_MCP_DEFAULT_MODEL

provider default

Default model

VISION_MCP_PROVIDER_PRIORITY

table order

Provider priority (comma-separated, high first, e.g. openai,dashscope,zhipu)

VISION_MCP_MAX_RETRIES

0 (off)

Per-provider retry count before falling back

VISION_MCP_MAX_FALLBACKS

0 (off)

Max provider fallbacks before giving up

VISION_MCP_MAX_IMAGE_BYTES

20 MB

Image size limit

VISION_MCP_MAX_IMAGES

9

Max images per tool call

VISION_MCP_TIMEOUT_MS

60000

Download & request timeout (ms)

Fallback chain

When multiple providers are available, calls walk the priority chain: configured default → VISION_MCP_PROVIDER_PRIORITY list → table order (unavailable providers are skipped).

  • each provider is retried up to VISION_MCP_MAX_RETRIES times on provider errors (upstream failures, timeouts)

  • after a provider exhausts its retries, the next available provider in the chain is tried, up to VISION_MCP_MAX_FALLBACKS fallbacks

  • only provider errors trigger retry/fallback; config or image errors fail fast

  • an explicitly requested provider argument is tried alone (no fallback)

  • when everything fails, the error lists every provider attempted and its last error

Also available as argv: --provider-priority=..., --max-retries=N, --max-fallbacks=N (beat env vars).

MCP startup arguments (argv)

Every provider's apiKey / baseUrl / model can be overridden via startup arguments (higher priority than environment variables), format --<provider>-<field>:

node dist/index.js \
  --openai-api-key=sk-xxx \
  --openai-base-url=https://my-gateway.example.com/v1 \
  --openai-model=gpt-4o-mini \
  --dashscope-api-key=sk-xxx \
  --default-provider=dashscope
  • Global: --default-provider <name> / --default-model <name>

  • Per provider: --<provider>-api-key, --<provider>-base-url, --<provider>-model (equals or space form both work)

  • Any OpenAI-compatible third-party service: wire it up in one line with --openai-compat-base-url + --openai-compat-api-key + --openai-compat-model; or point any built-in provider's base-url at a mirror/proxy

Priority: tool args provider/model > startup args (per-provider > global default) > environment variables > provider built-in defaults.

Tools

Tool

Arguments

Description

analyze_image

images*, prompt?, provider?, model?

General image analysis

describe_image

images*, provider?, model?

Describe image content (default instruction)

ocr_image

images*, language? (auto/zh/en/zh-en), provider?, model?

OCR, preserving layout

list_providers

—

Provider list and configuration status

images accepts a single image or an array (up to VISION_MCP_MAX_IMAGES, default 9): local path / http(s):// URL / data: URI / raw base64, auto-sniffed. Multiple images are seen by the model in the given order (compare, diff, or combine them).

Security note: URL downloads are SSRF-protected — every hop (including redirects) is validated and URLs resolving to loopback, private, or link-local addresses are blocked (hint in the error explains why).

Provider integration (three-tier fallback chain)

provider

Integration

Notes

openai / stepfun / ollama / bailian / siliconflow / openrouter / openai-compat

OpenAI-compatible adapter (openai SDK)

One adapter, configurable baseURL

anthropic

Official SDK @anthropic-ai/sdk

messages + image content block

gemini

Official SDK @google/generative-ai

generateContent + inlineData

dashscope

Native fetch

official npm package has no vision; direct multimodal-generation API

zhipu

Native fetch

official SDK accepts string content only; direct v4 API

volcengine

Native fetch

official openapi is a management plane; direct Ark API

qianfan

Native fetch

official SDK is string-only; AK/SK → token → v2 API

Adding a provider: for OpenAI-compatible endpoints, add one row to RULES in src/core/config.ts plus one mapping in the factory table in src/index.ts — zero new code. Official SDK or native fetch implementations: see SPEC §1.

Development

pnpm check        # biome checks
pnpm test         # rstest unit tests (injected mocks, no network)
pnpm build        # rslib build

Real-call smoke tests (only run against providers whose keys are configured; skipped otherwise):

OPENAI_API_KEY=sk-... pnpm exec rstest tests/e2e

Architecture

src/
├── index.ts            # Entry: composition root, stdio startup
├── core/               # Abstraction: interfaces / image loading / config / registry
├── providers/          # Adapters: official SDK or compatible endpoints, protocol conversion only
└── server/tools.ts     # MCP tool layer: zod validation + error mapping

Full spec: SPEC.md.

Available Tools

4 tools
analyze_imageA

Analyze one or more images with a vision model and return the text result. Accepts 1 to 9 images (local path, URL, data URI, or base64; types can be mixed). Pass several images to compare, diff, or combine them — the model sees them in the given order. Use for reading screenshots, photos, charts, UI states, document pages, etc.

Inputs: images (required), model, prompt, provider.

describe_imageA

Describe the image content: subject, layout, text, details. Accepts 1 to 9 images; each image is described in the given order. Equivalent to analyze_image with the default description instruction.

Inputs: images (required), model, provider.

list_providersA

List all registered vision model providers, their default models, and configuration status. Providers without keys will error when called.

Inputs: no named parameters.

ocr_imageA

OCR: transcribe all text in the image(s), preserving reading order and paragraph structure. Accepts 1 to 9 images; transcripts follow the given order. Suitable for screenshots, scans, invoices, slides, etc.

Inputs: images (required), model, language, provider.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.7/5.0

    Scored across 4 tools

    Disambiguation2/5

    analyze_image, describe_image, and ocr_image all accept the same input and return text results. describe_image is explicitly described as equivalent to analyze_image with a default instruction, and ocr_image is just a specialized prompt variant. This creates significant overlap and makes it unclear when to choose one over another. Only list_providers is clearly distinct.

    Naming Consistency4/5

    All tool names use snake_case with a verb-first pattern: analyze_image, list_providers, describe_image, ocr_image. The only minor deviation is ocr_image using an acronym instead of a plain verb, but it still fits the pattern. Overall, naming is predictable and consistent.

    Tool Count3/5

    With only 4 tools, the server is on the low end of the typical range. However, 3 of the 4 tools essentially perform the same task with different prompt variations, so the effective functionality is even more limited. The count feels padded rather than well-scoped, and could be reduced to just analyze_image and list_providers without loss.

    Completeness4/5

    The server covers the core functionality of image analysis, including general analysis, description, and OCR, plus provider list management. Since analyze_image is generic and accepts multiple images for comparison, it covers most basic vision tasks. Minor gaps include lack of explicit model management or configuration tools, but list_providers partially addresses this.

    Maintenance

    ActivityNo data
    ResponsivenessSyncing

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      MCP server for analyzing images using multiple vision LLM providers (OpenCode, OpenAI, Anthropic, Google, and custom OpenAI-compatible endpoints). Provides tools to analyze single or multiple images, list providers, and test vision capabilities.
      MIT