Chapter 22 · MCP Protocol Integration
Learning objectives: Understand what problem MCP (Model Context Protocol) solves, learn to connect to MCP servers via stdio / SSE / Streamable HTTP using
MCPTools, plug external tool capabilities into Agents on demand, and守住安全边界 (maintain security boundaries).
22.1 What Is MCP
Every framework has its own tool format; every time you integrate a new system (GitHub, a database, a filesystem …) you rewrite the wrapper from scratch. MCP (Model Context Protocol) is an open protocol initiated by Anthropic: the tool provider implements a single MCP Server, and any MCP-aware client (Agent framework, IDE, chat app) can directly discover and call all of its tools.
An analogy:
- Without MCP: every "Agent × external system" pair needs a custom integration — N×M cost;
- With MCP: the Server is written once (N+M), and clients discover and call by the standard.
Agno ships built-in MCP client capability (from agno.tools.mcp import MCPTools), supporting three transport methods.
22.2 Stdio: Connecting to a Local Server
stdio is the default transport: Agno launches the MCP Server as a child process and communicates over stdin/stdout — ideal for local tools (files, Git, local commands). Using the official filesystem server as an example:
# 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():
# Launch npx @modelcontextprotocol/server-filesystem as a child process,
# limiting it to the ./docs directory only
mcp_tools = MCPTools(command="npx -y @modelcontextprotocol/server-filesystem ./docs")
await mcp_tools.connect() # Connect and pull the tool list
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], # Pass in like any ordinary tool
markdown=True,
)
await agent.aprint_response("List Markdown files in the docs directory and summarize the structure of the first one")
finally:
await mcp_tools.close() # Always close the connection and reclaim the child process
asyncio.run(run())Dependency preparation:
pip install "agno[mcp]" # Install MCP client dependencies
npx --version # Requires Node.js environment to run npx-launched servers22.3 Choosing Among Three Transports
| Transport | Connection target | Suitable scenario |
|---|---|---|
| stdio | Local child process | Local files / CLI / Git and other private tools |
| SSE | HTTP(S) server push | Remote-hosted legacy MCP services |
| Streamable HTTP | Standard HTTP request | The currently recommended remote connection; easier to scale and deploy |
For remote connections swap the command parameter for URL-based ones; e.g., SSE uses MCPTools(url="https://example.com/sse"); consult the specific server's documentation for exact parameters.
import asyncio
from agno.tools.mcp import MCPTools
async def remote_tools():
# Remote server: SSE transport; credentials via env vars, not hardcoded
sse_tools = MCPTools(url="https://mcp.example.com/sse")
await sse_tools.connect()
try:
yield sse_tools # Reuse the connection across a FastAPI request lifecycle
finally:
await sse_tools.close()Composing Multiple Servers
Earlier versions used MultiMCPTools to connect to multiple servers simultaneously, but it has been deprecated — the current recommendation is to create multiple MCPTools instances and place them in the same tools=[...] list, with clearer responsibility boundaries.
22.4 Mixing with Custom Tools
MCP tools and your hand-written @tool functions compose freely; the model sees a single unified tool pool:
agent = Agent(
model=model,
tools=[
mcp_tools, # External tools from an MCP server
get_current_user, # Your own internal-function tool
DuckDuckGoTools(), # Agno built-in toolkit
],
)This mix is precisely MCP's value proposition: hand generic capabilities to the ecosystem's server, write business logic yourself — without interfering with each other.
22.5 Security Boundaries
While MCP dramatically lowers integration cost, it also amplifies supply-chain risk. Four boundaries to hold:
- Least privilege: filesystem server exposes only necessary directories; database server uses read-only accounts;
- Trusted sources: enable only audited server packages;
npx -yauto-downloads and runs arbitrary code — pin versions in production; - Confirmation on sensitive ops: layer the confirmation mechanism or guardrail from Chapter 21 onto dangerous MCP tools;
- Egress control: remote server URLs and credentials go through env vars / secrets managers — never hardcode.
from agno.guardrails import PIIDetectionGuardrail
# Layer the Chapter 21 defenses on top of MCP tools
safe_agent = Agent(
model=model,
tools=[mcp_tools], # External server's tool pool
pre_hooks=[PIIDetectionGuardrail()], # PII doesn't enter the model or external tools
instructions=["Confirm the target path with the user before invoking file tools."],
)Chapter Summary
- MCP is an open protocol for "implement once, reuse everywhere" — reducing N×M integrations to N+M;
MCPTools(command=...)+connect()/close()connects to stdio local servers; use SSE or Streamable HTTP for remote;- For multiple servers, use multiple
MCPToolsinstances side by side (MultiMCPToolsis deprecated); - MCP tools compose freely with custom tools and built-in Toolkits via
tools=[...]; - Security is the #1 priority for MCP deployment: least privilege, trusted sources, confirmation on dangerous ops.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. What core problem does the MCP protocol solve?
2. What is the correct way to connect to a local MCP server via stdio in Agno?
3. When needing to connect to multiple MCP servers simultaneously, what does the official recommendation say?
4. Regarding MCP security practices, which statement is false?
🛠️ Hands-On Exercises
- Connect to the filesystem server via stdio and have the Agent count files by type in a given directory.
- Connect to a Git MCP server (
uvx mcp-server-git) and have the Agent summarize the last 5 commits in the current repository. - Combine an MCP tool with a custom
@toolto complete the task "read the local README and post the summary to an internal API."
A single Agent is now rich enough in capability. We return to the main production track: Chapter 23: AgentOS, where Agents are published as services; multi-agent collaboration was covered in Chapters 9–10.