diff --git a/src/mcp/server/mcpserver/resources/resource_manager.py b/src/mcp/server/mcpserver/resources/resource_manager.py index e56e3ba17..0263bc268 100644 --- a/src/mcp/server/mcpserver/resources/resource_manager.py +++ b/src/mcp/server/mcpserver/resources/resource_manager.py @@ -57,6 +57,18 @@ def add_resource(self, resource: Resource) -> Resource: self._resources[str(resource.uri)] = resource return resource + def add_resource_template(self, template: ResourceTemplate) -> ResourceTemplate: + """Add a resource template to the manager. + + Args: + template: A ResourceTemplate instance to add. + + Returns: + The added resource template. + """ + self._templates[template.uri_template] = template + return template + def add_template( self, fn: Callable[..., Any], @@ -83,8 +95,7 @@ def add_template( meta=meta, security=security, ) - self._templates[template.uri_template] = template - return template + return self.add_resource_template(template) async def get_resource( self, uri: AnyUrl | str, context: Context[LifespanContextT, RequestT] diff --git a/src/mcp/server/mcpserver/server.py b/src/mcp/server/mcpserver/server.py index 7bf1993e2..cade416c4 100644 --- a/src/mcp/server/mcpserver/server.py +++ b/src/mcp/server/mcpserver/server.py @@ -79,6 +79,7 @@ Resource, ResourceManager, ResourceSecurity, + ResourceTemplate, ) from mcp.server.mcpserver.tools import Tool, ToolManager from mcp.server.mcpserver.utilities.context_injection import find_context_parameter @@ -729,6 +730,14 @@ def add_resource(self, resource: Resource) -> None: """ self._resource_manager.add_resource(resource) + def add_resource_template(self, template: ResourceTemplate) -> None: + """Add a resource template to the server. + + Args: + template: A ResourceTemplate instance to add + """ + self._resource_manager.add_resource_template(template) + def resource( self, uri: str, @@ -846,7 +855,7 @@ def decorator(fn: _CallableT) -> _CallableT: ) # Register as template - self._resource_manager.add_template( + template = ResourceTemplate.from_function( fn=fn, uri_template=uri, name=name, @@ -858,6 +867,7 @@ def decorator(fn: _CallableT) -> _CallableT: security=security if security is not None else self._resource_security, meta=meta, ) + self._resource_manager.add_resource_template(template) else: if func_params: raise ValueError( diff --git a/tests/server/mcpserver/test_server.py b/tests/server/mcpserver/test_server.py index 48e900dca..48e65d42c 100644 --- a/tests/server/mcpserver/test_server.py +++ b/tests/server/mcpserver/test_server.py @@ -1004,6 +1004,18 @@ def get_csv(user: str) -> str: ) ) + async def test_add_resource_template(self): + """Test that a resource template can be added without using the @resource decorator.""" + from mcp.server.mcpserver.resources import ResourceTemplate + + mcp = MCPServer() + + def get_data(param: str) -> str: # type: ignore # pragma: no cover + return "Data" + + template = ResourceTemplate.from_function(get_data, "resource://{param}") + mcp.add_resource_template(template) + class TestServerResourceMetadata: """Test MCPServer @resource decorator meta parameter for list operations.