Skip to main content
Glama

office-mcp

一个 MCP 服务器:让 AI agent 能读 Word、Excel、PPT、PDF。

模型能读代码、能读网页,但读不了你的 .docx。这个项目用 MCP 协议把办公文档接给 agent——接上之后,一句"看看这份报告讲了什么"就能直接出结论。

为什么是 MCP

方案

问题

写个脚本让 agent 调

每个 agent 都要单独适配

把文档转成 txt 再喂

丢结构(表格、标题层级、备注全没了)

MCP 服务器

一次实现,任何支持 MCP 的客户端都能用

MCP(Model Context Protocol)是标准协议,stdio 上跑 JSON-RPC 2.0。接一次,Claude Desktop / Cline / VS Code Copilot / DeepSeek Harness 都能用。

Related MCP server: MinerU Document Explorer

架构

┌─────────────┐   JSON-RPC over stdio   ┌──────────────┐
│  AI agent   │ ◀─────────────────────▶ │  office-mcp  │
│ (MCP 客户端) │   initialize/tools/call │   server.py  │
└─────────────┘                         └──────┬───────┘
                                               │
                                    ┌──────────┴──────────┐
                                    ▼                     ▼
                              python-docx           openpyxl
                              python-pptx           pymupdf

四个工具

工具

输入

输出

doc_read

.docx

Markdown:标题、段落、列表、表格(按原文顺序)

sheet_read

.xlsx

列出所有工作表,指定表转 Markdown 表格(取公式计算结果)

slide_read

.pptx

按页输出标题、正文要点、表格、演讲者备注

pdf_extract

.pdf

按页范围提文本;扫描件会明确说"没有文字层"

所有输出都有截断上限,防止 300 页的文档把上下文撑爆。

快速开始

1. 装依赖

pip install -r requirements.txt

四个库各管一种格式,只读 Word 就只装 python-docx。

2. 自检

python server.py --selftest "D:\某处\报告.docx"

会列出工具清单,并真的读一次那份文档。

3. 接进 MCP 客户端

配置形如(各客户端字段名略有差异):

{
  "mcpServers": {
    "office": {
      "command": "python",
      "args": ["D:\\path\\to\\office-mcp\\server.py"]
    }
  }
}

注意:command 要用装了上述依赖的那个 Python。如果系统 Python 没装库,就填虚拟环境或其它解释器的绝对路径。

4. 手动验证协议

python examples/test_client.py

它会把完整对话跑一遍:initialize → tools/list → 三次 tools/call(真实文档)→ 两个错误场景。

实测输出:

[id=1] initialize -> {'name': 'office-mcp', 'version': '1.0.0'} 协议 2024-11-05
[id=2] tools/list -> 4 个工具: ['doc_read', 'sheet_read', 'slide_read', 'pdf_extract']

[id=3] ✅ 返回 631 字符:
     # 家庭用电分析报告.docx
     (家庭用电分析报告.docx:53 段、3 表)
     | 报告名称 | 家庭用电情况分析报告 |

协议实现说明

不用官方 SDK,手写不到 200 行,好处是协议长什么样一目了然:

# 一条请求进来
{"jsonrpc": "2.0", "id": 3, "method": "tools/call",
 "params": {"name": "doc_read", "arguments": {"path": "报告.docx"}}}

# 一条响应出去
{"jsonrpc": "2.0", "id": 3,
 "result": {"content": [{"type": "text", "text": "# 报告.docx\n…"}], "isError": false}}

三个容易踩的点:

  1. stdout 只能出 JSON。任何 print 调试都会污染协议流,日志必须走 stderr。

  2. 通知没有 id,不能回复。notifications/initialized 回了就会让客户端困惑。

  3. 工具异常不能弄死服务器。工具里任何异常都转成 isError: true 的响应,循环继续。

接入 DeepSeek Harness(实测记录)

我把这个服务接进 DSH 时踩了两个坑,都修好了,记录在这里省得别人再踩。

抓到的真实协议流

DSH 内置的 MCP 客户端比 2024-11-05 规范要新,握手时会先探测一个 server/discover:

IN  <<< {"method":"server/discover","params":{"_meta":{
             "io.modelcontextprotocol/protocolVersion":"2026-07-28", ...}}}
OUT >>> {"error":{"code":-32601,"message":"不支持的方法: server/discover"}}

IN  <<< {"method":"initialize","params":{"protocolVersion":"2025-11-25", ...}}
OUT >>> {"protocolVersion":"2024-11-05","capabilities":{"tools":{}}, ...}

IN  <<< {"jsonrpc":"2.0","method":"notifications/initialized"}
IN  <<< {"method":"tools/list","jsonrpc":"2.0","id":1}
OUT >>> {"id":1,"result":{"tools":[{"name":"doc_read", ...}]}}

好消息:回 2024-11-05 它仍然接受,向下兼容。拒掉 server/discover 也不影响握手。

坑一:Windows 上中文变乱码,还会崩

接上后工具描述显示成 ��ȡ Word。原因是 Python 连管道时默认用 GBK,而客户端按 UTF-8 解码。

更麻烦的是会直接崩——文档里有 ✅ 这种 GBK 编不出来的字符:

'gbk' codec can't encode character '\u2705' in position 22

双保险修法(server.py 里的 _force_utf8 + _dumps):

for stream in (sys.stdout, sys.stderr):
    stream.reconfigure(encoding="utf-8", errors="replace", newline="\n")

