搜索文档

浏览 Awaken Agents 文档
Docs/Awaken Agentsv1.0.0-dev/内部机制/理解系统使用 MCP Tools
提示·你正在阅读发布前文档(v1.0.0-dev)。接口与行为在稳定发布前仍可能变化。

内部机制 · 理解系统

使用 MCP Tools

本页内容

当你想连接外部 Model Context Protocol(MCP)server,并把它们的工具暴露给 awaken agent 时,使用本页。

当你想连接外部 Model Context Protocol(MCP)server,并把它们的工具暴露给 awaken agent 时,使用本页。

前置条件

  • 一个可运行的 awaken agent 运行时(见第一个 Agent
  • Cargo.toml 中添加 awaken-ext-mcp crate
  • 一个可连接的 MCP server(stdio 或 streaming-HTTP 传输)
[dependencies]
awaken-runtime = { git = "https://github.com/AwakenWorks/awaken" }
awaken-ext-mcp = { git = "https://github.com/AwakenWorks/awaken" }
tokio = { version = "1", features = ["full"] }
serde_json = "1"

MCP 工具被作为普通的 RawTool 实例导入,因此它们与任何内置工具一样,流经同一条 gate、executor 和 context 路径。每个被导入的工具会得到一个 id mcp__{server}__{tool}awaken_ext_mcp::to_tool_id),而一个 server 的工具共享能力命名空间 mcp__{server}__

步骤

  1. 打开一个到 server 的传输。

一个传输是通往某个 MCP server 的连线。用 StdioTransport 派生一个子进程,或用 HttpTransport 连接一个运行中的 streaming-HTTP server。

use std::sync::Arc;
use awaken_ext_mcp::{StdioTransport, McpToolTransport, DEFAULT_TIMEOUT};

// Stdio transport: spawn `command args...` and complete the MCP handshake.
let stdio = StdioTransport::connect(
    "npx",
    &["-y".into(), "@modelcontextprotocol/server-everything".into()],
    DEFAULT_TIMEOUT,
)
.await
.expect("spawn + handshake");

let transport: Arc<dyn McpToolTransport> = Arc::new(stdio);
  1. 发现 server 的工具。

connect_tools 把 server 的工具列出一次,并把每个包装成一个 awaken 工具。它返回一个 McpConnection,其中同时持有可执行的 toolsArc<dyn RawTool>)和它们面向模型的 descriptorsToolDescriptor)。

use awaken_ext_mcp::connect_tools;

let conn = connect_tools("everything", transport)
    .await
    .expect("discover tools");

for tool in &conn.tools {
    println!("discovered: {}", tool.id()); // e.g. mcp__everything__echo
}
  1. 把工具注册进运行时和 agent。

with_tool 把每个可执行工具安装到 Runtime 上,并把匹配的描述符交给 agent 的 ExecutableAgentSnapshot,好让模型看到它们。

use awaken_runtime::Runtime;
use awaken_runtime_contract::snapshot::ExecutableAgentSnapshot;
use awaken_runtime_contract::resolved::ModelBinding;

// Build a runtime as in [Add a Plugin](/docs/agents/runtime/how-to/add-a-plugin/), then
// register the discovered tools:
let mut runtime = Runtime::new().with_llm(llm);
for tool in conn.tools {
    runtime = runtime.with_tool(tool);
}

let config = ExecutableAgentSnapshot::builder("mcp-agent")
    .instructions("Use MCP tools when they help answer the user.")
    .model(ModelBinding::new("anthropic", "claude-sonnet", "anthropic"))
    .tools(conn.descriptors)
    .build();
  1. 用一个实时插件跟踪变化中的工具集(可选)。

connect_tools 是一次性的快照。当一个 server 可能在运行时增删工具 (tools/list_changed)时,改用 McpServer:它持有一个在后台刷新的实时工具注册表, 并把它投影为一个插件。

