Skip to content

fix: make initialize idempotent instead of erroring on repeat calls#257

Open
VictorPuga wants to merge 1 commit into
modelcontextprotocol:mainfrom
victorpuga-forks:initialize
Open

fix: make initialize idempotent instead of erroring on repeat calls#257
VictorPuga wants to merge 1 commit into
modelcontextprotocol:mainfrom
victorpuga-forks:initialize

Conversation

@VictorPuga

Copy link
Copy Markdown

Repeated initialize requests previously failed with "Server is already initialized", breaking stateless HTTP servers and clients that retry initialization. Per the MCP spec, initialize should be safe to call again, so the server now re-negotiates and returns a fresh result instead of throwing.

Fixes #219
Fixes #144

Motivation and Context

Stateless HTTP deployments (and clients that retry initialize for robustness) call initialize more than once against the same Server instance.
The SDK rejected every call after the first with MCPError.invalidRequest("Server is already initialized"), which breaks protocol compliance and forced consumers to write middleware workarounds to synthesize a fake successful response.

How Has This Been Tested?

  • Added unit tests in Tests/MCPTests/ServerTests.swift covering:
    • Two consecutive initialize requests over the same connection both succeed and return serverInfo, with no "error" in the response.
    • The initializeHook is invoked again on each repeated initialize call, confirming re-negotiation happens every time rather than being skipped after the first call.

Breaking Changes

None. Clients that never re-initialize see no change in behavior. Clients that previously relied on getting an error on a second initialize call will now get a successful, re-negotiated result instead.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

Additional context

The fix removes the isInitialized guard in Server.swift's initialize handler so the server always re-runs version negotiation (and re-invokes the initializeHook, if registered) and returns a fresh Initialize.Result, rather than throwing on subsequent calls.
This applies uniformly across all transports (stdio, in-memory, HTTP); no test or documented behavior relies on stdio rejecting a second initialize, and tolerating a duplicate call is not a spec violation.

Repeated `initialize` requests previously failed with "Server is already
initialized", breaking stateless HTTP servers and clients that retry
initialization. Per the MCP spec, initialize should be safe to call
again, so the server now re-negotiates and returns a fresh result
instead of throwing.

Fixes modelcontextprotocol#219
Fixes modelcontextprotocol#144

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant