The Model Context Protocol (MCP) provides a standardized way for AI agents to provide context to LLMs by communicating with external services, known as MCP Servers.CrewAI offers two approaches for MCP integration:
Use the mcps field directly on agents for seamless MCP tool integration. The DSL supports both string references (for quick setup) and structured configurations (for full control).
Perfect for remote HTTPS servers and CrewAI AMP marketplace:
Copy
Ask AI
from crewai import Agentagent = Agent( role="Research Analyst", goal="Research and analyze information", backstory="Expert researcher with access to external tools", mcps=[ "https://mcp.exa.ai/mcp?api_key=your_key", # External MCP server "https://api.weather.com/mcp#get_forecast", # Specific tool from server "crewai-amp:financial-data", # CrewAI AMP marketplace "crewai-amp:research-tools#pubmed_search" # Specific AMP tool ])# MCP tools are now automatically available to your agent!
For advanced use cases requiring manual connection management, the crewai-tools library provides the MCPServerAdapter class.We currently support the following transport mechanisms:
Stdio: for local servers (communication via standard input/output between processes on the same machine)
Server-Sent Events (SSE): for remote servers (unidirectional, real-time data streaming from server to client over HTTP)
Streamable HTTPS: for remote servers (flexible, potentially bi-directional communication over HTTPS, often utilizing SSE for server-to-client streams)
from crewai import Agent, Task, Crew# Create agent with MCP tools using string referencesresearch_agent = Agent( role="Research Analyst", goal="Find and analyze information using advanced search tools", backstory="Expert researcher with access to multiple data sources", mcps=[ "https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile", "crewai-amp:weather-service#current_conditions" ])# Create taskresearch_task = Task( description="Research the latest developments in AI agent frameworks", expected_output="Comprehensive research report with citations", agent=research_agent)# Create and run crewcrew = Crew(agents=[research_agent], tasks=[research_task])result = crew.kickoff()
from crewai import Agent, Task, Crewfrom crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE# Create agent with structured MCP configurationsresearch_agent = Agent( role="Research Analyst", goal="Find and analyze information using advanced search tools", backstory="Expert researcher with access to multiple data sources", mcps=[ # Local stdio server MCPServerStdio( command="python", args=["local_server.py"], env={"API_KEY": "your_key"}, ), # Remote HTTP server MCPServerHTTP( url="https://api.research.com/mcp", headers={"Authorization": "Bearer your_token"}, ), ])# Create taskresearch_task = Task( description="Research the latest developments in AI agent frameworks", expected_output="Comprehensive research report with citations", agent=research_agent)# Create and run crewcrew = Crew(agents=[research_agent], tasks=[research_task])result = crew.kickoff()
That’s it! The MCP tools are automatically discovered and available to your agent.
The mcps field supports both string references (for quick setup) and structured configurations (for full control). You can mix both formats in the same list.
mcps=[ # Full server - get all available tools "https://mcp.example.com/api", # Specific tool from server using # syntax "https://api.weather.com/mcp#get_current_weather", # Server with authentication parameters "https://mcp.exa.ai/mcp?api_key=your_key&profile=your_profile"]
mcps=[ # Full AMP MCP service - get all available tools "crewai-amp:financial-data", # Specific tool from AMP service using # syntax "crewai-amp:research-tools#pubmed_search", # Multiple AMP services "crewai-amp:weather-service", "crewai-amp:market-analysis"]
The MCP DSL integration is designed to be resilient and handles failures gracefully:
Copy
Ask AI
from crewai import Agentfrom crewai.mcp import MCPServerStdio, MCPServerHTTPagent = Agent( role="Resilient Agent", goal="Continue working despite server issues", backstory="Agent that handles failures gracefully", mcps=[ # String references "https://reliable-server.com/mcp", # Will work "https://unreachable-server.com/mcp", # Will be skipped gracefully "crewai-amp:working-service", # Will work # Structured configs MCPServerStdio( command="python", args=["reliable_server.py"], # Will work ), MCPServerHTTP( url="https://slow-server.com/mcp", # Will timeout gracefully ), ])# Agent will use tools from working servers and log warnings for failing ones
All connection errors are handled gracefully:
Connection failures: Logged as warnings, agent continues with available tools
Timeout errors: Connections timeout after 30 seconds (configurable)
Authentication errors: Logged clearly for debugging
Invalid configurations: Validation errors are raised at agent creation time
For complex scenarios requiring manual connection management, use the MCPServerAdapter class from crewai-tools. Using a Python context manager (with statement) is the recommended approach as it automatically handles starting and stopping the connection to the MCP server.
The MCPServerAdapter supports several configuration options to customize the connection behavior:
connect_timeout (optional): Maximum time in seconds to wait for establishing a connection to the MCP server. Defaults to 30 seconds if not specified. This is particularly useful for remote servers that may have variable response times.
Copy
Ask AI
# Example with custom connection timeoutwith MCPServerAdapter(server_params, connect_timeout=60) as tools: # Connection will timeout after 60 seconds if not established pass
Copy
Ask AI
from crewai import Agentfrom crewai_tools import MCPServerAdapterfrom mcp import StdioServerParameters # For Stdio Server# Example server_params (choose one based on your server type):# 1. Stdio Server:server_params=StdioServerParameters( command="python3", args=["servers/your_server.py"], env={"UV_PYTHON": "3.12", **os.environ},)# 2. SSE Server:server_params = { "url": "http://localhost:8000/sse", "transport": "sse"}# 3. Streamable HTTP Server:server_params = { "url": "http://localhost:8001/mcp", "transport": "streamable-http"}# Example usage (uncomment and adapt once server_params is set):with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: print(f"Available tools: {[tool.name for tool in mcp_tools]}") my_agent = Agent( role="MCP Tool User", goal="Utilize tools from an MCP server.", backstory="I can connect to MCP servers and use their tools.", tools=mcp_tools, # Pass the loaded tools to your agent reasoning=True, verbose=True ) # ... rest of your crew setup ...
This general pattern shows how to integrate tools. For specific examples tailored to each transport, refer to the detailed guides below.
Accessing a specific tool using dictionary-style indexing.
Copy
Ask AI
with MCPServerAdapter(server_params, connect_timeout=60) as mcp_tools: print(f"Available tools: {[tool.name for tool in mcp_tools]}") my_agent = Agent( role="MCP Tool User", goal="Utilize tools from an MCP server.", backstory="I can connect to MCP servers and use their tools.", tools=[mcp_tools["tool_name"]], # Pass the loaded tools to your agent reasoning=True, verbose=True ) # ... rest of your crew setup ...
Pass a list of tool names to the MCPServerAdapter constructor.
Copy
Ask AI
with MCPServerAdapter(server_params, "tool_name", connect_timeout=60) as mcp_tools: print(f"Available tools: {[tool.name for tool in mcp_tools]}") my_agent = Agent( role="MCP Tool User", goal="Utilize tools from an MCP server.", backstory="I can connect to MCP servers and use their tools.", tools=mcp_tools, # Pass the loaded tools to your agent reasoning=True, verbose=True ) # ... rest of your crew setup ...
To use MCPServer tools within a CrewBase class, use the get_mcp_tools method. Server configurations should be provided via the mcp_server_params attribute. You can pass either a single configuration or a list of multiple server configurations.
Copy
Ask AI
@CrewBaseclass CrewWithMCP: # ... define your agents and tasks config file ... mcp_server_params = [ # Streamable HTTP Server { "url": "http://localhost:8001/mcp", "transport": "streamable-http" }, # SSE Server { "url": "http://localhost:8000/sse", "transport": "sse" }, # StdIO Server StdioServerParameters( command="python3", args=["servers/your_stdio_server.py"], env={"UV_PYTHON": "3.12", **os.environ}, ) ] @agent def your_agent(self): return Agent(config=self.agents_config["your_agent"], tools=self.get_mcp_tools()) # get all available tools # ... rest of your crew setup ...
When a crew class is decorated with @CrewBase, the adapter lifecycle is managed for you:
The first call to get_mcp_tools() lazily creates a shared MCPServerAdapter that is reused by every agent in the crew.
The adapter automatically shuts down after .kickoff() completes thanks to an implicit after-kickoff hook injected by @CrewBase, so no manual cleanup is required.
If mcp_server_params is not defined, get_mcp_tools() simply returns an empty list, allowing the same code paths to run with or without MCP configured.
This makes it safe to call get_mcp_tools() from multiple agent methods or selectively enable MCP per environment.
You can configure the connection timeout for MCP servers by setting the mcp_connect_timeout class attribute. If no timeout is specified, it defaults to 30 seconds.
SSE transports can be vulnerable to DNS rebinding attacks if not properly secured.
To prevent this:
Always validate Origin headers on incoming SSE connections to ensure they come from expected sources
Avoid binding servers to all network interfaces (0.0.0.0) when running locally - bind only to localhost (127.0.0.1) instead
Implement proper authentication for all SSE connections
Without these protections, attackers could use DNS rebinding to interact with local MCP servers from remote websites.For more details, see the Anthropic’s MCP Transport Security docs.
Supported Primitives: Currently, MCPServerAdapter primarily supports adapting MCP tools.
Other MCP primitives like prompts or resources are not directly integrated as CrewAI components through this adapter at this time.
Output Handling: The adapter typically processes the primary text output from an MCP tool (e.g., .content[0].text). Complex or multi-modal outputs might require custom handling if not fitting this pattern.