内容
# pptx-mcp-server
用于创建、读取和编辑PowerPoint (.pptx)演示文稿的MCP服务器。
提供37种工具用于幻灯片管理、形状/文本操作、表格操作、复合布局、布局验证和幻灯片渲染——所有这些都可以通过模型上下文协议访问。
## 安装
`pptx-mcp-server`有两个安装路径:一个最小的库安装,用于以编程方式驱动引擎,另一个是`[mcp]`额外的安装,用于运行MCP服务器CLI。
```bash
# 库使用(无MCP运行时 - 仅python-pptx + lxml):
pip install pptx-mcp-server
# MCP服务器(包括mcp SDK):
pip install 'pptx-mcp-server[mcp]'
```
MCP SDK位于`[mcp]`额外之下,这样纯库消费者就不必在安装时支付MCP SDK和任何io传输依赖的费用。 `pptx-mcp-server` CLI和`pptx_mcp_server.server`模块需要`[mcp]`额外;如果没有它,则会引发一个明确的ImportError,指向此处。
## Claude 桌面配置
将以下内容添加到您的Claude Desktop MCP配置(`claude_desktop_config.json`)中:
```json
{
"mcpServers": {
"pptx-editor": {
"command": "pptx-mcp-server"
}
}
}
```
或者,如果从源代码运行:
```json
{
"mcpServers": {
"pptx-editor": {
"command": "python",
"args": ["-m", "pptx_mcp_server"]
}
}
}
```
## 作为Python库使用
`pptx-mcp-server`还提供了一个纯Python引擎,您可以直接驱动它,而无需启动MCP服务器。 `engine`和`theme`模块在导入时没有依赖于MCP SDK,因此您可以从脚本、笔记本或批处理作业中构建幻灯片。
像安装其他包一样安装它——裸安装不会拉取MCP SDK:
```bash
# 从PyPI(发布后)- 仅限库:
pip install pptx-mcp-server
# 从本地checkout(开发期间的可编辑安装):
pip install -e /path/to/pptx-mcp-server
```
然后通过直接调用引擎函数来组成一个幻灯片:
```python
from pptx_mcp_server.engine.pptx_io import create_presentation, open_pptx
from pptx_mcp_server.engine.shapes import add_textbox
from pptx_mcp_server.engine.slides import add_slide
from pptx_mcp_server.theme import MCKINSEY
out = "deck.pptx"
create_presentation(out, width_inches=13.333, height_inches=7.5)
add_slide(out, layout_index=6)
add_textbox(
out,
slide_index=0,
left=1.0, top=1.0, width=10.0, height=1.0,
text="Hello from pptx_mcp_server",
font_name=MCKINSEY.fonts.get("body", "Arial"),
font_size=24,
bold=True,
)
prs = open_pptx(out)
print(f"Slides: {len(prs.slides)}")
```
`mcp` SDK是一个**可选**额外项(`pip install 'pptx-mcp-server[mcp]'`),仅在启动`pptx-mcp-server` CLI / 导入`pptx_mcp_server.server`时需要。 `pptx_mcp_server.engine`或`pptx_mcp_server.theme`中的任何内容都不导入它——`tests/test_library_usage.py`中的AST级CI防护栏强制执行这一点,`tests/test_packaging_extras.py`强制执行打包方面的内容。
### 内置主题
`pptx_mcp_server.theme`提供了四种被动主题预设。 通过在幻灯片/幻灯片规范中传递`"theme": "<name>"`来选择一个,或者直接导入模块常量(`MCKINSEY`、`DELOITTE`、`NEUTRAL`、`IR`):
| 名称 | 描述 |
|------|-------------|
| `mckinsey` | 麦肯锡风格。 深海军蓝(`#051C2C`)主要颜色 + 明亮蓝色(`#2251FF`)在白色上的强调色。 16:9 宽屏(13.333x7.5英寸)。 |
| `deloitte` | 德勤风格。 海军蓝(`#002776`)主要颜色 + 绿色(`#81BC00`)强调色,多种颜色调色板。 16:9 宽屏。 |
| `neutral` | 清洁,通用安全。 深灰色(`#333333`)主要颜色 + 软蓝色(`#4A90D9`)强调色。 16:9 宽屏。 |
| `ir` | 日本企业IR / 季报样式。 奶油色背景(`#F8F9F5`),深海军蓝(`#0A2540`)主要颜色 + 蓝色(`#1E3A8A`)强调色。 HD宽屏尺寸(20x11.25英寸)。 Yu Gothic东亚字体。 |
### 支持的脚本
自动布局引擎(`pptx_mcp_server.engine.text_metrics`)使用启发式宽度/高度估计器。 只有以下列出的脚本经过校准并被`tests/test_calibration.py`覆盖;其他脚本则回落到ASCII正常宽度,可能会被静默低估。
| 脚本 | 状态 | 准确度 / 注意 |
|---|---|---|
| ASCII / Latin-1(Arial度量兼容字体) | 支持 | ±10% 混合大小写字符串,±17% 每字符 |
| CJK统一表意文字 + 平假名 + 片假名(Yu Gothic / Meiryo / Hiragino Sans / Noto Sans CJK) | 支持 | ±15% |
| CJK扩展A / B / SIP / Compat表意文字 | 支持 | 视为全宽 |
| 半宽片假名(U+FF61–U+FF9F) | 支持 | 映射到ASCII正常宽度 |
| 零宽度连接符,变体选择器,结合标记 | 支持 | 0宽度 |
| 韩文(Korean)U+AC00–U+D7AF | **不支持** | 回落到ASCII → 高度约2倍低估 |
| 阿拉伯语U+0600–U+06FF | **不支持** | ASCII回落 + RTL忽略 |
| 泰语U+0E00–U+0E7F | **不支持** | 无换行逻辑 + 组合标记 |
| 天竺语U+0900–U+097F | **不支持** | 组合标记忽略 |
| 希伯来语 | **不支持** | RTL忽略 |
| 西里尔字母 | 近似 | ASCII宽度回落(实际上可接受) |
添加新脚本涉及扩展 `_CJK_RANGES`(或新的脚本集),校准宽度常数,并将前置字符添加到 `tests/test_calibration.py`。 参见 `CONTRIBUTING.md` → “添加新脚本”。
## 响应形状(v0.3.0+)
> **BREAKING CHANGE(v0.3.0)。** `result` 现在**始终是一个字典**。 以前返回原始人类可读字符串的工具现在将其包装在 `{"message": "..."}`中。 具有自动渲染集成的复合工具在同一个字典中添加 `preview_path` / `render_warning` 键,而不是在 `value` 键下包装主要有效载荷。 `pptx_check_layout(detailed=True)` 返回查找字典内联 - 单个 `json.loads()` 完全解码它(以前字典被重新编码为字符串在 `result` 下)。 参见问题 #98,#99。
> **BREAKING CHANGE(v0.2.0)。** 所有MCP工具响应现在都是JSON编码的,并包装在 `{ok, result | error}` 信封中。 以前工具返回原始人类可读字符串(成功)和括号前缀错误,如 `"[INVALID_PARAMETER] ..."`。 消费者必须 `json.loads()` 响应并在 `ok` 字段上分支。 参见问题 #88。
成功:
```json
{"ok": true, "result": {"message": "Added content slide [1]: Revenue Analysis"}}
```
成功且自动渲染:
```json
{"ok": true, "result": {"message": "Added content slide [1]: ...", "preview_path": "/tmp/slide-01.png"}}
```
详细布局检查:
```json
{"ok": true, "result": {"slides": [...], "summary": {"errors": 0, "warnings": 0, "infos": 0}}}
```
错误:
```json
{
"ok": false,
"error": {
"code": "INVALID_PARAMETER",
"parameter": "items",
"message": "items must be a list of dicts.",
"hint": "Pass a native Python list, e.g., [{\"sizing\":\"fixed\",\"size\":2,\"type\":\"rectangle\"}].",
"issue": 97
}
}
```
错误代码`code`值镜像`EngineError.code`:`INVALID_PARAMETER`,`FILE_NOT_FOUND`,`SLIDE_NOT_FOUND`,`SHAPE_NOT_FOUND`,`INDEX_OUT_OF_RANGE`,`INVALID_PPTX`,`TABLE_ERROR`,`CHART_ERROR`,`INTERNAL_ERROR`。 `parameter`,`hint`和`issue`字段是可选的。
## 结构化参数(v0.3.0+)
> **BREAKING CHANGE(v0.3.0)。** `*_json: str` 工具参数被结构化类型(原生 `list` / `dict`)取代。 FastMCP从Python类型注释中验证顶级;工具在工具边界强制执行字典键约定(例如`CardSpec`未知键拒绝)。 参见问题 #97。
之前(v0.2.x):
```python
pptx_add_table(path, 0, rows_json='[["H1","H2"],["a","b"]]', 1, 1, 5)
pptx_build_deck(path, slides_json='[{"layout":"content",...}]')
```
之后(v0.3.0+):
```python
pptx_add_table(path, 0, rows=[["H1","H2"],["a","b"]], 1, 1, 5)
pptx_build_deck(path, slides=[{"layout":"content", ...}])
```
受影响的工具(和替换的参数名称):
| 工具 | 旧参数 | 新参数 |
|------|-----------|-----------|
| `pptx_add_flex_container` | `items_json: str` | `items: list[dict]` |
| `pptx_add_responsive_card_row` | `cards_json: str` | `cards: list[dict]` |
| `pptx_build_slide` | `spec_json: str` | `spec: dict` |
| `pptx_build_deck` | `slides_json: str` | `slides: list[dict]` |
| `pptx_add_chart` | `chart_json: str` | `chart: dict` |
| `pptx_add_kpi_row` | `kpis_json: str` | `kpis: list[dict]` |
| `pptx_add_table` | `rows_json: str` + `col_widths_json: str` | `rows: list[list]` + `col_widths: list[float] \| None` |
| `pptx_add_bullet_block` | `items_json: str` | `bullets: list[str]` |
| `pptx_edit_table_cells` | `edits_json: str` | `edits: list[dict]` |
## 自动渲染(v0.2.0+)
> **BREAKING CHANGE(v0.2.0)。** 复合工具(`pptx_add_content_slide`,`pptx_build_slide`,`pptx_build_deck`,`pptx_add_kpi_row`,`pptx_add_bullet_block`,`pptx_add_section_divider`,`pptx_add_responsive_card_row`,`pptx_add_connector`,`pptx_add_callout`,`pptx_add_chart`,`pptx_add_icon`)以前分叉LibreOffice以渲染每个成功编辑后的PNG预览(~1.5s,无超时,无关闭开关)。 自动渲染现在**默认关闭**。 参见问题 #86。
通过环境变量启用自动渲染:
```bash
export PPTX_MCP_AUTO_RENDER=1 # 启用
export PPTX_MCP_RENDER_TIMEOUT=10 # 秒(默认10)
```
启用时,成功的有效载荷带有额外的`preview_path`键与`message`:`{"message": "<legacy string>", "preview_path": "/path/to/slide-01.png"}`。 如果渲染超时或失败,结果有效载荷带有`render_warning`字段而不是`preview_path`(v0.3.0统一此形状 - 以前的版本在`value`键下包装,参见问题 #98)。 对于显式同步渲染,直接使用`pptx_render_slide`工具 - 该工具不受此门控影响。
## 工具
### 演示文稿
| 工具 | 描述 |
|------|-------------|
| `pptx_create` | 创建一个新的空白PPTX文件(默认16:9宽屏) |
| `pptx_get_info` | 获取演示文稿概述:幻灯片数量、尺寸、形状摘要 |
| `pptx_read_slide` | 读取幻灯片的详细内容 - 所有形状、文本、表格 |
| `pptx_list_shapes` | 列出幻灯片上的所有形状及其索引、类型、位置、文本预览 |
### 幻灯片
| 工具 | 描述 |
|------|-------------|
| `pptx_add_slide` | 添加一个具有指定布局的新幻灯片 |
| `pptx_move_slide` | 将幻灯片从一个位置移动到另一个位置(0基索引) |
| `pptx_delete_slide` | 通过0基索引删除幻灯片 |
| `pptx_duplicate_slide` | 复制幻灯片(追加到末尾) |
| `pptx_set_slide_background` | 为幻灯片设置纯背景颜色 |
| `pptx_set_dimensions` | 以英寸为单位设置演示文稿幻灯片尺寸 |
### 文本和形状
| 工具 | 描述 |
|------|-------------|
| `pptx_add_textbox` | 添加一个具有完整格式化选项的文本框 |
| `pptx_add_auto_fit_textbox` | 添加一个文本框,自动缩小字体以适应宽度/高度 |
| `pptx_add_flex_container` | 添加一个灵活布局容器,沿轴排列子项 |
| `pptx_edit_text` | 编辑现有形状中的文本内容和格式 |
| `pptx_add_paragraph` | 在现有形状中追加一个新段落 |
| `pptx_add_shape` | 添加一个自动形状(矩形、椭圆、箭头、箭头等) |
| `pptx_add_image` | 添加一个图像(PNG,JPG,SVG)到幻灯片,可选大小 |
| `pptx_delete_shape` | 通过索引从幻灯片中删除形状 |
| `pptx_format_shape` | 重新定位、调整现有形状的大小或样式 |
### 表格
| 工具 | 描述 |
|------|-------------|
| `pptx_add_table` | 添加具有标题和交替行的专业格式表格 |
| `pptx_edit_table_cell` | 编辑单个表格单元格的文本和格式 |
| `pptx_edit_table_cells` | 批量编辑多个表格单元格 |
| `pptx_format_table` | 对整个表格应用批量格式 |
### 复合
| 工具 | 描述 |
|------|-------------|
| `pptx_build_deck` | 从JSON规范构建整个幻灯片(单个文件I/O) |
| `pptx_build_slide` | 从JSON规范构建单个幻灯片 |
| `pptx_add_content_slide` | 添加具有操作标题、分隔符、页脚、页码的内容幻灯片 |
| `pptx_add_section_divider` | 添加具有暗背景和强调条纹的章节分隔符幻灯片 |
| `pptx_add_kpi_row` | 添加一行KPI调用盒 |
| `pptx_add_bullet_block` | 添加具有多个项目的项目符号文本块 |
| `pptx_add_responsive_card_row` | 添加一行自动调整大小的卡片形状 + 正文 |
| `pptx_add_connector` | 添加连接器(直线 / 弯曲 / 曲线)可选箭头 |
| `pptx_add_callout` | 添加注释文本框 + 箭头指向目标 |
| `pptx_add_chart` | 添加原生图表(条形、列、线、饼图、面积图、雷达图、甜圈图) |
| `pptx_add_icon` | 添加内置矢量图标到幻灯片 |
| `pptx_list_icons` | 列表所有内置图标可用于`pptx_add_icon` |
### 验证和渲染
| 工具 | 描述 |
|------|-------------|
| `pptx_check_layout` | 验证幻灯片布局:重叠、超出范围、溢出、易读性 |
| `pptx_render_slide` | 将一个或多个幻灯片渲染为PNG文件,供视觉验证 |
## 依赖
必需(通过`pip install pptx-mcp-server`安装):
- [python-pptx](https://python-pptx.readthedocs.io/) – PPTX文件操作
- [lxml](https://lxml.de/) – XML处理
可选额外项:
- `[mcp]` -- `pip install 'pptx-mcp-server[mcp]'` 拉取 [mcp](https://modelcontextprotocol.io/) SDK,需要 `pptx-mcp-server` CLI / `pptx_mcp_server.server`。
- `[validation]` -- `pip install 'pptx-mcp-server[validation]'` 拉取 [fontTools](https://fonttools.readthedocs.io/) 并启用真正的字体溢出验证路径。参见下面的“布局验证”。
### 布局验证
`check_deck_extended` / `check_text_overflow` 提供两种文本溢出检测路径:
- `font_source="heuristic"` (默认)- 零依赖;使用树内宽度启发式(与 `add_auto_fit_textbox` 共享)。
- `font_source="real"` (可选,需额外 `[validation]`)- 从 TTF/TTC 读取真正的提前宽度,使用 fontTools。 这给出了一个 **独立的真实性来源**,以防止启发式和PowerPoint的实际渲染之间的漂移,从而隐藏了自动拟合原语后面的溢出。
```python
from pptx import Presentation
from pptx_mcp_server.engine.font_metrics import discover_system_fonts
from pptx_mcp_server.engine.validation import check_deck_extended
prs = Presentation("deck.pptx")
report = check_deck_extended(
prs,
font_source="real",
font_paths=discover_system_fonts(), # 或 {"Arial": "/path/to/Arial.ttf"}
)
print(report["summary"])
```
无法解析的字体会回落到每个段落的启发式并发出 `font_not_measured` 警告,以便部分覆盖仍然有用。
### 系统工具
- **LibreOffice** -- `pptx_render_slide` 所需(PPTX 到 PDF 转换)。 使用 `brew install --cask libreoffice` (macOS)或系统包管理器进行安装。
- **pdftoppm** (poppler-utils)-- `pptx_render_slide` 所需(PDF 到 PNG 转换)。 使用 `brew install poppler` (macOS)或 `apt install poppler-utils` (Debian/Ubuntu)进行安装。
## 开发
```bash
# 以可编辑模式安装
pip install -e .
# 运行测试
python -m pytest tests/ -v
```
参见 [CONTRIBUTING.md](CONTRIBUTING.md) 了解开发约定。
## 许可证
MIT - 详情请参见 [LICENSE](LICENSE)。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器