You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Static resources whose URIs differ only in the fragment or user info collapse into one #1970
Two static resources whose URIs differ only in the fragment collapse into one. WithResources silently drops the second, and reading it returns the first.
Repro at 5221939, in-process over two Pipes:
services.AddMcpServer().WithResources([McpServerResource.Create(()=>"intro text",new(){UriTemplate="docs://guide#intro",Name="intro"}),McpServerResource.Create(()=>"setup text",new(){UriTemplate="docs://guide#setup",Name="setup"}),]);// ...McpServer.Create over StreamServerTransport, McpClient.CreateAsync over StreamClientTransportforeach(varrinawaitclient.ListResourcesAsync())Console.WriteLine($"listed: {r.Uri}");varread=awaitclient.ReadResourceAsync("docs://guide#setup");
$ dotnet run -c Release # net10.0, SDK 10.0.403, ProjectReference to src/ModelContextProtocol at 5221939
listed: docs://guide#intro
read docs://guide#setup -> intro text
Expected: both listed, and the read returns setup text. A server exposing one resource per heading anchor loses every section after the first, with no error. The spec says each resource "is uniquely identified by a URI" (server/resources), and RFC 3986 section 3 puts the fragment in it. Section 3.5 strips it for dereference, not for two entries a server registered.
UriTemplateComparer (UriTemplate.cs:502) says it uses "regular System.Uri equality comparison (host name is case insensitive)", and its tests cover host case only. Uri.Equals also ignores UserInfo and Fragment, so docs://alice@host/x and docs://bob@host/x collide too. McpServerOptionsSetup.cs:63 uses TryAdd, so nothing throws.
I'd keep System.Uri and add && uri1.UserInfo == uri2.UserInfo && uri1.Fragment == uri2.Fragment at line 519:
$ dotnet run -c Release # same app, with that change at UriTemplate.cs:519
listed: docs://guide#intro
listed: docs://guide#setup
read docs://guide#setup -> setup text
# not run: test suite with the change
The comparer also backs IsMatch (AIFunctionMcpServerResource.cs:325) and the SubscribeToResourceAsync filter (McpClient.Methods.cs:832), so a read or update for docs://guide#x would stop matching a static docs://guide. That fits the spec but changes behavior for clients sending fragments today. Shall I open that pull request with a test in McpServerResourceTests?
Activity
Keep static resources distinct when URIs differ only in fragment or u…