MCP

MCP 把 A3S Code session 连接到外部工具服务器。stdio server 可以加入 live session、检查状态、通过注册工具调用,并在不需要时移除。server 的工具会注册到 session 中,名称格式为 mcp__<server>__<tool>。

添加 Server

新代码优先使用 object-shaped addMcp(...) API。它直接对应 core 的 McpServerConfig 形状,避免 positional overload 的参数顺序问题。

TypeScript
const count = await session.addMcp({
name: 'echo',
transport: {
type: 'stdio',
command: process.execPath,
args: ['tools/mcp_echo_server.mjs', 'example-value'],
},
timeoutMs: 30000,
});
console.log('registered tools:', count);

Python 暴露相同的对象式 API:session.add_mcp({...})。 addMcpServer(...) / add_mcp_server(...) 和 addMcpServerConfig(...) / add_mcp_server_config(...) 仍作为兼容别名保留。

远程 server 使用嵌套 transport object,type 取 'http' 或 'streamable-http'。凭据应由宿主环境或 secret manager 注入;在生产文档或发布说明依赖前,先针对你的 server 做集成测试。

检查和移除

TypeScript
console.log(await session.mcpStatus());
console.log(session.toolNames().filter((name) => name.startsWith('mcp__')));
await session.tool('mcp__echo__echo', { message: 'docs mcp ok' });
await session.removeMcpServer('echo');

所有权与 Session 隔离

MCP capability discovery 与 live mutation 分属不同 owner:

  • Agent-global manager 持有从全局配置加载的 server。
  • 通过 Rust SessionOptions 传入的 manager 是该 session 继承的只读 capability source。
  • 每个已构建 session 都新建一个私有 manager,专门承接 live addMcp 与 removeMcpServer 操作。

Session assembly 会读取继承 source 的 tool definition,但不会把 session 配置 merge 回这些 manager。本地新增 server 可以在当前 session 内 shadow 同名的 inherited fully-qualified tool;移除本地 server 后,继承工具会重新出现。这个操作不会 unregister、disconnect 或改变 global/host-owned source,sibling session 也不会受 影响。

Delegated child 会收到有序 capability source,从而调用同一批 MCP tool,但不会 取得 owner 身份。session.close() 只断开私有 manager 的 server;agent.close() 和 disconnectIdleMcp(...) 仍负责 agent-global manager。

Rust 中,宿主传入的 MCP source 需要异步 session 构建,使 discovery 不阻塞:

Rust
let session = agent
.session_builder("/repo")
.options(SessionOptions::new().with_mcp(manager))
.build()
.await?;

Idle Disconnect

已连接的 stdio MCP server 即使处于空闲状态也会占用资源——file descriptor 和一个后台 worker。在长期运行的 cluster session 中,这些安静的 server 会越积越多。disconnectIdleMcp(CHANGELOG [3.3.0] "MCP idle disconnect")按需回收它们:断开每个最后活动时间早于阈值的全局 MCP server,释放 FD 和 worker,同时保留每个 server 已注册的 config,这样后续的 tool 调用可以按需重连。

这是一个 agent 级方法(它只作用于 agent 的全局 MCP manager,底层由 McpManager::disconnect_idle(threshold_ms) 支持)。它返回被断开的 server 名称列表。

TypeScript
// 回收空闲超过 5 分钟的 server,返回被断开的名称。
const dropped = await agent.disconnectIdleMcp(5 * 60 * 1000);
console.log('disconnected:', dropped);
Python
# 回收空闲超过 5 分钟的 server,返回被断开的名称。
dropped = agent.disconnect_idle_mcp(5 * 60 * 1000)
print('disconnected:', dropped)

运行成千上万长期 session 的 host 应通过 sweeper 周期性调用它(例如每 60s、阈值 5 分钟)。对已断开 server 的后续 tool 调用会从其保留的 config 重新建立连接——无需重新注册。

disconnect 还会清除孤儿时间戳:touch()-without-connect 的条目(为一个从未真正连接过的 server 记录的时间戳)会在每次 disconnect_idle 调用时被清扫,使活动映射在 manager 的长期生命周期内不会无限增长(CHANGELOG [3.3.0] Fixed "MCP timestamp leak")。

安全

外部 tool server 应视为特权集成,凭据只放在环境变量或宿主 secret manager 中。