Skip to content

Commit 6f36d70

Browse files
authored
Lorenze/feat mcp first class support (#3850)
* WIP transport support mcp * refactor: streamline MCP tool loading and error handling * linted * Self type from typing with typing_extensions in MCP transport modules * added tests for mcp setup * added tests for mcp setup * docs: enhance MCP overview with detailed integration examples and structured configurations * feat: implement MCP event handling and logging in event listener and client - Added MCP event types and handlers for connection and tool execution events. - Enhanced MCPClient to emit events on connection status and tool execution. - Updated ConsoleFormatter to handle MCP event logging. - Introduced new MCP event types for better integration and monitoring.
1 parent 9e5906c commit 6f36d70

File tree

20 files changed

+2838
-38
lines changed

20 files changed

+2838
-38
lines changed

docs/en/mcp/overview.mdx

Lines changed: 268 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,13 @@ The [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP)
1111

1212
CrewAI offers **two approaches** for MCP integration:
1313

14-
### Simple DSL Integration** (Recommended)
14+
### 🚀 **Simple DSL Integration** (Recommended)
1515

16-
Use the `mcps` field directly on agents for seamless MCP tool integration:
16+
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).
17+
18+
#### String-Based References (Quick Setup)
19+
20+
Perfect for remote HTTPS servers and CrewAI AMP marketplace:
1721

1822
```python
1923
from crewai import Agent
@@ -32,6 +36,46 @@ agent = Agent(
3236
# MCP tools are now automatically available to your agent!
3337
```
3438

39+
#### Structured Configurations (Full Control)
40+
41+
For complete control over connection settings, tool filtering, and all transport types:
42+
43+
```python
44+
from crewai import Agent
45+
from crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE
46+
from crewai.mcp.filters import create_static_tool_filter
47+
48+
agent = Agent(
49+
role="Advanced Research Analyst",
50+
goal="Research with full control over MCP connections",
51+
backstory="Expert researcher with advanced tool access",
52+
mcps=[
53+
# Stdio transport for local servers
54+
MCPServerStdio(
55+
command="npx",
56+
args=["-y", "@modelcontextprotocol/server-filesystem"],
57+
env={"API_KEY": "your_key"},
58+
tool_filter=create_static_tool_filter(
59+
allowed_tool_names=["read_file", "list_directory"]
60+
),
61+
cache_tools_list=True,
62+
),
63+
# HTTP/Streamable HTTP transport for remote servers
64+
MCPServerHTTP(
65+
url="https://api.example.com/mcp",
66+
headers={"Authorization": "Bearer your_token"},
67+
streamable=True,
68+
cache_tools_list=True,
69+
),
70+
# SSE transport for real-time streaming
71+
MCPServerSSE(
72+
url="https://stream.example.com/mcp/sse",
73+
headers={"Authorization": "Bearer your_token"},
74+
),
75+
]
76+
)
77+
```
78+
3579
### 🔧 **Advanced: MCPServerAdapter** (For Complex Scenarios)
3680

3781
For advanced use cases requiring manual connection management, the `crewai-tools` library provides the `MCPServerAdapter` class.
@@ -68,12 +112,14 @@ uv pip install 'crewai-tools[mcp]'
68112

69113
## Quick Start: Simple DSL Integration
70114

71-
The easiest way to integrate MCP servers is using the `mcps` field on your agents:
115+
The easiest way to integrate MCP servers is using the `mcps` field on your agents. You can use either string references or structured configurations.
116+
117+
### Quick Start with String References
72118

73119
```python
74120
from crewai import Agent, Task, Crew
75121

76-
# Create agent with MCP tools
122+
# Create agent with MCP tools using string references
77123
research_agent = Agent(
78124
role="Research Analyst",
79125
goal="Find and analyze information using advanced search tools",
@@ -96,13 +142,53 @@ crew = Crew(agents=[research_agent], tasks=[research_task])
96142
result = crew.kickoff()
97143
```
98144

145+
### Quick Start with Structured Configurations
146+
147+
```python
148+
from crewai import Agent, Task, Crew
149+
from crewai.mcp import MCPServerStdio, MCPServerHTTP, MCPServerSSE
150+
151+
# Create agent with structured MCP configurations
152+
research_agent = Agent(
153+
role="Research Analyst",
154+
goal="Find and analyze information using advanced search tools",
155+
backstory="Expert researcher with access to multiple data sources",
156+
mcps=[
157+
# Local stdio server
158+
MCPServerStdio(
159+
command="python",
160+
args=["local_server.py"],
161+
env={"API_KEY": "your_key"},
162+
),
163+
# Remote HTTP server
164+
MCPServerHTTP(
165+
url="https://api.research.com/mcp",
166+
headers={"Authorization": "Bearer your_token"},
167+
),
168+
]
169+
)
170+
171+
# Create task
172+
research_task = Task(
173+
description="Research the latest developments in AI agent frameworks",
174+
expected_output="Comprehensive research report with citations",
175+
agent=research_agent
176+
)
177+
178+
# Create and run crew
179+
crew = Crew(agents=[research_agent], tasks=[research_task])
180+
result = crew.kickoff()
181+
```
182+
99183
That's it! The MCP tools are automatically discovered and available to your agent.
100184

