关于 excel-vision-mcp
Excel Vision MCP 是一个用于读写 xlsx 文件的 MCP 服务,可提取工作表中的嵌入图片并以 ImageContent 返回给模型。它同时保留单元格文本、格式标记和公式,适合依赖图表或截图的表格分析。文件在本地处理,不会离开用户机器。
主要功能
- 01提取嵌入图片并映射到单元格位置
- 02返回文本、格式标记与图片的完整内容
- 03跳过隐藏行列,除非公式引用
- 04支持创建工作簿、写入单元格与公式
- 05原子保存,写入失败不损坏原文件
适用场景
- 01让 AI 助手审阅包含流程图的需求文档
- 02读取单元格颜色或删除线所表达的状态
- 03通过 MCP 客户端批量写入或格式化表格
MCP 相关
该项目是一个 MCP 服务,向 MCP 客户端暴露列出工作表、读取内容、提取图片、搜索及写入 Excel 文件的工具。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
13收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| file_path | string | 是 |
详细介绍
📊 Excel Vision MCP
你的 AI 能读取电子表格,却看不到 B12 单元格中的图表。
这正是本工具要解决的问题。 其他 Excel MCP 服务只返回单元格值,并悄悄丢弃所有嵌入的图像,因此你的规范所依赖的流程图根本无法传递给模型。Excel Vision MCP 会将图像作为原生 ImageContent 返回,让你的 AI 真正能够查看图像,同时还能获取文本、格式和公式。
🤔 问题所在
请助手审阅一份需求规范。内容有一半藏在粘贴到单元格中的屏幕截图、流程图和标注图里——而所有 Excel MCP 服务都只会向模型提供文本。模型从未知道这些图片存在,因此给出的答案听起来很有把握,内容却不完整。
同样的盲区也存在于作者留下的其他线索中:
| 作者的操作 | 其他 MCP 服务的报告内容 | Excel Vision MCP 的报告内容 |
|---|---|---|
在 B12 中粘贴流程图 | 无 | 图像本身,并映射到 B12 |
| 为取消的行添加删除线 | Legacy export | Legacy export [S] — 删除线 |
| 高亮一行以供审阅 | Pending | Pending [HL:yellow] |
| 隐藏内部成本列 | 将隐藏值当作普通内容显示 | 跳过 — 除非公式需要这些值 |
同一个文件。一个 Agent 看到的是字符串表格,另一个看到的则是作者真正想表达的内容。
✨ 主要功能
| 功能 | 说明 |
|---|---|
| 🖼️ 图像提取 | 提取所有嵌入的图像,并映射其单元格位置 |
| 📄 完整内容读取 | 一次调用即可读取文本和图像,不会遗漏任何内容 |
| 🏷️ 感知格式的读取 | 报告粗体、删除线、高亮和字体颜色,让 Agent 读取意图而不只是文本 |
| 🙈 感知隐藏内容 | 默认跳过隐藏的行和列,同时保留公式所依赖的内容 |
| ✍️ 写入支持 | 创建工作簿、更新单元格、写入公式、插入图像 |
| 🎨 格式设置 | 颜色、字体、边框、对齐方式、数字格式、列宽自动适配 |
| 🛡️ 原子保存 | 写入失败绝不会损坏原始文件 |
| 📊 智能分页 | 处理大型电子表格而不会撑爆上下文 |
| 🔍 文本搜索 | 即时查找所有工作表中的内容 |
| 🔒 100% 本地运行 | 文件永远不会离开你的设备 |
| ⚡ 快速 | 处理包含 40 张图像的 16MB 文件约需 4 秒 |
| 🖥️ 跨平台 | macOS、Linux、Windows |
图像提取 — 与众不同之处
大多数 Excel MCP 服务只读取单元格值。本服务采用双重提取策略:
- 单元格位置映射(主要方式)——使用
openpyxl-image-loader将每张图像映射到其确切的单元格位置 - 归档扫描(备用方式)——扫描 xlsx ZIP 归档中的
xl/media/目录,捕获方法 1 遗漏的所有图像
最终效果:零图像遗漏,并在可用时提供位置元数据。
👀 实际效果
一份需求规格说明,其中工作流放在粘贴的图表里,状态则通过单元格颜色表示:
你: 审查这份规格说明,告诉我哪些功能仍在范围内,以及调度流程是怎样的。
read_full_content 会以带格式标记的文本形式返回工作表,然后将嵌入的图表作为图像返回:
Row 1: A1: Feature [B] [HL:blue] | B1: Status [B] [HL:blue]
Row 2: A2: Vehicle dispatch | B2: Approved [HL:green]
Row 3: A3: Legacy CSV export [S] | B3: Cancelled [S]
Row 4: A4: Driver roll call | B4: Needs review [HL:yellow]
ℹ️ Skipped 3 hidden row(s) with content. Pass include_hidden=true to read them.
**[Image 1]** Sheet: `Spec` | Cell: `B12` | Original: 1180×840px
[the actual flowchart, as ImageContent]
现在,模型可以回答问题的两部分:“旧版 CSV 导出已被划掉并标记为已取消,因此仍在范围内的功能有三项;而 B12 中的流程图显示,分配任务前必须先确认点名结果。”
没有图像支持,就无法回答问题的第二部分。没有格式信息,被取消的行看起来就和有效行一模一样。
🚀 快速开始
通过 uvx 安装(推荐)
无需安装 — 直接运行:
uvx excel-vision-mcp
通过 pip 安装
pip install excel-vision-mcp
然后运行:
excel-vision-mcp
从源代码安装
git clone https://github.com/VOYAGER-Inc/excel-vision-mcp.git
cd excel-vision-mcp
uv sync
uv run excel-vision-mcp
使用 Docker 运行
docker build -t excel-vision-mcp .
docker run --rm -i -v /path/to/spreadsheets:/data excel-vision-mcp
该服务通过 stdin/stdout 使用 JSON-RPC,因此必须以附加模式运行(-i)。挂载存放文件的目录,并使用容器内路径引用文件(/data/report.xlsx)。该镜像设置了 EXCEL_VISION_MCP_ALLOWED_DIRS=/data,因此读写操作都限制在挂载目录内。
作为 MCP 客户端配置:
{
"mcpServers": {
"excel-reader": {
"command": "docker",
"args": ["run", "--rm", "-i", "-v", "/path/to/spreadsheets:/data", "excel-vision-mcp"]
}
}
}
🔧 配置
将该服务添加到 MCP 客户端的配置文件中。
Claude Desktop
编辑 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或 %APPDATA%\Claude\claude_desktop_config.json(Windows):
{
"mcpServers": {
"excel-reader": {
"command": "uvx",
"args": ["excel-vision-mcp"]
}
}
}
Cursor
编辑项目根目录下的 .cursor/mcp.json:
{
"mcpServers": {
"excel-reader": {
"command": "uvx",
"args": ["excel-vision-mcp"]
}
}
}
Windsurf / VS Code (Copilot)
编辑 MCP 设置文件:
{
"mcpServers": {
"excel-reader": {
"command": "uvx",
"args": ["excel-vision-mcp"]
}
}
}
Antigravity IDE
编辑 ~/.gemini/config/mcp_config.json:
{
"mcpServers": {
"excel-reader": {
"command": "uvx",
"args": ["excel-vision-mcp"]
}
}
}
注意: 编辑配置后,请重启 IDE/客户端以加载新的服务。
限制文件访问(可选)
默认情况下,该服务可以读写用户帐户有权访问的任何 Excel 文件。若要将其限制在特定目录中,请设置 EXCEL_VISION_MCP_ALLOWED_DIRS(在 macOS/Linux 上用 : 分隔多个路径,在 Windows 上用 ; 分隔):
{
"mcpServers": {
"excel-reader": {
"command": "uvx",
"args": ["excel-vision-mcp"],
"env": {
"EXCEL_VISION_MCP_ALLOWED_DIRS": "/Users/me/Documents/spreadsheets:/Users/me/Projects/data"
}
}
}
}
🛠️ 可用工具
list_sheets
列出所有工作表及其尺寸、合并单元格数量和图像总数。首先使用此工具了解工作簿的结构。
list_sheets(file_path="/path/to/file.xlsx")
返回: 工作表名称、行×列尺寸、数据范围、合并单元格数量和图像总数。
read_excel_data
读取特定工作表中的单元格数据,并支持分页。
read_excel_data(
file_path="/path/to/file.xlsx",
sheet_name="Sheet1", # optional, defaults to first sheet
start_row=1, # optional, 1-indexed
max_rows=200, # optional, default 200
include_hidden=False # optional, read hidden rows/columns too
)
返回: 按行整理的单元格值,带坐标标签以及合并单元格和格式标记。
Row 1: A1: Feature [B] [HL:blue] | B1: Status [B] [HL:blue]
Row 3: A3: Legacy export [S] | B3: Cancelled [S]
Row 4: A4: Report | B4: Needs review [HL:yellow] | C4: Urgent [B] [C:red]
| 标记 | 含义 |
|---|---|
[M] | 合并单元格 |
[B] [I] [S] | 粗体 · 斜体 · 删除线 |
[HL:color] | 突出显示的背景(颜色名称,例如 yellow、red) |
[C:color] | 字体颜色 |
[HIDDEN-REF] | 因被可见公式引用而保留的隐藏单元格 |
只有实际使用格式的工作表才会显示标记和简短图例,因此普通工作表不会占用额外上下文。
extract_images
将工作簿中的所有嵌入图像提取为 base64 ImageContent。
extract_images(
file_path="/path/to/file.xlsx",
sheet_name="Overview", # optional, None = all sheets
max_width=1024, # optional, resize limit
max_height=1024 # optional, resize limit
)
返回: ImageContent(base64)列表及元数据 — 单元格位置、工作表名称和原始尺寸。
read_full_content ⭐
明星工具。 一次调用即可读取所有文本数据和所有嵌入图像。适合进行全面的文档分析。
read_full_content(
file_path="/path/to/file.xlsx",
max_rows_per_sheet=500, # optional
max_image_width=1024, # optional
max_image_height=1024 # optional
)
返回: 完整的工作簿内容 — 每个工作表的数据均以结构化文本形式呈现(带格式标记),随后是所有嵌入图像及其单元格位置映射。
示例用例: “分析这份需求文档并总结所有用例,包括工作流图表。”
隐藏的行和列
默认情况下,所有读取工具都会跳过隐藏的行和列——隐藏它们的作者表明,这些内容不属于待审阅的内容。
**一个例外:**可见公式引用的隐藏单元格仍会返回,并标记为 [HIDDEN-REF],因为它的值会影响你看到的结果。被跳过的内容始终会报告,因此不会有内容在不知情的情况下消失:
ℹ️ Skipped 2 hidden row(s) with content. 1 hidden cell(s) are shown anyway
because visible formulas reference them. Pass include_hidden=true to read them.
传入 include_hidden=true,即可使用 read_excel_data、read_full_content 或 search_excel 读取所有内容。
get_workbook_overview
快速概览工作簿结构,包括文件大小、工作表列表、维度和图像数量。
get_workbook_overview(file_path="/path/to/file.xlsx")
search_excel
对工作簿中的所有单元格进行不区分大小写的文本搜索。
search_excel(
file_path="/path/to/file.xlsx",
query="revenue",
sheet_name="Q4 Report" # optional, None = all sheets
)
**返回:**匹配的单元格及其工作表名称、坐标和值。最多返回 100 条结果。
create_excel_file
创建一个包含指定工作表的新空工作簿。
create_excel_file(
file_path="/path/to/new.xlsx",
sheet_names=["Summary", "Detail"], # optional, default ["Sheet1"]
overwrite=False # optional, refuses to replace by default
)
add_excel_sheet
向现有工作簿添加一个新的空工作表。
add_excel_sheet(file_path="/path/to/file.xlsx", sheet_name="Q3", position=0)
update_excel_cells
按坐标设置单元格。以 = 开头的值会作为公式写入。
update_excel_cells(
file_path="/path/to/file.xlsx",
updates={"A1": "Title", "B2": 42, "C2": "=SUM(B2:B10)"},
sheet_name="Data" # optional, defaults to first sheet
)
注意:新写入的公式在文件于 Excel 中打开之前不会显示计算结果。对于合并区域,请写入左上角的锚定单元格。
write_excel_rows
通过一次调用写入一个矩形表格数据块。
write_excel_rows(
file_path="/path/to/file.xlsx",
rows=[["Item", "Qty"], ["Widget", 4], ["Gadget", 7]],
sheet_name="Data", # optional
start_cell="A1" # optional
)
insert_excel_image
将本地图片文件插入工作簿,并锚定到指定单元格。
insert_excel_image(
file_path="/path/to/file.xlsx",
image_path="/path/to/chart.png",
cell="B2",
sheet_name="Report", # optional
width=480, height=320 # optional display size in px
)
format_excel_cells
设置区域样式:字体、颜色、边框、对齐方式和数字格式。只会更改传入的属性,保留现有样式。
format_excel_cells(
file_path="/path/to/file.xlsx",
cell_range="A1:D1",
bold=True,
font_color="FFFFFF",
fill_color="4472C4",
horizontal_align="center",
border_style="thin", # thin | medium | thick | double | dashed | dotted
border_edges="all", # "all" or "outline" (outer edge of range only)
number_format="#,##0.00" # any Excel format code
)
set_excel_column_widths
手动设置列宽,和/或根据内容自动调整列宽。
set_excel_column_widths(
file_path="/path/to/file.xlsx",
widths={"A": 12, "B": 35}, # explicit widths (skipped by auto-fit)
auto_fit=True, # size remaining columns to content
max_width=60, # cap for auto-fit
wrap_overflow=True # wrap cells longer than the cap
)
自动调整列宽时,全角 CJK 字符(日本語)按 2 个单位计算。超过
max_width的单元格会启用自动换行,而不会拉宽列;在 Excel 中打开时,行高会自动扩展。
所有写入工具都会使用原子保存:先将工作簿写入临时文件,再替换原文件,因此保存失败也不会损坏原文件。
.xlsm宏会保留。已知的 openpyxl 限制:重新保存时不会保留数据透视表和部分复杂图表功能。
⚙️ 工作原理
架构
Your AI Client (Claude, Cursor, etc.)
│
│ stdio (JSON-RPC)
▼
┌─────────────────────────────┐
│ Excel Vision MCP │
│ │
│ ┌───────────────────────┐ │
│ │ openpyxl │ │──→ Cell data, formulas, merged cells
│ │ (Excel parser) │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ openpyxl-image-loader │ │──→ Images with cell positions
│ │ + zipfile (fallback) │ │
│ └───────────────────────┘ │
│ │
│ ┌───────────────────────┐ │
│ │ Pillow │ │──→ Resize, optimize, base64 encode
│ │ (image processing) │ │
│ └───────────────────────┘ │
└─────────────────────────────┘
│
│ TextContent + ImageContent
▼
AI sees text AND images
数据流与隐私
- **你的文件始终保留在本机。**服务通过
stdio在本地运行——不会发起网络请求、上传文件或使用云服务。 - **读取工具绝不会修改你的文件。**所有图像处理都在内存中完成(
BytesIO缓冲区)。写入工具只会通过原子保存(临时文件 + 替换)更改你指定的确切文件,绝不会留下只写入一半的工作簿。 - **可选的目录沙盒。**设置
EXCEL_VISION_MCP_ALLOWED_DIRS(以路径分隔符分隔的列表),可限制服务能够读取或写入的目录。未设置 = 不受限制。 - **内存会自动释放。**每次请求完成后,Python 垃圾回收器都会回收所有缓冲区。
图像处理管道
Original image in .xlsx (e.g., 2048×1536px PNG)
↓ Extract from ZIP archive / drawing layer
↓ Resize to fit max dimensions (default 1024px)
↓ Compress (JPEG 80% / PNG optimized)
↓ Base64 encode
→ ImageContent returned to AI client (~100-300KB per image)
📋 支持的格式
| 格式 | 状态 | 说明 |
|---|---|---|
.xlsx | ✅ 完全支持 | Excel 2007+ Open XML |
.xlsm | ✅ 完全支持 | 启用宏的工作簿 |
.xls | ❌ 不支持 | 旧版 Excel 97-2003 格式 |
.csv | ❌ 不支持 | 请使用专用的 CSV 工具 |
图像类型
| 图像类型 | 映射到单元格 | 从存档中提取 |
|---|---|---|
| PNG | ✅ | ✅ |
| JPEG | ✅ | ✅ |
| GIF | ✅ | ✅ |
| BMP | ✅ | ✅ |
| TIFF | ⚠️ 部分支持 | ✅ |
| EMF/WMF | ❌ | ✅ |
=IMAGE() 公式 | ❌ | ❌ |
| 批注中的图像 | ❌ | ❌ |
📊 性能
在真实企业 Excel 文件上进行的测试(macOS、Apple Silicon):
| 文件 | 大小 | 工作表 | 提取的图片 | 耗时 |
|---|---|---|---|---|
| 需求文档 A | 4.5 MB | 12 | 24 | 2.4s |
| 需求文档 B | 5.0 MB | 6 | 18 | 2.4s |
| 需求文档 C | 10.7 MB | 6 | 13 | 1.5s |
| 主规格说明 | 16.0 MB | 12 | 40 | 4.4s |
❓ 常见问题
为什么无法从 .xls 文件中提取图片?
.xls 是旧版二进制格式(Excel 97-2003)。与 .xlsx(基于 ZIP 的 Open XML)相比,它采用了完全不同的内部结构(BIFF)。所用的库(openpyxl、openpyxl-image-loader)仅支持现代 Open XML 格式。如果你有 .xls 文件,请先使用 Excel 或 LibreOffice 将其转换为 .xlsx。
为什么有些图片被标记为“孤立图片”?
主要提取方法(openpyxl-image-loader)会将图片映射到特定单元格,但可能会漏掉未锚定到标准绘图层的图片。备用的存档扫描器会从 xl/media/ 目录中捕获这些“孤立图片”——你仍能获取所有图片,只是孤立图片没有单元格位置信息。
我可以将它与不支持视觉能力的模型搭配使用吗?
可以!文本数据提取可与任何模型完美配合。图片提取仍会返回 ImageContent,但纯文本模型只会忽略图片数据,不会报错。
我的数据安全吗?
安全。服务完全通过 stdio 传输在你的本地计算机上运行。不会通过网络发送数据,也不会将文件上传到任何地方。读取工具绝不会修改你的文件;写入工具只会更改你明确指定的文件,并使用原子保存,因此写入失败不会损坏文件。你还可以使用 EXCEL_VISION_MCP_ALLOWED_DIRS 环境变量,将服务限制在特定目录中运行。
如何处理超大文件(100MB 以上)?
服务使用 read_only 模式迭代数据,并逐个在内存中处理图片。对于特别大的文件,请使用带分页参数(start_row + max_rows)的 read_excel_data,而不要使用 read_full_content,以控制内存用量。
🗺️ 路线图
- 写入支持 — 创建工作簿、更新单元格、写入公式、插入图片 (v1.1.0)
- 格式感知读取 — 粗体、删除线、突出显示、颜色;处理隐藏内容 (v1.2.0)
- 公式计算 — 同时显示公式及其计算结果
- CSV/TSV 支持 — 扩展支持其他表格格式
- 条件格式 — 提取格式规则
- 图表提取 — 将图表渲染为图片
🤝 参与贡献
欢迎贡献!请先创建 issue,讨论你想要进行的更改。
git clone https://github.com/VOYAGER-Inc/excel-vision-mcp.git
cd excel-vision-mcp
uv sync
uv run pytest # Run the test suite
📄 许可证
MIT — 随你使用。
为需要纵览全局而非仅查看文本的 AI Agent 而构建。
如果这个仓库对你有帮助,请点个星标!
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。