Skip to main content
Glama

llm-vision

Give vision to vision-less LLMs — a local MCP server powered by Alibaba DashScope.

Python MCP DashScope License: MIT

English | 简体中文

Vision-less models (e.g. DeepSeek) can't see images — but they don't have to. llm-vision is a local MCP server that acts as their eyes: hand it a local image path, and it returns a text description generated by Alibaba Cloud's vision models (qwen3-vl-plus / qwen3.5-ocr).


✨ Features

  • Two tools, one pipelinedescribe_image for general image understanding, extract_text for OCR & document parsing (ID cards, invoices, receipts)

  • Bring your own model — model IDs configurable via environment variables, no code changes

  • Zero-cost test suite — 68 tests, most run offline against mocked HTTP

  • Portable setup — ship .mcp.json with your repo; works anywhere after uv sync

  • Model-consumable errors — every tool returns a readable error string, never an exception

Related MCP server: Vision MCP Server

🚀 Quick Start

Prerequisites

1. Install

git clone https://github.com/1710782766/llm_vision.git && cd llm-vision
uv sync
export DASHSCOPE_API_KEY=sk-xxx   # or add to your shell profile

2. Register with Claude Code

The repo ships with a portable .mcp.json — just open Claude Code in the project directory and ask:

"Use describe_image to look at path/to/your/image.jpg and tell me what's in it."

Approve the server connection once, and every future session has vision.

Prefer the CLI? Register manually:

claude mcp add llm-vision --env DASHSCOPE_API_KEY=sk-xxx -- uv run python main.py

Use it in every project — register globally (user scope) so any project directory has vision:

claude mcp add -s user llm-vision --env DASHSCOPE_API_KEY=sk-xxx -- uv run python /absolute/path/to/llm_vision/main.py

⚠️ With global registration, relative image paths resolve against the MCP process's working directory (your current project), not this repo — pass absolute paths to the model.

The project-local .mcp.json (portable, cwd: ".") and global -s user registration serve different setups: the former keeps the server bound to this repo, the latter makes it available everywhere.

🛠 Tools

Tool

Arguments

Description

describe_image

image_path (required) · prompt (optional) · perspective (optional)

View an image; perspective=normal (default) natural description, perspective=critical inspecting — proactively reports text misalignment/overlap/missing elements, for screenshot bug-hunting

extract_text

image_path (required) · prompt (optional)

OCR & text localization — documents, ID cards, invoices; ask for structured output (e.g. "extract the name and ID number as JSON")

Supported formats: jpg · jpeg · png · webp · gif · bmp · heic/heif (HEIC/HEIF via macOS sips) — single file < 10 MB.

⚙️ Configuration

Variable

Required

Default

Description

DASHSCOPE_API_KEY

DashScope API key (sk- prefix)

LLM_VISION_MODEL

qwen3-vl-plus

Vision model used by describe_image

LLM_VISION_OCR_MODEL

qwen3.5-ocr

OCR model used by extract_text

LLM_VISION_TIMEOUT

120

Per-attempt timeout (seconds)

LLM_VISION_MAX_RETRIES

2

Retries for transient errors (timeouts, network, HTTP 5xx); 0 disables

LLM_VISION_DESCRIBE_PROMPT

(built-in)

Override the default prompt for perspective=critical (normal uses a built-in natural-description prompt)

LLM_VISION_OCR_PROMPT

(built-in)

Override the default OCR prompt

LLM_VISION_CACHE

1

Result cache on/off (0/false/off/no disables)

LLM_VISION_CACHE_DIR

~/.cache/llm-vision

Cache location (or $XDG_CACHE_HOME/llm-vision)

LLM_VISION_MAX_EDGE

1568

Max image edge (px) before auto-scaling; 0 disables scaling

LLM_VISION_COMPRESS

1

Auto-preprocess oversize images on/off

🛡️ Reliability & Cost

Designed to "just work" in real use — including screenshot-heavy workflows:

  • Auto-compression — images over 1568px (the DashScope recommended edge) are scaled down via the macOS built-in sips (zero runtime dependencies); oversized files are re-encoded (JPEG q85, transparent PNGs preserved). Only oversize images are touched; normal images pass through untouched. Fixes the classic "big screenshot times out" failure. Non-macOS platforms skip preprocessing and rely on timeout + retry instead.

  • Retries — transient errors (timeout, network, HTTP 5xx) retry up to LLM_VISION_MAX_RETRIES times with exponential backoff and a shrinking per-attempt budget (total ≤ 2× timeout). Errors are tagged (已重试 N 次) so you know the failure survived retries.

  • Result cache — identical image + model + prompt + preprocess settings hits a content-addressed cache (keyed by file SHA-256) at ~/.cache/llm-vision/responses.json; re-viewing the same screenshot costs nothing. Only the model's text answer is stored — never image bytes. The file being replaced (new hash) invalidates the entry automatically. Disable with LLM_VISION_CACHE=0.

    • ⚠️ Note: OCR results (e.g. ID-card numbers extracted via extract_text) are stored in plain text in that cache file for up to 30 days (file permission 0600). For sensitive documents, set LLM_VISION_CACHE=0.

    • Animated GIFs over 1.5 MB are converted to their first frame.

🧠 Model Selection

  • qwen3-vl-plus (default vision) — benchmarked as the only hallucination-free option in our model evaluation; qwen3.7-plus is a promising upgrade candidate

  • qwen3.5-ocr (default OCR) — cheap, and notably strong at document & card-key-value extraction

  • ⚠️ The qwen3-vl-plus-latest alias has been retired (returns 404) — use stable model IDs

