Chapter 19 · MCP Integration
Chapter goals: Understand MCP protocol's position in multi-agent systems, master CrewAI 1.15's recommended
mcpsDSL syntax and the advancedMCPServerAdapter, and safely mount local/remote MCP server tools for your Agents.
19.1 MCP Protocol in One Minute
MCP (Model Context Protocol) is an open protocol initiated by Anthropic that standardizes "how models call external capabilities" into three things:
- Tools (tools): functions the model can call (the core concern of this tutorial);
- Resources: readable data context;
- Prompts: preset prompt templates.
MCP adopts a client-server architecture: your CrewAI application is the MCP client, connecting to MCP servers through three transport mechanisms:
| Transport | Use Case | Communication |
|---|---|---|
| Stdio | Local processes (same machine) | Standard input/output |
| Streamable HTTP | Remote services (recommended default) | HTTPS, bidirectional |
| SSE | Remote services (real-time streaming) | HTTP unidirectional push |
Version note
CrewAI 1.15 provides two MCP integration approaches: the official recommended mcps field DSL (automatic connection management), and MCPServerAdapter in crewai-tools (manual connection management, suited for complex scenarios). Older tutorials claiming "only MCPServerAdapter works" are outdated.
19.2 Approach 1: mcps DSL Field (Recommended)
The simplest way is to add the mcps field directly on Agent; CrewAI auto-discovers tools, manages connection lifecycle, and prefixes tool names to prevent conflicts:
import os
from crewai import Agent, Task, Crew, LLM
# Third-party OpenAI-compatible model
llm = LLM(
model="openai/deepseek-chat",
base_url="https://api.deepseek.com/v1",
api_key=os.getenv("DEEPSEEK_API_KEY"),
temperature=0.7,
)
researcher = Agent(
role="Research Analyst",
goal="Investigate the latest developments in AI Agent frameworks using external search tools",
backstory="Senior researcher skilled at cross-validating information from multiple data sources",
llm=llm,
mcps=[
# Remote MCP server (string reference; can carry auth params)
"https://mcp.exa.ai/mcp?api_key=your_exa_key",
# Use # syntax to select only one tool from this server
"https://api.weather.com/mcp#get_forecast",
],
)
task = Task(
description="Research key evolutionary directions in multi-agent frameworks in 2025",
expected_output="Chinese research brief with cited sources, under 500 words",
agent=researcher,
)
crew = Crew(agents=[researcher], tasks=[task])
result = crew.kickoff()
print(result.raw)No need to manually start/stop connections, no need to pass tools= — tools are auto-mounted.
19.3 Structured Config: Three Transports + Tool Filtering
For full control over connection parameters, use structured config objects from the crewai.mcp module:
import os
from crewai import Agent
from crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE
from crewai.mcp.filters import create_static_tool_filter
# Static filter: only allow whitelist tools, block dangerous ones
file_filter = create_static_tool_filter(
allowed_tool_names=["read_file", "list_directory"],
blocked_tool_names=["delete_file"],
)
agent = Agent(
role="Document Organizer",
goal="Safely organize local and remote documents",
backstory="Cautious and meticulous document administrator",
llm=llm,
mcps=[
# 1) Stdio: local filesystem server (start official example server via npx)
MCPServerStdio(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp/docs"],
tool_filter=file_filter, # Only expose read-type tools
cache_tools_list=True, # Cache tool list; speeds subsequent connections
),
# 2) Streamable HTTP: remote service (default streamable=True)
MCPServerHTTP(
url="https://api.example.com/mcp",
headers={"Authorization": f"Bearer {os.getenv('MCP_TOKEN')}"},
cache_tools_list=True,
),
# 3) SSE: real-time streaming remote service
MCPServerSSE(
url="https://stream.example.com/mcp/sse",
headers={"Authorization": f"Bearer {os.getenv('MCP_TOKEN')}"},
),
],
)Common parameters across the three config objects:
tool_filter:None(all tools) / static filter (allow/block lists) / dynamic filter function (can decide percontext.agent.rolewhich tools to expose);cache_tools_list: cache discovered tools after first fetch; avoids re-pulling on every connection;- Connection failure gracefully degrades: if one server goes down, only a warning log is emitted; the Agent continues with remaining tools; invalid config raises a validation error at Agent creation time.
19.4 Approach 2: MCPServerAdapter Manual Management
When you need fine-grained control over connection lifecycle (e.g., connection reuse, per-tool granularity), use MCPServerAdapter from crewai-tools. Recommended to pair with with context manager for auto start/stop:
import os
from crewai import Agent, Task, Crew
from crewai_tools import MCPServerAdapter
from mcp import StdioServerParameters
# Local stdio server launch parameters
server_params = StdioServerParameters(
command="python3",
args=["servers/filesystem_server.py"],
env={"UV_PYTHON": "3.12", **os.environ},
)
# Remote server can also use dict form:
# server_params = {"url": "http://localhost:8000/sse", "transport": "sse"}
# server_params = {"url": "http://localhost:8001/mcp", "transport": "streamable-http"}
with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools:
print(f"Available tools: {[t.name for t in mcp_tools]}")
agent = Agent(
role="File Manager",
goal="Complete file organization using MCP tools",
backstory="Automation assistant familiar with filesystems",
llm=llm,
tools=[mcp_tools["read_file"]], # Dict-style index: grab only one tool
)
task = Task(
description="Read /tmp/docs/notes.md and summarize key points",
expected_output="3-5 key point list",
agent=agent,
)
crew = Crew(agents=[agent], tasks=[task])
result = crew.kickoff()
print(result.raw)
# Connection auto-closes when with block exitsTwo filtering approaches: dict-style index mcp_tools["tool_name"], or pass a tool name list at construction MCPServerAdapter(server_params, "tool_1", "tool_2").
19.5 Using MCP in @CrewBase Engineering Projects
In the Chapter 17 CLI engineering structure, the @CrewBase class provides a get_mcp_tools() method; connection lifecycle is managed by the framework (auto-closes after kickoff ends):
import os
from mcp import StdioServerParameters
from crewai import Agent, Crew, Process, Task
from crewai.project import CrewBase, agent, crew, task
@CrewBase
class DocCrew:
"""Doc-processing Crew with MCP file tools"""
# Supports single config or config list (can mix three transports)
mcp_server_params = [
StdioServerParameters(
command="npx",
args=["-y", "@modelcontextprotocol/server-filesystem", "/tmp/docs"],
),
{"url": "http://localhost:8001/mcp", "transport": "streamable-http"},
]
mcp_connect_timeout = 60 # Default 30s; increase as needed
@agent
def reader(self) -> Agent:
return Agent(
config=self.agents_config["reader"],
tools=self.get_mcp_tools("read_file", "list_directory"), # Select by name
)
@task
def summarize(self) -> Task:
return Task(config=self.tasks_config["summarize"])
@crew
def crew(self) -> Crew:
return Crew(agents=self.agents, tasks=self.tasks, process=Process.sequential)get_mcp_tools() with no args returns all tools; the first call lazily creates a shared adapter; the entire Crew reuses the same connection.
19.6 MCP Security Considerations
MCP plugs "external services that can execute code / read files" directly into your Agent — treat it as carefully as "giving a stranger an account to your server":
- Only connect to trusted servers: the official docs repeatedly emphasize — you must trust the MCP server before using it. A malicious server can inject prompts via tool descriptions, inducing the model to leak data;
- Prevent DNS rebinding (SSE scenario): local SSE servers should validate the
Originheader, bind only to127.0.0.1not0.0.0.0, and add authentication; - Principle of least privilege: use
tool_filterwhitelist to expose only必需 tools;坚决 blockdelete_*,execute_*high-risk tools; - Credentials never on disk:
env=andheaders=credentials must always be read from environment variables (see Chapter 25); - Timeout as fallback: always configure
connect_timeoutfor remote servers to prevent one slow server from grinding the entire Crew to a halt (DSL defaults to 30-second timeout with graceful skip).
Known limitations
MCPServerAdapter currently primarily supports the MCP tools primitive; prompts and resources are not yet directly mapped to CrewAI components; complex/multi-modal tool outputs typically only grab .content[0].text.
Chapter Summary
- MCP standardizes three capability types: tools, resources, and prompts; CrewAI as client supports Stdio, Streamable HTTP, and SSE transports;
- Recommended: use
mcpsDSL — string references (supporting#tool_nameprecise selection) or structured config (MCPServerStdio/HTTP/SSE); - Advanced: use
crewai-tools'MCPServerAdapter+withcontext for manual management; useget_mcp_tools()in@CrewBaseprojects; - Tool filtering (static whitelist / dynamic function) + connection timeout + graceful degradation are production must-haves;
- Security surface: only connect to trusted servers, prevent DNS rebinding, least privilege, credentials via environment variables.
🧪 随堂测验
点击你认为正确的选项。答错时会展示正确答案与原因解析。
1. In CrewAI 1.15, what is the officially recommended MCP integration approach?
2. What does the # syntax in mcps string "https://api.weather.com/mcp#get_forecast" do?
3. Regarding MCPServerAdapter connection management, what is the correct approach?
4. Which is NOT an official MCP security recommendation?
🛠️ Hands-On Exercises
- Start a local filesystem server with
npx -y @modelcontextprotocol/server-filesystem /tmp/mcp-lab; mount it with DSLMCPServerStdio; configure a whitelist allowing onlyread_fileandlist_directory; have the Agent list and summarize a text file. - Refactor practice 1 into
@CrewBaseproject structure (mcp_server_params+get_mcp_tools("read_file")); verify the connection is auto-closed after kickoff (observe connection logs on the server side). - Add an unreachable remote
mcpsentry to practice 1's config (e.g.,https://unreachable.example.com/mcp); run and observe the log: confirm the Crew does not crash but warns and continues.
Next chapter addresses "how to scientifically evaluate whether a Crew is good or bad": Chapter 20 · Testing and Evaluation.