v0.2 协议升级指南¶
协议版本:0.1.x → 0.2.0 目标读者:python-sdk / rust-sdk 实现工程师 发布节奏:破坏性升级,需同步发布三方(Agent / Computer / MCP Server helper)
DPE 已独立为单独协议(2026-05-08)
v0.2 早期草案曾把 DPE(Document-Page-Element)内嵌进 A2C-SMCP(dpe:// URI、client:get_dpe 事件、4011/4012/4013 错误码、Resolver Hook、双 mimetype 等),后判断该模块与 A2C-SMCP 控制面属性不匹配,已从本协议全量移除。客户端实现请直接对接独立的 DPE 协议,不再走 A2C-SMCP 通道。
本指南只覆盖 v0.2 中保留的非 DPE 改动:Window URI 纯标识符化、协议版本握手、错误码扩展(4006/4007/4008/4014/4015)、priority 类型变更等。
Greenfield 阅读提示
本指南默认 SDK 已实现 v0.1 完整功能并据此描述"迁移路径"。如果你所维护的 SDK 从未实现某个子系统(典型如 Window URI 解析器),那么相关章节应按 Greenfield 实现规范阅读:旧形式作反面参考,新形式 + 行为约束作目标。
1. 摘要¶
v0.2 是一次破坏性协议升级,包含五组保留改动:
- Window URI 纯标识符化:
window://不再携带元数据 query;元数据下沉到 MCPResource.annotations+Resource._meta - 协议版本握手:引入 Socket.IO connect 阶段的版本校验机制(详见 versioning.md);4008 显式定义为 HTTP body code,不是 WS close code
- MCP Server host 跨 Server SHOULD 唯一(注册期记 WARN,不阻塞)
- client:get_resources 新增:透明转发 MCP 标准
resources/list给 Agent(含 cursor 翻页),用于 Window 等资源发现 - 错误码扩展:新增
4006/4007/4008/4014/4015;4001 描述收紧
核心改动一句话版¶
- Window URI 变成纯标识符——元数据通过 MCP
Resource.annotations/_meta声明 - 新增
client:get_resources——Agent 通过它发现 Computer 上各 MCP Server 的资源 - Socket.IO 连接必带 URL query
?a2c_version=0.2.0;Server HTTP 中间件校验,不兼容时返回 HTTP 400 +X-A2C-Error-Code: 4008header + body - MCP Server host 跨 Server SHOULD 唯一(lint-style 引导,不阻塞注册)
- 元数据字段分工:MCP 标准
annotations(priority/audience/lastModified)MUST 放入annotations;A2C 自定义字段(fullscreen/keywords等)放入_meta
2. 受影响范围¶
2.1 代码影响矩阵¶
本表只描述"职能模块"——具体文件路径由各 SDK 自决。
| 职能模块 | 职责契约 | 说明 |
|---|---|---|
| WindowURI 解析器 | window:// URI 解析 + 校验 |
移除 priority / fullscreen query 解析;含 query 时按分层处理(Agent 构造层失败 / Computer 解析层 WARN 丢弃) |
| Desktop 组织职能 | 按 audience / priority 整理 windows,按 size 截断 | 从 Resource.annotations.priority 读优先级(float [0,1],不再是 int [0,100]);Resource._meta.fullscreen 读全屏标记 |
| client:get_resources 处理 | 透明转发 MCP resources/list |
必填 mcp_server,Computer 不做协议级过滤;不返回 resourceTemplates |
| 协议版本中间件 | Socket.IO connect 阶段校验 a2c_version |
不兼容时返回 HTTP 400 + X-A2C-Error-Code: 4008 |
| 错误处理器 | 新增 4006/4007/4008/4014/4015 处理 |
见 error-handling.md |
2.2 非代码影响¶
- 现有 v0.1 部署的 MCP Server 必须升级以适配元数据下沉与 host 风格建议
- Agent / Computer SDK 必须同步升版(HTTP 握手层 a2c_version 不兼容直接断连)
2.3 不变的部分¶
- Socket.IO 三角色架构、房间模型、
server:*/notify:*事件 - 工具调用(
client:tool_call+ MCPCallToolResult) - Desktop 桌面系统的整体行为(仅元数据来源变化)
3. 破坏性变更详表¶
| 变更 ID | 范围 | 旧形式 | 新形式 |
|---|---|---|---|
| W1 | Window URI | window://host/path?priority=5&fullscreen=1 |
window://host/path |
| W2 | priority 类型 | int [0, 100] |
float [0, 1] |
| W3 | fullscreen 来源 | URI query | Resource._meta.fullscreen |
| W4 | priority 来源 | URI query | Resource.annotations.priority |
| H1 | host 唯一性 | 未约束 | 跨 Server SHOULD 唯一(不符合时 WARN) |
| V1 | 协议版本 | 无显式协商 | URL query a2c_version 必带;HTTP 握手校验 |
| E1 | 错误码 4001 | 通用 "Tool Not Found" | 描述收紧为"工具调用前的查找失败"——执行失败用 4003 |
| E2 | 错误码新增 | — | 4006 / 4007(MCP 上游授权)+ 4008(HTTP 握手 body code)+ 4014 / 4015(MCP 路由) |
| R1 | client:get_resources | 不存在 | 新增;透明转发 resources/list |
4. 详细变更规范¶
4.1 Window URI 重构¶
URI 语法¶
校验规则¶
scheme固定windowhost不能为空(推荐反向域名风格)path0..N 段,URL 编码- 不允许 query / fragment:Agent SDK 构造层硬错误;Computer 解析层容错丢弃 + WARN
元数据声明(MCP Server 在 resources/list 响应中设置)¶
# 旧(v0.1)
{
"uri": "window://com.example.app/main?priority=8&fullscreen=1",
"name": "Main Window"
}
# 新(v0.2)
{
"uri": "window://com.example.app/main",
"name": "Main Window",
"annotations": {
"priority": 0.8, # float [0, 1]
"audience": ["assistant"], # MUST 标识 assistant
"lastModified": "2026-04-12T08:30:00Z"
},
"_meta": {
"fullscreen": true # A2C 扩展
}
}
Desktop 组织职能行为变更¶
organize_desktop 函数读取数据源从 URI query 改为 Resource annotations / _meta。算法本身不变——按 audience 过滤、按 priority 排序、按 size 截断。
4.2 MCP Server host 唯一性¶
v0.2 软约束:跨 MCP Server host SHOULD 唯一;冲突时 Computer 在注册阶段记 WARN,不阻塞注册。
设计取向¶
- v0.2 不强制硬约束,避免阻断既有部署的 MCP Server 上线
- host 推荐使用反向域名风格(如
com.example.editor)以天然回避冲突 - 客户端 desktop 组织算法按 MCP Server 名称分组、不强依赖 host 唯一
4.3 错误码扩展¶
MCP 上游授权(4006 / 4007)¶
| 码 | 名称 | 触发 |
|---|---|---|
| 4006 | Tool Authorization Required | 工具需要 MCP 上游授权(如 OAuth 2.0),Computer 当前无有效凭证 |
| 4007 | Tool Authorization Failed | MCP 上游授权流程失败、Token 已失效、刷新失败、或权限不足 |
详见 error-handling.md 的判定决策表。
MCP Server 路由(4014 / 4015)¶
| 码 | 名称 | 触发 |
|---|---|---|
| 4014 | MCP Server Not Found | 客户端事件引用的 mcp_server 名字未注册 |
| 4015 | MCP Capability Not Supported | MCP Server 已注册但未声明所需 capability |
4001 描述收紧¶
| 旧 | 新 |
|---|---|
Tool Not Found:工具调用相关失败的兜底码 |
Tool Not Found:工具调用前的查找失败(不存在 / 已下线);执行失败用 4003 Tool Execution Failed |
4.4 协议版本握手¶
为什么选 URL query¶
- WebSocket 握手阶段无 body 可读
- HTTP middleware 可在升级到 WebSocket 前完成校验,节省连接建立成本
- URL query 与 cookie / header 同样在 connect 阶段可读,且不与业务字段冲突
客户端¶
# Python reference impl
from socketio import AsyncClient
sio = AsyncClient()
await sio.connect("https://server.example.com/?a2c_version=0.2.0", transports=["websocket"])
Server¶
Socket.IO HTTP 中间件层校验 a2c_version:
- 缺失 → HTTP 400 + X-A2C-Error-Code: 4008 + body {"code": 4008, "message": "missing a2c_version"}
- 不兼容 → HTTP 400 + 同上 header + body 内附 server_version / min_supported / max_supported
4008 显式定义为 HTTP body code¶
不是 WebSocket close code(WS close code 范围有限且语义混淆)。SDK 收到 HTTP 400 + 4008 后必须主动 disconnect,不再尝试 WS upgrade。
4.5 client:get_resources(新增)¶
透明转发 MCP resources/list 给 Agent,用于 Window 等资源发现。详见 events.md - client:get_resources。
5. 迁移步骤¶
5.1 MCP Server 实现者¶
- 移除 URI 中的 query 参数(
window://不再携带 priority / fullscreen) - 在
resources/list响应中通过annotations/_meta声明元数据 - priority 改为 float [0, 1](按语义重新映射,如 v0.1 的
8/100-style 映射到0.08通常是错的;按真实优先级语义映射到0.8) - 检查 host 是否符合反向域名风格
5.2 Computer SDK 工程师¶
- WindowURI 解析器移除 query 解析路径
- organize_desktop 数据源从 URI 改为
Resource.annotations/_meta - 实现
client:get_resources透明转发(含 cursor 翻页) - 注册 host 冲突检测,记 WARN(不阻塞)
- 实现
?a2c_version中间件校验
5.3 Agent SDK 工程师¶
- WindowURI 构造时不再附加 query
- priority 字段读取从 URI query 改为
Resource.annotations.priority - 处理
client:get_resources响应(含 cursor 翻页) - 处理新错误码(4006 / 4007 / 4008 / 4014 / 4015)
- Socket.IO 连接 URL 必带
?a2c_version=0.2.0
6. 测试矩阵¶
6.1 URI 解析器(Computer 解析层 — 容错丢弃)¶
- ✅
window://host/path解析成功 - ✅
window://host/path?priority=5Computer 端容错丢弃 query + WARN,不返回 4012/4001 类硬错 - ❌ Agent SDK 构造时附 query → 构造层硬错误
6.2 organize_desktop¶
与 v0.1 保持算法一致,仅元数据来源变化。测试用例:从 v0.1 的 URI query 切换到 Resource annotations / _meta 后输出顺序应一致。
6.3 client:get_resources(资源发现)¶
- ✅ 调用合法 MCP Server 返回
{resources, next_cursor} - ✅ cursor 翻页正确处理
- ❌ 引用未注册 server →
4014 MCP Server Not Found - ❌ MCP Server 不支持
resourcescapability →4015 MCP Capability Not Supported
6.4 协议版本握手¶
- ✅ 兼容版本 → connect 成功
- ❌ 缺
a2c_version→ HTTP 400 + 4008 - ❌ 不兼容版本 → HTTP 400 + 4008 + 服务器版本范围
- ✅ Client 收到 4008 后主动 disconnect,不再尝试 WS upgrade
7. priority int [0,100] → float [0,1] 迁移¶
换算对照表¶
| v0.1(int [0, 100]) | v0.2(float [0, 1]) | 语义 |
|---|---|---|
| 100 | 1.0 | 最高优先级 |
| 80 | 0.8 | 高 |
| 50 | 0.5 | 中 |
| 30 | 0.3 | 低 |
| 0 | 0.0 | 最低 |
不存在自动迁移工具——SDK 必须在加载 v0.1 数据时显式转换。
8. 兼容性策略¶
8.1 协议层:硬切换¶
v0.2 不向后兼容 v0.1。Socket.IO connect 阶段 a2c_version 不匹配直接断连。
8.2 不内建 v0.1 MCP Server fallback¶
部署侧需先升级 MCP Server 再升级 Computer / Agent。
8.3 升级顺序建议¶
- 先升 MCP Server——更新 URI 与元数据声明形态(最先发布也最容易回滚)
- 再升 Computer——支持新 URI 解析、新事件、版本握手
- 最后升 Agent——发布新 SDK 版本
9. 联系与反馈¶
- 协议仓库:github.com/A2C-SMCP/a2c-smcp-protocol
- python-sdk:github.com/A2C-SMCP/python-sdk
- rust-sdk:github.com/A2C-SMCP/rust-sdk
- DPE 协议(独立仓库):github.com/A2C-SMCP/dpe-protocol
- 实现疑问 / 跨 SDK 不一致 / 协议歧义 → 在协议仓库开 issue