关于 Word
WordMcp 是面向 AI 助手的 MCP 服务,通过 Windows 上的 Microsoft Word 桌面应用自动化处理文档;提供从文本编辑到审阅和版式设置的操作。
主要功能
- 01创建、打开、保存和导出文档
- 02读取、查找、替换及格式化文本
- 03管理段落、表格和图片
- 04设置样式、列表、页眉页脚和页面布局
- 05处理批注、修订、书签及脚注
适用场景
- 01批量修改文档文本与格式
- 02维护表格、图片和文档结构
- 03审阅修订并管理批注
- 04将文档导出为 PDF
MCP 相关
作为 MCP 服务,通过 stdio 向客户端提供 Word 文档操作工具。需要 Windows 和本机安装的 Microsoft Word。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
WordMcp — Microsoft Word MCP 服务
一个 MCP 服务,可通过 COM 自动化让 AI 助手操控 Microsoft Word for Windows:打开文档、读取和编辑文本、管理段落和表格、设置文档属性并导出为 PDF。
仅限 Windows。 需要本地安装 Microsoft Word — 此服务自动化操控真实应用,不会解析
.docx文件。
要求
| OS | Windows 10/11 |
| Runtime | .NET 9 SDK 或运行时 |
| Office | Microsoft Word 2016 或更高版本(桌面版,非 Microsoft Store 版本) |
安装
VS Code
vscode-extension/ 中的轻量扩展会将此服务注册到 VS Code,因此无需手动配置。它不会捆绑此服务,而是通过 dnx 启动,因此无需发布新的扩展版本,服务也能更新。
从代码库检出版本构建并安装:
cd vscode-extension
npx @vscode/vsce package
code --install-extension word-mcp-0.1.0.vsix
然后从命令面板运行 MCP: List Servers,并启动 Word。
作为 .NET 工具
dotnet tool install --global WordMcp.McpServer
之后即可通过 mcp-word 使用该工具。
mcp-word --version
mcp-word --help
之后如需更新或移除:
dotnet tool update --global WordMcp.McpServer
dotnet tool uninstall --global WordMcp.McpServer
如需运行尚未发布的构建版本,请在本地打包并从输出文件夹安装:
dotnet pack src\WordMcp.McpServer\WordMcp.McpServer.csproj -c Release -o artifacts
dotnet tool install --global --add-source .\artifacts WordMcp.McpServer
无需安装
此服务已在 MCP 注册表 中列出,名称为 io.github.trsdn/mcp-server-word。能够自行解析软件包的客户端可通过 dnx 运行它;dnx 会按需获取版本,而无需将其作为全局工具保留:
{
"servers": {
"word": {
"type": "stdio",
"command": "dnx",
"args": ["[email protected]", "--yes"]
}
}
}
客户端配置
此服务使用 stdio 通信。
VS Code / GitHub Copilot
.vscode/mcp.json:
{
"servers": {
"word": {
"type": "stdio",
"command": "mcp-word"
}
}
}
Claude Desktop
%APPDATA%\Claude\claude_desktop_config.json:
{
"mcpServers": {
"word": {
"command": "mcp-word"
}
}
}
Copilot CLI
copilot mcp add word --command mcp-word
概念
每项操作都在一个 会话 中运行。一个会话拥有一个 Word 实例和一个打开的文档,通过 session_id 标识,例如 word-a1b2c3d4e5f6g。
file(open|create) ──► session_id ──► text / paragraph / table / document ──► file(save) ──► file(close)
- 路径必须是绝对路径(
C:\Users\me\Documents\report.docx)。 - 支持的输入格式:
.docx、.docm、.doc、.dotx、.dotm、.rtf。 - 文档不得已在 Word 中打开 — WordMcp 需要独占访问权限。
- Word 会在后台隐式运行,并在会话关闭时终止。
会话服务
会话通常驻留在 MCP 服务进程中,并随该进程退出而消失。WordMcp.Service.exe 是一个可选的后台守护进程,可代为持有会话,这样客户端重启后会话仍会保留,也可供多个客户端共享:
WordMcp.Service.exe --daemon [--idle-minutes 30] # listen until idle or stopped
WordMcp.Service.exe --status # what is it doing?
WordMcp.Service.exe --stop # save open documents and exit
通常无需手动启动 — 配置为使用它的客户端会按需启动它。它监听的管道中包含你的 SID,并通过 ACL 限制为仅该 SID 可访问,因此不同账户之间绝不会共享会话。当空闲超时期间没有会话保持打开状态时,它会自动退出。
如需使用它,请为 MCP 服务设置 WORDMCP_SERVICE_MODE=daemon。之后,每次工具调用都会发送到守护进程,而不是在服务自身进程中运行。不启用时,服务会自行持有会话;对于单个客户端,这是更合适的方式:无需第二个进程,也无需等待启动。
工具
共有十七个工具,每个工具都有一个 action 参数。
file — 会话生命周期
| 操作 | 用途 |
|---|---|
open | 打开现有文档并启动会话 |
create | 在 path 处创建新文档 |
save | 保存打开的文档 |
close | 保存(可选)并关闭会话 |
list | 列出所有活动会话 |
test | 检查此计算机上是否能够自动化操控 Word |
file(action: "open", path: "C:\\Users\\me\\Documents\\report.docx")
// → { "sessionId": "word-a1b2c3d4e5f6g", "fileName": "report.docx", ... }
text — 内容
| 操作 | 用途 |
|---|---|
get | 读取全文或指定字符范围(start、end、max_length) |
append | 追加文本,可选择将其作为新段落 |
find | 查找词语;返回位置及周边上下文 |
replace | 替换匹配项(match_case、match_whole_word、replace_all) |
format | 对指定范围应用 bold、italic、underline、font_name、font_size、color |
get 和 find 返回的字符位置是 Word 范围偏移量。
paragraph — 结构
| 操作 | 用途 |
|---|---|
list | 列出段落及其索引、文本、样式、对齐方式和大纲级别 |
add | 追加段落,可选择指定 style |
insert | 在指定索引之前插入段落 |
delete | 按索引删除段落 |
set-style | 应用 Heading 1 等样式 |
set-alignment | 设置为 left、center、right 或 justify |
段落索引从 1 开始,与 Word 一致。
table — 表格
| 操作 | 用途 |
|---|---|
list | 列出表格及其维度和样式 |
create | 创建包含 rows × columns 的表格 |
read | 将表格的所有单元格作为行/列矩阵读取 |
set-cell | 写入单个单元格(row、column、text) |
add-row | 追加一行 |
delete-row | 删除一行 |
set-style | 应用 Table Grid 等表格样式 |
document — 元数据和导出
| 操作 | 用途 |
|---|---|
get-info | 获取单词、字符、段落、页面、表格和节的数量 |
get-properties | 获取标题、作者、主题、关键词、评论和公司信息 |
set-properties | 更新这些内置属性 |
export-pdf | 导出为 PDF,不影响打开的文档 |
save-as | 以其他格式保存副本 |
image — 图片
| 操作 | 用途 |
|---|---|
list | 列出嵌入式图片及其索引、尺寸、替代文本和链接状态 |
insert | 插入图片,可选择指定 width、height、caption 和 alt_text |
resize | 按 width/height 或 scale_percent 调整尺寸 |
replace | 替换索引对应的图片,默认保留其尺寸 |
delete | 按索引删除图片 |
set-alt-text | 设置用于无障碍访问的替代文本 |
field — 域和目录
| 操作 | 用途 |
|---|---|
list | 列出所有域及其索引、类型和域代码 |
insert-toc | 插入目录(upper_heading_level、lower_heading_level) |
update-toc | 重新计算所有目录 |
update-all | 更新所有域,包括页眉和页脚中的域 |
insert-page-number | 在页眉或页脚中添加页码 |
section — 节和页面设置
| 操作 | 用途 |
|---|---|
list | 列出所有节及其起始类型、页边距、纸张大小和方向 |
add | 插入分节符(start_type:next-page、continuous、even-page、odd-page) |
page-setup | 为某个节或整个文档设置页边距、orientation 和 paper_size |
header-footer — 页眉和页脚
| 操作 | 用途 |
|---|---|
get | 读取某个节或所有节的页眉或页脚 |
set | 写入文本,可选择指定 alignment |
clear | 清空页眉或页脚 |
kind 用于选择 header 或 footer,type 用于选择 primary、first-page 或 even-pages。
style — 样式
| 操作 | 用途 |
|---|---|
list | 列出样式;默认仅列出文档中使用的样式 |
create | 添加自定义样式,可选择基于现有样式创建 |
modify | 更改样式的字体和段落格式 |
delete | 删除自定义样式 |
style_type 用于选择 paragraph、character、table 或 list。在本地化的 Word 中,完整样式集有 370 多项;传入 in_use_only: false 后使用
list 获取完整列表。
style(action: "create", session_id: "...", name: "Callout", base_style: "Normal")
style(action: "modify", session_id: "...", name: "Callout",
font_size: 11, bold: true, color: "#C00000", space_after: 12)
list — 项目符号和编号
| 操作 | 用途 |
|---|---|
get | 报告段落的列表格式,包括渲染后的项目符号或编号 |
apply | 将段落范围格式化为 bullet、number 或 outline-number 列表 |
set-level | 设置段落范围的列表级别(1–9) |
restart | 从某个段落重新开始编号 |
remove | 移除列表格式 |
省略 end_index 时,仅对 start_index 执行操作。
list(action: "apply", session_id: "...", start_index: 2, end_index: 5, list_type: "number")
list(action: "set-level", session_id: "...", start_index: 3, end_index: 4, level: 2)
list(action: "restart", session_id: "...", start_index: 6)
comment — 审阅备注
| 操作 | 用途 |
|---|---|
list | 列出评论的作者、日期、文本和评论所针对的文本 |
add | 为段落或段落中的短语添加评论 |
resolve | 将评论标记为已完成,或重新打开评论 |
delete | 移除评论 |
除非 anchor_text 指定了段落中的短语,否则 add 会对整段添加评论。删除后索引会发生变化,因此删除第二条评论前请再次列出评论。
comment(action: "add", session_id: "...", paragraph_index: 4,
text: "Source?", anchor_text: "fifteen percent")
comment(action: "list", session_id: "...", unresolved_only: true)
revision — 修订跟踪
| 操作 | 用途 |
|---|---|
list | 列出跟踪的修订,并报告修订跟踪是否开启 |
accept | 接受一条或全部修订 |
reject | 拒绝一条或全部修订 |
set-tracking | 开启或关闭修订跟踪 |
在 accept/reject 中省略 index 时,将处理整个文档,包括页眉和页脚。
revision(action: "set-tracking", session_id: "...", enabled: true)
revision(action: "accept", session_id: "...")
bookmark — 稳定引用
| 操作 | 用途 |
|---|---|
list | 列出书签名称、段落索引以及标记文本的预览 |
add | 为段落、段落范围或段落中的短语添加书签 |
get-text | 读取完整的书签文本 |
delete | 移除书签;文本会保留 |
名称必须以字母开头,且只能包含字母、数字和下划线。即使文档其他位置发生编辑,书签仍会保留,因此段落索引发生变化后,书签是可靠地引用某段内容的方式。
bookmark(action: "add", session_id: "...", name: "Intro", paragraph_index: 2)
bookmark(action: "add", session_id: "...", name: "Growth",
paragraph_index: 4, anchor_text: "fifteen percent")
bookmark(action: "get-text", session_id: "...", name: "Intro")
footnote — 脚注和尾注
| 操作 | 用途 |
|---|---|
list | 列出脚注或尾注的索引、引用标记、段落和文本 |
add | 为段落或段落中的短语添加注释 |
set-text | 重写注释文本 |
delete | 连同引用标记一起移除注释 |
kind 用于选择 footnote(默认)或 endnote;在 Word 中,两者是独立的集合,编号也互不相关。这是读取脚注文本的唯一方式——text(get) 返回正文内容,不会返回注释。
footnote(action: "list", session_id: "...")
footnote(action: "add", session_id: "...", paragraph_index: 4,
text: "Annual report 2025, p. 14.", anchor_text: "fifteen percent")
footnote(action: "add", session_id: "...", paragraph_index: 4,
text: "Method described in appendix B.", kind: "endnote")
content-control — 模板字段
| 操作 | 用途 |
|---|---|
list | 列出内容控件的标签、标题、类型、锁定状态和当前文本 |
get | 读取由 tag 或 id 指定的控件 |
set-text | 填入内容;复选框控件使用 is_checked |
add | 将段落包装在新的控件中 |
delete | 移除控件,可选择同时移除其内容 |
内容控件是 Word 模板提供的结构化字段。填充这些字段是完成模板的可靠方式——对周围文本使用 text(replace) 会破坏控件及其绑定。tag 并非唯一,更新时会匹配所有控件,这正是模板重复使用字段时所需的行为;id 则精确指定一个控件。
content-control(action: "list", session_id: "...")
content-control(action: "set-text", session_id: "...",
tag: "CustomerName", text: "Contoso Ltd")
content-control(action: "set-text", session_id: "...",
tag: "TermsAccepted", is_checked: true)
content-control(action: "delete", session_id: "...", tag: "Draft",
delete_contents: true)
screenshot — 查看页面
| 操作 | 用途 |
|---|---|
page | 将页面渲染为 PNG |
页面布局问题——分页符、表格宽度、图像位置、页眉位置——通过渲染后的页面比通过测量数据更容易判断。PNG 会写入文件并返回路径;include_image: true 还会以内联 base64 形式返回图像,只有在需要查看图像时才值得占用上下文。
dpi 默认值为 150。快速检查布局时使用 96,接近打印效果时使用 300。
screenshot(action: "page", session_id: "...", page: 2)
screenshot(action: "page", session_id: "...", page: 1,
output_path: "C:/temp/page1.png", dpi: 300, include_image: true)
响应
每个工具都会返回 JSON。失败会以结构化载荷报告,而不会表现为传输错误:
{
"success": false,
"isError": true,
"tool": "text",
"action": "Replace",
"errorType": "KeyNotFoundException",
"errorMessage": "Session 'word-unknown' not found."
}
已知行为和注意事项
document(save-as)也会保存原始文件。 Word 没有可更改格式的“保存副本” API。对于 PDF 以外的任何目标格式,服务都会调用SaveAs2(target),然后调用SaveAs2(original),这会带来副作用,将待处理的更改保存到原始文件。需要无副作用地导出时,请使用export-pdf。- 颜色使用十六进制 RGB(
#0078D4)。服务会将其转换为 Word 所需的 BGR 值。 - 受权限保护的文档(IRM/AIP)会在启动 Word 前被拒绝。
- 在 Word 中打开的文档会阻塞会话——请先关闭文档。
- Word 对话框会导致自动化停滞。 如果调用超时,请检查桌面上是否有打开的对话框。
- 样式名称为英文。 内置样式(
Heading 1、Title、Table Grid等)会转换为与语言无关的 Word 样式 ID,因此在本地化安装中也能使用。其他名称会原样传递给 Word,以便使用自定义样式和本地化样式。请注意,Word 会以本地化名称报告样式(德语安装中为Überschrift 1),因此style(list)会同时返回name和english_name——如果存在english_name,请将其传回。 - 内置样式无法删除。
style(delete)会明确提示并拒绝删除,而不会透传 Word 通用的 COM 错误。仍应用于段落的自定义样式也无法删除;请先将这些段落设为其他样式。 - 新文档会直接写入,而非通过 Word 写入。
file(create)会自行写入一个空的.docx/.docm包,然后将其打开。在已登录 Microsoft 365 的计算机上,通过 Word 创建文档并不可靠,因为自动保存会将新文档保存到 OneDrive,并静默忽略指定的本地路径。 - 合并的表格单元格在
table(read)中会以空字符串返回。 - 图像尺寸的单位是点,而非像素(72 pt = 1 英寸)。除非将
lock_aspect_ratio设为false,否则image(insert)和image(resize)会保持纵横比,因此只传入width时,高度也会随之缩放。 image仅涵盖嵌入型图片。 浮动形状、文本框和图表不会受到影响,也不会出现在image(list)中,因此它们的存在不会改变图片索引。- 目录只会列出标题段落。 对于没有标题样式的文档,
field(insert-toc)会返回entry_count: 0——请先通过paragraph(add|set-style)应用Heading 1/Heading 2,然后运行field(update-toc)。 field(update-all)也会遍历页眉和页脚。 Word 的Document.Fields只涵盖正文,因此否则页码永远不会刷新。image(insert)使用题注时会采用 Word 的题注编号,因此题注显示为Figure 1 <your text>(非英文安装中会本地化),并会纳入图表目录。- 所有度量单位均为点,包括页边距(1 cm = 28.35 pt,1 英寸 = 72 pt)。
section(page-setup)会先应用paper_size,再设置页边距,因为在 Word 中更改纸张大小会重置页边距。不指定section_index时,设置会应用于每个节。- 各节之间会继承页眉和页脚。 新节会显示上一节的页眉,直到为其写入内容。使用
section_index调用header-footer(set)会自动断开此链接,因此第 1 节会保留自己的文本。 first-page和even-pages页眉需要启用相应的节设置。header-footer(set)会为你分别启用DifferentFirstPage或DifferentOddEvenPages——否则 Word 虽会存储文本,却不会将其渲染出来。list(apply)默认会开始一个新列表。continue_previous_list默认关闭,因为继续无关的较早列表编号通常并非预期行为。两个编号列表之间若有普通段落,它们会保持独立;如果 Word 仍将它们合并,请使用list(restart)。- 只有大纲编号列表会渲染不同级别。
list(set-level)可用于任何列表,但普通的bullet或number列表在每个级别上都会显示相同的标记——段落只是增加了缩进。 comment(resolve)在 Microsoft 365 上经常失败。 Word 的现代批注会将通过 API 添加的每条批注都视为尚未发布的草稿,而草稿无法标记为已完成。服务会对此给出明确提示;请改为删除批注。在完全不公开状态的安装中,comment(list)会返回resolved: null。- 批注和修订的索引会变化。 删除批注或接受单条修订后,其后的所有索引都会重新编号,因此进行这类调用时,每次操作之间都应重新运行
list,不要重复使用旧索引。 - 不带索引的
revision(accept|reject)也会遍历页眉和页脚。 Word 的Document.AcceptAllRevisions()只涵盖正文,与field(update-all)存在相同的遗漏。 - 只有在启用修订跟踪时才会记录修订。
revision(set-tracking)不会追溯应用——请在要记录的编辑之前启用跟踪。 - Word 对书签名称有限制。 名称必须以字母开头,只能包含字母、数字和下划线,且不得超过 40 个字符。空格、连字符、句点和非 ASCII 字母会在调用到达 Word 前被拒绝,否则 Word 会返回通用的 COM 错误。
- 书签是引用文本内容的稳定方式。 每次插入都会改变段落索引,但书签不会。为一段内容添加书签后,可使用
bookmark(get-text)之后重新读取。 - 对段落使用
bookmark(add)时,书签不包含段落标记,因此get-text返回的文本不会带尾随换行符。跨多个段落的书签会保留中间的段落标记。 text(get)永远不会返回脚注。 脚注和尾注位于 Word 自己的故事范围中,因此,如果文档将来源放在注释中,看起来会很完整,实际上却缺少部分内容。总结或翻译任何内容之前,请先调用footnote(list)。- 删除注释会重新编号其余注释。
footnote(delete)会将之后的每个索引减 1,这与批注和修订的情况相同。删除多条注释时,请按索引从高到低操作。 - 脚注和尾注是两个独立集合。 它们的编号彼此独立,所有
footnote操作默认针对脚注——请明确传入kind: "endnote"。 - 填写模板应使用
content-control(set-text),而非text(replace)。 替换内容控件周围的文本会破坏控件及其数据绑定;通过控件写入则能保留两者。 - 内容控件标签并非唯一。 按
tag使用content-control(set-text)会更新所有匹配项并报告匹配数量,因为模板可能在页眉和签名栏中都显示客户名称。需要精确定位单个控件时,请使用id。 content-control(delete)默认会保留文本。 只有delete_contents: true才会连同控件一起删除内容。对于禁止删除的控件,系统会报告出来,而不是静默跳过。screenshot(page)会通过 PDF 渲染页面。 Word 没有将页面作为图像返回的 API,因此服务会通过ExportAsFixedFormat导出单页并将其栅格化。未保存的更改也会包含在内,临时 PDF 会在之后删除。- 页码来自最新的重新分页结果。 仅通过自动化编辑过的文档会报告过时的页数,因此
screenshot会先重新分页。这也意味着页数反映的是当前布局,而不是打开文档时的布局。
从源代码构建
git clone https://github.com/trsdn/mcp-server-word.git
cd mcp-server-word
dotnet build WordMcp.sln -c Release
dotnet test WordMcp.sln --filter "Category!=RequiresWord"
项目结构
| 项目 | 用途 |
|---|---|
src/WordMcp.ComInterop | Word COM 生命周期:STA 线程处理、会话、OLE 消息筛选器、文件验证 |
src/WordMcp.Core | 命令接口、命令实现和结果模型 |
src/WordMcp.Generators.Shared | 生成器共享的源文件;本身不是一个项目 |
src/WordMcp.Generators.Mcp | 用于生成 MCP 工具类的 Roslyn 源生成器 |
src/WordMcp.McpServer | 通过 stdio 提供 15 个工具的 MCP 服务 |
tests/WordMcp.Core.Tests | 单元测试,以及针对真实 Word 的集成测试 |
tests/WordMcp.McpServer.Tests | 工具层单元测试,无需 Word |
生成的工具层
15 个工具中有 14 个在构建时生成。src/WordMcp.Core/Commands 中的命令接口是线协议契约的唯一真实来源:
[ServiceCategory("section", "Section")]用于命名工具类WordSectionTool。[McpTool("section", Title = ..., Description = ...)]提供工具名称以及模型读取的提示词。- 每个方法上的
[ServiceAction("page-setup")]会成为生成的WordSectionAction枚举中的一个值。 - 接口参数的 XML 文档会成为 MCP 架构中的参数说明。
生成器会将所有操作的参数合并到一个方法中,因此,仅用于部分操作的参数会生成为可选参数。要更改 API,请编辑接口,绝不要修改生成的代码。file 保持手动编写,因为它管理会话,而不是在单个会话上执行操作。
检查 src/WordMcp.McpServer/obj/generated 下生成的代码。GeneratedToolContractTests 中的测试会将生成的接口与各接口进行比对,因此不匹配时会导致构建失败,而不会将问题带到客户端。
需要真实 Word 安装的测试会标记为 [Trait("Category", "RequiresWord")],并在 CI 中排除。失败的集成测试运行可能会遗留孤立的 WINWORD.EXE 进程,从而拖慢或阻止后续运行;重新运行前,请使用 Get-Process WINWORD | Stop-Process -Force 清理。
延伸阅读
| 文档 | 内容 |
|---|---|
| docs/architecture.md | 各层、请求流程以及工具层的生成方式 |
| docs/com-interop.md | STA 线程处理、释放 COM 对象,以及上述问题背后的 Word 行为 |
| CONTRIBUTING.md | 构建、测试、添加工具、发布 |
| skills/word-mcp/SKILL.md | 面向 Agent 的指南,介绍如何按正确顺序使用这些工具 |
故障排除
| 症状 | 原因和解决方法 |
|---|---|
Word is not installed or not registered for COM | 安装 Word 桌面版;Microsoft Store 版本无法自动化 |
Could not load file or assembly 'office' | 在 GAC 中找不到 office.dll——重新安装或修复 Office |
| 操作超时 | Word 对话框正在等待输入;关闭对话框后重试 |
The file is already open in Word | 在 Word 界面中关闭文档 |
参与贡献
错误报告和功能请求请通过问题模板提交。 欢迎提交拉取请求;CONTRIBUTING.md 介绍了如何构建、如何运行测试套件的两部分,以及添加工具所需的工作。
请先阅读行为准则。
请勿公开提交安全问题——请按照安全政策中的说明私下报告。
许可证
MIT——详见 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。