use std::sync::Arc;
use awaken_ext_mcp::{McpServer, StdioTransport};
use awaken_runtime_contract::plugin::Plugin;

let stdio = StdioTransport::connect("node", &["server.js".into()], DEFAULT_TIMEOUT)
    .await
    .expect("spawn");
let server = McpServer::connect_stdio("my-server", stdio)
    .await
    .expect("start + subscribe list_changed");

// The plugin's id is `mcp:{server}` — list it in the agent's plugin ids.
let plugin = server.plugin();
let runtime = Runtime::new()
    .with_llm(llm)
    .with_plugin(Arc::new(plugin) as Arc<dyn Plugin>);

let config = ExecutableAgentSnapshot::builder("mcp-agent")
    .instructions("Use MCP tools when they help answer the user.")
    .model(ModelBinding::new("anthropic", "claude-sonnet", "anthropic"))
    .plugins(["mcp:my-server".into()])
    .build();

McpPlugin 在 agent 每次解析时重新投影当前的注册表。因为该插件公布了 mcp__my-server__ 能力命名空间,它的动态工具在插件的能力 bound 下被准入。注册表版本 的一次变化向驱动循环发信号,让它在下一个步骤边界重新解析;进行中的 run 保持它们解析 时所用的工具集。

这套动态工具表面只有一个 owner:插件的 live_version 在下一个 step 边界驱动工具重算。

高级开发钩子

先使用 StdioTransport / HttpTransportconnect_tools / McpServer。只有当宿 主需要自定义的连线或策略时才下探到更低层:

  • 为一个非标准传输实现 McpToolTransport
  • 当 MCP server 要求客户端通过宿主模型 provider 进行 sampling 时,提供一个 SamplingHandler(通过 StdioTransport::connect_with_sampling);
  • McpServer::start_with_sensitive 上声明 SensitiveFields,使敏感的参数路径在每 次注册表加载时被标记(并脱敏);
  • 让注册表快照保持显式,使进行中的 run 不会看到变化中的工具目录。

验证

  1. 运行 agent,并让它使用由 MCP server 提供的一个工具。
  2. 检查后端日志里的 MCP 工具调用事件。
  3. 确认工具返回一个 ToolOutput,其 content 携带 server 的结果,且成功时 is_errorfalse

常见错误

症状原因修复
McpError::Transport(..)MCP server 未运行或不可达验证 server 进程在运行,且路径/URL 正确
没有发现工具server 返回了空的工具列表检查 MCP server 实现了 tools/list
McpError::InvalidToolIdComponentserver 或工具名净化后为空重命名 server/工具,使 mcp__{server}__{tool} 形态良好
McpError::ToolIdConflict两个工具映射到同一个 id确保每个 server 内工具名唯一
找不到 mcp__server__toolagent 未选中实时插件"mcp:{server}" 加进 agent 的 plugins([...]),并注册 server.plugin()

相关示例

  • crates/runtime/awaken-ext-mcp/tests/stdio_real_server.rs
  • crates/runtime/awaken-ext-mcp/tests/http_real_server.rs

关键文件

路径用途
crates/runtime/awaken-ext-mcp/src/lib.rs模块根与公开的 re-export
crates/runtime/awaken-ext-mcp/src/client.rsconnect_toolsMcpConnection
crates/runtime/awaken-ext-mcp/src/plugin.rsMcpServerMcpPlugin(实时注册表)
crates/runtime/awaken-ext-mcp/src/transport.rsMcpToolTransportListChangedKind
crates/runtime/awaken-ext-mcp/src/stdio.rsStdioTransport
crates/runtime/awaken-ext-mcp/src/http.rsHttpTransportHttpTransportBuilder
crates/runtime/awaken-ext-mcp/src/id_mapping.rsto_tool_idtool_namespace
crates/runtime/awaken-ext-mcp/src/sampling.rsSamplingHandler 与默认值

相关