Skip to content

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:

python
# 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:

bash
pip install "agno[mcp]"      # Install MCP client dependencies
npx --version                # Requires Node.js environment to run npx-launched servers

22.3 Choosing Among Three Transports ​

TransportConnection targetSuitable scenario
stdioLocal child processLocal files / CLI / Git and other private tools
SSEHTTP(S) server pushRemote-hosted legacy MCP services
Streamable HTTPStandard HTTP requestThe 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.

python
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:

python
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:

  1. Least privilege: filesystem server exposes only necessary directories; database server uses read-only accounts;
  2. Trusted sources: enable only audited server packages; npx -y auto-downloads and runs arbitrary code — pin versions in production;
  3. Confirmation on sensitive ops: layer the confirmation mechanism or guardrail from Chapter 21 onto dangerous MCP tools;
  4. Egress control: remote server URLs and credentials go through env vars / secrets managers — never hardcode.
python
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 MCPTools instances side by side (MultiMCPTools is 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 ​

  1. Connect to the filesystem server via stdio and have the Agent count files by type in a given directory.
  2. Connect to a Git MCP server (uvx mcp-server-git) and have the Agent summarize the last 5 commits in the current repository.
  3. Combine an MCP tool with a custom @tool to 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.