# Implements initialize method and returns capabilities

- **Pattern:** `ab-001836` (`mcp-server.transport-protocol.initialize-handshake`)
- **Severity:** critical
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-001836
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-001836)

## Why it matters

The MCP handshake (`initialize` → server capabilities → `notifications/initialized`) is a mandatory protocol sequence. A server that does not handle the `initialize` method returns a method-not-found error on the very first client message, causing immediate disconnection before any tool can be called. Processing tool requests before the handshake completes violates the protocol ordering guarantee and causes undefined behavior in clients that enforce the sequence. This is a baseline conformance requirement with no workaround on the client side.

## Severity rationale

Critical because a missing `initialize` handler causes clients to disconnect on first contact — no tools, resources, or prompts are reachable until the handshake completes successfully.

## Remediation

If using the MCP SDK, the handshake is handled automatically when you call `server.connect(transport)`. Verify your server config includes all capabilities you implement.

```ts
// src/index.ts — SDK handles initialize automatically
const server = new Server(
  { name: 'my-server', version: '1.0.0' },
  { capabilities: { tools: { listChanged: true }, resources: {} } }
)
const transport = new StdioServerTransport()
await server.connect(transport)  // handshake negotiated here
```

For custom implementations, add a handler for `initialize` that returns `protocolVersion`, `capabilities`, and `serverInfo`, and gates all other method handlers behind an `isInitialized` flag.

## Detection

- **ID:** `initialize-handshake`
- **Severity:** `critical`
- **What to look for:** Enumerate the initialization sequence. Count the steps: client sends initialize, server responds with capabilities, client sends initialized notification. The MCP spec requires a handshake: the client sends `initialize` with its capabilities, the server responds with its capabilities, then the client sends `notifications/initialized`. Check that the server handles the `initialize` method. If using an SDK, verify the SDK's server is instantiated with the correct capabilities object. For custom implementations, check that the server responds to `initialize` with `protocolVersion`, `capabilities`, and `serverInfo`. Check that the server does not process tool/resource requests before initialization is complete.
- **Pass criteria:** The server handles the `initialize` method and returns a valid response with `protocolVersion`, `capabilities` (listing which features are supported), and `serverInfo` (name and version). SDK-based servers have the server properly configured. The handshake must complete within no more than 3 message exchanges and under 5 seconds.
- **Fail criteria:** Custom server does not handle `initialize`, or the response is missing required fields, or the server processes requests before initialization, or capabilities are incorrect.
- **Skip (N/A) when:** All checks skip when no MCP server is detected.

- **Cross-reference:** For version negotiation during handshake, see `version-negotiation`.
- **Detail on fail:** `"Custom JSON-RPC handler has no case for 'initialize' method — clients will get a method-not-found error and disconnect"` or `"Server processes tool calls before receiving 'notifications/initialized' — violates the MCP handshake protocol"`
- **Remediation:** If using an SDK, the handshake is handled automatically. For custom implementations:

  ```ts
  // src/handlers/initialize.ts — proper handshake handler
  server.setRequestHandler(InitializeRequestSchema, async (request) => ({ protocolVersion: "2025-03-26", capabilities: { tools: {} } }))
  ```

  ```ts
  // Custom implementation — handle initialize
  function handleMessage(message: JsonRpcMessage) {
    if (message.method === 'initialize') {
      return {
        jsonrpc: '2.0',
        id: message.id,
        result: {
          protocolVersion: '2024-11-05',
          capabilities: {
            tools: { listChanged: true },
            resources: { subscribe: false, listChanged: true },
          },
          serverInfo: {
            name: 'my-mcp-server',
            version: '1.0.0',
          },
        },
      }
    }
    // Only process other methods after initialized
    if (!isInitialized) {
      return { jsonrpc: '2.0', id: message.id, error: { code: -32600, message: 'Not initialized' } }
    }
    // ... handle other methods
  }
  ```

## External references

- external mcp-spec-lifecycle — https://modelcontextprotocol.io/docs/concepts/lifecycle

Taxons: inference-contract

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