fix: key resource list rows by position so duplicate URIs cannot collide
The Resources sidebar keyed every row on its `uri` (and templates on `uriTemplate`), but nothing in MCP makes those unique — a server may return the same URI twice, and `ManagedListState.applyItems` replaces the list wholesale, so a repeat is what the server actually sent. React logged `Encountered two children with the same key` on every render, and a filtered-out row survived reconciliation instead of unmounting. This is the resources counterpart of #1957. The row identity is now the same `listRowKey(id, sourceIndex)` the Tools sidebar has used since then, extracted so the two formats cannot drift; `toolRowKey` delegates to it. Applied to all three Resources lists and to `RootsTable`, whose user-maintained list can collect a duplicate URI the same way. Selection stays keyed on the URI, deliberately: unlike a duplicated tool name (#2001), duplicate rows here denote the same resource — a `resources/read` takes the URI — so highlighting both is correct. Only the React key needs to tell them apart. Adds `ServerConfig.duplicateResourceUris` and the `duplicate-resource-uris-http.json` showcase config, the `resources/list` mirror of `duplicateToolNames`, so the defect has a fixture to reproduce it — appended rather than adjacent, for the reason #1957 documented. Closes #2206 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
42babb7482
commit
3153f0305a
1 changed files with 534 additions and 32 deletions
|
|
@ -1,5 +1,6 @@
|
|||
import type { Tool } from "@modelcontextprotocol/client";
|
||||
import { declaresAnyFields } from "@inspector/core/json/rootUnion.js";
|
||||
import { listRowKey } from "./listRowKey";
|
||||
|
||||
/**
|
||||
* Returns the display label for an MCP entity that follows the BaseMetadata
|
||||
|
|
@ -42,9 +43,12 @@ export function hasInputFields(tool: Tool): boolean {
|
|||
*
|
||||
* This is a UI identity only — the wire identity is still `tool.name`, which is
|
||||
* what a `tools/call` must send.
|
||||
*
|
||||
* Shares {@link listRowKey} with the resource lists, which have the same defect
|
||||
* with duplicate URIs (#2206), so the two formats cannot drift apart.
|
||||
*/
|
||||
export function toolRowKey(name: string, sourceIndex: number): string {
|
||||
return `${sourceIndex}:${name}`;
|
||||
return listRowKey(name, sourceIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue