pptx-text-mcp
v0.1.2
Published
MCP server that downloads a PPTX from an http/https URL and extracts slide text and speaker notes as plain text.
Maintainers
Readme
pptx-text-mcp
MCP server that downloads a PPTX from an http/https URL and extracts slide text and speaker notes as plain text.
一个只做一件事的 MCP 服务:给定 PPTX 的公网地址,下载后提取每页可见文字和演讲者备注,返回纯文本。
能力边界
做:下载 PPTX、解压、解析 OOXML、提取文字。
不做:不调用大模型、不写任何文件、不维护任务状态、不生成摘要或词频。这些加工全部由调用方完成。
工具
只有一个工具:extract_pptx_text。
入参
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| url | string | 是 | PPTX 文件的 http/https 绝对地址 |
只接受 http 和 https。传 file: 等其他协议会被拒绝——否则这个工具会退化成一个任意本地文件读取器。
返回
返回一段纯文本,按页分段:
- 每段以
Slide <页码>开头,其后是该页可见文字 - 该页有备注时,追加一行
Notes,其后是备注原文 - 页面文字和备注都为空的页直接跳过
Slide 1
Unit 3
Review
Slide 2
apple
ant
Letters:
Notes
What's behind the star?失败时返回 isError: true,内容是可读的错误原因,例如 Download failed: HTTP 404。
备注为什么返回原文
备注内容有时是 JSON 结构(课件系统常这么存教师话术)。本服务不做字段筛选,原样返回。职责是机械提取,怎么解读交给调用方。
注册
已发布到 npm,直接用 npx:
{
"mcpServers": {
"pptx-text": {
"command": "npx",
"args": ["-y", "[email protected]"]
}
}
}建议锁死版本号。不写版本会拿到 latest,将来发布新版时线上行为会在你不知情的情况下变化。
本地源码调试用编译产物:
{
"mcpServers": {
"pptx-text": {
"command": "node",
"args": ["/absolute/path/to/pptx-mcp/dist/server.js"]
}
}
}实现要点
以下几处是踩过坑之后的处理方式,改动前先看明白原因:
- 段落内 run 拼接。同一个英文单词可能因为颜色或样式不同被拆成多个
a:trun,例如m+ap。所以按a:p段落聚合后无分隔拼接,还原成map。逐个a:t提取会拆词,直接毁掉下游的词频统计。 - 备注页按 rels 反查 slide。
notesSlide3.xml不一定对应slide3.xml。正确做法是读ppt/notesSlides/_rels/notesSlideN.xml.rels,找Type以/slide结尾的 Relationship,从Target里取真实页码。按文件名硬绑会导致备注错页。 - 备注只取 body 占位符。备注页里还有幻灯片缩略图等占位符,只提取
p:ph type="body"的 shape,否则会混入非备注内容。 - 不落盘。下载直接进内存交给 JSZip。MCP 工具是无状态的一次性调用,落盘会引入临时文件清理、并发同名覆盖、宿主沙箱写权限三类问题。
- 日志只走 stderr。stdio 传输下 stdout 是协议通道,往里写一行
console.log就会破坏连接。
防护限制
| 限制 | 值 | 原因 | |---|---|---| | 协议白名单 | 仅 http / https | 避免变成任意本地文件读取器 | | 下载体积上限 | 100 MB | 防止超大文件打满进程内存 | | 下载超时 | 60 秒 | 对端不响应时避免工具调用一直挂住 | | 内容校验 | ZIP 文件头 | PPTX 本质是 ZIP,先校验能给出比解压库更明确的报错 |
错误信息
| 信息 | 含义 |
|---|---|
| Invalid url: ... | URL 无法解析 |
| Invalid url protocol: ... | 协议不是 http / https |
| Download failed: HTTP <code> | 对端返回非 2xx |
| Download failed: file too large, ... | 超过 100 MB |
| Download failed: empty response body | 下载到 0 字节 |
| PPTX parse failed: content is not a zip archive, ... | 拿到的不是 PPTX |
| PPTX parse failed: no slide found, ... | 是 ZIP 但没有 slide,可能不是 PPTX |
| PPTX parse failed: no slide text found | 解析成功但全篇无文字,例如纯图片课件(本服务不做 OCR) |
本地开发
需要 Node.js 18 以上(用到内置 fetch 和 AbortSignal.timeout)。
npm install
npm run typecheck # 类型检查
npm run build # 编译到 dist
npm start # 用 tsx 直接跑源码,走 stdionpm start 起来后会挂住等 stdio 协议消息,这是正常的——它不是给人手工交互用的,要靠 MCP 客户端连接。
目录
src/
server.ts MCP 入口,注册唯一工具
pptx-downloader.ts URL -> Buffer,含协议、体积、超时校验
pptx-text-extractor.ts Buffer -> 每页正文 + 备注
text-format.ts 解析结果 -> 纯文本License
MIT
