Conversation
…d match
parse() read the `*` modifier into part.exploded and match() used it,
but expand() never looked at it: `{?keys*}` and `{&keys*}` joined the
values with commas instead of repeating the name, and `{/list}` put one
path segment per value instead of joining them. match() had the same
gap from the other side, building the comma form for an exploded path
part, so a template this SDK advertises in `resources/templates/list`
could not read back its own expansion:
new UriTemplate('db://{/path*}').expand({ path: ['users', 'alice'] })
// 'db:///users/alice'
new UriTemplate('db://{/path*}').match('db:///users/alice')
// null -> ResourceNotFoundError on resources/read
Both sides now follow RFC 6570: an exploded path part spans segments and
splits back into a list, an exploded query repeats the name, and a plain
part keeps the comma-joined value (matched as one segment, commas
included). Two existing tests pinned the non-conformant output and are
updated with the section they contradict.
🦋 Changeset detectedLatest commit: 4d346a6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 6 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/core
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
This branch has not been deployed
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.
Motivation and Context
UriTemplateparses the RFC 6570 explode modifier (*) intopart.exploded, andmatch()reads it — butexpand()never did, andmatch()built the wrong pattern for an exploded path part. The result is that this SDK advertises a template inresources/templates/listthat it cannot read back itself:That
nullis whatMcpServerturns intoResourceNotFoundErroronresources/read, so a client that expands the advertised template correctly is told the resource does not exist.{?keys*}?keys=semi&keys=dot&keys=comma?keys=semi,dot,comma{&keys*}&keys=semi&keys=dot&keys=semi,dot{/list}/red,green,blue/red/green/blue{/list*}and{keys*}happened to be right, because for those two styles the exploded form is what the non-exploded code already produced.match()had the same gap from the other side: it built([^/,]+(?:,[^/,]+)*)for{/list*}, matching the comma form thatexpand()never produced. Both sides now follow the RFC, and agree with each other:Two existing tests pinned the non-conformant output —
{/list*}matching the comma form, and{?tags*}expanding to?tags=a,b,c. Both are updated with the RFC section they contradict in a comment, and the plain{?tags}form is now pinned separately so it stays covered.How Has This Been Tested?
vitest runincore-internal: 1467 passed. The five tests covering this (two corrected, three new) fail onmainwithout the change.vitest runinserver, which routesresources/readthroughmatch: 525 passed.tsc --noEmitincore-internalclean;prettier --checkclean on both files; the pre-push hook ran typecheck, build and lint across the workspace.Breaking Changes
None to the API.
expand()output changes for the three non-conformant forms above, which is the point: any client that expanded{?tags*}per RFC already disagreed with what the server matched. A client relying on the old comma form for an exploded query will now see repeated names; that combination was never matchable by this SDK.Types of changes
Checklist
Additional context
Three open PRs touch the same file for a different reason each: #2216 (multi-variable path expressions in
match) and #2732 / #2810 (percent-decoding the valuesmatchextracts). This one is the explode modifier only, so expect a textual conflict inpartToRegExpwith those, not a semantic overlap.Matching behaviour in general is the subject of #1079. This change only makes
*mean what RFC 6570 says and leaves that issue's questions alone: a query-only template ({?keys*}) still does not match its own expansion, becausematch()treats the input as a URI path — that is a separate question about what a template may match.