feat: #502 resource templates with basic template matcher#606
Merged
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
e5l
previously approved these changes
Mar 17, 2026
Contributor
e5l
left a comment
There was a problem hiding this comment.
lgtm, please check comments before merging
kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/shared/Protocol.kt
Show resolved
Hide resolved
kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/McpException.kt
Outdated
Show resolved
Hide resolved
8edad43 to
aa0ee0f
Compare
Introduce `ResourceTemplate` and `RegisteredResourceTemplate` implementation to register and manage parameterized resource templates. Added support for listing, reading, and removing resource templates. Updated error handling for unmatched URIs with a new `RESOURCE_NOT_FOUND` RPC error. Includes corresponding tests and API updates.
…lidation Replaced `check(options.capabilities.* != null)` with `checkNotNull` for improved clarity and consistency in validating server capabilities.
…ssion Add specific handling for `CancellationException` in `Protocol.kt` to ensure it is rethrown instead of being suppressed by the generic `Throwable` catch block.
…URI matching - Added `ResourceTemplateMatcher` interface and its implementation `SimpleUriResourceTemplateMatcher` to improve URI matching specificity and safety. - Replaced usage of `UriTemplate` and `UriTemplateMatcher` with `ResourceTemplateMatcher` in `RegisteredResourceTemplate`. - Updated `ServerOptions` to include a configurable `ResourceTemplateMatcherFactory`, defaulting to `SimpleUriResourceTemplateMatcher.factory`. - Enhanced resource registration logic to utilize matchers for improved URI matching robustness. - Improved template selection logic by prioritizing specificity, variable minimization, and registration order.
…tors - Enhanced `McpException` default message logic to ensure consistency and eliminate redundant prefixes. - Simplified test assertions in integration tests using `shouldBe` for better readability. - Added synthetic constructors in `ServerOptions` and `McpException` for better Kotlin compatibility. - Updated `Protocol` to rethrow `CancellationException` explicitly, ensuring proper cancellation behavior.
aa0ee0f to
9ce68b7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Important
Full support of RFC-6570 is out of scope and can be implemented by users or as an independent feature.
Reasoning: Safe and secure RFC-6570 implementation is a separate problem and should not block the support of basic MCP features.
Adds resource template matching for the MCP server, enabling handlers to be registered against RFC 6570 Level 1 URI templates (e.g.
files/{path},users/{id}/profile) and resolved by specificity when multiple templates match the same URI.ResourceTemplateMatcher/ResourceTemplateMatcherFactory— extension point for URItemplate matching;
ServerOptions.resourceTemplateMatcherFactoryis public so callers can inject a custom implementation.PathSegmentTemplateMatcher— default implementation: splits on/, parses the template once at construction, and scores each match (literal segment = 2 pts, variable capture = 1 pt) so the most-specific template always wins. Enforces safety limits (URI length cap, segment depth cap) and delegates dot-segment normalization to the platform URI parser (JVM:java.net.URI.normalize, JS:URLAPI, native/WASM: no-op — documented limitation).handleReadResourceusesmaxWithOrNull(O(n)) to select the highest-scoring match; ties broken by fewest variable captures, then registration order.CancellationException—Protocol.kthad acatch (cause: Throwable)that silently suppressed coroutine cancellation. The catch block now re-throwsCancellationExceptionbefore the generic handler runs.checkNotNullin capability validation — replacescheck(x != null)with the idiomaticcheckNotNull(x)across all capability guard sites inServer.kt.Security
PathSegmentTemplateMatcherapplies one percent-decode pass via Ktor'sdecodeURLPart. Decoded variable values are attacker-controlled and documented as such — handlers must validate before using values in file paths, database queries, or downstream URLs. A dedicated security regression test suite (PathSegmentTemplateMatcherSecurityTest) covers double-decode, null bytes, encoded slashes, depth exhaustion, dot-segment traversal, and query/fragment pass-through.Motivation and Context
Closes #502, #591
How Has This Been Tested?
Conformance test (resources-templates-read #591), unit/integration/security test
Breaking Changes
Any code that called
McpException(-32600, "Connection closed")previously receivedexception.message == "MCP error -32600: Connection closed". After this change it returns "Connection closed". This is a behavioral API break — theException.messagecontract changed without a deprecation path.Types of changes
Checklist
Additional context
#603, #604, #503