内容
# md-vision MCP 服务器
stdio MCP 服务器,包含两个只读工具,用于在 markdown 文档上进行智能 RAG:
- **读取带图片的 Markdown** — 返回 markdown 及引用的图片作为交织的图片块。避免为每个图片读取而额外调用工具。可选作用于特定章节或行范围。
- **索引 Markdown** — 返回文件、URL 或文件夹中 markdown 文件的紧凑标题索引。用于动态索引文件以进行目标读取。
典型流程:调用 `索引 Markdown` 以发现标题和结构,然后在需要的章节调用 `读取带图片的 Markdown`。
## 安装:MCP 客户端配置
已发布软件包:[md-vision on npm](https://www.npmjs.com/package/md-vision)
在代理配置文件(`.agents/mcp.json` 或类似)中,将 MCP 主机指向服务器。示例:
```json
{
"mcpServers": {
"md-vision": {
"command": "npx",
"args": [
"md-vision",
"--allow-path",
"/absolute/path/to/docs",
"--allow-domain",
"none"
]
}
}
}
```
**使用远程 Markdown** (允许所有 HTTP(S) 主机,或列出特定域名):
```json
{
"mcpServers": {
"md-vision": {
"command": "npx",
"args": [
"md-vision",
"--allow-path",
"/absolute/path/to/docs",
"--allow-domain",
"all"
]
}
}
}
```
```json
{
"mcpServers": {
"md-vision": {
"command": "npx",
"args": [
"md-vision",
"--allow-path",
"/absolute/path/to/docs",
"--allow-domain",
"raw.githubusercontent.com"
]
}
}
}
```
如果省略 `--allow-path` 或 `--allow-domain`,服务器将在启动时退出。
更改配置后重启 MCP 主机。
### 限制允许的路径和域名
| 参数 | 是否必需 | 效果 |
|------|----------|--------|
| `--allow-path <dir>` | 是(至少一个) | 本地文件必须解析为允许的目录之一(可重复)。 |
| `--allow-domain <host>` | 是(至少一个) | 控制 HTTP(S) 访问。使用 `all` 允许任何主机,`none` 禁用 URL(仅本地文件),或列出特定主机(可重复;支持后缀匹配,例如 `example.com` 允许 `docs.example.com`)。 |
等效形式: `--allow-path=/path`, `--allow-domain=host.example`, `--allow-domain=all`, `--allow-domain=none`。
不要将裸 `*` 作为单独的 shell 参数传递 — shell 会将其展开为当前目录中的文件名。使用 `all` 或 `--allow-domain=all` 代替。
### 需求
- Node.js 20+
## 工具
### 读取带图片的 Markdown
读取 markdown 文件并内联引用图片作为 MCP 图片内容。
| 参数 | 类型 | 描述 |
|-----------|------|-------------|
| `uri` | 字符串 | 本地路径或 `http(s)://` URL |
| `section` | 字符串,可选 | 精确标题读取,例如 `## 介绍`(使用时匹配;否则回退到 `line_range`) |
| `line_range` | `[start, end]`,可选 | 包含 1-based 文档行范围(在省略或未找到 `section` 时使用) |
| `max_images` | 整数,可选 | 最大内联图片数(默认 `10`,最大 `50`) |
**返回:** MCP 内容数组 — 交替的 `text` 和 `image` 块(PNG,base64)在文档顺序;前面的文本保留 frontmatter。在每个内联图片之前,一个短的 `text` 块带有解析的图片 URL(省略 `data:` URIs 和其他长引用)。超过 `max_images` 的图片保留为 markdown 图片语法在文本中。
**URI 形式:** 本地文件系统路径和 `http(s)://` URLs。本地路径必须位于配置的 `--allow-path` 目录下。相对图片路径相对于 markdown 文件位置或文档 URL 解析。图片可以使用 markdown `` 语法或 HTML `<img src="...">` 标签。
### 索引 Markdown
索引标题以便在目标读取前导航。
| 参数 | 类型 | 描述 |
|-----------|------|-------------|
| `uri` | 字符串 | markdown 文件,`http(s)://` URL 或本地文件夹 |
**返回:** Markdown 字符串。对于每个文件:
1. 如果存在 YAML frontmatter。
2. 一个围栏 `tsv` 代码块,包含列:`heading`,`line_start`,`n_images`,`char_count`。
每个文件都包裹在:
```xml
<file path="..." lines=X chars=Y>
...
</file>
```
文件夹 `uri` 值递归扫描以获取 `*.md` / `*.markdown` 文件,排序稳定。 标题内嵌代码块不索引。
## 关于使用此 MCP 服务器部署代理的说明
stdio MCP 服务器作为调用它们的代理运行时 subprocess 运行。 有两种常用的部署模式:
- **代理在沙盒中** (运行时共享代理的文件系统):服务器可以原地读取文档;将 `--allow-path` 限定为要公开的文档树。
- **沙盒作为工具** (运行时文件系统与工具沙盒不同):MCP 进程通常在运行时环境中运行,因此 markdown 必须复制或同步到服务器可以读取的位置。
## 基准测试(WIP)
参见 [`benchmark/`](benchmark/) 以获取 MMLongBench-Doc A/B 测试框架,比较仅限文件系统的智能 RAG 与带有 `md-vision` MCP 工具的相同代理。
## 独立索引
`md-vision` 还可以用作库,当需要在 MCP 主机之外索引 markdown 时 — 例如在智能 RAG 的离线预处理管道中。
安装软件包:
```bash
npm install md-vision
```
### 索引 Markdown 文本
在内存中已有 markdown 内容时使用 `indexMarkdownText`。
```ts
import { indexMarkdownText } from "md-vision";
const markdown = `# Guide
Intro text.
## Setup

`;
const index = indexMarkdownText(markdown);
console.log(index.rows);
```
示例结果:
```ts
[
{
heading: "# Guide",
lineStart: 1,
imageCount: 1,
charCount: 42
},
{
heading: "## Setup",
lineStart: 5,
imageCount: 1,
charCount: 24
}
]
```
### 索引文件
使用 `indexMarkdownFile` 加载并索引本地 markdown 文件。
```ts
import { indexMarkdownFile } from "md-vision";
const index = await indexMarkdownFile("./docs/guide.md");
await saveToVectorStoreMetadata({
path: index.path,
frontmatter: index.frontmatter,
headings: index.rows,
});
```
### 索引文件夹
使用 `indexMarkdownFolder` 递归索引 `*.md` 和 `*.markdown` 文件,排序稳定。
```ts
import { indexMarkdownFolder } from "md-vision";
const files = await indexMarkdownFolder("./docs");
for (const file of files) {
console.log(file.path, file.rows);
}
```
### 输出形状
每个索引文件返回结构化数据:
```ts
type MarkdownFileIndex = {
path?: string;
frontmatter: string;
lineCount: number;
charCount: number;
rows: HeadingIndexRow[];
};
type HeadingIndexRow = {
heading: string;
lineStart: number;
imageCount: number;
charCount: number;
};
```
标题内嵌代码块被忽略,因为索引使用 markdown AST 而不是正则表达式匹配。