From 02070e400b72bbe462c790508e0b16e1154ff242 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Mon, 12 Jan 2026 11:46:59 +0100 Subject: [PATCH 1/2] fix: keep all resources registered for resources/read requests The ForMCPRequest optimization was incorrectly filtering resources by doing an exact string match between the URI template pattern and the concrete URI. This would never match because templates like 'repo://{owner}/{repo}/contents{/path*}' don't match concrete URIs like 'repo://owner/repo/contents/file.py'. Instead of implementing template matching in the inventory, we simply keep all resources registered for resources/read requests and let the SDK handle URI template matching internally (which it already does correctly via uritemplate.Regexp().MatchString()). This fixes resources/read returning 'Resource not found' for valid URIs. --- pkg/inventory/registry.go | 6 ++---- pkg/inventory/registry_test.go | 12 +++++------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/pkg/inventory/registry.go b/pkg/inventory/registry.go index f3691e38a..885617b43 100644 --- a/pkg/inventory/registry.go +++ b/pkg/inventory/registry.go @@ -91,7 +91,7 @@ const ( // - MCPMethodToolsList: All available tools (no resources/prompts) // - MCPMethodToolsCall: Only the named tool // - MCPMethodResourcesList, MCPMethodResourcesTemplatesList: All available resources (no tools/prompts) -// - MCPMethodResourcesRead: Only the named resource template +// - MCPMethodResourcesRead: All resources (SDK handles URI template matching) // - MCPMethodPromptsList: All available prompts (no tools/resources) // - MCPMethodPromptsGet: Only the named prompt // - Unknown methods: Empty (no items registered) @@ -134,10 +134,8 @@ func (r *Inventory) ForMCPRequest(method string, itemName string) *Inventory { case MCPMethodResourcesList, MCPMethodResourcesTemplatesList: result.tools, result.prompts = nil, nil case MCPMethodResourcesRead: + // Keep all resources registered - SDK handles URI template matching internally result.tools, result.prompts = nil, nil - if itemName != "" { - result.resourceTemplates = r.filterResourcesByURI(itemName) - } case MCPMethodPromptsList: result.tools, result.resourceTemplates = nil, nil case MCPMethodPromptsGet: diff --git a/pkg/inventory/registry_test.go b/pkg/inventory/registry_test.go index 2c3262873..136f8e523 100644 --- a/pkg/inventory/registry_test.go +++ b/pkg/inventory/registry_test.go @@ -775,17 +775,15 @@ func TestForMCPRequest_ResourcesRead(t *testing.T) { } reg := NewBuilder().SetResources(resources).WithToolsets([]string{"all"}).Build() - filtered := reg.ForMCPRequest(MCPMethodResourcesRead, "repo://{owner}/{repo}") + // Pass a concrete URI - all resources remain registered, SDK handles matching + filtered := reg.ForMCPRequest(MCPMethodResourcesRead, "repo://owner/repo") + // All resources should be available - SDK handles URI template matching internally available := filtered.AvailableResourceTemplates(context.Background()) - if len(available) != 1 { - t.Fatalf("Expected 1 resource for resources/read, got %d", len(available)) - } - if available[0].Template.URITemplate != "repo://{owner}/{repo}" { - t.Errorf("Expected URI template 'repo://{owner}/{repo}', got %q", available[0].Template.URITemplate) + if len(available) != 2 { + t.Fatalf("Expected 2 resources for resources/read (SDK handles matching), got %d", len(available)) } } - func TestForMCPRequest_PromptsList(t *testing.T) { tools := []ServerTool{ mockTool("tool1", "repos", true), From 41a1aae2920bd479acff600909a45c9be036ab1e Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Mon, 12 Jan 2026 12:49:57 +0100 Subject: [PATCH 2/2] chore: remove unused filterResourcesByURI function --- pkg/inventory/filters.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/pkg/inventory/filters.go b/pkg/inventory/filters.go index c5156e61a..533bba552 100644 --- a/pkg/inventory/filters.go +++ b/pkg/inventory/filters.go @@ -203,17 +203,6 @@ func (r *Inventory) filterToolsByName(name string) []ServerTool { return result } -// filterResourcesByURI returns resource templates matching the given URI pattern. -// Uses linear scan - optimized for single-lookup per-request scenarios (ForMCPRequest). -func (r *Inventory) filterResourcesByURI(uri string) []ServerResourceTemplate { - for i := range r.resourceTemplates { - if r.resourceTemplates[i].Template.URITemplate == uri { - return []ServerResourceTemplate{r.resourceTemplates[i]} - } - } - return []ServerResourceTemplate{} -} - // filterPromptsByName returns prompts matching the given name. // Uses linear scan - optimized for single-lookup per-request scenarios (ForMCPRequest). func (r *Inventory) filterPromptsByName(name string) []ServerPrompt {