101185
## MCP Reference Formats
102186

103-
The `mcps` field supports various reference formats for maximum flexibility:
187+
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.
104188

105-
### External MCP Servers
189+
### String-Based References
190+
191+
#### External MCP Servers
106192

107193
```python
108194
mcps=[
@@ -117,7 +203,7 @@ mcps=[
117203
]
118204
```
119205

120-
### CrewAI AMP Marketplace
206+
#### CrewAI AMP Marketplace
121207

122208
```python
123209
mcps=[
@@ -133,17 +219,166 @@ mcps=[
133219
]
134220
```
135221

222+
### Structured Configurations
223+
224+
#### Stdio Transport (Local Servers)
225+
226+
Perfect for local MCP servers that run as processes:
227+
228+
```python
229+
from crewai.mcp import MCPServerStdio
230+
from crewai.mcp.filters import create_static_tool_filter
231+
232+
mcps=[
233+
MCPServerStdio(
234+
command="npx",
235+
args=["-y", "@modelcontextprotocol/server-filesystem"],
236+
env={"API_KEY": "your_key"},
237+
tool_filter=create_static_tool_filter(
238+
allowed_tool_names=["read_file", "write_file"]
239+
),
240+
cache_tools_list=True,
241+
),
242+
# Python-based server
243+
MCPServerStdio(
244+
command="python",
245+
args=["path/to/server.py"],
246+
env={"UV_PYTHON": "3.12", "API_KEY": "your_key"},
247+
),
248+
]
249+
```
250+
251+
#### HTTP/Streamable HTTP Transport (Remote Servers)
252+
253+
For remote MCP servers over HTTP/HTTPS:
254+
255+
```python
256+
from crewai.mcp import MCPServerHTTP
257+
258+
mcps=[
259+
# Streamable HTTP (default)
260+
MCPServerHTTP(
261+
url="https://api.example.com/mcp",
262+
headers={"Authorization": "Bearer your_token"},
263+
streamable=True,
264+
cache_tools_list=True,
265+
),
266+
# Standard HTTP
267+
MCPServerHTTP(
268+
url="https://api.example.com/mcp",
269+
headers={"Authorization": "Bearer your_token"},
270+
streamable=False,
271+
),
272+
]
273+
```
274+
275+
#### SSE Transport (Real-Time Streaming)
276+
277+
For remote servers using Server-Sent Events:
278+
279+
```python
280+
from crewai.mcp import MCPServerSSE
281+
282+
mcps=[
283+
MCPServerSSE(
284+
url="https://stream.example.com/mcp/sse",
285+
headers={"Authorization": "Bearer your_token"},
286+
cache_tools_list=True,
287+
),
288+
]
289+
```
290+
136291
### Mixed References
137292

293+
You can combine string references and structured configurations:
294+
138295
```python
296+
from crewai.mcp import MCPServerStdio, MCPServerHTTP
297+
139298
mcps=[
299+
# String references
140300
"https://external-api.com/mcp", # External server
141-
"https://weather.service.com/mcp#forecast", # Specific external tool
142301
"crewai-amp:financial-insights", # AMP service
143-
"crewai-amp:data-analysis#sentiment_tool" # Specific AMP tool
302+
303+
# Structured configurations
304+
MCPServerStdio(
305+
command="npx",
306+
args=["-y", "@modelcontextprotocol/server-filesystem"],
307+
),
308+
MCPServerHTTP(
309+
url="https://api.example.com/mcp",
310+
headers={"Authorization": "Bearer token"},
311+
),
144312
]
145313
```
146314

