Skip to content

Commit 74ae395

Browse files
committed
fix: reject changed duplicate initialize
1 parent 2397319 commit 74ae395

2 files changed

Lines changed: 25 additions & 1 deletion

File tree

src/mcp/server/runner.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,12 @@ def _negotiate_initialize(params: Mapping[str, Any] | None) -> tuple[InitializeR
398398

399399
def _handle_initialize(self, params: Mapping[str, Any] | None) -> InitializeResult:
400400
"""Build the `initialize` result; state commits later in `_on_request`."""
401-
_, negotiated = self._negotiate_initialize(params)
401+
init, negotiated = self._negotiate_initialize(params)
402+
if self.connection.client_params is not None and init != self.connection.client_params:
403+
raise MCPError(
404+
code=INVALID_PARAMS,
405+
message="Session already initialized with different parameters",
406+
)
402407
opts = self.init_options if self.init_options is not None else self.server.create_initialization_options()
403408
return InitializeResult(
404409
protocol_version=negotiated,

tests/server/test_runner.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,25 @@ async def test_runner_handles_initialize_and_populates_connection(server: SrvT):
172172
assert runner.connection.initialize_accepted is True
173173

174174

175+
@pytest.mark.anyio
176+
async def test_runner_rejects_changed_duplicate_initialize(server: SrvT):
177+
async with connected_runner(server, initialized=False) as (client, runner):
178+
first_params = _initialize_params()
179+
await client.send_raw_request("initialize", first_params)
180+
assert runner.connection.client_params is not None
181+
assert runner.connection.client_params.client_info.name == "test-client"
182+
183+
second_params = _initialize_params()
184+
second_params["clientInfo"] = {"name": "second-client", "version": "1.0"}
185+
with pytest.raises(MCPError) as exc:
186+
await client.send_raw_request("initialize", second_params)
187+
188+
assert exc.value.error.code == INVALID_PARAMS
189+
assert "already initialized" in exc.value.error.message
190+
assert runner.connection.client_params is not None
191+
assert runner.connection.client_params.client_info.name == "test-client"
192+
193+
175194
@pytest.mark.anyio
176195
async def test_runner_initialize_opens_gate_but_event_fires_only_after_initialized_notification(server: SrvT):
177196
"""`initialize` commits the gate flag and peer info, but the public

0 commit comments

Comments
 (0)