Capabilities object accurately matches implementation
Why it matters
The capabilities object in the initialize response is the contract that tells clients which MCP features to use. Declaring resources with subscribe: true but providing no subscription implementation causes clients to attempt subscriptions that fail silently. Implementing prompts but not declaring prompts in capabilities means clients never discover them — the feature is invisible. These mismatches are a form of contract violation: the server lies about its interface, and clients built against that lie fail in ways that are hard to diagnose.
Severity rationale
High because capabilities mismatches cause systematic failures — either clients invoking unimplemented features or silently missing features the server provides — both producing broken integrations.
Remediation
Audit your capabilities object against your actual handler registrations before every release. Declare exactly what you implement, nothing more.
// src/index.ts — capabilities must match implementation
const server = new Server(
{ name: 'my-server', version: '1.0.0' },
{
capabilities: {
tools: { listChanged: true }, // only if tools are registered
resources: { subscribe: false }, // only if resources are registered
// omit 'prompts' if no prompts are registered
},
}
)
Do not copy a capability template and leave unused fields in — remove subscribe: true if you don't implement the resources/subscribe handler.
Detection
-
ID:
capability-declaration -
Severity:
high -
What to look for: Count all capability declarations in the server config. Enumerate which MCP capabilities are declared (tools, resources, prompts, logging). Compare the
capabilitiesobject in the server's initialize response against what the server actually implements. Ifcapabilities.toolsis declared, verify the server handlestools/listandtools/call. Ifcapabilities.resourcesis declared, verifyresources/listandresources/readare handled. Ifcapabilities.promptsis declared, verifyprompts/listandprompts/getare handled. Check for capabilities that are declared but not implemented (false advertising) or implemented but not declared (hidden features clients can't discover). -
Pass criteria: Every capability declared in the initialize response has a corresponding implementation. Every implemented feature is declared in capabilities. No capabilities are advertised but unimplemented, and no features exist but are undeclared. At least 1 capability must be declared, and declared capabilities must match implemented features.
-
Fail criteria: Capabilities declare
toolsbuttools/listreturns empty or errors, or server implementsresources/readbut doesn't declareresourcesin capabilities, or capabilities include features with no implementation. -
Skip (N/A) when: All checks skip when no MCP server is detected.
-
Report even on pass: Report the declared capabilities: "Server declares X capabilities: [list]."
-
Cross-reference: For tool annotations that extend capabilities, see
tool-annotations. -
Detail on fail:
"Capabilities declares 'resources' with 'subscribe: true' but the server has no subscription implementation — clients will attempt to subscribe and get errors"or"Server implements 3 prompts but capabilities object does not declare 'prompts' — clients will never discover them" -
Remediation: Keep capabilities in sync with implementation:
// src/index.ts — capability declaration const server = new Server({ name: "my-server", version: "1.0.0" }, { capabilities: { tools: {}, resources: {}, prompts: {} } })const server = new McpServer({ name: 'my-server', version: '1.0.0', capabilities: { tools: { listChanged: true }, // only if you register tools resources: { subscribe: false }, // only if you register resources // Don't declare prompts if you don't register any }, })
External references
- external · mcp-spec-capabilities — MCP Specification — Server capabilities object
Taxons
History
- 2026-04-18·v1.0.0·Initial import from mcp-server·automated