1 unstable release
| 0.1.0 | Feb 2, 2026 |
|---|
#246 in #agent
Used in 5 crates
(4 directly)
24KB
461 lines
a2c-smcp
The official Rust SDK for A2C-SMCP
A2C-SMCP Rust SDK
A Rust implementation of the A2C-SMCP protocol, providing Agent, Computer, and Server components for building intelligent agent systems with tool execution capabilities.
🚀 Quick Start
Add to your Cargo.toml:
[dependencies]
a2c-smcp = { version = "0.1.0", features = ["agent", "computer"] }
Or use all features:
[dependencies]
a2c-smcp = { version = "0.1.0", features = ["full"] }
📦 Features
- agent - Agent client for connecting to SMCP servers and calling tools
- computer - Computer client for managing MCP servers and desktop resources
- server - Server implementation with Socket.IO support
- full - Enables all features
📜 协议规范
A2C-SMCP 协议规范已拆分为独立仓库,支持多语言 SDK 开发。
- 协议仓库: a2c-smcp-protocol
- 当前协议版本: 0.1.2-rc1
开发时参考路径:
- 协议规范:
a2c-smcp-protocol/specification/ - Python 参考实现:
python-sdk/a2c_smcp/
📋 Project Structure
This is a real workspace with a main package that aggregates sub-crates:
rust-sdk/
├── src/ # Main package entry point (re-exports based on features)
├── tests/ # Cross-crate integration tests
├── crates/
│ ├── smcp/ # Core protocol types
│ ├── smcp-agent/ # Agent implementation
│ ├── smcp-computer/# Computer implementation
│ ├── smcp-server-core/ # Server core logic
│ └── smcp-server-hyper/ # Hyper adapter for server
└── Cargo.toml # Workspace + main package configuration
本仓库目标:使用 Rust 实现 A2C-SMCP 协议,并对齐 python-sdk 的能力边界与使用体验。
本 README 给出 Rust SDK 的技术选型与实现路线,并明确当前版本的能力边界。
1. 背景与协议轮廓(来自 python-sdk)
Python 参考实现中,A2C-SMCP 的最核心抽象是三大模块:
- Computer:管理 MCP Servers、聚合工具列表与桌面资源;并负责接收来自 Agent 的工具调用请求、执行工具并返回结果,同时向 Server 上报更新。
- Server:中心信令服务,负责会话管理、转发调用、广播通知。
- Agent:业务侧智能体客户端,通过协议事件调用 Computer 的工具。
传输层:python-sdk 选择 Socket.IO 做实时通信(带 namespace 与 room),并定义了 SMCP_NAMESPACE = /smcp。
事件命名规范(来自 python-sdk/a2c_smcp/smcp.py):
client:*:由 Agent 发起、由 Server 转发到特定 Computer 执行(例如client:tool_call、client:get_tools、client:get_desktop)。server:*:由 Computer/Agent 发起,Server 负责执行并转换为通知(例如 join/leave office、update desktop/config、cancel tool call)。notify:*:只由 Server 发出,向 room 广播状态变更(例如 enter/leave office、update config/tool list/desktop)。
Rust 版本以 smcp.py 的事件与数据结构为“权威源”,优先保证互通与行为一致,再逐步补齐 Computer/CLI/Desktop 等高级能力。
2. Rust 技术选型
2.1 异步运行时
- Tokio
- 选择理由:
- Rust 网络生态与 Socket.IO/WebSocket/HTTP client-server 基本都以 Tokio 为默认运行时。
- 便于统一 Server 与 Agent/Computer 客户端的并发模型。
2.2 Server 端框架:Socket.IO 紧绑定 + HTTP 承载层可插拔
Python 版本最小集成示例是 FastAPI + python-socketio(ASGI)。从 SMCP 视角:
- 实时通信层固定使用 Socket.IO(namespace/room/ack/notify)。
- 消息格式当前只支持 JSON(
serde_json)。 - HTTP 不等于必须提供 REST API;它主要作为 Socket.IO 的承载监听器,用于握手、升级(WebSocket)、以及 long-polling 回退。
为了保持“开源协议 SDK”依赖最小且方便使用者集成:
- Socket.IO Server:socketioxide(紧绑定,不可替换)。
socketioxide是当前 Rust 生态中唯一成熟的 Socket.IO Server 实现,SDK 直接依赖它。- 它通过 Tower Layer/Service 模式工作,天然支持与多种 HTTP 框架集成。
- HTTP 承载层默认:Hyper(最小依赖/最通用)。
- HTTP 承载层可替换:
socketioxide可作为 Tower Layer 嵌入任何 Tower 兼容框架(Axum/Salvo/Viz 等),使用者可以在自己的项目中选择框架。
2.3 Socket 客户端(Agent/Computer 模块)
Agent/Computer 需要连接 Server,并支持:
- connect with headers/auth
- emit/call(ack)
- on notify events
- room(office_id)管理
Rust 侧采用:
- tf-rust-socketio(客户端)
- 注意:
socketioxide是纯 Server 端实现,不提供客户端功能。Agent/Computer 作为客户端使用tf-rust-socketiocrate(基于rust_socketio增加了 ACK 响应支持)。 - 支持点(来自 docs.rs):
- namespace:
ClientBuilder::namespace("/smcp");但一个 socket 只能连接一个 namespace,多 namespace 需要多个 socket。 - ack + timeout:
emit_with_ack(event, data, Duration, callback),可按每次调用设置超时。 - reconnect/backoff:提供开关与参数:
reconnect(true)/reconnect_on_disconnect(true)reconnect_delay(min, max)(最小/最大重连间隔)max_reconnect_attempts(n)(最大重试次数)
- headers/auth:支持
opening_header(k, v)与auth(json!),可对齐 Python 端的 header api-key 与 auth payload。
- namespace:
- 注意点:
- async 版本需要开启 feature
async,且文档标注当前 async 实现处于 beta,接口可能变化。
- async 版本需要开启 feature
- 需要在正式开发前验证
tf-rust-socketio与socketioxide的互通性(见tests/e2e/)。
2.4 序列化 / 类型校验
Python 版大量使用 TypedDict/Pydantic 做校验。Rust 端遵循“一切从简”原则:优先保证协议载荷能稳定反序列化为结构化数据。
- serde + serde_json:作为 wire format 的默认实现(与 Socket.IO JSON payload 最契合),并承担“反序列化即结构校验”的职责。
- 类型建模策略:
- 协议结构体使用
#[derive(Serialize, Deserialize)] - 事件 payload 尽量用强类型,而不是
serde_json::Value
- 协议结构体使用
- 类型边界划分(方案 C):
smcpcrate:只放协议层公共类型(事件常量、AgentCallData、ToolCallReq、GetToolsReq/Ret、EnterOfficeReq等跨角色共享的协议结构)smcp-computercrate:放 Computer 专属配置类型(如MCPServerConfig、MCPServerStdioConfig等)smcp-agentcrate:放 Agent 专属类型(如AgentEventHandler)
说明:工具侧的 params_schema/return_schema 在本 SDK 中以 MCP Tools 的 schema 为准,当前仅做透传,不在 SDK 内生成或做额外 schema 校验。
2.5 错误处理
- thiserror:定义
SmcpError等错误枚举。 - anyhow:应用层(CLI/示例)快速聚合错误。
- 错误边界:
- SDK 层对外暴露稳定的
Result<T, SmcpError> - CLI/示例使用
anyhow::Result<()>即可。
- SDK 层对外暴露稳定的
2.6 日志与可观测性
- tracing + tracing-subscriber
- 原因:异步场景的结构化日志更适合排查事件流(尤其是 room 广播、ack 超时、重连)。
2.7 CLI(Computer 模块)
Python 版 Computer 侧提供交互式 CLI(添加 server、start/stop、status、socket connect/join、notify update)。
Rust 端采用:
- clap:命令行参数解析(只负责 args/subcommands,不负责交互能力)。
- pexpect 级交互:使用 expectrl 实现“spawn + PTY + expect/send”风格的交互控制;比直接用管道读写的 subprocess 方式更适合做强交互 CLI。
- 颜色与终端能力:
- 轻量彩色输出:
owo-colors(或兼容生态的anstyle体系) - 终端事件与渲染基础:
crossterm-(可选)更强交互体验: - TUI:
ratatui(基于crossterm) - 行编辑/补全:
reedline/rustyline(如需类似 shell 的输入体验)
- 轻量彩色输出:
2.8 测试策略
- 单元测试:协议结构体序列化/反序列化、事件路由与权限校验。
- 集成测试:起一个内嵌 Server(Socket.IO),用 Agent/Computer 客户端对打,覆盖:
- join office → notify enter_office
- get_tools / tool_call 的转发与 ack
- update_desktop 广播与 Agent 拉取
- 端到端(e2e):对齐 python 版的测试思路。
目录与文件组织(真实 Workspace 规范)
重要:本仓库采用真实 workspace(同时有
[workspace]和[package]段)。 根目录包a2c-smcp作为主入口,可以包含src/和tests/目录。
-
单元测试(unit tests)
- 放置位置:各 crate 的
src/**内#[cfg(test)] mod tests { ... }。 - 适用范围:纯函数/结构体方法、序列化/反序列化、错误映射、事件名称与 payload 组装等。
- 组织规范:
- 每个模块自己带测试,避免依赖真实网络/真实进程。
- 使用“表驱动”测试(
cases: Vec<(input, expected)>)来覆盖边界条件。 - 公共测试工具函数放到
src/test_utils.rs或src/test_utils/mod.rs(仅在cfg(test)下编译)。
- 放置位置:各 crate 的
-
集成测试(integration tests)
- 放置位置:
- 根目录
tests/:跨 crate 联合测试(如 Agent + Computer + Server) - 各 crate 的
tests/目录:单个 crate 的 API 测试 - 文件名按场景:join_leave.rs、tool_call_ack.rs、socketio_interop.rs。 - 文件名按场景:
full_stack.rs、agent_computer.rs、socketio_interop.rs。 - 测试函数按行为:
test_full_stack_integration()。
- 根目录
- 约束建议:
- 网络端口使用
127.0.0.1:0自动分配,避免 CI 冲突。 - 用超时(
tokio::time::timeout)包裹等待,避免卡死。 - 共享 fixtures 放到
tests/common/mod.rs。 - 使用
skip_if_no_feature!宏根据 features 跳过测试。 - 用超时(tokio::time::timeout)包裹等待,避免卡死。 - 共享 fixtures 放到 crate 内的
tests/common/mod.rs。
- 网络端口使用
- 放置位置:
-
端到端测试(e2e tests)
- 放置位置:根目录
tests/e2e/(如果需要更慢、更依赖环境的测试)。 - 适用范围:跨进程/跨组件的真实链路(例如启动 Computer 管理 MCP stdio server)。
- 组织规范:
- 依赖外部二进制(如
npx、真实 MCP server)要做可跳过策略。 - 产物(临时目录、日志)统一写到
target/tmp/<test_name>/。 ```
- 依赖外部二进制(如
- 运行方式:
cargo test -p smcp-e2e-tests - 组织规范:
- 依赖外部二进制(如
npx、真实 MCP server)要做可跳过策略(例如环境变量开关)。 - 产物(临时目录、日志)统一写到
target/tmp/<test_name>/。
- 依赖外部二进制(如
- 放置位置:根目录
3. 已确定的技术约束(Design Decisions)
3.1 传输层:必须 Socket.IO
本 SDK 的实时通信层固定使用 Socket.IO(对齐 python-sdk 的语义:namespace/room/ack/notify)。不考虑替换为 WebSocket/gRPC 等其它传输。
3.2 HTTP 承载层:最小依赖 + 可插拔
Socket.IO 在工程实现上需要一个 HTTP 监听器作为承载(握手、升级、long-polling)。为了保证依赖最小并方便使用者集成:
- 默认使用 Hyper 作为承载层(最小依赖/最通用)。
- SDK 设计应将“承载层”抽象为可替换接口/适配层:
- 使用者可以在自己的项目中选择 Axum/Actix/Salvo 等框架,并把请求转发给 Socket.IO handler。
- 本 SDK 不强制绑定任何具体 Web 框架。
3.3 消息格式:仅支持 JSON
当前版本只支持 JSON payload(serde_json),不支持二进制消息与大对象流式传输。后续若要支持图片/资源流,应通过独立通道或资源接口设计,而非在本版本内扩展。
4. Rust 端实现路线
路线按“先互通、再补齐”,避免一开始就把 Computer/CLI/Desktop 全部做完。
4.1 Milestone 1:协议与类型层(smcp)
- 定义
SMCP_NAMESPACE与全部事件常量(与smcp.py对齐) - 定义核心 payload:
AgentCallData、ToolCallReq、GetToolsReq/RetEnterOfficeReq、LeaveOfficeReqUpdate*Notification、ListRoomReq/Ret
- 统一
req_id生成策略(UUID)
4.2 Milestone 2:Server 最小实现(转发 + 广播)
- 核心原则:Socket.IO 层紧绑定 socketioxide,HTTP 承载层可插拔
- Server 核心逻辑依赖 Tokio +
socketioxide+ 协议类型;socketioxide是唯一的 Socket.IO 实现,不可替换。
- Server 核心逻辑依赖 Tokio +
socketioxide通过 Tower Layer/Service 模式工作,天然支持与 Axum/Salvo/Hyper 等框架集成。- 提供一个最小默认承载实现(Hyper),并将其作为“示例/默认 adapter”。使用者可以选择其他 Tower 兼容框架。
- 会话管理:sid ↔ name ↔ role ↔ office_id(类似 python
BaseNamespace) - 事件与语义:
server:join_office/server:leave_office→ 广播notify:*client:get_tools/client:get_desktop/client:tool_call→ 转发到指定 Computer 并等待 ackserver:update_desktop/server:update_config/server:update_tool_list→ 广播notify:update_*
- 鉴权:先实现 header api-key(对齐 Python
DefaultAuthenticationProvider),后续再扩展。 - 工程化约束:
- 统一对 ack/转发等待加 timeout,避免请求悬挂。
- handler 内只处理 JSON payload(
serde_json),不引入二进制分支。
4.3 Milestone 3:Agent 客户端最小实现
- connect(headers/auth)
- join_office
- emit_tool_call(带 timeout + cancel)
- 订阅
notify:*并提供回调接口
4.4 Milestone 4:Computer 客户端最小实现
- 提供 get_tools、tool_call、get_desktop 的事件处理(被 Server call)
- 支持上报 update_desktop/tool_list/config
5. 与 MCP 的关系(对齐 python-sdk)
Python 版在 Agent 侧返回 mcp.types::CallToolResult 风格的数据结构,并在 Computer 侧管理多种 MCP Server(stdio/sse/streamable)。
Rust 端先把 SMCP 的“信令与工具调用转发”跑通;MCP Server 管理(stdio/sse)按分层实现:
computer::mcp_manager:进程管理、连接管理computer::tool_registry:工具聚合与去重(解决 tool name 冲突,可对齐ToolMeta.alias思路)computer::desktop:window:// 资源聚合(后续迭代)
当前实现状态(截至 2025-12-25)
✅ 已完成的 Milestone
Milestone 1:协议与类型层(smcp) - 100% 完成
- ✅ 定义
SMCP_NAMESPACE与全部事件常量(与smcp.py对齐) - ✅ 定义核心 payload 类型(
AgentCallData、ToolCallReq/Ret、GetToolsReq/Ret等) - ✅ 统一
req_id生成策略(UUID v4 hex 格式) - ✅ 完整的序列化/反序列化测试覆盖
Milestone 2:Server 最小实现(转发 + 广播) - 100% 完成
- ✅
smcp-server-core:核心逻辑实现(会话/路由/鉴权) - ✅
smcp-server-hyper:默认 Hyper 承载适配器 - ✅ Socket.IO 层紧绑定
socketioxide - ✅ HTTP 承载层可插拔设计(Tower Layer/Service 模式)
- ✅ 会话管理(sid ↔ name ↔ role ↔ office_id)
- ✅ 事件处理:
join_office/leave_office→ 广播notify:* - ✅ 事件转发:
get_tools/get_desktop/tool_call→ 转发到指定 Computer 并等待 ack - ✅ 鉴权:header api-key(
DefaultAuthenticationProvider) - ✅ 完整的超时与错误处理
Milestone 3:Agent 客户端最小实现 - 100% 完成
- ✅
smcp-agentcrate:完整实现 - ✅ 支持 async 和 sync 两种模式(
AsyncSmcpAgent、SyncSmcpAgent) - ✅ connect(headers/auth)
- ✅ join_office/leave_office
- ✅ emit_tool_call(带 timeout + cancel)
- ✅ 订阅
notify:*事件并提供回调接口 - ✅ 完整的配置、认证、事件处理系统
- ✅ 基于
tf-rust-socketio的传输层实现
Milestone 4:Computer 客户端最小实现 - 100% 完成
- ✅
smcp-computercrate:完整实现 - ✅ get_tools/tool_call/get_desktop 事件处理
- ✅ update_desktop/tool_list/config 上报
- ✅ Socket.IO 客户端连接与会话管理
✅ 额外已完成的功能
MCP Server 管理 - 90% 完成
- ✅
mcp_clients/manager:进程管理与连接管理 - ✅ MCP 客户端实现:HTTP、SSE、Stdio 三种传输方式
- ✅ 工具聚合与去重(
tool_registry) - ✅ 配置管理(
MCPServerConfig,支持 stdio/sse/http) - ✅ 输入系统:CLI、Environment、Command 三种输入提供者
- ✅ VRL runtime 支持(可选特性)
- ✅ 缓存机制
Desktop 管理与资源聚合 - 80% 完成
- ✅
desktop/模块:window:// 资源解析与聚合 - ✅
WindowURI解析器(priority/fullscreen/路径) - ✅ 桌面组织算法(按 priority、fullscreen、history 排序)
- ✅ 窗口详情获取
- ⚠️ 实时订阅更新机制(部分完成)
CLI 工具 - 85% 完成
- ✅ 基于
clap的命令行参数解析 - ✅ 交互式 shell(基于
expectrl) - ✅ 核心命令:add/remove/list servers, start/stop client, status
- ✅ 配置管理(load/save/show)
- ✅ 工具调用历史记录
- ⚠️ 完整的 PTY 交互控制(进行中)
测试覆盖 - 95% 完成
- ✅ 341 个测试用例全部通过
- ✅ 单元测试:各 crate 内部的
#[cfg(test)]模块 - ✅ 集成测试:
tests/full_stack.rs(Agent + Computer + Server) - ✅ Socket.IO 互通性测试
- ✅ MCP 客户端测试(HTTP/SSE/Stdio)
- ✅ Desktop 组织算法测试
- ✅ CLI 命令测试
- ⚠️ E2E 测试(需要外部依赖,部分跳过)
- ✅ Clippy lint 检查通过(无警告)
- ✅ 代码格式化完成(
cargo fmt)
代码统计
- 总代码量:约 15,000+ 行 Rust 代码
- Crates 结构:5 个核心 crates(
smcp,smcp-agent,smcp-computer,smcp-server-core,smcp-server-hyper) - 测试覆盖:单元测试 + 集成测试 + E2E 测试
下一步(2025 Q1)
优先级 1:核心功能完善
-
完善 Desktop 资源订阅与实时更新
- 实现
resources/subscribe和resources/unsubscribe的完整流程 - 处理 SSE 长轮询的实时更新
- 优化缓存失效策略
- 实现
-
工具调用取消机制
- 实现
server:tool_call_cancel的完整处理流程 - 支持超时自动取消
- 支持客户端主动取消请求
- 实现
-
错误处理与恢复增强
- 完善 MCP Server 断线重连机制
- 增强错误恢复策略(exponential backoff)
- 添加更详细的错误上下文信息
-
性能优化
- 优化工具调用并发处理
- 减少不必要的序列化/反序列化开销
- 优化大量 window:// 资源的组织算法
优先级 2:生产就绪
-
文档完善
- API 文档(rustdoc)完善
- 使用指南与最佳实践
- 故障排查文档
- 示例代码(examples/)
-
可观测性增强
- 结构化日志(tracing)完善
- Metrics 收集(prometheus/client)
- 分布式追踪支持(可选 opentelemetry)
-
安全性增强
- Secret 管理(避免硬编码 api-key)
- TLS/SSL 支持
- 输入验证增强
- Rate limiting 机制
优先级 3:生态扩展
-
额外框架适配器(按需)
- 评估并提供
server-axumadapter - 评估并提供
server-actix-webadapter - 保持核心依赖最小与承载层可替换原则
- 评估并提供
-
高级 Desktop 特性
- 跨进程 window:// 资源共享
- Desktop 快照与恢复
- 窗口状态持久化
-
部署与运维
- Docker 镜像构建
- Kubernetes 部署示例
- 健康检查与就绪探针
- 配置管理最佳实践
Dependencies
~0.8–1.7MB
~35K SLoC