-
Notifications
You must be signed in to change notification settings - Fork 600
Fix reserved expansion (e.g. "{+var}") when matching resources #1142
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Add more test cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request fixes URI template parsing for reserved expansion ({+var}), label expansion ({.var}), and path-style parameters ({;var}). The bug was causing templates like samples://{dependency}/{+path} to fail when matching URIs with nested paths.
Changes:
- Fixed reserved expansion to properly match slashes and other reserved characters per RFC 6570
- Fixed label expansion to handle dot-prefixed values with correct separator logic
- Added support for path-style parameter expansion with semicolon-prefixed name=value pairs
- Added 757 lines of comprehensive tests covering all URI template operators and edge cases
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
src/ModelContextProtocol.Core/UriTemplate.cs |
Fixed operator handling in CreateParser switch statement, added AppendPathParameterExpression method, updated separator logic for multi-value expansions, and made UriTemplate class public |
tests/ModelContextProtocol.Tests/UriTemplateCreateParserTests.cs |
Added comprehensive test suite with 757 lines covering all RFC 6570 operators, edge cases, and regression tests for the fixed bugs |
tests/ModelContextProtocol.Tests/Configuration/McpServerResourceRoutingTests.cs |
Added integration test for the reserved expansion bug fix with nested path matching |
|
|
||
| switch (m.Groups["operator"].Value) | ||
| { | ||
| case "+": AppendExpression(ref pattern, paramNames, null, "[^?&#]+"); break; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new case is the primary fix for the "{+path}" issue reported to me by @heaths.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might not have enough context for the full call tree here, but an empty expansion should patch as well, so "*" instead of "+" in the regex. From https://modelcontextprotocol.io/specification/2025-03-26/server/resources#resource-templates, see the test cases in https://datatracker.ietf.org/doc/html/rfc6570#page-22 e.g., O{+empty}X matches OX.
| /// e.g. it may treat portions of invalid templates as literals rather than throwing. | ||
| /// </remarks> | ||
| internal static partial class UriTemplate | ||
| public static partial class UriTemplate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stephentoub @eiriktsarpalis I made UriTemplate.CreateParser and UriTemplate.FormatUri public mostly for testing purposes (although our tests don't directly call FormatUri yet). I'm happy to change this to IVT or reflection. Or we could put all these tests cases through a more complicated harness similar to what I have in McpServerResourceRoutingTests.
Another option might be labeling the API experimental.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't we just extend the test cases at
csharp-sdk/tests/ModelContextProtocol.Tests/Client/McpClientResourceTemplateTests.cs
Line 24 in 89b67b0
| public static IEnumerable<object[]> UriTemplate_InputsProduceExpectedOutputs_MemberData() |
I would like to avoid making these types public. ModelContextProtocol is not the library that should be exposing a UriTemplate implementation publicly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can. This was just a little more straightforward. I understand not wanting to support this API going forward though.
I'll convert these tests cases over to McpServerResourceRoutingTests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assuming the dependency graph is not too complex, couldn't we just link UriTemplate.cs in the test project and test there?
@heaths