@@ -545,69 +545,48 @@ await client.read_resource("test://resource")
545545await client.read_resource(str (my_any_url))
546546```
547547
548- ### Resource templates: RFC 6570 support and security hardening
548+ ### Resource templates: matching behavior changes
549549
550- Resource template matching has been rewritten to support RFC 6570 URI
551- templates (Levels 1-3 plus path-style explode) and to apply path-safety
552- checks to extracted parameters by default.
550+ Resource template matching has been rewritten with RFC 6570 support.
551+ Four behaviors have changed:
553552
554- ** New capabilities:**
555-
556- - ` {+path} ` (reserved expansion) now works — it matches multi-segment
557- paths like ` src/main.py ` . Previously only simple ` {var} ` was supported.
558- - All Level 3 operators: ` {.ext} ` , ` {/seg} ` , ` {;param} ` , ` {?query} ` , ` {&cont} `
559- - Path-style explode: ` {/path*} ` extracts a ` list[str] ` of segments
560- - Template literals are now regex-escaped (a ` . ` in your template no
561- longer matches any character — this was a bug)
562-
563- ** Security hardening (may require opt-out):**
564-
565- By default, extracted parameter values are now rejected if they:
566-
567- - Contain ` .. ` as a path component (e.g., ` .. ` , ` ../etc ` , ` a/../../b ` )
568- - Look like an absolute filesystem path (e.g., ` /etc/passwd ` , ` C:\Windows ` )
569-
570- These checks apply to the decoded value, so they catch traversal
571- regardless of encoding (` ../etc ` , ` ..%2Fetc ` , ` %2E%2E/etc ` all caught).
572-
573- If your template parameters legitimately contain ` .. ` (e.g., git commit
574- ranges like ` HEAD~3..HEAD ` ) or absolute paths, exempt them:
553+ ** Path-safety checks applied by default.** Extracted parameter values
554+ containing ` .. ` as a path component or looking like an absolute path
555+ (` /etc/passwd ` , ` C:\Windows ` ) now cause the template to not match.
556+ This is checked on the decoded value, so ` ..%2Fetc ` and ` %2E%2E ` are
557+ caught too. If a parameter legitimately contains these (a git commit
558+ range, a fully-qualified identifier), exempt it:
575559
576560``` python
577- from mcp.server.mcpserver import MCPServer, ResourceSecurity
578-
579- mcp = MCPServer()
561+ from mcp.server.mcpserver import ResourceSecurity
580562
581563@mcp.resource (
582564 " git://diff/{+range}" ,
583565 security = ResourceSecurity(exempt_params = {" range" }),
584566)
585- def git_diff (range : str ) -> str :
586- ...
567+ def git_diff (range : str ) -> str : ...
587568```
588569
589- Or relax the policy server-wide:
570+ Note that ` .. ` is only flagged as a standalone path component, so a
571+ value like ` v1.0..v2.0 ` is unaffected.
590572
591- ``` python
592- mcp = MCPServer(
593- resource_security = ResourceSecurity(reject_path_traversal = False ),
594- )
595- ```
573+ ** Template literals are regex-escaped.** Previously a ` . ` in your
574+ template matched any character; now it matches only a literal dot.
575+ ` data://v1.0/{id} ` no longer matches ` data://v1X0/42 ` .
596576
597- ** Filesystem handlers:** even with ` {+path} ` allowing slashes, you must
598- still guard against traversal in your handler. Use ` safe_join ` :
577+ ** Query parameters match leniently.** A template like
578+ ` search://{q}{?limit} ` now matches ` search://foo ` (with ` limit ` absent
579+ from the extracted params so your function default applies). Previously
580+ this returned no match. If you relied on all query parameters being
581+ required, add explicit checks in your handler.
599582
600- ``` python
601- from mcp.shared.path_security import safe_join
602-
603- @mcp.resource (" file://docs/{+path}" )
604- def read_doc (path : str ) -> str :
605- return safe_join(" /data/docs" , path).read_text()
606- ```
583+ ** Malformed templates fail at decoration time.** Unclosed braces,
584+ duplicate variable names, and unsupported syntax now raise
585+ ` InvalidUriTemplate ` when the decorator runs, rather than silently
586+ misbehaving at match time.
607587
608- ** Malformed templates now fail at decoration time** with
609- ` InvalidUriTemplate ` (a ` ValueError ` subclass carrying the error
610- position), rather than silently misbehaving at match time.
588+ See [ Resources] ( server/resources.md ) for the full template syntax,
589+ security configuration, and filesystem safety utilities.
611590
612591### Lowlevel ` Server ` : constructor parameters are now keyword-only
613592
0 commit comments