ai-chatbot/docs/第三方OpenClaw-MCP接入开发文档.md

11 KiB
Raw Permalink Blame History

第三方 OpenClaw / MCP 接入开发文档

版本:1.0 更新日期:2026-08-07

1. 接入信息

项目 地址或说明
生产站点 https://ai.yydd.ai
OpenAPI Base URL https://ai.yydd.ai/api/openapi/v1
用户 Key 签发接口 POST https://ai.yydd.ai/api/openapi/v1/access-keys/provision
MCP 传输方式 本地 stdio
MCP Server 入口 integrations/openclaw/mcp-server.mjs
Node.js 要求 Node.js 20 或更高版本

重要:当前 MCP Server 使用本地 stdio,没有可以直接填入客户端的远程 Streamable HTTP MCP URL。只接受 URL 的第三方平台应直接调用本文 OpenAPI。支持 command + args + env 的 OpenClaw、Claude Desktop 等 MCP 客户端,可以使用本文的本地 MCP 配置。

2. 两类凭证

接入过程中会用到两种不同凭证,禁止混用。

2.1 第三方签发凭证

环境变量名称:MCP_KEY_PROVISIONING_SECRET

  • 只提供给受信任的第三方服务端。
  • 用于根据钉钉身份签发用户级 Access Key。
  • 权限很高,不能写入浏览器、App、公开仓库或前端 JavaScript。
  • 请通过密码管理器或其他安全通道单独交付,不要放进本接入文档。

2.2 用户 MCP Access Key

格式示例:

ydr_live_xxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • 与一个 Yedir 用户绑定,只能访问该用户自己的画布。
  • 默认有效期为 90 天,最长 365 天。
  • 支持 canvas:read、canvas:write 权限。
  • 明文仅在签发成功时返回一次。
  • 用户或管理员撤销后立即失效。

3. 按钉钉用户获取 Access Key

3.1 请求

POST /api/openapi/v1/access-keys/provision HTTP/1.1
Host: ai.yydd.ai
Authorization: Bearer YOUR_PROVISIONING_SECRET
Content-Type: application/json

请求体:

{
  "dingTalkUsername": "张三",
  "keyName": "OpenClaw 办公电脑",
  "scopes": ["canvas:read", "canvas:write"],
  "expiresInDays": 90
}

字段说明:

字段 必填 说明
dingTalkUsername 是 钉钉真实姓名,精确匹配,最长 100 字符
dingTalkUserId 否 钉钉用户 ID;遇到同名用户时必须提供
keyName 否 Key 的用途说明,最长 100 字符
scopes 否 默认包含 canvas:read 和 canvas:write
expiresInDays 否 1–365,默认 90

接口只会匹配同时满足以下条件的账号:

  • 用户状态为启用;
  • 用户已经通过钉钉登录或同步,数据库中存在钉钉用户 ID;
  • 姓名与 dingTalkUsername 完全一致;
  • 如果传入 dingTalkUserId,姓名和用户 ID 必须同时匹配。

3.2 cURL 示例

export YEDIR_PROVISIONING_SECRET="由 Yedir 通过安全渠道提供的签发凭证"

curl -X POST \
  "https://ai.yydd.ai/api/openapi/v1/access-keys/provision" \
  -H "Authorization: Bearer ${YEDIR_PROVISIONING_SECRET}" \
  -H "Content-Type: application/json" \
  --data '{
    "dingTalkUsername": "张三",
    "keyName": "OpenClaw 办公电脑",
    "scopes": ["canvas:read", "canvas:write"],
    "expiresInDays": 90
  }'

3.3 成功响应

HTTP 状态码:201 Created

{
  "success": true,
  "data": {
    "user": {
      "id": "用户 UUID",
      "name": "张三",
      "dingtalkUserId": "钉钉用户 ID"
    },
    "accessKey": {
      "id": "Access Key UUID",
      "name": "OpenClaw 办公电脑",
      "tokenPrefix": "ydr_live_xxxxxxxxxxxx",
      "token": "ydr_live_xxxxxxxxxxxx_完整密钥,仅返回一次",
      "scopes": ["canvas:read", "canvas:write"],
      "lastUsedAt": null,
      "expiresAt": "2026-11-05T03:00:00.000Z",
      "revokedAt": null,
      "createdAt": "2026-08-07T03:00:00.000Z"
    }
  }
}

