We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/wenxint/ocp-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
# 从零开发一个 Cursor MCP 服务器:OCR 图片文字识别
> 本文将带你从零开始,开发一个可以在 Cursor 中使用的 MCP 服务器,实现图片文字识别(OCR)功能。
## 目录
1. [什么是 MCP?](#什么是-mcp)
- [一句话解释](#一句话解释)
- [通俗理解:AI 的"USB 接口"](#通俗理解ai-的usb-接口)
- [MCP 诞生的背景](#mcp-诞生的背景)
- [MCP 的核心角色](#mcp-的核心角色)
- [MCP 的三大能力](#mcp-的三大能力)
- [MCP 通信机制详解](#mcp-通信机制详解)
- [MCP 完整工作流程](#mcp-完整工作流程)
- [MCP vs 其他方案对比](#mcp-vs-其他方案对比)
2. [为什么要开发 OCR MCP?](#为什么要开发-ocr-mcp)
3. [技术架构](#技术架构)
4. [核心代码解析](#核心代码解析)
5. [如何在 Cursor 中配置](#如何在-cursor-中配置)
6. [实际演示](#实际演示)
7. [进阶扩展](#进阶扩展)
8. [总结](#总结)
---
## 什么是 MCP?
### 一句话解释
**MCP(Model Context Protocol,模型上下文协议)** 是一个让 AI 助手能够"连接外部世界"的标准协议。
### 通俗理解:AI 的"USB 接口"
想象一下,AI 助手(如 Claude、GPT)就像一台电脑的 CPU,它很聪明,但如果没有外设,它只能处理已有的信息。
```
┌─────────────────────────────────────────────────────────────────┐
│ 传统 AI 的局限 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 用户: "帮我查一下今天的天气" │
│ │
│ AI: "抱歉,我无法访问实时天气数据..." 😢 │
│ │
│ ─────────────────────────────────────────────────────────── │
│ │
│ 用户: "帮我读取桌面上的 data.xlsx 文件" │
│ │
│ AI: "抱歉,我无法访问你的本地文件..." 😢 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**MCP 就像是给 AI 装上了"USB 接口"**,让它可以连接各种"外设":
```
┌─────────────────────────────────────────────────────────────────┐
│ 有了 MCP 之后 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ 天气 API │ │
│ └──────┬──────┘ │
│ │ │
│ ┌─────────────┐ ┌──────┴──────┐ ┌─────────────┐ │
│ │ 文件系统 │──────│ AI │──────│ 数据库 │ │
│ └─────────────┘ │ (通过 MCP) │ └─────────────┘ │
│ └──────┬──────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ │ OCR 识别 │ ← 本项目 │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### MCP 诞生的背景
在 MCP 出现之前,各家 AI 公司都有自己的"插件系统":
| AI 平台 | 扩展方式 | 问题 |
|---------|----------|------|
| ChatGPT | GPT Actions / Plugins | 仅限 OpenAI 平台 |
| Claude | 无官方方案 | 无法扩展 |
| Cursor | 无标准方案 | 各自为政 |
这就像是:每个品牌的手机都有自己的充电接口,非常不方便。
**2024 年 11 月,Anthropic 推出了 MCP**,就像推出了"USB-C 标准":
- **开放协议**:任何人都可以实现
- **跨平台**:一次开发,多处使用(Cursor、Claude Desktop、未来更多)
- **标准化**:统一的通信格式,降低学习成本
### MCP 的核心角色
MCP 架构中有三个核心角色:
```
┌─────────────────────────────────────────────────────────────────┐
│ MCP 核心角色 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────────┐ ┌────────────────────┐ │
│ │ MCP Host │ │ MCP Server │ │
│ │ (宿主程序) │◄──── MCP 协议 ────►│ (服务器) │ │
│ │ │ │ │ │
│ │ 例如: │ │ 例如: │ │
│ │ - Cursor │ │ - OCR 服务器 │ │
│ │ - Claude │ │ - 数据库连接器 │ │
│ │ Desktop │ │ - 文件管理器 │ │
│ └────────────────┘ └────────────────────┘ │
│ │ │
│ │ 内置 │
│ ▼ │
│ ┌────────────────┐ │
│ │ MCP Client │ │
│ │ (客户端) │ 负责与 Server 通信 │
│ └────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
| 角色 | 说明 | 你需要关心吗? |
|------|------|---------------|
| **Host(宿主)** | 运行 AI 的应用程序,如 Cursor | 不需要,直接用 |
| **Client(客户端)** | Host 内置的 MCP 通信模块 | 不需要,已内置 |
| **Server(服务器)** | 提供具体功能的程序 | **需要!这是我们要开发的** |
### MCP 的三大能力
MCP Server 可以提供三种类型的能力:
```
┌─────────────────────────────────────────────────────────────────┐
│ MCP 三大能力 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 1. Tools(工具) │ │
│ │ 让 AI 执行操作,产生副作用 │ │
│ │ │ │
│ │ 例如: │ │
│ │ - 发送邮件 │ │
│ │ - 写入数据库 │ │
│ │ - OCR 识别图片 ← 本项目 │ │
│ │ - 执行代码 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 2. Resources(资源) │ │
│ │ 让 AI 读取数据,不产生副作用 │ │
│ │ │ │
│ │ 例如: │ │
│ │ - 读取本地文件内容 │ │
│ │ - 获取数据库记录 │ │
│ │ - 查询 API 数据 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ 3. Prompts(提示词模板) │ │
│ │ 预定义的提示词,可带参数 │ │
│ │ │ │
│ │ 例如: │ │
│ │ - 代码审查模板 │ │
│ │ - 翻译模板 │ │
│ │ - 文档生成模板 │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**本项目使用的是 Tools(工具)能力。**
### MCP 通信机制详解
#### 通信协议:JSON-RPC 2.0
MCP 使用 **JSON-RPC 2.0** 作为通信协议。简单来说,就是用 JSON 格式发送请求和接收响应。
**请求格式**:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "recognize_text",
"arguments": {
"image_path": "/path/to/image.png"
}
}
}
```
**响应格式**:
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "识别结果:Hello World"
}
]
}
}
```
#### 传输方式:stdio(标准输入输出)
Cursor 与 MCP Server 之间通过 **stdio** 通信:
```
┌─────────────────────────────────────────────────────────────────┐
│ stdio 通信机制 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Cursor MCP Server │
│ (node index.js) │
│ │ │ │
│ │ ────── stdin (标准输入) ───────────► │ │
│ │ 发送请求 JSON │ │
│ │ │ │
│ │ ◄───── stdout (标准输出) ──────────── │ │
│ │ 接收响应 JSON │ │
│ │ │ │
│ │ stderr (标准错误) ──────────► │ │
│ │ 日志输出(不影响通信) │ │
│ │
└─────────────────────────────────────────────────────────────────┘
```
**这就是为什么**:
- 代码中要用 `console.error()` 而不是 `console.log()`
- `console.log()` 会输出到 stdout,干扰 MCP 通信
### MCP 完整工作流程
当你在 Cursor 中说"识别这张图片"时,发生了什么?
```
┌─────────────────────────────────────────────────────────────────┐
│ MCP 完整工作流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ [1] 启动阶段 │
│ ════════════ │
│ Cursor 启动 → 读取 mcp.json 配置 → 启动 MCP Server 进程 │
│ │
│ [2] 初始化阶段 │
│ ════════════ │
│ Cursor ──────── initialize 请求 ────────► MCP Server │
│ Cursor ◄─────── 返回服务器信息 ─────────── MCP Server │
│ Cursor ──────── tools/list 请求 ────────► MCP Server │
│ Cursor ◄─────── 返回工具列表 ───────────── MCP Server │
│ │
│ 此时 Cursor 知道了有哪些工具可用: │
│ - recognize_text: 识别图片文字 │
│ - list_ocr_languages: 列出支持的语言 │
│ │
│ [3] 用户交互阶段 │
│ ════════════════ │
│ 用户输入: "请识别 /Desktop/img.png 中的文字" │
│ │ │
│ ▼ │
│ AI 理解用户意图,决定调用 recognize_text 工具 │
│ │ │
│ ▼ │
│ Cursor ──────── tools/call 请求 ────────► MCP Server │
│ { │
│ name: "recognize_text", │
│ arguments: { image_path: "..." } │
│ } │
│ │
│ [4] 执行阶段 │
│ ════════════ │
│ MCP Server │
│ │ │
│ ▼ │
│ 验证图片路径 │
│ │ │
│ ▼ │
│ 调用 Tesseract.js │
│ │ │
│ ▼ │
│ 执行 OCR 识别 │
│ │ │
│ ▼ │
│ Cursor ◄─────── 返回识别结果 ───────────── MCP Server │
│ { │
│ content: [{ │
│ type: "text", │
│ text: "识别结果: ..." │
│ }] │
│ } │
│ │
│ [5] 展示阶段 │
│ ════════════ │
│ AI 整合结果,以自然语言展示给用户 │
│ │
└─────────────────────────────────────────────────────────────────┘
```
### MCP vs 其他方案对比
| 对比项 | MCP | OpenAI Function Calling | 传统 API 调用 |
|--------|-----|------------------------|--------------|
| 标准化 | 开放标准 | OpenAI 专属 | 无标准 |
| 跨平台 | 支持多个 AI 平台 | 仅 OpenAI | 需自行适配 |
| 本地运行 | 支持 | 需要云端 | 支持 |
| 安全性 | 本地执行,数据不外传 | 数据需上传 | 取决于实现 |
| 学习成本 | 一次学习,多处使用 | 仅限 OpenAI | 每个 API 不同 |
### 小结
- **MCP 是什么**:AI 与外部工具通信的标准协议
- **解决什么问题**:让 AI 能够访问本地文件、调用外部服务、执行实际操作
- **核心角色**:Host(Cursor)、Client(内置)、Server(我们开发)
- **通信方式**:JSON-RPC 2.0 over stdio
- **三大能力**:Tools(工具)、Resources(资源)、Prompts(提示词)
---
## 为什么要开发 OCR MCP?
### 现有方案的局限
1. **Claude/GPT 的视觉能力**:虽然强大,但对于批量处理、特定格式(发票、表格)识别效果不稳定
2. **在线 OCR 工具**:需要手动上传下载,无法与开发流程集成
3. **专业 OCR 软件**:通常是独立应用,无法在 IDE 中直接使用
### MCP 方案的优势
- **无缝集成**:在 Cursor 对话中直接调用,无需切换应用
- **可定制**:可以接入任意 OCR 引擎(本地/云端)
- **可扩展**:识别结果可以直接用于代码生成、文档整理等后续操作
- **离线可用**:使用本地 OCR 引擎,无需联网
---
## 技术架构
### 技术选型
| 组件 | 选择 | 理由 |
|------|------|------|
| 运行时 | Node.js | 生态丰富,Cursor 原生支持 |
| MCP SDK | @modelcontextprotocol/sdk | 官方 SDK,稳定可靠 |
| OCR 引擎 | Tesseract.js | 纯 JS 实现,无需额外安装 |
| 通信方式 | stdio | Cursor 默认方式,简单高效 |
### 项目结构
```
ocr-mcp-server/
├── package.json # 项目配置
├── index.js # MCP 服务器主入口
├── ocr.js # OCR 识别模块
└── README.md # 使用说明
```
### 数据流
```
用户输入: "识别这张图片 /path/to/image.png"
│
▼
┌─────────────────────────────────────────────────────┐
│ Cursor (MCP Client) │
│ 1. 解析用户意图 │
│ 2. 匹配到 recognize_text 工具 │
│ 3. 构造 CallToolRequest │
└─────────────────────────────────────────────────────┘
│
│ JSON-RPC 请求 (via stdio)
│ {
│ "method": "tools/call",
│ "params": {
│ "name": "recognize_text",
│ "arguments": { "image_path": "/path/to/image.png" }
│ }
│ }
▼
┌─────────────────────────────────────────────────────┐
│ MCP Server (index.js) │
│ 1. 接收请求 │
│ 2. 路由到 recognize_text 处理器 │
│ 3. 调用 ocr.js 执行识别 │
└─────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ OCR Module (ocr.js) │
│ 1. 验证图片文件 │
│ 2. 调用 Tesseract.js 识别 │
│ 3. 返回识别结果 │
└─────────────────────────────────────────────────────┘
│
│ JSON-RPC 响应
│ {
│ "content": [{
│ "type": "text",
│ "text": "## OCR 识别结果\n\n识别内容: ..."
│ }]
│ }
▼
┌─────────────────────────────────────────────────────┐
│ Cursor 展示结果给用户 │
└─────────────────────────────────────────────────────┘
```
---
## 核心代码解析
### 1. MCP 服务器初始化
```javascript
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
// 创建服务器实例
const server = new Server(
{
name: 'ocr-mcp-server', // 服务器名称
version: '1.0.0',
},
{
capabilities: {
tools: {}, // 声明提供工具能力
},
}
);
```
**关键点**:
- `Server` 类是 MCP SDK 的核心
- `capabilities` 声明服务器提供的能力类型
- `tools: {}` 表示这是一个工具类服务器
### 2. 注册工具列表
```javascript
import { ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'recognize_text',
description: '识别图片中的文字内容(OCR)...',
inputSchema: {
type: 'object',
properties: {
image_path: {
type: 'string',
description: '图片文件的本地绝对路径',
},
languages: {
type: 'array',
items: { type: 'string' },
description: '识别语言代码数组',
default: ['chi_sim', 'eng'],
},
},
required: ['image_path'],
},
},
],
};
});
```
**关键点**:
- `description` 非常重要!AI 根据它判断何时调用工具
- `inputSchema` 使用 JSON Schema 规范定义参数
- `required` 数组指定必填参数
### 3. 处理工具调用
```javascript
import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case 'recognize_text': {
const result = await recognizeText(args.image_path, args.languages);
return {
content: [
{
type: 'text',
text: result.success
? `识别结果:${result.text}`
: `识别失败:${result.error}`,
},
],
};
}
}
});
```
**关键点**:
- `request.params` 包含工具名和参数
- 返回值必须是 `{ content: [...] }` 格式
- `content` 数组支持 `text`、`image` 等类型
### 4. OCR 识别实现
```javascript
import Tesseract from 'tesseract.js';
export async function recognizeText(imagePath, languages = ['chi_sim', 'eng']) {
const result = await Tesseract.recognize(
imagePath,
languages.join('+'), // 'chi_sim+eng'
);
return {
success: true,
text: result.data.text,
confidence: result.data.confidence,
};
}
```
**关键点**:
- Tesseract.js 的 `recognize` 方法是异步的
- 多语言用 `+` 连接
- 返回的 `confidence` 表示识别置信度(0-100)
### 5. 启动服务器
```javascript
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error('OCR MCP Server 已启动'); // 注意:用 stderr
}
main();
```
**关键点**:
- 使用 `StdioServerTransport` 通过标准输入输出通信
- 日志必须用 `console.error`,因为 `stdout` 被 MCP 协议占用
---
## 如何在 Cursor 中配置
### 方式一:通过 UI 配置
1. 打开 Cursor 设置:`Cmd/Ctrl + ,`
2. 搜索 `MCP`
3. 点击 `Edit in settings.json`
### 方式二:直接编辑配置文件
编辑 `~/.cursor/mcp.json`:
```json
{
"mcpServers": {
"ocr-tool": {
"command": "node",
"args": ["/完整路径/ocr-mcp-server/index.js"]
}
}
}
```
### 配置说明
| 字段 | 说明 |
|------|------|
| `ocr-tool` | 服务器标识名(自定义) |
| `command` | 启动命令(node/python/npx 等) |
| `args` | 命令参数数组 |
### 验证配置
配置完成后重启 Cursor,在 MCP 设置中应该能看到绿色状态指示器,表示连接成功。
---
## 实际演示
### 示例 1:基本使用
**用户输入**:
> 请识别这张图片中的文字:/Users/xxx/Desktop/screenshot.png
**AI 调用工具后返回**:
> ## OCR 识别结果
>
> **置信度**: 86.0%
>
> **识别内容**:
>
> 将 reconciliation/config/config.js 中的 '宝付Gep' 改为 'Payful'
### 示例 2:指定语言
**用户输入**:
> 用日文识别这张图片:/path/to/japanese.png
AI 会自动将 `languages` 参数设为 `['jpn']`。
### 示例 3:查询支持的语言
**用户输入**:
> OCR 支持哪些语言?
**返回**:
> ## 支持的 OCR 语言
>
> - `chi_sim`: 简体中文
> - `chi_tra`: 繁体中文
> - `eng`: 英文
> - `jpn`: 日文
> - ...
---
## 进阶扩展
### 1. 返回带标注的图片
MCP 支持返回图片类型的内容:
```javascript
return {
content: [
{
type: 'image',
data: base64ImageData, // Base64 编码的图片
mimeType: 'image/png',
},
],
};
```
可以在原图上标注识别出的文字区域,返回给用户。
### 2. 批量处理
添加一个扫描文件夹的工具:
```javascript
{
name: 'batch_ocr',
description: '批量识别文件夹中所有图片',
inputSchema: {
type: 'object',
properties: {
folder_path: { type: 'string' },
output_format: { enum: ['json', 'markdown', 'csv'] },
},
},
}
```
### 3. 接入云端 OCR
替换 Tesseract.js 为云端 API,获得更高精度:
```javascript
// 百度 OCR API 示例
async function baiduOCR(imagePath) {
const imageBase64 = fs.readFileSync(imagePath, 'base64');
const response = await fetch('https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic', {
method: 'POST',
body: `image=${encodeURIComponent(imageBase64)}`,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
});
return response.json();
}
```
### 4. 表格识别
专门处理表格图片,输出 Markdown 表格:
```javascript
{
name: 'recognize_table',
description: '识别图片中的表格,输出 Markdown 格式',
}
```
---
## 总结
### 本项目实现了什么
1. **一个完整的 MCP 服务器**:遵循 MCP 协议规范
2. **OCR 文字识别能力**:基于 Tesseract.js,支持多语言
3. **Cursor 无缝集成**:在对话中直接调用,提升开发效率
### 技术要点回顾
| 要点 | 说明 |
|------|------|
| MCP 协议 | 标准化 AI 与工具的通信 |
| stdio 传输 | 通过标准输入输出通信,简单高效 |
| JSON Schema | 定义工具参数,让 AI 理解如何调用 |
| 工具描述 | AI 根据描述判断何时调用,需要写得清晰准确 |
### 扩展思路
- **更多 OCR 引擎**:PaddleOCR、EasyOCR、云端 API
- **更多功能**:表格识别、公式识别、手写识别
- **更多工具**:文件处理、数据转换、自动化操作
### 参考资源
- [MCP 官方文档](https://modelcontextprotocol.io/)
- [MCP SDK GitHub](https://github.com/modelcontextprotocol/sdk)
- [Tesseract.js 文档](https://github.com/naptha/tesseract.js)
- [Cursor MCP 配置指南](https://cursor.com/docs/context/mcp)
---
## 完整代码
本项目完整代码见同目录下的 `index.js` 和 `ocr.js` 文件。
如有问题欢迎交流!🎉