# ADR-0025 按 MCP 规范补齐工具以外的能力 - 状态:Accepted · 日期:2026-10-29 · 补充 ADR-0021 · 设计见 [16-mcp-support](../design/16-mcp-support.md),接入指南见 [mcp-guide](../guides/mcp-guide.md) ## 背景 网关(ADR-0021)只用到了 MCP 的工具部分:工具提示只认只读,结构化结果在有文本时被丢弃,没有长任务、询问用户、OAuth、资源与提示模板。业务方的 MCP 工具有运行一小时以上的作业,原来的做法是拆成"触发"和"查询"两个工具让模型轮询,既花 token 又不可靠;后台调用(docs/design/15)保持连接等待,服务重启或断线就失败。 ## 决策 - **只实现规范中定义的机制,不自定义协议字段。** 曾考虑在工具结果里约定 `async_job` 字段由平台代为轮询,放弃:MCP 2025-11-25 已有 Tasks,自定义字段只在本平台有效。 - **长任务用 MCP Tasks**,与后台调用合并为同一套记录、唤醒、取消与界面,只多一个"等待方式"。服务不支持 Tasks 时仍按原来的方式保持连接等待。Tasks 在规范中是实验性的,相关代码集中在 `mcp-gateway/tasks.ts`。 - **破坏性提示只认明确声明的 true**:规范中非只读工具的 `destructiveHint` 默认为 true,若据此强制审批,所有没写提示的工具在自动模式下都要审批。明确声明的工具默认"总是审批";管理员可以逐个工具覆盖提示。 - **询问用户(Elicitation)必须能确定属于哪个会话**:规范的询问请求不带发起调用的信息,因此 HTTP 服务按"服务 × 会话"建立连接;本地进程只在连接上的调用都属于同一个会话时才接受询问,否则拒绝。长任务中的询问按任务 id 找发起方。 - **OAuth 按服务共享**:管理员授权一次,所有会话共用这个账号,与请求头令牌一致;不引入"终端使用者"概念(01-requirements 中明确不做)。 - **资源由模型按需读取,或由用户附加**;不做 Profile 固定附加与资源订阅。提示模板展开后放进输入框,由用户修改后发送。 - **不做 Sampling**(服务借用平台的模型):花平台的 token,外部服务可以借此驱动模型,安全与费用难以控制。 ## 后果 - `interactions` 增加 `form` 类交互,`runId` 可以为空;Agent API / Bot API 的回复增加 `{ action, content }`,`` 增加表单与网址卡片。 - 后台调用增加 `mode`、任务 id 等字段;长任务在服务重启后继续查询(前提是服务按认证身份而不是 MCP 会话归属任务)。 - HTTP 服务的连接数从"每个服务一个"变为"每个服务 × 会话一个"(空闲 10 分钟关闭);长任务进行中占用的连接不关闭。 - 新增《MCP 接入指南》与参考服务 `examples/mcp-reference-server`,测试 `mcp-reference.test.ts` 保证两者与平台一致。