Skip to content

Commit 616e81b

Browse files
committed
Move the identifier grammar matrix to the shared test home
The accepted/rejected identifier parametrizations exercise the raw validator, which lives in mcp.shared.extension; the server suite keeps its class-level validation tests.
1 parent 02b8519 commit 616e81b

2 files changed

Lines changed: 47 additions & 63 deletions

File tree

tests/server/mcpserver/test_extension.py

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
ResourceBinding,
2828
ToolBinding,
2929
compose_tool_call_interceptor,
30-
validate_extension_identifier,
3130
)
3231
from mcp.server.mcpserver import Context, MCPServer, require_client_extension
3332
from mcp.server.mcpserver.resources import TextResource
@@ -363,50 +362,6 @@ async def test_version_pinned_method_is_method_not_found_at_a_disallowed_version
363362
assert exc_info.value.error.data == "com.example/pinned"
364363

365364

366-
@pytest.mark.parametrize(
367-
"identifier",
368-
[
369-
"io.modelcontextprotocol/ui",
370-
"com.example/my_ext",
371-
"com.x-y.z2/n.a-b_c",
372-
"example/x",
373-
"a/b",
374-
"com.example/9start",
375-
],
376-
)
377-
def test_grammar_conformant_extension_identifiers_are_accepted(identifier: str) -> None:
378-
"""Spec `_meta` key grammar: dot-separated labels (letter start, letter/digit end,
379-
hyphens interior), a slash, then a name that starts and ends alphanumeric."""
380-
validate_extension_identifier(identifier, owner="T")
381-
382-
383-
@pytest.mark.parametrize(
384-
"identifier",
385-
[
386-
"noprefix",
387-
"-foo/bar",
388-
".leading/x",
389-
"a..b/x",
390-
"foo-/x",
391-
"9foo/x",
392-
"foo/-bar",
393-
"foo/bar-",
394-
"foo/",
395-
"/bar",
396-
"foo/ba r",
397-
"io.modelcontextprotocol/ui\n",
398-
"",
399-
None,
400-
42,
401-
],
402-
)
403-
def test_malformed_extension_identifiers_are_rejected(identifier: Any) -> None:
404-
"""Spec `_meta` key grammar: malformed prefixes (bad label start/end, empty labels)
405-
and malformed names are rejected, as are non-strings."""
406-
with pytest.raises(TypeError):
407-
validate_extension_identifier(identifier, owner="T")
408-
409-
410365
@pytest.mark.parametrize("method", ["tools/list", "completion/complete"])
411366
def test_method_binding_rejects_spec_methods(method: str) -> None:
412367
"""SDK-defined: extension methods are additive — binding a spec-defined request method

tests/shared/test_extension.py

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,60 @@
11
"""Tests for `mcp.shared.extension` — the extension-identifier grammar shared by
2-
the server and client extension surfaces.
2+
the server and client extension surfaces."""
33

4-
The grammar matrix (accepted and rejected identifiers) lives with the original
5-
server tests in `tests/server/mcpserver/test_extension.py`, which exercise the
6-
same function via the server module's re-export.
7-
"""
4+
from typing import Any
85

96
import pytest
107

118
import mcp.server.extension
129
import mcp.shared.extension
13-
14-
15-
def test_validator_importable_from_shared_home() -> None:
16-
"""SDK-defined: the identifier grammar lives in `mcp.shared.extension` — one
17-
source of truth for both the server and client extension surfaces."""
18-
mcp.shared.extension.validate_extension_identifier("com.example/thing", owner="T")
19-
20-
21-
def test_validator_rejects_malformed_identifier_via_shared_path() -> None:
22-
"""SDK-defined: the shared-home function enforces the same `vendor-prefix/name`
23-
grammar the server side always has."""
24-
with pytest.raises(TypeError):
25-
mcp.shared.extension.validate_extension_identifier("noprefix", owner="T")
10+
from mcp.shared.extension import validate_extension_identifier
2611

2712

2813
def test_server_extension_module_reexports_shared_validator() -> None:
2914
"""SDK-defined: `mcp.server.extension.validate_extension_identifier` remains
3015
importable after the move and is the very same function object."""
3116
assert mcp.server.extension.validate_extension_identifier is mcp.shared.extension.validate_extension_identifier
17+
18+
19+
@pytest.mark.parametrize(
20+
"identifier",
21+
[
22+
"io.modelcontextprotocol/ui",
23+
"com.example/my_ext",
24+
"com.x-y.z2/n.a-b_c",
25+
"example/x",
26+
"a/b",
27+
"com.example/9start",
28+
],
29+
)
30+
def test_grammar_conformant_extension_identifiers_are_accepted(identifier: str) -> None:
31+
"""Spec `_meta` key grammar: dot-separated labels (letter start, letter/digit end,
32+
hyphens interior), a slash, then a name that starts and ends alphanumeric."""
33+
validate_extension_identifier(identifier, owner="T")
34+
35+
36+
@pytest.mark.parametrize(
37+
"identifier",
38+
[
39+
"noprefix",
40+
"-foo/bar",
41+
".leading/x",
42+
"a..b/x",
43+
"foo-/x",
44+
"9foo/x",
45+
"foo/-bar",
46+
"foo/bar-",
47+
"foo/",
48+
"/bar",
49+
"foo/ba r",
50+
"io.modelcontextprotocol/ui\n",
51+
"",
52+
None,
53+
42,
54+
],
55+
)
56+
def test_malformed_extension_identifiers_are_rejected(identifier: Any) -> None:
57+
"""Spec `_meta` key grammar: malformed prefixes (bad label start/end, empty labels)
58+
and malformed names are rejected, as are non-strings."""
59+
with pytest.raises(TypeError):
60+
validate_extension_identifier(identifier, owner="T")

0 commit comments

Comments
 (0)