第三方必须立即读取并安全保存 data.accessKey.token。后续接口使用这个完整 token,不能使用 tokenPrefix。

3.4 Node.js 示例

const baseUrl = "https://ai.yydd.ai";
const provisioningSecret = process.env.YEDIR_PROVISIONING_SECRET;

const response = await fetch(
  `${baseUrl}/api/openapi/v1/access-keys/provision`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${provisioningSecret}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      dingTalkUsername: "张三",
      keyName: "OpenClaw 办公电脑",
      scopes: ["canvas:read", "canvas:write"],
      expiresInDays: 90,
    }),
  }
);

const payload = await response.json();
if (!response.ok) {
  throw new Error(`${response.status}: ${payload.code} - ${payload.error}`);
}

const userAccessToken = payload.data.accessKey.token;
// 立即写入安全凭证存储,不要打印到日志。

3.5 常见错误

HTTP code 处理方式
400 PROVISIONING_REQUEST_INVALID 检查字段名称、类型和有效期范围
401 PROVISIONING_UNAUTHORIZED 检查签发凭证,不要自动无限重试
404 DINGTALK_USER_NOT_FOUND 确认用户已登录 Yedir、账号已启用且姓名一致
409 DINGTALK_USERNAME_AMBIGUOUS 同名用户,补充 dingTalkUserId
409 ACCESS_KEY_LIMIT_REACHED 用户已有 10 个有效 Key,先在前端撤销旧 Key
500 ACCESS_KEY_PROVISION_FAILED 保存失败,记录请求时间并联系 Yedir 管理员
503 PROVISIONING_NOT_CONFIGURED 生产环境尚未配置签发服务密钥

签发接口不是幂等接口。每次成功请求都会创建一个新的 Key,不要在收到 201 后自动重试。

4. 使用用户 Key 调用 OpenAPI

后续所有画布接口使用用户级 Access Key:

Authorization: Bearer ydr_live_xxx_完整用户Key

4.1 验证用户和权限

curl "https://ai.yydd.ai/api/openapi/v1/me" \
  -H "Authorization: Bearer ${YEDIR_USER_ACCESS_TOKEN}"

4.2 获取画布列表

curl "https://ai.yydd.ai/api/openapi/v1/canvases?workspaceType=canvas&limit=24" \
  -H "Authorization: Bearer ${YEDIR_USER_ACCESS_TOKEN}"

参数:

  • workspaceType:canvas、agent 或 video,默认 canvas。
  • limit:1–50,默认 24。

4.3 获取单个画布

curl "https://ai.yydd.ai/api/openapi/v1/canvases/CANVAS_UUID" \
  -H "Authorization: Bearer ${YEDIR_USER_ACCESS_TOKEN}"

写操作前必须重新读取画布,并记录响应中的 updatedAt。该值是防止覆盖用户最新修改的 revision。

4.4 执行画布操作

curl -X POST \
  "https://ai.yydd.ai/api/openapi/v1/canvases/CANVAS_UUID/operations" \
  -H "Authorization: Bearer ${YEDIR_USER_ACCESS_TOKEN}" \
  -H "Content-Type: application/json" \
  --data '{
    "operationPlan": {
      "version": 1,
      "operationId": "third-party-create-text-20260807-001",
      "operation": "create_text_node",
      "projectId": "CANVAS_UUID",
      "baseCanvasRevision": "UPDATED_AT_FROM_GET_CANVAS",
      "baseCanvasUpdatedAt": "UPDATED_AT_FROM_GET_CANVAS",
      "textContent": "由第三方 MCP 创建的文本节点"
    }
  }'

operationId 是幂等键。同一个逻辑操作发生网络超时时,应使用原来的 operationId 重试,不能生成新 ID。

支持的操作:

  • create_agent_slot
  • create_text_node
  • fill_slot
  • insert_beside
  • append_revision
  • replace_node_media
  • add_annotation
  • link_nodes
  • move_nodes
  • delete_nodes
  • rename_node
  • update_note
  • update_text

