UniDoc说明中心下载 .udoc
UNIDOC / KNOWLEDGE IN MOTION

UniDoc MCP 协议

从理解,到动手实现。步骤、协议与可复制的示例,都在这份文档中。

版本:2026-09-16

UniDoc MCP 是编辑器之外的可选 AI 能力层。没有 MCP 客户端时,编辑器、DOCX/UDoc
转换和离线 WASM 路径照常运行;MCP 也不会暴露 Rust 后端源码或浏览器 Cookie。

端点

生产端点为 https://app.unidoc.top/mcp。客户端应先读取:

GET /.well-known/oauth-protected-resource/mcp
GET /.well-known/oauth-authorization-server

服务器支持 OAuth 2.1 授权码流程和 S256 PKCE:

POST /oauth/mcp/register
GET  /oauth/mcp/authorize
POST /oauth/mcp/consent       (UniDoc 登录后的确认页)
POST /oauth/mcp/token

动态注册只接受 ChatGPT 官方回调、本机 localhost/127.0.0.1 回调,或由部署者通过
UNIDOC_MCP_REDIRECT_URIS 明确配置的精确 URI。客户端不得把 access token 放进 URL;调用
MCP 时使用:

Authorization: Bearer <access_token>
Content-Type: application/json

授权范围为 mcp:read、可选的 mcp:write 和单独的 mcp:publish。网站发布必须同时
持有 mcp:readmcp:publish;已有的 read/write 授权不会自动获得公开发布权限。
文档编辑仍使用 mcp:write。发布工具只接受显式获得 mcp:publish 的 OAuth grant,
浏览器 Cookie 回落路径不会自动获得该权限。新增发布授权是补充权限;已有登录会话有效时
不要求用户重新登录。当前 UniDoc 浏览器会话也可在受保护环境中调用文档工具;
匿名公开快照和只读分享不会被提升为 MCP 身份。

JSON-RPC

请求使用 JSON-RPC 2.0:

{"jsonrpc":"2.0","id":1,"method":"tools/list"}

初始化后调用 tools/call

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "unidoc_list_blocks",
    "arguments": {"documentId": "doc_…"}
  }
}

工具结果同时放在 content[0].text(JSON 字符串)和 structuredContent,便于不同 MCP
客户端选择文本或结构化读取。未知方法返回 JSON-RPC -32601;工具业务错误返回
result.isError=true

生产 MCP 请求与 AI 接口共用账户配额:默认每分钟 12 次请求、12 万预算单位、3 并发;
每天 200 次请求、100 万预算单位,另受全局上限约束。超额返回 HTTP 429 和
Retry-After,配额持久保存,重启不会清空。认证失败返回 HTTP 401;不要把这两种
HTTP 错误当成 tools/call 的成功结果。

工具

工具范围用途
unidoc_open_documentread在隔离 MCP 会话中打开已校验的 UDoc JSON
unidoc_list_documentsread列出当前 MCP 身份打开的文稿
unidoc_get_documentread读取完整 UDoc JSON 和 revision
unidoc_get_capabilitiesread读取模型、批注和写入约束
unidoc_list_blocks / unidoc_get_blockread按稳定 para_id 读取段落
unidoc_list_commentsread读取原生批注、回复和扩展字段
unidoc_validateread校验 UDoc JSON,不打开会话
unidoc_create_commentwrite按 Unicode 文本偏移创建原生批注
unidoc_reply_commentwrite通过 parentId 回复,不创建第二个锚点
unidoc_update_commentwrite修改批注正文,保留锚点
unidoc_resolve_commentwrite设置 resolved
unidoc_delete_commentwrite删除批注、回复和持久锚点
unidoc_apply_patchwrite原子执行段落级 HTML 更新、插入、删除
unidoc_export_udocread导出当前 UDoc 容器的 base64
unidoc_publish_websiteread + publish将显式提交的 HTML 保存为账户归属的 UDoc 来源,并发布为独立公网网站
unidoc_get_websitereadsiteId 读取当前账户所属网站的发布信息
unidoc_export_websitereadsiteId 导出当前账户所属网站的原生 .udoc 来源

AI 发布网站

AI 已持有网页 HTML 时,可直接调用 unidoc_publish_website,不必先开编辑器、创建文稿
会话或调用浏览器上传接口。这是立即公开发布操作,只有用户要求发布的内容才应提交。

