# Capabilities object accurately matches implementation

- **Pattern:** `ab-001846` (`mcp-server.security-capabilities.capability-declaration`)
- **Severity:** high
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001846
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001846)

## 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.

```ts
// 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 `capabilities` object in the server's initialize response against what the server actually implements. If `capabilities.tools` is declared, verify the server handles `tools/list` and `tools/call`. If `capabilities.resources` is declared, verify `resources/list` and `resources/read` are handled. If `capabilities.prompts` is declared, verify `prompts/list` and `prompts/get` are 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 `tools` but `tools/list` returns empty or errors, or server implements `resources/read` but doesn't declare `resources` in 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:

  ```ts
  // src/index.ts — capability declaration
  const server = new Server({ name: "my-server", version: "1.0.0" }, { capabilities: { tools: {}, resources: {}, prompts: {} } })
  ```

  ```ts
  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 — https://modelcontextprotocol.io/docs/concepts/lifecycle#capability-negotiation

Taxons: inference-contract

HTML version: https://auditbuffet.com/patterns/ab-001846