🏗 Architecture

main.py (MCP server)
  ├── describe_image(path, prompt?, perspective="normal")   → LLM_VISION_MODEL
  ├── extract_text(path, prompt?)     → LLM_VISION_OCR_MODEL
  └── _analyze_image pipeline
        → image_loader      path/extension/10MB validation, base64 + MIME
        → dashscope_client  httpx → DashScope OpenAI-compatible endpoint

Tools always return a string: the model's answer on success, a readable Chinese error message on failure — never an exception to the client.

🔒 Security & Privacy

  • DASHSCOPE_API_KEY lives only in your environment — never in .mcp.json or in git

  • When a tool is invoked, the image is sent as base64 to Alibaba DashScope — only hand the model images you're comfortable leaving your machine

🧪 Development

uv run pytest tests/ -q                                   # full suite (22 tests, mostly offline)
uv run python scripts/smoke_test.py [image_path ...]      # real-API smoke test (billed, ~¥0.01/call); pass paths or provide your own under images/
uv run python scripts/compare_models.py qwen3-vl-plus qwen3.7-plus   # model bake-off (billed)

Developer notes for Claude Code: see CLAUDE.md.

Available Tools

2 tools
describe_imageB

查看本地图片并描述内容或回答问题。image_path: 本地图片路径;prompt: 可选的问题或指令。

ParametersJSON Schema
NameRequiredDescriptionDefault
promptNo请详细描述这张图片的内容
image_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It only states the basic operation (view and describe), with no mention of limitations, error handling, or side effects. The description does not go beyond the obvious purpose to add meaningful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that states the purpose and immediately explains the parameters. Every word earns its place, making it highly efficient and easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity and the presence of an output schema, the description covers the core purpose and parameters. However, it lacks usage guidance and behavioral caveats (e.g., supported image formats, failure modes), so it is adequate but not fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description explicitly explains both parameters: 'image_path: 本地图片路径' and 'prompt: 可选的问题或指令'. This adds meaningful semantic information beyond the schema's bare property names and types, and the schema has 0% description coverage, so this compensation is valuable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool views a local image and describes content or answers questions. It identifies the resource (local image) and the action (describe/answer), but does not explicitly differentiate from the sibling tool extract_text, so it falls short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus the sibling extract_text. It does not mention any alternative or exclusion criteria, leaving the agent to infer usage from the basic functionality.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

extract_textA

提取图片中的文字,支持文档解析与卡证关键信息抽取。image_path: 本地图片路径;prompt: 可选的抽取指令(如要求 JSON 输出)。

ParametersJSON Schema
NameRequiredDescriptionDefault
promptNo请提取图片中的全部文字
image_pathYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It adds useful context about document parsing and JSON output capability via prompt, but lacks details on file format support, language limitations, or side effects. It does not indicate any destructive behavior, which is consistent with a read-only operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is comprised of two concise sentences. The first front-loads the purpose, and the second explains parameters. There is no redundancy or filler, making it highly efficient and scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema, so return values are communicated elsewhere. The description covers the core purpose and parameter semantics, but omits comparison with the sibling tool and potential limitations like file types or error conditions. Given the moderate complexity, it is sufficient but not exhaustive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero description coverage for parameters. The description compensates by explaining both parameters: 'image_path' as local path and 'prompt' as an optional instruction with an example (JSON output). This adds meaningful semantic value beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's primary function—extracting text from images—with a specific verb and resource. It further specifies support for document parsing and card key-information extraction, which distinguishes it from the sibling tool 'describe_image'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool should be used for text extraction from images, but does not explicitly state when to use it versus 'describe_image' or provide exclusions. There is no guidance on alternative tools or when not to use this one.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 2 tool updatesv0.1.0
    • First observeddescribe_image
    • First observedextract_text

TDQS

A3.5/5.0

Scored across 2 tools

Disambiguation4/5

The two tools have clear primary purposes: describe_image handles general visual understanding and Q&A, while extract_text is specialized for OCR and structured text extraction. There is slight overlap if someone uses describe_image for text-heavy images, but the descriptions sufficiently differentiate them.

Naming Consistency5/5

Both tool names follow the verb_noun pattern in snake_case (describe_image, extract_text), which is consistent, predictable, and matches the server's vision-oriented domain.

Tool Count3/5

With only 2 tools, the server feels thin for a broad 'vision' scope. While the tools are focused and purposeful, the count is at the low end and leaves little room for a comprehensive vision toolkit.

Completeness3/5

The tools cover the two most common vision tasks (generic description/QA and text extraction), but many other vision capabilities (e.g., object detection, image comparison, classification) are absent. The surface is minimal and may require workarounds for non-OCR/description tasks.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that enables any LLM to describe images from file paths, URLs, or base64 data by forwarding them to a supported vision provider such as OpenAI, Anthropic, or local Ollama models.
    1,060
    10
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    A local MCP server that gives LLMs eyes for images by performing object detection (YOLOv8) and text recognition (EasyOCR), outputting descriptive statements about objects and text positions without any API key or cloud dependency.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server that provides a 'borrowed eye' for text-only LLMs, enabling them to identify and describe local images via the Qwen VL vision model, including face recognition, scene description, OCR, and targeted visual questioning.
    3
    Apache 2.0

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/1710782766/llm_vision'

If you have feedback or need assistance with the MCP directory API, please join our Discord server