315+
### Tool Filtering
316+
317+
Structured configurations support advanced tool filtering:
318+
319+
```python
320+
from crewai.mcp import MCPServerStdio
321+
from crewai.mcp.filters import create_static_tool_filter, create_dynamic_tool_filter, ToolFilterContext
322+
323+
# Static filtering (allow/block lists)
324+
static_filter = create_static_tool_filter(
325+
allowed_tool_names=["read_file", "write_file"],
326+
blocked_tool_names=["delete_file"],
327+
)
328+
329+
# Dynamic filtering (context-aware)
330+
def dynamic_filter(context: ToolFilterContext, tool: dict) -> bool:
331+
# Block dangerous tools for certain agent roles
332+
if context.agent.role == "Code Reviewer":
333+
if "delete" in tool.get("name", "").lower():
334+
return False
335+
return True
336+
337+
mcps=[
338+
MCPServerStdio(
339+
command="npx",
340+
args=["-y", "@modelcontextprotocol/server-filesystem"],
341+
tool_filter=static_filter, # or dynamic_filter
342+
),
343+
]
344+
```
345+
346+
## Configuration Parameters
347+
348+
Each transport type supports specific configuration options:
349+
350+
### MCPServerStdio Parameters
351+
352+
- **`command`** (required): Command to execute (e.g., `"python"`, `"node"`, `"npx"`, `"uvx"`)
353+
- **`args`** (optional): List of command arguments (e.g., `["server.py"]` or `["-y", "@mcp/server"]`)
354+
- **`env`** (optional): Dictionary of environment variables to pass to the process
355+
- **`tool_filter`** (optional): Tool filter function for filtering available tools
356+
- **`cache_tools_list`** (optional): Whether to cache the tool list for faster subsequent access (default: `False`)
357+
358+
### MCPServerHTTP Parameters
359+
360+
- **`url`** (required): Server URL (e.g., `"https://api.example.com/mcp"`)
361+
- **`headers`** (optional): Dictionary of HTTP headers for authentication or other purposes
362+
- **`streamable`** (optional): Whether to use streamable HTTP transport (default: `True`)
363+
- **`tool_filter`** (optional): Tool filter function for filtering available tools
364+
- **`cache_tools_list`** (optional): Whether to cache the tool list for faster subsequent access (default: `False`)
365+
366+
### MCPServerSSE Parameters
367+
368+
- **`url`** (required): Server URL (e.g., `"https://api.example.com/mcp/sse"`)
369+
- **`headers`** (optional): Dictionary of HTTP headers for authentication or other purposes
370+
- **`tool_filter`** (optional): Tool filter function for filtering available tools
371+
- **`cache_tools_list`** (optional): Whether to cache the tool list for faster subsequent access (default: `False`)
372+
373+
### Common Parameters
374+
375+
All transport types support:
376+
- **`tool_filter`**: Filter function to control which tools are available. Can be:
377+
- `None` (default): All tools are available
378+
- Static filter: Created with `create_static_tool_filter()` for allow/block lists
379+
- Dynamic filter: Created with `create_dynamic_tool_filter()` for context-aware filtering
380+
- **`cache_tools_list`**: When `True`, caches the tool list after first discovery to improve performance on subsequent connections
381+
147382
## Key Features
148383

149384
- 🔄 **Automatic Tool Discovery**: Tools are automatically discovered and integrated
@@ -152,26 +387,47 @@ mcps=[
152387
- 🛡️ **Error Resilience**: Graceful handling of unavailable servers
153388
- ⏱️ **Timeout Protection**: Built-in timeouts prevent hanging connections
154389
- 📊 **Transparent Integration**: Works seamlessly with existing CrewAI features
390+
- 🔧 **Full Transport Support**: Stdio, HTTP/Streamable HTTP, and SSE transports
391+
- 🎯 **Advanced Filtering**: Static and dynamic tool filtering capabilities
392+
- 🔐 **Flexible Authentication**: Support for headers, environment variables, and query parameters
155393

156394
## Error Handling
157395

158-
The MCP DSL integration is designed to be resilient:
396+
The MCP DSL integration is designed to be resilient and handles failures gracefully:
159397

160398
```python
399+
from crewai import Agent
400+
from crewai.mcp import MCPServerStdio, MCPServerHTTP
401+
161402
agent = Agent(
162403
role="Resilient Agent",
163404
goal="Continue working despite server issues",
164405
backstory="Agent that handles failures gracefully",
165406
mcps=[
407+
# String references
166408
"https://reliable-server.com/mcp", # Will work
167409
"https://unreachable-server.com/mcp", # Will be skipped gracefully
168-
"https://slow-server.com/mcp", # Will timeout gracefully
169-
"crewai-amp:working-service" # Will work
410+
"crewai-amp:working-service", # Will work
411+
412+
# Structured configs
413+
MCPServerStdio(
414+
command="python",
415+
args=["reliable_server.py"], # Will work
416+
),
417+
MCPServerHTTP(
418+
url="https://slow-server.com/mcp", # Will timeout gracefully
419+
),
170420
]
171421
)
172422
# Agent will use tools from working servers and log warnings for failing ones
173423
```
174424

425+
All connection errors are handled gracefully:
426+
- **Connection failures**: Logged as warnings, agent continues with available tools
427+
- **Timeout errors**: Connections timeout after 30 seconds (configurable)
428+
- **Authentication errors**: Logged clearly for debugging
429+
- **Invalid configurations**: Validation errors are raised at agent creation time
430+
175431
## Advanced: MCPServerAdapter
176432

177433
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.

0 commit comments

Comments
 (0)