第 17 章 · MCP 协议集成
本章目标:理解 MCP(Model Context Protocol)要解决什么问题,学会用
MCPTools通过 stdio/SSE/Streamable HTTP 连接 MCP 服务器,把外部工具能力即插即用地挂给 Agent,并守住安全边界。
17.1 MCP 是什么
每个框架都有自己的工具格式,每接一个新系统(GitHub、数据库、文件系统……)都要重写一遍封装。**MCP(Model Context Protocol)**是 Anthropic 发起的开放协议:工具提供方实现一次 MCP Server,任何支持 MCP 的客户端(Agent 框架、IDE、聊天应用)都能直接发现并调用它的全部工具。
类比理解:
- 没有 MCP:每对"Agent × 外部系统"都要写定制集成,N×M 的接入成本;
- 有 MCP:Server 只写一次(N+M),客户端按标准发现与调用。
Agno 内置了完整的 MCP 客户端能力(from agno.tools.mcp import MCPTools),支持三种传输方式。
17.2 Stdio 连接本地 Server
stdio 是默认传输:Agno 把 MCP Server 作为子进程启动,通过标准输入输出通信,最适合本机工具(文件、Git、本地命令)。以官方 filesystem server 为例:
# mcp_fs.py
import asyncio
import os
from agno.agent import Agent
from agno.models.openai import OpenAIChat
from agno.tools.mcp import MCPTools
async def run():
# 以子进程方式启动 npx @modelcontextprotocol/server-filesystem,
# 并限定它只能访问 ./docs 目录
mcp_tools = MCPTools(command="npx -y @modelcontextprotocol/server-filesystem ./docs")
await mcp_tools.connect() # 连接并拉取该 server 提供的工具清单
try:
agent = Agent(
model=OpenAIChat(
id="deepseek-chat",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com/v1",
),
tools=[mcp_tools], # 像普通工具一样传入即可
markdown=True,
)
await agent.aprint_response("列出 docs 目录下有哪些 Markdown 文件,并总结第一个文件的目录结构")
finally:
await mcp_tools.close() # 务必关闭连接、回收子进程
asyncio.run(run())依赖准备:
pip install "agno[mcp]" # 安装 MCP 客户端依赖
npx --version # 需要Node.js 环境运行 npx 启动的 server17.3 三种 Transport 的选择
| Transport | 连接对象 | 适用场景 |
|---|---|---|
| stdio | 本地子进程 | 本机文件/命令行/Git 等私有工具 |
| SSE | HTTP(S) 服务端推送 | 远程托管的旧版 MCP 服务 |
| Streamable HTTP | 普通 HTTP 请求 | 当前推荐的远程连接方式,易扩展、好部署 |
远程连接时改传 URL 类参数而不是 command,例如 SSE 用 MCPTools(url="https://example.com/sse") 形式;具体参数以所用 server 的文档为准。
import asyncio
from agno.tools.mcp import MCPTools
async def remote_tools():
# 远程 server:SSE 传输,凭证走环境变量而非硬编码
sse_tools = MCPTools(url="https://mcp.example.com/sse")
await sse_tools.connect()
try:
yield sse_tools # 在 FastAPI 请求生命周期内复用连接
finally:
await sse_tools.close()多 Server 组合
早期版本用 MultiMCPTools 同时连多个 server,但它已被标记废弃——现在推荐创建多个 MCPTools 实例放进同一个 tools=[...] 列表,职责更清晰。
17.4 与自定义工具混用
MCP 工具和你手写的 @tool 函数可以自由组合,模型看到的是一个统一的工具池:
agent = Agent(
model=model,
tools=[
mcp_tools, # 来自 MCP server 的外部工具
get_current_user, # 自己写的内部函数工具
DuckDuckGoTools(), # Agno 内置工具包
],
)这种组合正是 MCP 的价值:通用能力交给生态的 server,业务逻辑自己写,互不干扰。
17.5 安全边界
MCP 大幅降低接入成本的同时也放大了供应链风险,务必守住四条边界:
- 最小授权:filesystem server 只开放必要目录;数据库 server 用只读账号;
- 来源可信:只启用经过审计的 server 包,
npx -y会自动下载执行任意代码,生产环境应固定版本号; - 敏感操作加确认:给危险的 MCP 工具叠加第 16 章的确认机制或 guardrail;
- 出口管控:远程 server 的 URL 与凭证走环境变量/密钥管理,不要硬编码。
from agno.guardrails import PIIDetectionGuardrail
# 把第 16 章的防线叠加到 MCP 工具上
safe_agent = Agent(
model=model,
tools=[mcp_tools], # 外部 server 的工具池
pre_hooks=[PIIDetectionGuardrail()], # 敏感信息不进模型,也不进外部工具
instructions=["调用文件工具前先向用户确认目标路径。"],
)本章小结
- MCP 是"工具提供方实现一次、所有客户端通用"的开放协议,把 N×M 集成降为 N+M;
MCPTools(command=...)+connect()/close()接入 stdio 本地 server;远程用 SSE 或 Streamable HTTP;- 多 server 场景用多个
MCPTools实例并列(MultiMCPTools已废弃); - MCP 工具可与自定义工具、内置 Toolkit 自由混合传给
tools=[...]; - 安全是 MCP 落地的第一优先级:最小授权、可信来源、危险操作确认。
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. MCP 协议解决的核心问题是?
2. 在 Agno 中通过 stdio 连接本地 MCP server 的正确做法是?
3. 需要同时连接多个 MCP server 时,官方现在的建议是?
4. 关于 MCP 安全实践,下列说法错误的是?
🛠️ 动手实践
- 用 stdio 方式连接 filesystem server,让 Agent 统计某个目录下各类型文件的数量。
- 再连接一个 Git MCP server(
uvx mcp-server-git),让 Agent 总结当前仓库最近 5 条提交。 - 把 MCP 工具和一个自定义
@tool组合使用,完成"读取本地 README 并把摘要发布到内部 API"的任务。
单个 Agent 能力已足够丰富,接下来让多个 Agent 协同作战:第 18 章:Agent Team 入门。