{
  "jsonrpc": "2.0",
  "id": 20,
  "method": "tools/call",
  "params": {
    "name": "unidoc_publish_website",
    "arguments": {
      "html": "<!doctype html><html lang=\"zh-CN\"><meta charset=\"utf-8\"><title>学习实验室</title><button onclick=\"this.textContent='实验开始'\">开始实验</button></html>",
      "title": "学习实验室",
      "requestId": "lesson-site-20260916-v1"
    }
  }
}

htmlrequestId 必填;titlebaseUrl 可选。baseUrl 用于解析 HTML 中的相对
资源地址,不是让服务器抓取该 URL。它应指向资源实际所在的公开 HTTPS 基址,例如
https://assets.example.com/lesson/index.html。本地 HTML 旁边的图片、CSS、JS 文件不会
自动上传;请把这些资源内联,或先提供可公开访问的 HTTPS 构建产物。

成功结果的 structuredContent 包含 siteId、别名 idurlstatus:"published"
titlecontentSha256bytescreatedAtreplayed,以及
source:{"kind":"udoc","persisted":true}。将服务器返回的 URL 交给用户,不自行猜测
地址。公开页面运行在 https://sites.unidoc.top/,保留脚本交互,并与编辑器账户隔离。
其沙箱环境不能被当成原网站登录会话、Cookie、同源存储或后端服务的迁移;外部模块、API
和字体仍须满足各自的可访问性及 CORS 条件。

发布会持久保存账户归属的 .udoc 来源和发布收据。相同账户以相同 requestId 和相同
内容重试,应得到原发布结果;同一个 ID 配不同内容会被拒绝。发布是不可变快照;更新网站
内容时使用新的 requestId 创建新版本。unidoc_get_website
unidoc_export_website 接收 {"siteId":"服务器返回的站点 ID"},只允许来源所属账户
读取发布信息和导出 UDoc,不因持有公开 URL 而获得来源读取权限。查询返回上述发布元信息;
导出返回 siteIdfileNamemimeType: "application/vnd.unidoc.udoc3"base64
将 base64 解码为原始字节,以返回的 .udoc 文件名保存,不改写成 HTML 或 JSON。

完整调用说明见 AI 网页发布说明。浏览器原有 /sites/publish
流程仍校验其 OmniDoc sourceObjectId;MCP 不通过伪造 Cookie、Origin 或云对象 ID 来
调用该浏览器接口。

批注模型

批注是 UDoc 的原生 comments[] 项。根批注的正文块 HTML 中保存三个零宽标记:

<span data-ud-comment-id="7" data-ud-comment-edge="start" …></span>
<span data-ud-comment-id="7" data-ud-comment-edge="end" …></span>
<span data-ud-comment-id="7" data-ud-comment-edge="reference" …></span>

点批注只保存 reference。回复是带 parentId 的普通 comments[] 项,复用根批注的
范围,所以 DOCX ↔ UDoc 不会因回复增加第二个范围。start/end 是渲染后文本的 Unicode
标量偏移,HTML 标签和实体不计作 HTML 字节;客户端应先读取段落再提交偏移。

编辑器的 CSS Highlight 只是显示层,导出 DOCX 时由转换器生成 Word 原生黄色批注范围;
它不与“开始”面板的文字高亮状态混用。

写入一致性

文档修改工具都要求:

{"expectedRevision":3,"requestId":"ai-run-42-op-7"}

expectedRevision 不匹配时不会写入,返回 structuredContent.conflict=true 以及当前
revision。相同 requestId 重试会返回第一次的结果;同一个 ID 配不同参数会被拒绝。批量
patch 会先在副本上执行和校验,失败时整批不提交;含有原生批注标记的块不能被 patch 删除,
避免生成无锚点批注。

网站发布不修改进程内文稿 revision,使用上述持久化 requestId 机制,不要求
expectedRevision

部署边界

第一版 MCP 会话存放在当前 Rust 进程内存中,unidoc_open_document 接收显式 UDoc JSON,
适合作为 AI 转换、审阅和局部编辑的安全能力层。它不会自动读取当前浏览器画布、Vault 或
其他账号的文稿。生产多实例部署应在网关保持会话粘性,或后续把 McpState 接到同一账号
授权的持久文稿存储后再开放跨实例会话。这项内存会话边界不适用于网站的持久来源与发布
收据;后端部署必须保留站点数据目录及其所有权记录。