# 万一 reconfigure 没生效,就退化成纯 ASCII 输出(中文变 \uXXXX 转义)
ascii_only = (sys.stdout.encoding or "").lower().replace("-", "") != "utf8"
json.dumps(payload, ensure_ascii=ascii_only)

JSON 客户端解析转义后会还原成正常中文,所以任何控制台编码下都不会崩。

坑二:回复"通知"会被判违规

JSON-RPC 规定没有 id 的消息是通知,不能回复。我早期对未知通知也回了一条 id: null 的错误,客户端直接判定协议违规断开。

is_notification = "id" not in request
...
if is_notification:
    return None

坑三:残留多个子进程 → 工具调用永远超时(最坑的一个)

症状:握手、tools/list 全正常,工具也确实注册上了,但一调用就 Request timed out 或 Connection closed,服务端日志里根本收不到 tools/call。

排查过程(值得记下来):

  1. 以为编码问题 → 修了,没用

  2. 以为协议不兼容 → 抓包发现握手完全正常

  3. 以为要重启 DSH → 重启了,还是超时

  4. 最后用任务管理器数进程,发现同时有 2 个 server.py 在跑

结论:调试时反复开关插件、手动杀进程,会留下多个实例;工具调用绑在最早那个已经死掉的实例上,请求发进了一个没有读者的管道——所以服务端永远收不到,客户端只能等到超时。

修法:把所有 server.py 进程全部结束(客户端会自动重连拉起一个干净的),再调用就通了。

一句话教训:MCP 是"一个连接一个进程"的模型,调试时只留一个实例,别靠反复开关插件去撞状态。

DSH 里不需要写插件代码,一个纯配置文件就能挂上(样例见 examples/dsh-bundle/):

- insert:
    - id: office-mcp
      name: '@deepseek-ai/dsh-mcp-client'
      config:
        serverName: office
        transport: stdio
        command: '<装了依赖的那个 python 绝对路径>'
        args:
          - '<server.py 的绝对路径>'
        failOnStartupError: true

装好后工具名是 mcp__office__doc_read 这种格式。

接入后的实测结果

四个工具在真实文档上都跑通了:

工具

实测对象

结果

doc_read

家庭用电分析报告.docx

53 段 / 3 表,表格按原位置还原

sheet_read

家庭用电数据分析.xlsx

识别 3 个工作表,正确读出月度用电表

slide_read

家庭用电情况分析.pptx

7 页全部输出,含正文要点

pdf_extract

一份 1 页简历 PDF

整页文字完整提取

一个实际暴露的体验问题:Excel 里算出来的 13.290322580645162 会原样进表格,模型没法用。已在 _cell() 里收敛到 4 位小数(13.2903),整数不带 .0,日期转 ISO。

调试建议

给 bundle 加一个环境变量就能看协议原文,排查编码/协议问题非常有用:

        env:
          OFFICE_MCP_DEBUG: '1'

之后每次收发都会追加到 %TEMP%\office-mcp-debug.log,形如:

IN <<< {"method":"tools/call", ...}
OUT >>> {"jsonrpc":"2.0","id":2,"result":{"content":[...]}}

实现细节

Word 按原顺序输出

document.paragraphs 和 document.tables 是两个独立列表,分别遍历会丢掉表格和段落的相对位置。所以直接遍历 XML body:

for child in document.element.body.iterchildren():
    tag = child.tag.split("}")[-1]
    if tag == "p":    ...Paragraph(child, document)
    elif tag == "tbl": ...Table(child, document)

Excel 取公式结果而不是公式

openpyxl.load_workbook(path, data_only=True)

代价:如果文件是程序生成、从未被 Excel 打开过,公式没有缓存值,读出来是 None。这是 Excel 的机制,不是 bug。

截断要说清楚

不是静默截断,而是明确告诉模型:

…(已截断,原文 24311 字符,只返回前 8000 字符)

这样模型知道"我没看到全部",不会拿半份内容下结论。

已知限制

  1. 只读。写入工具还没做——写坏原文件是最糟的失败模式,要单独设计(先写副本、变更前备份)。

  2. 不支持旧格式 .doc / .xls,请先另存为新格式。

  3. 扫描件 PDF 提不出文字(没有文字层),需要 OCR,本项目不做。

  4. 复杂排版(艺术字、SmartArt、文本框嵌套)读不干净,只保证正文、表格、备注。

  5. slide_read 不输出图表里的数据(图表是图片级对象)。

Roadmap

  • doc_write:Markdown → Word(先写副本,不覆盖原文件)

  • sheet_append:往工作表追加行

  • office_convert:docx ↔ md ↔ pdf

  • 批量:一次读整个目录的文档并汇总

License

MIT

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to search, deep-read, and build knowledge bases from Markdown, PDF, DOCX, and PPTX documents via MCP tools for retrieval, document navigation, and ingestion.
    25 npm
    650
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Convert PDF, DOCX, HTML, and URLs into clean, LLM-ready markdown with tables preserved and boilerplate stripped, through three MCP tools (URL, local file, or raw bytes). Hosted API with no local dependencies; 50 free conversions with a self-serve key, then $0.002 per call.
    3
    59 npm
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables LLMs to read, search, edit, and create Excel, Word, and PowerPoint files through MCP, including sheet/table operations, slide and chart creation, text replacement, and automatic backups.
    29
    MIT