Skip to content

Commit fb019cf

Browse files
committed
fix(mcpserver): honor warn_on_duplicate_resources for URI templates
1 parent af4c6f4 commit fb019cf

2 files changed

Lines changed: 52 additions & 1 deletion

File tree

‎src/mcp/server/mcpserver/resources/resource_manager.py‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,11 @@ def add_template(
7070
meta: dict[str, Any] | None = None,
7171
security: ResourceSecurity = DEFAULT_RESOURCE_SECURITY,
7272
) -> ResourceTemplate:
73-
"""Add a template from a function."""
73+
"""Add a template from a function.
74+
75+
If a template with the same URI template already exists, the existing
76+
template is kept and returned, mirroring `add_resource`.
77+
"""
7478
template = ResourceTemplate.from_function(
7579
fn,
7680
uri_template=uri_template,
@@ -83,6 +87,11 @@ def add_template(
8387
meta=meta,
8488
security=security,
8589
)
90+
existing = self._templates.get(template.uri_template)
91+
if existing:
92+
if self.warn_on_duplicate_resources:
93+
logger.warning(f"Resource template already exists: {template.uri_template}")
94+
return existing
8695
self._templates[template.uri_template] = template
8796
return template
8897

‎tests/server/mcpserver/resources/test_resource_manager.py‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,48 @@ def test_disable_warn_on_duplicate_resources(temp_file: Path, caplog: pytest.Log
7171
assert "Resource already exists" not in caplog.text
7272

7373

74+
def test_add_duplicate_template():
75+
"""Test adding the same template twice keeps the first one."""
76+
77+
def first(item_id: str) -> str:
78+
return f"first:{item_id}"
79+
80+
def second(item_id: str) -> str:
81+
return f"second:{item_id}"
82+
83+
manager = ResourceManager()
84+
first_template = manager.add_template(first, uri_template="items://{item_id}")
85+
second_template = manager.add_template(second, uri_template="items://{item_id}")
86+
87+
assert first_template is second_template
88+
assert first_template.fn("a") == "first:a"
89+
assert manager.list_templates() == [first_template]
90+
91+
92+
def test_warn_on_duplicate_templates(caplog: pytest.LogCaptureFixture):
93+
"""Test warning on duplicate templates."""
94+
95+
def handler(item_id: str) -> str:
96+
return item_id
97+
98+
manager = ResourceManager()
99+
manager.add_template(handler, uri_template="items://{item_id}")
100+
manager.add_template(handler, uri_template="items://{item_id}")
101+
assert "Resource template already exists" in caplog.text
102+
103+
104+
def test_disable_warn_on_duplicate_templates(caplog: pytest.LogCaptureFixture):
105+
"""Test disabling warning on duplicate templates."""
106+
107+
def handler(item_id: str) -> str:
108+
return item_id
109+
110+
manager = ResourceManager(warn_on_duplicate_resources=False)
111+
manager.add_template(handler, uri_template="items://{item_id}")
112+
manager.add_template(handler, uri_template="items://{item_id}")
113+
assert "Resource template already exists" not in caplog.text
114+
115+
74116
@pytest.mark.anyio
75117
async def test_get_resource(temp_file: Path):
76118
"""Test getting a resource by URI."""

0 commit comments

Comments
 (0)