@@ -167,81 +167,82 @@ async def noop_validate(self: Any, name: str, result: Any) -> None:
167167
168168def patch_server_output_validation () -> None :
169169 """
170- Patch MCP server to skip structured output validation.
170+ Patch MCP server to skip structured output validation and auto-generate
171+ structuredContent for FastMCP tools with x-fastmcp-wrap-result.
171172 """
172173 try :
173174 import json
174- from typing import cast
175175
176176 import mcp .types as types
177177 from mcp .server .lowlevel .server import Server
178178
179- original_call_tool = Server .call_tool
180-
181179 def patched_call_tool (
182180 self : Any , validate_input : bool = True , validate_output : bool = False
183181 ) -> Any :
184182 """Patched call_tool that skips output validation."""
185- from collections .abc import Awaitable , Callable
186-
187- # Type aliases from original
188- UnstructuredContent = list [types .TextContent | types .ImageContent | types .EmbeddedResource ]
189- StructuredContent = dict [str , Any ]
190- CombinationContent = tuple [UnstructuredContent , StructuredContent ]
191-
192- def decorator (
193- func : Callable [
194- ...,
195- Awaitable [UnstructuredContent | StructuredContent | CombinationContent | types .CallToolResult ],
196- ],
197- ) -> Any :
183+
184+ def decorator (func : Any ) -> Any :
198185 async def handler (req : types .CallToolRequest ) -> Any :
199186 try :
200187 tool_name = req .params .name
201188 arguments = req .params .arguments or {}
202189 tool = await self ._get_cached_tool_definition (tool_name )
203190
204- # input validation (keep this)
205191 if validate_input and tool :
206192 try :
207193 import jsonschema
208- jsonschema .validate (instance = arguments , schema = tool .inputSchema )
194+
195+ jsonschema .validate (
196+ instance = arguments , schema = tool .inputSchema
197+ )
209198 except jsonschema .ValidationError as e :
210- return self ._make_error_result (f"Input validation error: { e .message } " )
199+ return self ._make_error_result (
200+ f"Input validation error: { e .message } "
201+ )
211202
212- # tool call
213203 results = await func (tool_name , arguments )
214204
215205 # output normalization
216- unstructured_content : UnstructuredContent
217- maybe_structured_content : StructuredContent | None
206+ unstructured_content : list [ Any ]
207+ maybe_structured_content : dict [ str , Any ] | None
218208 if isinstance (results , types .CallToolResult ):
219209 return types .ServerResult (results )
220210 elif isinstance (results , tuple ) and len (results ) == 2 :
221- unstructured_content , maybe_structured_content = cast ( CombinationContent , results )
211+ unstructured_content , maybe_structured_content = results
222212 elif isinstance (results , dict ):
223- maybe_structured_content = cast (StructuredContent , results )
224- unstructured_content = [types .TextContent (type = "text" , text = json .dumps (results , indent = 2 ))]
213+ maybe_structured_content = results
214+ text = json .dumps (results , indent = 2 )
215+ unstructured_content = [
216+ types .TextContent (type = "text" , text = text )
217+ ]
225218 elif hasattr (results , "__iter__" ):
226- unstructured_content = cast ( UnstructuredContent , results )
219+ unstructured_content = list ( results )
227220 maybe_structured_content = None
228221 else :
229- return self ._make_error_result (f"Unexpected return type from tool: { type (results ).__name__ } " )
222+ return self ._make_error_result (
223+ f"Unexpected return type: { type (results ).__name__ } "
224+ )
230225
231- # Auto-generate structuredContent for FastMCP tools with x-fastmcp-wrap-result
232- # FastMCP generates outputSchema but doesn't populate structuredContent
226+ # Auto-generate structuredContent for FastMCP tools
227+ # FastMCP generates outputSchema but doesn't populate it
233228 if maybe_structured_content is None and tool :
234- output_schema = getattr (tool , 'outputSchema' , None )
235- if output_schema and output_schema .get ('x-fastmcp-wrap-result' ):
229+ output_schema = getattr (tool , "outputSchema" , None )
230+ if output_schema and output_schema .get (
231+ "x-fastmcp-wrap-result"
232+ ):
236233 for item in unstructured_content :
237234 if isinstance (item , types .TextContent ):
238235 try :
239- maybe_structured_content = {"result" : json .loads (item .text )}
236+ parsed = json .loads (item .text )
237+ maybe_structured_content = {
238+ "result" : parsed
239+ }
240240 except json .JSONDecodeError :
241- maybe_structured_content = {"result" : item .text }
241+ maybe_structured_content = {
242+ "result" : item .text
243+ }
242244 break
243245
244- # result
245246 return types .ServerResult (
246247 types .CallToolResult (
247248 content = list (unstructured_content ),
0 commit comments