From fb019cf0784d247a0df7a8219259b63fa2766611 Mon Sep 17 00:00:00 2001 From: jack12178 Date: Wed, 4 Nov 2026 10:39:26 +0800 Subject: [PATCH] fix(mcpserver): honor warn_on_duplicate_resources for URI templates --- .../mcpserver/resources/resource_manager.py | 11 ++++- .../resources/test_resource_manager.py | 42 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/mcp/server/mcpserver/resources/resource_manager.py b/src/mcp/server/mcpserver/resources/resource_manager.py index e56e3ba177..0709200900 100644 --- a/src/mcp/server/mcpserver/resources/resource_manager.py +++ b/src/mcp/server/mcpserver/resources/resource_manager.py @@ -70,7 +70,11 @@ def add_template( meta: dict[str, Any] | None = None, security: ResourceSecurity = DEFAULT_RESOURCE_SECURITY, ) -> ResourceTemplate: - """Add a template from a function.""" + """Add a template from a function. + + If a template with the same URI template already exists, the existing + template is kept and returned, mirroring `add_resource`. + """ template = ResourceTemplate.from_function( fn, uri_template=uri_template, @@ -83,6 +87,11 @@ def add_template( meta=meta, security=security, ) + existing = self._templates.get(template.uri_template) + if existing: + if self.warn_on_duplicate_resources: + logger.warning(f"Resource template already exists: {template.uri_template}") + return existing self._templates[template.uri_template] = template return template diff --git a/tests/server/mcpserver/resources/test_resource_manager.py b/tests/server/mcpserver/resources/test_resource_manager.py index bbb7de7eb8..816f7d5b93 100644 --- a/tests/server/mcpserver/resources/test_resource_manager.py +++ b/tests/server/mcpserver/resources/test_resource_manager.py @@ -71,6 +71,48 @@ def test_disable_warn_on_duplicate_resources(temp_file: Path, caplog: pytest.Log assert "Resource already exists" not in caplog.text +def test_add_duplicate_template(): + """Test adding the same template twice keeps the first one.""" + + def first(item_id: str) -> str: + return f"first:{item_id}" + + def second(item_id: str) -> str: + return f"second:{item_id}" + + manager = ResourceManager() + first_template = manager.add_template(first, uri_template="items://{item_id}") + second_template = manager.add_template(second, uri_template="items://{item_id}") + + assert first_template is second_template + assert first_template.fn("a") == "first:a" + assert manager.list_templates() == [first_template] + + +def test_warn_on_duplicate_templates(caplog: pytest.LogCaptureFixture): + """Test warning on duplicate templates.""" + + def handler(item_id: str) -> str: + return item_id + + manager = ResourceManager() + manager.add_template(handler, uri_template="items://{item_id}") + manager.add_template(handler, uri_template="items://{item_id}") + assert "Resource template already exists" in caplog.text + + +def test_disable_warn_on_duplicate_templates(caplog: pytest.LogCaptureFixture): + """Test disabling warning on duplicate templates.""" + + def handler(item_id: str) -> str: + return item_id + + manager = ResourceManager(warn_on_duplicate_resources=False) + manager.add_template(handler, uri_template="items://{item_id}") + manager.add_template(handler, uri_template="items://{item_id}") + assert "Resource template already exists" not in caplog.text + + @pytest.mark.anyio async def test_get_resource(temp_file: Path): """Test getting a resource by URI."""