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: llm-vision-mcp

🚀 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.

Install Server
A
license - permissive license
A
quality
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • MCP server for AI dialogue using various LLM models via AceDataCloud

  • MCP server for GLM chat completions using Zhipu AI models via AceDataCloud

  • MCP server for ByteDance Seedream AI image generation

View all MCP Connectors

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