11"""
22MCP Resources package - Auto-discovers and registers all resources in this directory.
33"""
4+ import functools
45import inspect
56import logging
67from pathlib import Path
78
89from fastmcp import FastMCP
10+ from pydantic import BaseModel
911from core .telemetry_decorator import telemetry_resource
1012from core .logging_decorator import log_execution
1113
1820__all__ = ['register_all_resources' ]
1921
2022
23+ def _serialize_pydantic (func ):
24+ """Wrap a resource function so Pydantic models are serialized to JSON strings.
25+
26+ FastMCP 3.x expects resource functions to return str, bytes, or ResourceResult.
27+ Our resource functions return MCPResponse (a Pydantic BaseModel). This wrapper
28+ converts them to JSON strings automatically.
29+ """
30+ @functools .wraps (func )
31+ async def wrapper (* args , ** kwargs ):
32+ result = await func (* args , ** kwargs )
33+ if isinstance (result , BaseModel ):
34+ return result .model_dump_json ()
35+ if isinstance (result , dict ):
36+ import json
37+ return json .dumps (result )
38+ return result
39+ return wrapper
40+
41+
2142def register_all_resources (mcp : FastMCP , * , project_scoped_tools : bool = True ):
2243 """
2344 Auto-discover and register all resources in the resources/ directory.
@@ -55,7 +76,8 @@ def register_all_resources(mcp: FastMCP, *, project_scoped_tools: bool = True):
5576 has_query_params = '{?' in uri
5677
5778 if has_query_params :
58- wrapped_template = log_execution (resource_name , "Resource" )(func )
79+ wrapped_template = _serialize_pydantic (func )
80+ wrapped_template = log_execution (resource_name , "Resource" )(wrapped_template )
5981 wrapped_template = telemetry_resource (
6082 resource_name )(wrapped_template )
6183 wrapped_template = mcp .resource (
@@ -69,7 +91,8 @@ def register_all_resources(mcp: FastMCP, *, project_scoped_tools: bool = True):
6991 registered_count += 1
7092 resource_info ['func' ] = wrapped_template
7193 else :
72- wrapped = log_execution (resource_name , "Resource" )(func )
94+ wrapped = _serialize_pydantic (func )
95+ wrapped = log_execution (resource_name , "Resource" )(wrapped )
7396 wrapped = telemetry_resource (resource_name )(wrapped )
7497 wrapped = mcp .resource (
7598 uri = uri ,
0 commit comments