@@ -72,12 +72,6 @@ async def __call__(self, *args, **kwargs):
7272 ReadResourceRequest = None
7373
7474
75- try :
76- from fastmcp import __version__ as FASTMCP_VERSION
77- except ImportError :
78- FASTMCP_VERSION = None
79-
80-
8175# Collect available FastMCP implementations for parametrization
8276fastmcp_implementations = []
8377fastmcp_ids = []
@@ -320,24 +314,10 @@ def add_numbers(a: int, b: int) -> dict:
320314 request_id = "req-123" ,
321315 )
322316
323- if (
324- isinstance (mcp , StandaloneFastMCP )
325- and FASTMCP_VERSION is not None
326- and FASTMCP_VERSION .startswith ("2" )
327- ):
328- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
329- {"result" : 15 , "operation" : "addition" }, separators = ("," , ":" )
330- )
331- elif (
332- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
333- ): # Checking for None is not precise.
334- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
335- {"result" : 15 , "operation" : "addition" }
336- )
337- else :
338- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
339- {"result" : 15 , "operation" : "addition" }, indent = 2
340- )
317+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
318+ "result" : 15 ,
319+ "operation" : "addition" ,
320+ }
341321
342322 (tx ,) = events
343323 assert tx ["type" ] == "transaction"
@@ -581,41 +561,12 @@ def get_user_data(user_id: int) -> dict:
581561 request_id = "req-complex" ,
582562 )
583563
584- if (
585- isinstance (mcp , StandaloneFastMCP )
586- and FASTMCP_VERSION is not None
587- and FASTMCP_VERSION .startswith ("2" )
588- ):
589- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
590- {
591- "id" : 123 ,
592- "name" : "Alice" ,
593- "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
594- "tags" : ["admin" , "verified" ],
595- },
596- separators = ("," , ":" ),
597- )
598- elif (
599- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
600- ): # Checking for None is not precise.
601- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
602- {
603- "id" : 123 ,
604- "name" : "Alice" ,
605- "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
606- "tags" : ["admin" , "verified" ],
607- }
608- )
609- else :
610- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
611- {
612- "id" : 123 ,
613- "name" : "Alice" ,
614- "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
615- "tags" : ["admin" , "verified" ],
616- },
617- indent = 2 ,
618- )
564+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
565+ "id" : 123 ,
566+ "name" : "Alice" ,
567+ "nested" : {"preferences" : {"theme" : "dark" , "notifications" : True }},
568+ "tags" : ["admin" , "verified" ],
569+ }
619570
620571 (tx ,) = events
621572 assert tx ["type" ] == "transaction"
@@ -1057,24 +1008,9 @@ def stdio_tool(n: int) -> dict:
10571008 request_id = "req-stdio" ,
10581009 )
10591010
1060- if (
1061- isinstance (mcp , StandaloneFastMCP )
1062- and FASTMCP_VERSION is not None
1063- and FASTMCP_VERSION .startswith ("2" )
1064- ):
1065- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
1066- {"squared" : 49 }, separators = ("," , ":" )
1067- )
1068- elif (
1069- isinstance (mcp , StandaloneFastMCP ) and FASTMCP_VERSION is not None
1070- ): # Checking for None is not precise.
1071- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
1072- {"squared" : 49 }
1073- )
1074- else :
1075- assert result .message .root .result ["content" ][0 ]["text" ] == json .dumps (
1076- {"squared" : 49 }, indent = 2
1077- )
1011+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
1012+ "squared" : 49
1013+ }
10781014
10791015 (tx ,) = events
10801016
@@ -1118,10 +1054,11 @@ def package_specific_tool(x: int) -> int:
11181054 assert tx ["type" ] == "transaction"
11191055
11201056
1057+ @pytest .mark .asyncio
11211058@pytest .mark .skipif (
11221059 not HAS_STANDALONE_FASTMCP , reason = "standalone fastmcp not installed"
11231060)
1124- def test_standalone_fastmcp_specific_features (sentry_init , capture_events ):
1061+ async def test_standalone_fastmcp_specific_features (sentry_init , capture_events , stdio ):
11251062 """Test features specific to standalone fastmcp package"""
11261063 sentry_init (
11271064 integrations = [MCPIntegration ()],
@@ -1139,12 +1076,19 @@ def standalone_specific_tool(message: str) -> dict:
11391076 return {"echo" : message , "length" : len (message )}
11401077
11411078 with start_transaction (name = "standalone fastmcp tx" ):
1142- result = call_tool_through_mcp (
1143- mcp , "standalone_specific_tool" , {"message" : "Hello FastMCP" }
1079+ result = await stdio (
1080+ mcp ._mcp_server ,
1081+ method = "tools/call" ,
1082+ params = {
1083+ "name" : "standalone_specific_tool" ,
1084+ "arguments" : {"message" : "Hello FastMCP" },
1085+ },
11441086 )
11451087
1146- assert result ["echo" ] == "Hello FastMCP"
1147- assert result ["length" ] == 13
1088+ assert json .loads (result .message .root .result ["content" ][0 ]["text" ]) == {
1089+ "echo" : "Hello FastMCP" ,
1090+ "length" : 13 ,
1091+ }
11481092
11491093 (tx ,) = events
11501094 assert tx ["type" ] == "transaction"
@@ -1155,8 +1099,11 @@ def standalone_specific_tool(message: str) -> dict:
11551099# =============================================================================
11561100
11571101
1102+ @pytest .mark .asyncio
11581103@pytest .mark .parametrize ("FastMCP" , fastmcp_implementations , ids = fastmcp_ids )
1159- def test_fastmcp_tool_with_no_arguments (sentry_init , capture_events , FastMCP ):
1104+ async def test_fastmcp_tool_with_no_arguments (
1105+ sentry_init , capture_events , FastMCP , stdio
1106+ ):
11601107 """Test FastMCP tool with no arguments"""
11611108 sentry_init (
11621109 integrations = [MCPIntegration ()],
@@ -1172,16 +1119,26 @@ def no_args_tool() -> str:
11721119 return "success"
11731120
11741121 with start_transaction (name = "fastmcp tx" ):
1175- result = call_tool_through_mcp (mcp , "no_args_tool" , {})
1122+ result = await stdio (
1123+ mcp ._mcp_server ,
1124+ method = "tools/call" ,
1125+ params = {
1126+ "name" : "no_args_tool" ,
1127+ "arguments" : {},
1128+ },
1129+ )
11761130
1177- assert result [ "result " ] == "success"
1131+ assert result . message . root . result [ "content" ][ 0 ][ "text " ] == "success"
11781132
11791133 (tx ,) = events
11801134 assert tx ["type" ] == "transaction"
11811135
11821136
1137+ @pytest .mark .asyncio
11831138@pytest .mark .parametrize ("FastMCP" , fastmcp_implementations , ids = fastmcp_ids )
1184- def test_fastmcp_tool_with_none_return (sentry_init , capture_events , FastMCP ):
1139+ async def test_fastmcp_tool_with_none_return (
1140+ sentry_init , capture_events , FastMCP , stdio
1141+ ):
11851142 """Test FastMCP tool that returns None"""
11861143 sentry_init (
11871144 integrations = [MCPIntegration ()],
@@ -1197,10 +1154,16 @@ def none_return_tool(action: str) -> None:
11971154 pass
11981155
11991156 with start_transaction (name = "fastmcp tx" ):
1200- result = call_tool_through_mcp (mcp , "none_return_tool" , {"action" : "log" })
1157+ result = await stdio (
1158+ mcp ._mcp_server ,
1159+ method = "tools/call" ,
1160+ params = {
1161+ "name" : "none_return_tool" ,
1162+ "arguments" : {"action" : "log" },
1163+ },
1164+ )
12011165
1202- # Helper function normalizes to {"result": value} format
1203- assert result ["result" ] is None
1166+ assert len (result .message .root .result ["content" ]) == 0
12041167
12051168 (tx ,) = events
12061169 assert tx ["type" ] == "transaction"
0 commit comments