Skip to content

Commit 4a45f59

Browse files
committed
docs: fix stale docstrings and export DEFAULT_MAX_* constants
match() docstring: qualified the round-trip claim with the RFC section 1.4 caveat that values containing their operator's separator unencoded do not round-trip (e.g. {.ext} with 'tar.gz'). resource() decorator docstring: removed the 'or the function has parameters' clause which commit 674783f made stale; template/static is now decided purely by URI variables. Added DEFAULT_MAX_TEMPLATE_LENGTH, DEFAULT_MAX_EXPRESSIONS, and DEFAULT_MAX_URI_LENGTH to __all__ to match the stated intent that these are part of the public API. Moved DEFAULT_MAX_URI_LENGTH import in test file from function body to top-level per repo convention.
1 parent 1500ca3 commit 4a45f59

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

src/mcp/server/mcpserver/server.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,8 +644,9 @@ def resource(
644644
- bytes for binary content
645645
- other types will be converted to JSON
646646
647-
If the URI contains parameters (e.g. "resource://{param}") or the function
648-
has parameters, it will be registered as a template resource.
647+
If the URI contains parameters (e.g. "resource://{param}"), it is
648+
registered as a template resource. Otherwise it is registered as a
649+
static resource; function parameters on a static URI raise an error.
649650
650651
Args:
651652
uri: URI for the resource (e.g. "resource://my-resource" or "resource://{param}")

src/mcp/shared/uri_template.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,15 @@
4141
from typing import Literal, cast
4242
from urllib.parse import quote, unquote
4343

44-
__all__ = ["InvalidUriTemplate", "Operator", "UriTemplate", "Variable"]
44+
__all__ = [
45+
"DEFAULT_MAX_EXPRESSIONS",
46+
"DEFAULT_MAX_TEMPLATE_LENGTH",
47+
"DEFAULT_MAX_URI_LENGTH",
48+
"InvalidUriTemplate",
49+
"Operator",
50+
"UriTemplate",
51+
"Variable",
52+
]
4553

4654
Operator = Literal["", "+", "#", ".", "/", ";", "?", "&"]
4755

@@ -387,8 +395,12 @@ def match(self, uri: str, *, max_uri_length: int = DEFAULT_MAX_URI_LENGTH) -> di
387395
388396
This is the inverse of :meth:`expand`. The URI is matched against
389397
a regex derived from the template and captured values are
390-
percent-decoded. For any value ``v``, ``match(expand({k: v}))``
391-
returns ``{k: v}``.
398+
percent-decoded. The round-trip ``match(expand({k: v})) == {k: v}``
399+
holds when ``v`` does not contain its operator's separator
400+
unencoded: ``{.ext}`` with ``ext="tar.gz"`` expands to
401+
``.tar.gz`` but matches back as ``ext="tar"`` since the ``.``
402+
pattern stops at the first dot. RFC 6570 §1.4 notes this is an
403+
inherent reversal limitation.
392404
393405
Matching is structural at the URI level only: a simple ``{name}``
394406
will not match across a literal ``/`` in the URI (the regex stops

tests/shared/test_uri_template.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import pytest
44

5-
from mcp.shared.uri_template import InvalidUriTemplate, UriTemplate, Variable
5+
from mcp.shared.uri_template import DEFAULT_MAX_URI_LENGTH, InvalidUriTemplate, UriTemplate, Variable
66

77

88
def test_parse_literal_only():
@@ -567,8 +567,6 @@ def test_match_accepts_uri_within_custom_limit():
567567

568568

569569
def test_match_default_uri_length_limit():
570-
from mcp.shared.uri_template import DEFAULT_MAX_URI_LENGTH
571-
572570
t = UriTemplate.parse("{+var}")
573571
# Just at the limit: should match
574572
assert t.match("x" * DEFAULT_MAX_URI_LENGTH) is not None

0 commit comments

Comments
 (0)