Skip to content

Commit ba784d3

Browse files
committed
docs: note AnyUrl pre-normalisation in get_resource docstring
Pydantic's AnyUrl resolves %2E%2E and traversal during validation, so str(AnyUrl("file:///a/%2E%2E/b")) yields "file:///b". The JSON-RPC protocol layer uses raw str and is unaffected, but internal callers wrapping in AnyUrl get silently different security semantics. The normalisation is mostly protective (resolved paths won't match templates with fixed prefixes), so this documents the inconsistency rather than narrowing the signature.
1 parent ec63c20 commit ba784d3

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,17 @@ def add_template(
8383
return template
8484

8585
async def get_resource(self, uri: AnyUrl | str, context: Context[LifespanContextT, RequestT]) -> Resource:
86-
"""Get resource by URI, checking concrete resources first, then templates."""
86+
"""Get resource by URI, checking concrete resources first, then templates.
87+
88+
Note:
89+
Pydantic's ``AnyUrl`` normalises percent-encoding and
90+
resolves ``..`` segments during validation, so a value
91+
constructed as ``AnyUrl("file:///a/%2E%2E/b")`` arrives
92+
here as ``file:///b``. The JSON-RPC protocol layer passes
93+
raw ``str`` values and is unaffected, but internal callers
94+
wrapping URIs in ``AnyUrl`` should be aware that security
95+
checks see the already-normalised form.
96+
"""
8797
uri_str = str(uri)
8898
logger.debug("Getting resource", extra={"uri": uri_str})
8999

0 commit comments

Comments
 (0)