@@ -76,11 +76,6 @@ async def __call__(self, *args, **kwargs):
7676 GetPromptRequest = None
7777 ReadResourceRequest = None
7878
79- try :
80- from fastmcp import __version__ as FASTMCP_VERSION
81- except ImportError :
82- FASTMCP_VERSION = None
83-
8479
8580# Collect available FastMCP implementations for parametrization
8681fastmcp_implementations = []
@@ -324,24 +319,10 @@ def add_numbers(a: int, b: int) -> dict:
324319 request_id = "req-123" ,
325320 )
326321
327- if (
328- isinstance (mcp , StandaloneFastMCP )
329- and FASTMCP_VERSION is not None
330- and FASTMCP_VERSION .startswith ("2" )
331- ):
332- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
333- {"result" : 15 , "operation" : "addition" }, separators = ("," , ":" )
334- )
335- elif (
336- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
337- ): # Checking for None is not precise.
338- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
339- {"result" : 15 , "operation" : "addition" }
340- )
341- else :
342- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
343- {"result" : 15 , "operation" : "addition" }, indent = 2
344- )
322+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
323+ "result" : 15 ,
324+ "operation" : "addition" ,
325+ }
345326
346327 (tx ,) = events
347328 assert tx ["type" ] == "transaction"
@@ -416,26 +397,10 @@ async def multiply_numbers(x: int, y: int) -> dict:
416397 request_id = "req-456" ,
417398 )
418399
419- if (
420- isinstance (mcp , StandaloneFastMCP )
421- and FASTMCP_VERSION is not None
422- and FASTMCP_VERSION .startswith ("2" )
423- ):
424- assert result .json ()["result" ]["structuredContent" ] == {
425- "result" : 42 ,
426- "operation" : "multiplication" ,
427- }
428- elif (
429- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
430- ): # Checking for None is not precise.
431- assert result .json ()["result" ]["content" ][0 ]["text" ] == json .dumps (
432- {"result" : 42 , "operation" : "multiplication" },
433- )
434- else :
435- assert result .json ()["result" ]["content" ][0 ]["text" ] == json .dumps (
436- {"result" : 42 , "operation" : "multiplication" },
437- indent = 2 ,
438- )
400+ assert json .loads (result .json ()["result" ]["content" ][0 ]["text" ]) == {
401+ "result" : 42 ,
402+ "operation" : "multiplication" ,
403+ }
439404
440405 transactions = select_mcp_transactions (events )
441406 assert len (transactions ) == 1
@@ -618,41 +583,12 @@ def get_user_data(user_id: int) -> dict:
618583 request_id = "req-complex" ,
619584 )
620585
621- if (
622- isinstance (mcp , StandaloneFastMCP )
623- and FASTMCP_VERSION is not None
624- and FASTMCP_VERSION .startswith ("2" )
625- ):
626- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
627- {
628- "id" : 123 ,
629- "name" : "Alice" ,
630- "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
631- "tags" : ["admin" , "verified" ],
632- },
633- separators = ("," , ":" ),
634- )
635- elif (
636- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
637- ): # Checking for None is not precise.
638- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
639- {
640- "id" : 123 ,
641- "name" : "Alice" ,
642- "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
643- "tags" : ["admin" , "verified" ],
644- }
645- )
646- else :
647- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
648- {
649- "id" : 123 ,
650- "name" : "Alice" ,
651- "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
652- "tags" : ["admin" , "verified" ],
653- },
654- indent = 2 ,
655- )
586+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
587+ "id" : 123 ,
588+ "name" : "Alice" ,
589+ "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
590+ "tags" : ["admin" , "verified" ],
591+ }
656592
657593 (tx ,) = events
658594 assert tx ["type" ] == "transaction"
@@ -1098,23 +1034,9 @@ def http_tool(data: str) -> dict:
10981034 request_id = "req-http" ,
10991035 )
11001036
1101- if (
1102- isinstance (mcp , StandaloneFastMCP )
1103- and FASTMCP_VERSION is not None
1104- and FASTMCP_VERSION .startswith ("2" )
1105- ):
1106- assert result .json ()["result" ]["structuredContent" ] == {"processed" : "TEST" }
1107- elif (
1108- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
1109- ): # Checking for None is not precise.
1110- assert result .json ()["result" ]["content" ][0 ]["text" ] == json .dumps (
1111- {"processed" : "TEST" },
1112- )
1113- else :
1114- assert result .json ()["result" ]["content" ][0 ]["text" ] == json .dumps (
1115- {"processed" : "TEST" },
1116- indent = 2 ,
1117- )
1037+ assert json .loads (result .json ()["result" ]["content" ][0 ]["text" ]) == {
1038+ "processed" : "TEST"
1039+ }
11181040
11191041 transactions = select_mcp_transactions (events )
11201042 assert len (transactions ) == 1
@@ -1152,24 +1074,9 @@ def stdio_tool(n: int) -> dict:
11521074 request_id = "req-stdio" ,
11531075 )
11541076
1155- if (
1156- isinstance (mcp , StandaloneFastMCP )
1157- and FASTMCP_VERSION is not None
1158- and FASTMCP_VERSION .startswith ("2" )
1159- ):
1160- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
1161- {"squared" : 49 }, separators = ("," , ":" )
1162- )
1163- elif (
1164- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
1165- ): # Checking for None is not precise.
1166- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
1167- {"squared" : 49 }
1168- )
1169- else :
1170- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
1171- {"squared" : 49 }, indent = 2
1172- )
1077+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
1078+ "squared" : 49
1079+ }
11731080
11741081 (tx ,) = events
11751082
@@ -1213,10 +1120,11 @@ def package_specific_tool(x: int) -> int:
12131120 assert tx ["type" ] == "transaction"
12141121
12151122
1123+ @pytest .mark .asyncio
12161124@pytest .mark .skipif (
12171125 not HAS_STANDALONE_FASTMCP , reason = "standalone fastmcp not installed"
12181126)
1219- def test_standalone_fastmcp_specific_features (sentry_init , capture_events ):
1127+ async def test_standalone_fastmcp_specific_features (sentry_init , capture_events , stdio ):
12201128 """Test features specific to standalone fastmcp package"""
12211129 sentry_init (
12221130 integrations = [MCPIntegration ()],
@@ -1234,12 +1142,19 @@ def standalone_specific_tool(message: str) -> dict:
12341142 return {"echo" : message , "length" : len (message )}
12351143
12361144 with start_transaction (name = "standalone fastmcp tx" ):
1237- result = call_tool_through_mcp (
1238- mcp , "standalone_specific_tool" , {"message" : "Hello FastMCP" }
1145+ result = await stdio (
1146+ mcp ._mcp_server ,
1147+ method = "tools/call" ,
1148+ params = {
1149+ "name" : "standalone_specific_tool" ,
1150+ "arguments" : {"message" : "Hello FastMCP" },
1151+ },
12391152 )
12401153
1241- assert result ["echo" ] == "Hello FastMCP"
1242- assert result ["length" ] == 13
1154+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
1155+ "echo" : "Hello FastMCP" ,
1156+ "length" : 13 ,
1157+ }
12431158
12441159 (tx ,) = events
12451160 assert tx ["type" ] == "transaction"
@@ -1250,8 +1165,11 @@ def standalone_specific_tool(message: str) -> dict:
12501165# =============================================================================
12511166
12521167
1168+ @pytest .mark .asyncio
12531169@pytest .mark .parametrize ("FastMCP" , fastmcp_implementations , ids = fastmcp_ids )
1254- def test_fastmcp_tool_with_no_arguments (sentry_init , capture_events , FastMCP ):
1170+ async def test_fastmcp_tool_with_no_arguments (
1171+ sentry_init , capture_events , FastMCP , stdio
1172+ ):
12551173 """Test FastMCP tool with no arguments"""
12561174 sentry_init (
12571175 integrations = [MCPIntegration ()],
@@ -1267,16 +1185,26 @@ def no_args_tool() -> str:
12671185 return "success"
12681186
12691187 with start_transaction (name = "fastmcp tx" ):
1270- result = call_tool_through_mcp (mcp , "no_args_tool" , {})
1188+ result = await stdio (
1189+ mcp ._mcp_server ,
1190+ method = "tools/call" ,
1191+ params = {
1192+ "name" : "no_args_tool" ,
1193+ "arguments" : {},
1194+ },
1195+ )
12711196
1272- assert result [ "result " ] == "success"
1197+ assert result . message . root . result [ "content" ][ 0 ][ "text " ] == "success"
12731198
12741199 (tx ,) = events
12751200 assert tx ["type" ] == "transaction"
12761201
12771202
1203+ @pytest .mark .asyncio
12781204@pytest .mark .parametrize ("FastMCP" , fastmcp_implementations , ids = fastmcp_ids )
1279- def test_fastmcp_tool_with_none_return (sentry_init , capture_events , FastMCP ):
1205+ async def test_fastmcp_tool_with_none_return (
1206+ sentry_init , capture_events , FastMCP , stdio
1207+ ):
12801208 """Test FastMCP tool that returns None"""
12811209 sentry_init (
12821210 integrations = [MCPIntegration ()],
@@ -1292,10 +1220,16 @@ def none_return_tool(action: str) -> None:
12921220 pass
12931221
12941222 with start_transaction (name = "fastmcp tx" ):
1295- result = call_tool_through_mcp (mcp , "none_return_tool" , {"action" : "log" })
1223+ result = await stdio (
1224+ mcp ._mcp_server ,
1225+ method = "tools/call" ,
1226+ params = {
1227+ "name" : "none_return_tool" ,
1228+ "arguments" : {"action" : "log" },
1229+ },
1230+ )
12961231
1297- # Helper function normalizes to {"result": value} format
1298- assert result ["result" ] is None
1232+ assert len (result .message .root .result ["content" ]) == 0
12991233
13001234 (tx ,) = events
13011235 assert tx ["type" ] == "transaction"
0 commit comments