Content
center">
# VisionPower
**Equip Your AI Agent with Eyes -weight, Secure, and Plug-and-Play Image Understanding Capability, Supporting Both MCP and Skill Integration.**
[](./README.en.md)
[
[](https://nodejs.org)
</div>
VisionPower enables agents, Claude Desktop, Cline, and Cherry **recognize image content text from screenshots (OCR, and analyze multiple images sequentially**.
It is **not bound to any specific model**: by default, it uses Qwen-VL (OpenAI-compatible interface) from Alibaba Cloud's Bailian/DashScope, but can also be configured to use GPT-4o or any other service compatible with OpenAI's `/chat/completions` visual input by specifying the model name and base URL. VisionPower provides **two integration forms** - [MCP](#using-as-mcp) and [Skill](#using-as-skill), allowing you to choose the one that best fits your agent's capabilities## ✨ Features
- 🧩 **One Capability,** - The same core be used as either an MCP tool `describe_image` or a self-contained Skill (adependency script that can be used immediately after download).
- 🖼️ **Four Input Sources** - Local path `image_path`, public URL `image_url`, `image_base64`, and ordered array of multiple images `images[]`.
- 🔢 ** Images** - Automatically labels `Image 1 / Image 2 / …` the model to respond in the same order.
- 🔌 **Model-Agnostic** - Any OpenAI-compatible visual service can be used; switching models requires only two environment variable changes.
- 🔒 **Security-First** - Path whitelist, file magic, private network/ protection, and strict base input schema validation. See [Security Design](#-security for details.
- 🔁** - Automatic retryponential backoff) rate limiting / 5 network jitter; timeouts by response body reads to prevent request hangs.
- 🪶 **Minimal Dependencies** - the official MCP zod at runtime; no native modules or image libraries.
- 🌐 **China-Friendly** - Built-in npmmirror image and local installation path for stable startup even in weak networks.
---
## 🎬 What It Can Do
Provide an image to your agent and let it analyze:
**Input**
```json
{
"image "/Users/me/Desktop",
" "Read the key numbers in this screenshot and summarize."
}
```
**Output)**
```text
sales dashboard screenshot. The top KPI shows this month's GMV ¥1,284,500, up 12.3% MoM;
the number of orders is 8,420, up 4.1% MoM. The middle line chart shows a steady increase over the past 6 months, noticeable drop in March.
The right pie chart shows 'East China' has the highest proportion (38%), followed by 'South China' (25%)…
```
> 📸 Screenshot reading, 🧾 invoice/table extraction, 📊 chart interpretation, 🧭 UI inspection, screenshot diagnosis - all scenarios where an agent needs to "look at an image" are applicable## 🧭 Two Forms, How to Choose two forms **offer equivalent functionality**; the difference lies in the integration approach. Choose based agent's capabilities:
| | Choose Which | Why |
| --- | --- |
| Claude Desktop, Cline, Cherry to MCP, possibly without) | **[MCP](#using-as-mcp Exposes structured `` tool with schema validation and deterministic calls |
| Codex, Claude Code, etc., shell/code execution**Skill](#using-as-s | Runs a self zero-dependency script; or persistent process required Pure chat, MCP host execution | **M | Skill form lacks a environment |
> Both forms can be **installed simultaneously**. like Codex that can both connect to MCP and execute, either form can be---
## Using as MCP
### Quickest Path: Let Your Agent Install It
Copy the following text and send your agent (replace with Key):
```text install and configure VisionPower MCP.
Vision model API Key: Fill in your API Key (will be written in plain text, so be mindful of file security)
Model: qwen3-vl-flash
Base URL: https://dashscope.aliyuncs.com/compatible-mode/v1
【Installation】First, test npm:
- Official source npx -package visionpower@power
- Unstable/China mainland network → npx -y --registry.npmmirror.com visionpower@power
- Onlypx fails continuously, then -g visionpower and configure the command to
【Write configuration - key point】
Don't use a generic template. Find an existing MCP server configuration in your agent's configuration directory
as a format template, and strictly follow its file location and field structure to add visionpower.
If there are, use the one that an existing MCP server is using.
【Verification】Two steps to confirm:
1. Process level the written command and env to start the process for MCP handshake, and confirm that tools/list returns describe_image;
2. Inform the user: The configuration is read when the host and the agent needs restarted for the tool to take effect in the conversation.
```
**Preparation**: Node.js 18+, and an OpenAI-compatible API Key for a visualapply for an Alibaba Cloud Bailian Key: <https://bailian.console.aliyun.com/?tab=model#/api-key>).
### Manual Installation
For tools like Claude Desktop, Cline, Studio that use JSON/TOML for MCP configuration. These hosts **won't download test connections** - confirm that the package can be the API Key works, then paste the configuration.
**① Download and Self-Test in Terminal**
Run the command once to pull VisionPower and attempt an MCP handshake; successful handshake indicates that your network, package, and Key are all good:
``` Official source
-y --package visionpower@latest visionpower
# China mainland / weak network
npx -y --registry=https://registry.npmmirror.com --package visionpower@latest visionpower
```
> If the process hangs normally (seeing `Running VisionPower MCP server` output), it indicates success; `Ctrl+C` to exit. The package is cached locally, and subsequent host startups will be faster.
> Occasional failures? Weak network or long-term use can be changed to global installation: `npm install -g visionpower@latest` (add `--registry=https://registry.npmmirror.com` for China mainland).
**② Write into Host Configuration**
```json
{
"mcpServers": {
"visionpower": {
"command": "npx",
"args": ["-y", "--package", "visionpower@latest", "visionpower"],
"env": {
"VISIONPOWER_API_KEY": "Fill in your API Key",
"VISIONPOWER_MODEL": "qwen3-vl-flash",
"VISIONPOWER_BASE_URL": "https://dashscope.aliyuncs.com/compatible-mode/v1"
}
}
}
}
```
> For China mainland mirrors, change `args` to `["-y", "--registry=https://registry.nirror.com", "-- "visionpower@latest",power"]`.
x Uses TOM (not JSON), `~/.code.toml`:
```tom[mcp_servers."visionpower"]
type = "stdio = "npx = ["-ypackage", "visionpower@latest", "visionpower"]
[mcp_servers."visionpower".env]
VISIONP = "Fill in your API Key"
VISION = "ql-flashOWER_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
```
> Configuration is **host startup**; **restart** the to take effect.
---
## UsingThe Skill form **self-contained,ation, zero- [`VisionPower-SVisionPower-Skill): it contains `SKILL and a script `describe_image.mjs` that can be run directly with `node`. **No CLI dependencies, no `npm install`**; just Node 18+ and an API Key. Suitable for agents like Codex and Claude Code with **code execution capabilities**.
> The folder is named `VisionPower-Skill` (for easy download identification), but the skill itself is named `visionpower` (see `name:` in `SKILL.md`). So, install it to `~/.claude/skills/visionpower/` to match the skill name.
### Quickest Path: Let Your Agent Install
Send the following text to your agent will install the Skill **ask you which model to use and write the API Key to a persistent configuration file**:
```text
Please help me install VisionPower Skill.
1. Download the VisionPower-Skill folder from https://github.com/RunhuaHuang/VisionPower
(clone the entire repository or download the folder alone). It's self-contained; no npm install needed.
2. Install the folder's content as a skill named visionpower (Cl):
mkdir -claude/skisionpower
cp VisionPower-Skill/SKILL.md VisionPower-Skill/describe_image.mjs ~/.claude/skills/v. Confirm Node 18+: node --version; then run node ~/.claude/skills/visionpower/describe_image.mjs --help to validate.
4. Then, ask me which visual model to use (default-vl-flash, also optional qwen3-vl-plus or gpt-4o),
and request my API Key, then help me write it to the persistent configuration file ~/.visionpower (mode 600),
format: {"...","model (add "https://api.com/v1").
the complete Key back.
5. confirm the Skill is an example image., the script will ~/.visionpower/skill-state.json (config future calls don't repeat configuration checks
unless returns a Key/auth, then guide me to configure again.
```
Installation
1. Install the skill content as `visionpower` (Cl example):
mkdir -claude/skillspower
cpkill/SK VisionPower-Skill_image.mjs ~/./skills/vision ```
For projects, place it in `<>/.claude/skills/visionpower Other agents put it in their designated skill directory - auto-loading, you can still have it "read this SKILL.md and run describe_image.mjs as per instructions".
2. Confirm Node 18+, and write the API Key to the **persistent configuration file** (script reads it automatically; configure once for permanent effect):
```bash
node --version # Needs v18+
mkdir -p ~/.visionpower
cat > ~/.visionpower/config.json <<'JSON'
{ "api "Fill in your API Key", "modelwen3-vash" }
JSON
chmod 600 ~/.visionpower/config.json
```
> Why use a configuration file instead of `export VISIONPOWER_API_KEY=...`? Because the agent's child shell **usually can't read** environment variables written in `~/.zshrc`, making it unreliable. The configuration file is shell-agnostic and. Environment variables are still usable and override the configuration file. `SKILL.md` has a "first-time setup" process: if the Key isn't configured, the agent guides you through selecting a model and writing this file; successful calls write `~/.visionpower/skill-state.json` as a verified switch, skipping future configuration checks unless calls fail.
### Usage
Then, directly tell your agent to "read this screenshot's text" and provide the **absolute path** to the image; it will automatically trigger and execute:
```bash
node <skill>/describe_image.mjs --image-path /absolute/path/to/imageprompt "Read text"
```
See the [Interface Reference - Skill Script](#skill-script) for the full usage.
---
## It Worksmermaid
flowchart TB
M[" Host<br/> Desktop · Cursor · C Cherry Studio"]
["Agents with ShellCodex · Claude Code · …"]
M -- "describe_image tool" --> S -- "node describe_image.mself-contained script)" --> CORE
COREPower Core<br/> · Security Checks · Normalization"]
CORE["Visual Model<br/>Qwen-VL ·o · …"]
API --> CORE
```
Both forms share the same core logic (`src/vision-core.js` + `src/config.js`): the MCP server directly references it, while the Skill's `describe_image.mjs` is **automatically bundled** from the same core into a zero script ( synchronization, never divergent). The core only handles " + forwarding doesn't cache images or fetch `image_url` ( upstream model service## Reference
### `describe (MCP CLI JSON Request)
| Type || --- | --- |
| `image string |** to the. |
| `` | stringPublicly accessible** `http`/`https`. |
| `64` | Standard base64 without:` prefix. `image_mime enum | ` `image/pngimage/webpimage/gif`, `mp`; usedimage_base64`; not specified.images` | array of; each item is of the above. **Don't mix-level single image fields.** |
| `prompt` | Specific question or instruction for the image; empty for a detailed overall description> Choose one of `image_path` /_url` / `image_base64` ( array of these for).
<details open>
><b>Examples Image / Base64 / Multiple Images</b></summary>
{ "": "/absolute/path/to/image.png", "prompt": text in summarize." }
{": "https.com/image.png", "prompt": "What's image?" }
```
{ "image_base64": "...",_mime_type":/png", " "Extract all visible text." }
```
```{
"images { "imageabsolute/pathirst.png" },
{ "image_url://example.com" }
],
prompt": " in each image sequentially and summarize."
}
```
with multiple images, labels them as 1`, `2`, etc., the model to respond in the same order.
</details>
### Skill Script
Skill form uses the built-in script `describe_image.mjs` (`<skill>` is the absolute path to the skill folder):
```text
node <skill>/describe_image.mjs --image-path <absolute path> [--prompt <text>]
node <skill>/describe_image.mjs --image-url <https URL> [--prompt <text>]
node <skill>/describe_image.mjs request.json # Pass JSON request file
echo '<JSON request>' | node <skill>/describe_image.mjs # Or pass from stdin
```
| Option | Description |
| --- | --- |
| `--image-path <p>` | Local image absolute path |
| `--image-url <u>` | Public http(s) image URL |
| `--image-base64 <b>` | Base64 data (for large data, consider using JSON file or stdin) |
| `--mime <type>` | MIME type for `--image-base64` |
| `--prompt <text>` | Question or instruction (optional) |
| `--input <file>` or positional argument | Read JSON request from file (structure same as `describe_image`) |
| `--help` | Show help |
If no source parameters are provided, the script reads JSON request from **stdin** (structure same as MCP, including multiple images `images[]`). The result is printed to stdout; on failure, it prints `VisionPower error: <reason>` to stderr and exits with a non-zero code.
## 🤖 Supported Models
Any service provider compatible with OpenAI's `/chat/completions` visual input format can be integrated. Change `VISIONPOWER_MODEL` and `VISIONPOWER_BASE_URL` to switch.
| Service Provider | `VISIONPOWER_MODEL` | `VISIONPOWER_BASE_URL` | Description |
| --- | --- | --- | --- |
| Alibaba Cloud Baichen / DashScope | `qwen3-vl-flash` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | **Default**, fast and cost-effective. |
| Alibaba Cloud Baichen / DashScope | `qwen3-vl-plus` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | Higher quality Qwen-VL, depends on account permissions. |
| Alibaba Cloud Baichen / DashScope | `qwen3.6-flash` | `https://dashscope.aliyuncs.com/compatible-mode/v1` | Available if the account has access to this multimodal model. |
| OpenAI | `gpt-4o` | `https://api.openai.com/v1` | General visual understanding capabilities. |
| OpenAI | `gpt-4o-mini` | `https://api.openai.com/v1` | Cost-effective OpenAI option. |
| Other OpenAI-compatible | Model ID provided by service provider | `/v1` URL provided by service provider | Replace model name and interface URL with your configuration. |
<details>
<summary><b>OpenAI Example (MCP env)</b></summary>
```json
"env": {
"VISIONPOWER_API_KEY": "Your API Key",
"VISIONPOWER_MODEL": "gpt-4o",
"VISIONPOWER_BASE_URL": "https://api.openai.com/v1"
}
```
</details>
## ⚙️ Configuration (Environment Variables / Config File)
Both forms share the same configuration. Priority: **environment variables > config file > default values**.
**Config File**: `~/.visionpower/config.json` (path can be changed using `VISIONPOWER_CONFIG`). This is the recommended configuration method for Skill, as the Agent's child shell usually cannot read environment variables set in the shell profile. The configuration is automatically read and takes effect permanently. Key names: `apiKey`, `model`, `baseUrl`, `maxImages`, `timeoutMs`, etc.
```json
{
"apiKey": "Your API Key",
"model": "qwen3-vl-flash"
}
```
**Environment Variables** (override config file):
| Name | Required | Default Value | Description |
| --- | --- | --- | --- |
| `VISIONPOWER_API_KEY` | ✅ | | Visual model service provider's API Key. |
| `VISIONPOWER_MODEL` | | `qwen3-vl-flash` | Visual model name. |
| `VISIONPOWER_BASE_URL` | | `https://dashscope.aliyuncs.com/compatible-mode/v1` | OpenAI-compatible Base URL, **do not** include `/chat/completions`. |
| `VISIONPOWER_ALLOWED_DIRS` | | (empty = no restriction) | Comma-separated list of allowed directory whitelist, `image_path` must be within. |
| `VISIONPOWER_MAX_IMAGE_BYTES` | | `20971520` (20MB) | Maximum bytes for a single local/Base64 image. |
| `VISIONPOWER_TIMEOUT_MS` | | `60000` | Upstream interface timeout (milliseconds). |
| `VISIONPOWER_MAX_TOKENS` | | `2048` | Maximum output tokens. |
| `VISIONPOWER_MAX_IMAGES` | | `8` | Maximum number of images analyzed in a single call. |
| `VISIONPOWER_MAX_RETRIES` | | `2` | Automatic retries on upstream 429/5xx or network errors (exponential backoff + jitter). |
| `VISIONPOWER_DEBUG` | | `false` | Set to `true` to output debug information (request model, image count, and time consumption) to stderr. |
| `VISIONPOWER_SKILL_STATE` | | `~/.visionpower/skill-state.json` | Only used by Skill script: records configuration validation status to avoid repeated validation. |
> **Naming Convention**: The main prefix is `VISIONPOWER_*`. API Key can also be read from `OPENAI_API_KEY`.
### Migration (0.x → 1.x)
- The old `RUN_VISION_API_KEY` has been renamed to `VISIONPOWER_API_KEY`. Please update MCP configuration or shell environment variables accordingly.
- It is recommended to replace `npx -y visionpower` with `npx -y --package visionpower@latest visionpower` to avoid `npx` preferring the local old version in `node_modules/.bin/visionpower`.
- For users in mainland China, use `npx -y --registry=https://registry.npmmirror.com --package visionpower@latest visionpower`.
## 🔒 Security Design
VisionPower performs multiple checks before passing images to the model, making it suitable for use in Agents that can read local files:
- **Path Whitelist** - After configuring `VISIONPOWER_ALLOWED_DIRS`, `image_path` must be within the whitelist directory; resolve symbolic links and compare to prevent soft link escaping.
- **Absolute Path Enforcement** - Reject relative paths to avoid ambiguity.
- **Magic-byte Verification** - Local images are verified for consistency between file bytes and extension; if they do not match, the image is rejected.
- **Strict Base64 Verification** - Reject `data:` prefixes, invalid characters, incorrect padding, and perform a re-encoding consistency check.
- **Private Network / SSRF Protection** - `image_url` intercepts `localhost`, private/reserved IPv4 ranges, IPv6 unique local/ link-local addresses, and IPv4-mapped IPv6 addresses, and rejects URLs with credentials.
- **Size and Quantity Limits** - Single image byte count, image count per call, output tokens, and request timeout are all configurable and enforced.
- **Strict Input Schema** - Based on zod validation, unknown fields and field combination conflicts are explicitly rejected.
## 🧪 Local Development
```bash
npm install
npm test # Unit tests (configuration parsing + image normalization + security verification + Skill script synchronization verification)
npm run smoke # End-to-end: start MCP server to confirm tool availability + Skill script rejects empty requests
npm run build:skill # After modifying the kernel, regenerate VisionPower-Skill/describe_image.mjs
npm start # Start MCP server directly using stdio
```
Source structure: `src/vision-core.js` (kernel logic), `src/config.js` (configuration), `src/schema.js` (MCP input schema), `src/index.js` (MCP export). Skill export `VisionPower-Skill/describe_image.mjs` is automatically generated from the kernel by `scripts/build-skill.mjs` (verified by `npm test`).
## ❓ Frequently Asked Questions
<details>
<summary><b>What is the difference between MCP and Skill? Which one should I install?</b></summary>
Functionally equivalent, the difference lies in the integration method: MCP exposes a structured tool, is cross-MCP host universal, and can be used even with pure chat hosts that do not support code execution; Skill is an instruction + a self-contained zero-dependency script that requires the Agent to have shell/code execution capabilities (like Codex, Claude Code). See [Which form to choose](#-which-form-to-choose). Both can be installed simultaneously.
</details>
<details>
<summary><b>Skill triggered but script does not run?</b></summary>
Confirm that Node 18+ is installed (`node --version`) and the script is called with its **absolute path** (e.g., `node ~/.claude/skills/visionpower/describe_image.mjs --help`). If it reports "API key not configured," follow the "Initial Setup" in `SKILL.md` to write the Key into `~/.visionpower/config.json`. If you "exported environment variables but they are still not recognized," it is likely that the Agent's child shell did not inherit them - switch to using a configuration file.
</details>
<details>
<summary><b>First startup is slow / occasionally fails?</b></summary>
`npx` downloads VisionPower on the first run and usually uses local caching afterward. Weak network or long-term usage suggests global installation.
</details>
<details>
<summary><b>Model not available / image_path not allowed?</b></summary>
Model availability depends on your service provider account, region, and permissions; switch to a model available under your account. `image_path` errors usually occur because `VISIONPOWER_ALLOWED_DIRS` is configured and the image is not within the whitelist, or the path is not an absolute path.
</details>
## 📄 License
[MIT](./LICENSE) © Runhua
<div align="center">
<sub>If VisionPower helps you, feel free to star it.</sub>
</div>
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available