Found during review of #1943.
Problem
detectVerbs (components/mcp/tools/application.ts:694) tests for verb presence without comparing against the base prototype:
create: typeof p.post === 'function' || typeof p.update === 'function',
resources/Resource.ts defines async post() on Resource.prototype, so every class extending Resource reports create: true — whether or not its author implemented post.
The codebase already has the correct version of this check a file away, in components/mcp/toolRegistry.ts (hasClassLevelVerbs), which does compare:
post: (typeof prototype.post === 'function' && prototype.post !== resourcePrototype.post) || typeof prototype.update === 'function',
Its own comment says it "mirrors resources/openApi.ts" — so OpenAPI and MCP's toolRegistry agree, and detectVerbs is the odd one out.
Impact
Every exported Resource gets a spurious create_* tool advertised to the model, described as "Creates a new X record. Runtime RBAC (allowCreate) enforces per-record access at call time." Calling it hits the base post no-op rather than doing anything meaningful, so the LLM is offered an action the Resource does not implement — wasted tool-selection context and a confusing result.
This reaches Harper's own built-ins: resources/login.ts registers class Login extends Resource into the same registry MCP walks, producing a create_login tool.
Suggested fix
Have detectVerbs use hasClassLevelVerbs, or apply the same !== resourcePrototype.<verb> comparison inline. Worth checking get/search/put/patch/delete in the same pass — Resource.prototype may define defaults for those too, in which case the over-registration is broader than create_*.
Note this is independent of #1940/#1943: that PR changes who sees these tools; this one is about which tools exist at all.
Issue generated by kAIle (Claude Opus 4.8).
Found during review of #1943.
Problem
detectVerbs(components/mcp/tools/application.ts:694) tests for verb presence without comparing against the base prototype:resources/Resource.tsdefinesasync post()onResource.prototype, so every class extendingResourcereportscreate: true— whether or not its author implementedpost.The codebase already has the correct version of this check a file away, in
components/mcp/toolRegistry.ts(hasClassLevelVerbs), which does compare:Its own comment says it "mirrors
resources/openApi.ts" — so OpenAPI and MCP'stoolRegistryagree, anddetectVerbsis the odd one out.Impact
Every exported Resource gets a spurious
create_*tool advertised to the model, described as "Creates a new X record. Runtime RBAC (allowCreate) enforces per-record access at call time." Calling it hits the basepostno-op rather than doing anything meaningful, so the LLM is offered an action the Resource does not implement — wasted tool-selection context and a confusing result.This reaches Harper's own built-ins:
resources/login.tsregistersclass Login extends Resourceinto the same registry MCP walks, producing acreate_logintool.Suggested fix
Have
detectVerbsusehasClassLevelVerbs, or apply the same!== resourcePrototype.<verb>comparison inline. Worth checkingget/search/put/patch/deletein the same pass —Resource.prototypemay define defaults for those too, in which case the over-registration is broader thancreate_*.Note this is independent of #1940/#1943: that PR changes who sees these tools; this one is about which tools exist at all.
Issue generated by kAIle (Claude Opus 4.8).