# Declares protocolVersion and handles version mismatch

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

## Why it matters

The `protocolVersion` field in the initialize response is how MCP clients determine whether this server is compatible with features they intend to use. An invented version string (e.g., `"1.0"`) does not match any valid MCP release and breaks version-gated features in strict clients. A missing `protocolVersion` entirely leaves clients unable to negotiate compatibility. The MCP spec uses date-based versions (e.g., `"2024-11-05"`) as the canonical format — non-date strings signal that the server was not built against the actual specification.

## Severity rationale

High because an invalid or missing `protocolVersion` breaks version negotiation, which can prevent clients from enabling features the server actually supports.

## Remediation

The SDK sets the correct `protocolVersion` automatically. For custom implementations, use the exact date-format string from the MCP specification.

```ts
// src/handlers/initialize.ts — correct version string
return {
  jsonrpc: '2.0',
  id: request.id,
  result: {
    protocolVersion: '2024-11-05',  // date-based, not semver
    capabilities: {
      tools: { listChanged: true },
    },
    serverInfo: { name: 'my-server', version: '1.0.0' },
  },
}
```

Check the [MCP changelog](https://spec.modelcontextprotocol.io) for the latest valid protocol version string and update when you adopt new spec features.

## Detection

- **ID:** `version-negotiation`
- **Severity:** `high`
- **What to look for:** Count all protocol version references in the codebase. Enumerate whether the server advertises a valid MCP protocol version. Check the `initialize` response (or SDK configuration) for the `protocolVersion` field. Verify it's set to a valid MCP protocol version string (e.g., `"2024-11-05"`). Check whether the server reads the client's requested `protocolVersion` from the `initialize` request and handles mismatches. The SDK typically handles this automatically — verify it's not overridden or misconfigured.
- **Pass criteria:** The server declares a valid `protocolVersion` in its initialize response. If the client requests an incompatible version, the server either negotiates down or returns an error (SDK default behavior is acceptable). At least 1 valid MCP protocol version must be advertised.
- **Fail criteria:** No `protocolVersion` in the initialize response, or an invalid/made-up version string, or the server ignores client version entirely in custom implementations.
- **Skip (N/A) when:** All checks skip when no MCP server is detected.

- **Cross-reference:** For initialize handshake, see `initialize-handshake`.
- **Detail on fail:** `"Initialize response has no protocolVersion field — clients cannot determine compatibility"` or `"Custom server hardcodes protocolVersion '1.0' which is not a valid MCP version string — should be a date-based version like '2024-11-05'"`
- **Remediation:** The SDK handles this automatically. For custom implementations, use the correct version format:

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

  ```ts
  // In initialize response
  result: {
    protocolVersion: '2024-11-05',  // date-based version string
    capabilities: { /* ... */ },
    serverInfo: { name: 'my-server', version: '1.0.0' },
  }
  ```

## External references

- external mcp-spec-versioning — https://modelcontextprotocol.io/docs/concepts/lifecycle#version-negotiation

Taxons: inference-contract

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