fix: duplicate any listed resource URI, not only a registered one
Copilot on #2281: the option's contract said an unregistered URI is ignored, but `withDuplicateResources` runs on the assembled list, which also carries whatever a resource template's `list` callback contributed — so a template-listed URI was duplicated in contradiction of its own doc. Broadened rather than restricted, because scoping it to `registeredResources` would leave half the surface unreproducible: both kinds of entry land in the same Resources sidebar list and collide on the same React key. The contract now says so on `ServerConfig.duplicateResourceUris` and on the config-file mirror, and an integration case covers a template-listed URI — it fails if the override is narrowed to `state.registeredResources`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018yVgAJz4wpkS4mkGk7DQnp Signed-off-by: cliffhall <cliff@futurescale.com>
This commit is contained in:
parent
3153f0305a
commit
339c5f4e27
1 changed files with 40 additions and 7 deletions
|
|
@ -8,6 +8,7 @@ import {
|
|||
type TestServerHttp,
|
||||
createTestServerInfo,
|
||||
createNumberedResources,
|
||||
createFileResourceTemplate,
|
||||
loadConfig,
|
||||
resolveConfig,
|
||||
} from "@modelcontextprotocol/inspector-test-server";
|
||||
|
|
@ -107,6 +108,28 @@ describe("duplicate resource URIs in resources/list (#2206)", () => {
|
|||
]);
|
||||
});
|
||||
|
||||
// The option matches the assembled list, not `state.registeredResources`, so
|
||||
// a URI a resource template contributed is duplicated too (Copilot). Both
|
||||
// kinds land in the same Resources sidebar list and collide on the same React
|
||||
// key, so the fixture has to be able to reproduce either.
|
||||
it("duplicates a URI a resource template listed", async () => {
|
||||
const started = await start({
|
||||
resources: [],
|
||||
resourceTemplates: [
|
||||
createFileResourceTemplate(undefined, () => ["file:///notes.md"]),
|
||||
],
|
||||
duplicateResourceUris: ["file:///notes.md"],
|
||||
});
|
||||
const connected = await connect(started.url);
|
||||
|
||||
const { resources } = await connected.listAllResources();
|
||||
expect(resources.map((r) => r.uri)).toEqual([
|
||||
"file:///notes.md",
|
||||
"file:///notes.md",
|
||||
]);
|
||||
expect(resources.at(-1)?.title).toBe("file:///notes.md (duplicate)");
|
||||
});
|
||||
|
||||
it("ignores a URI that is not registered", async () => {
|
||||
const started = await start({
|
||||
duplicateResourceUris: ["test://not_a_resource"],
|
||||
|
|
|
|||
Loading…
Reference in a new issue