MOV 工具开发规范 · 官方契约
生态内任何工具 / MCP 的开发契约:声明、命名、参数、输出、错误、并行、权限——一页对照,对齐 dsh(DeepSeek Harness)官方设计。
要点(30 秒)
- 工具声明四件套 + MCP 暴露面四字段——与 tools/list 实态同源(铁律)。
- 命名规范 + 参数与输出契约。
- 错误契约统一 16 类。
- 并行与作用域(dsh 同款纪律)、权限分级(readonly/write 职责)。
- 含与 dsh 官方对比现状、「外部工具(市场安装)」特殊说明。
展开全文(完整表格 / 代码 / 细节)
一、工具声明(与 dsh 对齐的完整契约)
每个工具按以下字段声明(dsh ToolDefinition 同构):
{
name: "mov.roomList", // ① 唯一名:领域.动作
description: "列出当前房间", // ② 描述:给模型看,禁止占位
parameters: { ... }, // ③ JSON Schema(类型/必填/描述)
output: { schema: {...} }, // ④ 输出声明(可选,供 render)
timeoutMs: 20000, // ⑤ 超时(策略层用,绝不发给模型)
isConcurrencySafe: (args) => true, // ⑥ 并发:精确 true 才并行,未声明保守串行
scope: ["main"], // ⑦ 作用域:main / subagent
execute: async (args, runCtx) => value
}
工厂接收 defineTool() 风格的参数声明(dsh 已落盘 ToolDefinition,见 docs/MCP_TOOL_DEV_GUIDE.md)。
二、命名规范
- 格式:
领域.动作(小写点分),如mov.roomList、torch.on、file.read、vault.get、market.install; - 保留黑名单(禁止用作工具名):
sms.read / pay.query / identity.read / a2a.message / contact.read / call.log / location.read; - 市场外部工具:
ext.<服务器>.<工具>;不需要版本后缀(版本/分类存在于市场目录)。
三、参数与输出契约
参数一律 JSON Schema(类型/必填/描述),模型侧校验:非法参数必须返回 INVALID_ARGS,禁止运行时再手写防错。
输出二选一:
// 成功
{ ok: true, data: { ... } }
// 失败(见错误契约)
{ ok: false, error: { code: "TOOL_TIMEOUT", message: "..." } }
MCP 侧投影为 MCP 标准 content / isError(McpServer 已实现)。
四、错误契约(统一 16 类)
工具内部不要自造错误文本——用统一分类(ERROR_CLASSES 单源表):
| code | 典型场景 | 能否重试 |
|---|---|---|
| RATE_LIMIT / TIMEOUT / TRANSPORT | 上游限流/超时/网络 | 可 |
| CONTEXT_WINDOW_EXCEEDED / QUOTA / EMPTY_RESPONSE | 模型/配额类 | 可 |
| TOOL_NOT_FOUND / TOOL_TIMEOUT / TOOL_ERROR / UNKNOWN | 工具执行类 | 看场景 |
| PERMISSION_DENIED / APPROVAL_DENIED | 权限/审批类 | 不可 |
| INVALID_CREDENTIAL / MISSING_CREDENTIAL / INVALID_ARGS / UI_ONLY_TOOL / SERVER | 配置/参数类 | 看场景 |
调度层错误码固定:SCOPE_DENIED / BUSY / UI_ONLY_TOOL / TOOL_NOT_FOUND / APPROVAL_DENIED;错误消息走 formatToolError 脱敏,禁止把密钥/路径明文返回。
五、并行与作用域(dsh 同款纪律)
dsh 明确:只有 isConcurrencySafe(args) === true 才允许并行,否则 fail-closed 为串行(exclusive 屏障)。并行工具 handler 内部必须线程安全(不得修改父状态;共享状态要么并发安全要么 fail-closed)。
作用域:main(默认)/ subagent——调用方 scope 与工具 scope 相交才放行。
六、权限分级(工具属性的职责)
审批分级不是工具元数据,而是 PermissionGuard 外部名单(底线永远 DENY):
- 敏感集:读取凭据/支付/身份(sms.read 等)→ 永远 DENY;
- 写类集:写文件/发消息/支付 → 需要用户审批(ASK);
- 无害级:查询/状态类 → 自动放行(harmless auto-allow);
- 高危:shell 等 → 强制 ASK(plan 闸 + 更高审批级)。
七、MCP 暴露面(四字段)
工具上架后出现在 tools/list:name / description / inputSchema / level(读/写)。
ToolDefinition 登记层单源(声明/描述/Schema/输出声明一处声明多面消费),且 tools/list 已补传完整 inputSchema(此前仅部分工具携带)——外部服务器建议同样返回完整四字段,与内置面体验对齐。八、与 dsh 官方对比(现状)
| 契约项 | dsh 官方 | MOV 现状 |
|---|---|---|
| 工具四件套(name/description/parameters/execute) | ToolDefinition | ✅ ToolDefinition 已落地(BuiltinMcpTools 全套践行) |
| 参数为 JSON Schema + 模型侧校验 | defineTool 编译 + INVALID_ARGS | ✅ 有(toolParamSchemas + 校验) |
| 输出声明(output/render/presentationMeta) | ToolOutputDefinition | ⚠️ 登记层单源已承载(BuiltinMcpTools 全套 + browser 14 实测返回键);存量 output 清偿批 3 在途 |
| 并行(isConcurrencySafe 精确 true) | 并行池 + exclusive 屏障 | ✅ 同款(ToolRegistry + Semaphore 屏障) |
| scope(agent 级掩码) | agent.ctx + restrict | ✅ 声明机制在(subagent 落地进行中) |
| 错误分类(结构化 code + message) | HarnessError info{name, code} | ✅ ERROR_CLASSES 16 类单源 |
| 权限门(allow/deny/ask,不改写参数) | PreToolDecision + approval service | ✅ PermissionGuard 同款(ASK/DENY/auto) |
| 工具描述/空 Schema 占位 | 不允许 | ✅ 大幅收口(2026-08-29):登记层三通道收敛单源 + tools/list 补传 inputSchema + provider/scene 真描述;残留收口批 3/4 |
结论:契约主体(声明/错误/并行/权限/命名)已与 dsh 对齐;描述/Schema 已随登记层单源收敛(2026-08-29),收口项 = 存量 output 声明清偿(批 3 在途)。
九、外部工具(市场安装)的特殊说明
从能力市场安装的外部 MCP 服务器,其工具以 ext.<服务器名>.<工具名> 热挂进工具面(服务器名取目录 name,非字母数字字符转下划线)。与内置工具同走调度层与权限管线:
- 目录里声明了保留黑名单(sms.read 等)的条目会被剔除,黑名单工具外部服务器永远不可达;
level=readonly默认放行;level=write当前版本不挂出(只读先行);- token 只存用户本地,任何市场接口响应都不回显。