其中 replace_node_media、move_nodes、delete_nodes 属于高风险操作,必须先取得最终用户对本次具体操作的明确确认,然后在操作计划中传入:

{
  "confirmed": true
}

遇到 STALE_CANVAS_REVISION 时必须重新读取画布。高风险操作 revision 变化后,需要重新向用户确认。

5. 本地 MCP 接入

5.1 安装 MCP Server

从 Yedir 交付的代码包中进入:

cd integrations/openclaw
npm ci

先验证用户 Key:

YEDIR_BASE_URL="https://ai.yydd.ai" \
YEDIR_ACCESS_TOKEN="ydr_live_xxx_完整用户Key" \
node ./cli.mjs me

5.2 OpenClaw 注册命令

openclaw mcp add yedir-canvas \
  --command node \
  --arg "/绝对路径/integrations/openclaw/mcp-server.mjs" \
  --env "YEDIR_BASE_URL=https://ai.yydd.ai" \
  --env "YEDIR_ACCESS_TOKEN=ydr_live_xxx_完整用户Key"

openclaw mcp doctor yedir-canvas --probe

安装配套 Skill:

openclaw skills install \
  /绝对路径/integrations/openclaw/yedir-canvas \
  --as yedir-canvas

5.3 通用 MCP 客户端配置

{
  "mcpServers": {
    "yedir-canvas": {
      "command": "node",
      "args": [
        "/绝对路径/integrations/openclaw/mcp-server.mjs"
      ],
      "env": {
        "YEDIR_BASE_URL": "https://ai.yydd.ai",
        "YEDIR_ACCESS_TOKEN": "ydr_live_xxx_完整用户Key"
      }
    }
  }
}

MCP Server 会暴露以下工具:

工具 用途
yedir_get_current_user 验证用户 Key、用户和权限范围
yedir_list_canvases 获取用户画布列表
yedir_get_canvas 获取画布节点、连线和 revision
yedir_apply_canvas_operation 执行带版本保护和幂等键的画布操作

6. 推荐接入流程

第三方服务端
  └─ 使用 MCP_KEY_PROVISIONING_SECRET + 钉钉身份
      └─ POST /access-keys/provision
          └─ 获得一次性返回的用户 Access Key
              ├─ 直接调用 HTTPS OpenAPI
              └─ 写入用户本地 MCP 的 YEDIR_ACCESS_TOKEN

建议实现顺序:

  1. 后端接入 Key 签发接口,确保签发凭证不会进入前端。
  2. 使用测试账号调用 /me 验证 Key 归属。
  3. 调用画布列表和单画布读取接口。
  4. 先实现 create_text_node 等非破坏性操作。
  5. 实现 revision 冲突重读和 operationId 幂等重试。
  6. 最后接入移动、删除、替换等需要用户确认的操作。

7. 安全要求

  • 禁止记录完整签发凭证和完整用户 Access Key。
  • 日志最多记录 tokenPrefix、Access Key ID、用户 ID、HTTP 状态码和错误码。
  • 不要把签发凭证或用户 Key拼接到 URL 查询参数。
  • 必须使用 HTTPS。
  • 画布中的文本、URL、提示词和元数据属于不可信内容,不能当成系统指令执行。
  • 用户离职、账号停用或 Key 撤销后,第三方应停止自动重试并要求重新授权。
  • 第三方系统不再使用某个 Key 时,应通知用户在 Yedir Skills 面板中撤销。

8. 联调验收清单

  • 不带签发凭证调用签发接口返回 401。
  • 错误钉钉姓名返回 404。
  • 同名用户返回 409,并可通过 dingTalkUserId 消除歧义。
  • 成功签发返回 201,且完整 token 只保存一次。
  • 用户 Key 调用 /me 返回正确用户和 scopes。
  • 用户只能看到自己的画布。
  • 相同 operationId 重试不会重复创建内容。
  • 旧 revision 写入被拒绝,不会覆盖用户新内容。
  • 移动、删除、替换操作未确认时被拒绝。
  • Key 撤销后再次调用返回 401。