Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/mcp/shared/tool_name_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@
warnings.append("Tool name starts or ends with a dot, which may cause parsing issues in some contexts")

# Check for invalid characters
if not TOOL_NAME_REGEX.match(name):
if not TOOL_NAME_REGEX.fullmatch(name):

Check notice on line 80 in src/mcp/shared/tool_name_validation.py

View check run for this annotation

Claude / Claude Code Review

Same re.match + $ trailing-newline bug remains in ResourceTemplate.matches() on v1.x

Pre-existing issue, not introduced by this PR: the same `$`-with-`re.match` trailing-newline bug fixed here for tool names also exists on v1.x in `ResourceTemplate.matches()` (src/mcp/server/fastmcp/resources/templates.py:89), where `'resource://user/123\n'` matches template `'resource://user/{id}'` with the newline captured into the extracted parameter. The wire path is protected by pydantic `AnyUrl` normalization, but `FastMCP.read_resource`/`Context.read_resource` accept raw `str`, so conside
Comment thread
claude[bot] marked this conversation as resolved.
# Find all invalid characters (unique, preserving order)
invalid_chars: list[str] = []
seen: set[str] = set()
Expand Down
5 changes: 5 additions & 0 deletions tests/shared/test_tool_name_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,17 @@ def test_rejects_name_exceeding_max_length(self) -> None:
("get,user,profile", "','"),
("user/profile/update", "'/'"),
("user@domain.com", "'@'"),
# a single trailing newline slipped past `$` with re.match
("valid_name\n", "'\\n'"),
("a" * 127 + "\n", "'\\n'"),
],
ids=[
"with_spaces",
"with_commas",
"with_slashes",
"with_at_symbol",
"with_trailing_newline",
"max_length_with_trailing_newline",
],
)
def test_rejects_invalid_characters(self, tool_name: str, expected_char: str) -> None:
Expand Down
Loading