6
6
from crewai_tools import MCPServerAdapter
7
7
from crewai_tools .adapters .tool_collection import ToolCollection
8
8
9
+
9
10
@pytest .fixture
10
11
def echo_server_script ():
11
12
return dedent (
12
- '''
13
+ """
13
14
from mcp.server.fastmcp import FastMCP
14
15
15
16
mcp = FastMCP("Echo Server")
16
17
17
18
@mcp.tool()
18
19
def echo_tool(text: str) -> str:
19
- "" "Echo the input text"" "
20
+ \" \" \ " Echo the input text\" \" \ "
20
21
return f"Echo: {text}"
21
22
22
23
@mcp.tool()
23
24
def calc_tool(a: int, b: int) -> int:
24
- "" "Calculate a + b"" "
25
+ \" \" \ " Calculate a + b\" \" \ "
25
26
return a + b
26
27
27
28
mcp.run()
28
- '''
29
+ """
29
30
)
30
31
31
32
32
33
@pytest .fixture
33
34
def echo_server_sse_script ():
34
35
return dedent (
35
- '''
36
+ """
36
37
from mcp.server.fastmcp import FastMCP
37
38
38
39
mcp = FastMCP("Echo Server", host="127.0.0.1", port=8000)
39
40
40
41
@mcp.tool()
41
42
def echo_tool(text: str) -> str:
42
- "" "Echo the input text"" "
43
+ \" \" \ " Echo the input text\" \" \ "
43
44
return f"Echo: {text}"
44
45
45
46
@mcp.tool()
46
47
def calc_tool(a: int, b: int) -> int:
47
- "" "Calculate a + b"" "
48
+ \" \" \ " Calculate a + b\" \" \ "
48
49
return a + b
49
50
50
51
mcp.run("sse")
51
- '''
52
+ """
52
53
)
53
54
54
55
@@ -75,15 +76,16 @@ def echo_sse_server(echo_server_sse_script):
75
76
76
77
def test_context_manager_syntax (echo_server_script ):
77
78
serverparams = StdioServerParameters (
78
- command = "uv " , args = ["run" , "python" , "-c" , echo_server_script ]
79
+ command = "python " , args = ["-c" , echo_server_script ]
79
80
)
80
81
with MCPServerAdapter (serverparams ) as tools :
81
82
assert isinstance (tools , ToolCollection )
82
83
assert len (tools ) == 2
83
84
assert tools [0 ].name == "echo_tool"
84
85
assert tools [1 ].name == "calc_tool"
85
86
assert tools [0 ].run (text = "hello" ) == "Echo: hello"
86
- assert tools [1 ].run (a = 5 , b = 3 ) == '8'
87
+ assert tools [1 ].run (a = 5 , b = 3 ) == "8"
88
+
87
89
88
90
def test_context_manager_syntax_sse (echo_sse_server ):
89
91
sse_serverparams = echo_sse_server
@@ -92,22 +94,26 @@ def test_context_manager_syntax_sse(echo_sse_server):
92
94
assert tools [0 ].name == "echo_tool"
93
95
assert tools [1 ].name == "calc_tool"
94
96
assert tools [0 ].run (text = "hello" ) == "Echo: hello"
95
- assert tools [1 ].run (a = 5 , b = 3 ) == '8'
97
+ assert tools [1 ].run (a = 5 , b = 3 ) == "8"
98
+
96
99
97
100
def test_try_finally_syntax (echo_server_script ):
98
101
serverparams = StdioServerParameters (
99
- command = "uv " , args = ["run" , "python" , "-c" , echo_server_script ]
102
+ command = "python " , args = ["-c" , echo_server_script ]
100
103
)
104
+ mcp_server_adapter = None # Define before try block
101
105
try :
102
106
mcp_server_adapter = MCPServerAdapter (serverparams )
103
107
tools = mcp_server_adapter .tools
104
108
assert len (tools ) == 2
105
109
assert tools [0 ].name == "echo_tool"
106
110
assert tools [1 ].name == "calc_tool"
107
111
assert tools [0 ].run (text = "hello" ) == "Echo: hello"
108
- assert tools [1 ].run (a = 5 , b = 3 ) == '8'
112
+ assert tools [1 ].run (a = 5 , b = 3 ) == "8"
109
113
finally :
110
- mcp_server_adapter .stop ()
114
+ if mcp_server_adapter :
115
+ mcp_server_adapter .stop ()
116
+
111
117
112
118
def test_try_finally_syntax_sse (echo_sse_server ):
113
119
sse_serverparams = echo_sse_server
@@ -118,13 +124,14 @@ def test_try_finally_syntax_sse(echo_sse_server):
118
124
assert tools [0 ].name == "echo_tool"
119
125
assert tools [1 ].name == "calc_tool"
120
126
assert tools [0 ].run (text = "hello" ) == "Echo: hello"
121
- assert tools [1 ].run (a = 5 , b = 3 ) == '8'
127
+ assert tools [1 ].run (a = 5 , b = 3 ) == "8"
122
128
finally :
123
129
mcp_server_adapter .stop ()
124
130
131
+
125
132
def test_context_manager_with_filtered_tools (echo_server_script ):
126
133
serverparams = StdioServerParameters (
127
- command = "uv " , args = ["run" , "python" , "-c" , echo_server_script ]
134
+ command = "python " , args = ["-c" , echo_server_script ]
128
135
)
129
136
# Only select the echo_tool
130
137
with MCPServerAdapter (serverparams , "echo_tool" ) as tools :
@@ -138,24 +145,27 @@ def test_context_manager_with_filtered_tools(echo_server_script):
138
145
with pytest .raises (KeyError ):
139
146
_ = tools ["calc_tool" ]
140
147
148
+
141
149
def test_context_manager_sse_with_filtered_tools (echo_sse_server ):
142
150
sse_serverparams = echo_sse_server
143
151
# Only select the calc_tool
144
152
with MCPServerAdapter (sse_serverparams , "calc_tool" ) as tools :
145
153
assert isinstance (tools , ToolCollection )
146
154
assert len (tools ) == 1
147
155
assert tools [0 ].name == "calc_tool"
148
- assert tools [0 ].run (a = 10 , b = 5 ) == '15'
156
+ assert tools [0 ].run (a = 10 , b = 5 ) == "15"
149
157
# Check that echo_tool is not present
150
158
with pytest .raises (IndexError ):
151
159
_ = tools [1 ]
152
160
with pytest .raises (KeyError ):
153
161
_ = tools ["echo_tool" ]
154
162
163
+
155
164
def test_try_finally_with_filtered_tools (echo_server_script ):
156
165
serverparams = StdioServerParameters (
157
- command = "uv " , args = ["run" , "python" , "-c" , echo_server_script ]
166
+ command = "python " , args = ["-c" , echo_server_script ]
158
167
)
168
+ mcp_server_adapter = None # Define before try block
159
169
try :
160
170
# Select both tools but in reverse order
161
171
mcp_server_adapter = MCPServerAdapter (serverparams , "calc_tool" , "echo_tool" )
@@ -166,24 +176,41 @@ def test_try_finally_with_filtered_tools(echo_server_script):
166
176
assert tools [0 ].name == "calc_tool"
167
177
assert tools [1 ].name == "echo_tool"
168
178
finally :
169
- mcp_server_adapter .stop ()
179
+ if mcp_server_adapter :
180
+ mcp_server_adapter .stop ()
181
+
170
182
171
183
def test_filter_with_nonexistent_tool (echo_server_script ):
172
184
serverparams = StdioServerParameters (
173
- command = "uv " , args = ["run" , "python" , "-c" , echo_server_script ]
185
+ command = "python " , args = ["-c" , echo_server_script ]
174
186
)
175
187
# Include a tool that doesn't exist
176
188
with MCPServerAdapter (serverparams , "echo_tool" , "nonexistent_tool" ) as tools :
177
189
# Only echo_tool should be in the result
178
190
assert len (tools ) == 1
179
191
assert tools [0 ].name == "echo_tool"
180
192
193
+
181
194
def test_filter_with_only_nonexistent_tools (echo_server_script ):
182
195
serverparams = StdioServerParameters (
183
- command = "uv " , args = ["run" , "python" , "-c" , echo_server_script ]
196
+ command = "python " , args = ["-c" , echo_server_script ]
184
197
)
185
198
# All requested tools don't exist
186
199
with MCPServerAdapter (serverparams , "nonexistent1" , "nonexistent2" ) as tools :
187
200
# Should return an empty tool collection
188
201
assert isinstance (tools , ToolCollection )
189
202
assert len (tools ) == 0
203
+
204
+
205
+ def test_adapter_raises_import_error_if_mcp_is_missing (monkeypatch ):
206
+ """
207
+ Tests that MCPServerAdapter raises ImportError if the mcp package is not available.
208
+ """
209
+ # 1. Simulate the condition where 'mcp' is not installed by setting the
210
+ # MCP_AVAILABLE flag to False in the adapter's module.
211
+ monkeypatch .setattr ("crewai_tools.adapters.mcp_adapter.MCP_AVAILABLE" , False )
212
+
213
+ # 2. Assert that instantiating the adapter under this condition raises an
214
+ # ImportError with our specific error message.
215
+ with pytest .raises (ImportError , match = "`mcp` package not found" ):
216
+ MCPServerAdapter (serverparams = {})
0 commit comments