Skip to content

[Server] Add an opt-in per-session lock - #582

Closed
chr-hertel wants to merge 4 commits into
modelcontextprotocol:mainfrom
chr-hertel:feat-session-lock
Closed

chr-hertel wants to merge 4 commits into
modelcontextprotocol:mainfrom
chr-hertel:feat-session-lock

Conversation

@chr-hertel

Copy link
Copy Markdown
Member

Stacked on #572 - that one keeps disjoint keys, but read-modify-write on the same key (a counter in a tool handler, _mcp.pending_requests, _mcp.outgoing_queue) still loses updates under parallel requests. Follows the lock idea from #275.

  • Builder::setSessionLock() with a small SessionLockInterface, off by default
  • SymfonySessionLock on top of symfony/lock (optional dependency), bounded wait => TimeoutException
  • Protocol holds the lock from loading to saving the session; a suspended request saves and returns, so the lock is free while it waits on the client - the polling loop locks again only to take a response or queued messages

Fixes chr-hertel#58 (together with #572)

🤖 Generated with Claude Code

Concurrent requests of one session no longer overwrite each other's changes to different keys.
Concurrent requests of one session take turns instead of losing each other's changes to the same key.
@chr-hertel
chr-hertel requested a review from Nyholm as a code owner October 10, 2026 02:18
@chr-hertel chr-hertel added this to the 0.9.0 milestone Oct 10, 2026
@chr-hertel chr-hertel added bug Something isn't working Server Issues & PRs related to the Server component labels Oct 10, 2026
@chr-hertel
chr-hertel requested a balanced review from Copilot October 12, 2026 20:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Concurrent saves, resumed fibers, session destruction, and lease expiry still leave serialization gaps.

4 open findings
What changed in this PR

Adds concurrency protections for session-backed protocol state through incremental saves and an opt-in per-session lock.

Changes:

  • Merges changed session keys onto freshly loaded data.
  • Adds configurable Symfony-based session locking.
  • Adds concurrency tests and usage documentation.
File Description
CHANGELOG.md Records concurrency improvements.
composer.json Suggests and tests with symfony/lock.
docs/​run/​sessions.md Documents concurrent requests and lock setup.
src/​Server/​Builder.php Exposes session-lock configuration.
src/​Server/​Protocol.php Applies locking around protocol session operations.
src/​Server/​Session/​Session.php Tracks and merges changed keys.
src/​Server/​Session/​SessionLockInterface.php Defines the locking contract.
src/​Server/​Session/​SymfonySessionLock.php Implements Symfony-backed locking.
tests/​Unit/​Server/​ProtocolSessionLockTest.php Tests protocol locking behavior.
tests/​Unit/​Server/​Session/​Fixture/​FiberSessionLock.php Simulates locking between fibers.
tests/​Unit/​Server/​Session/​SessionTest.php Tests changed-key merge semantics.
tests/​Unit/​Server/​Session/​SymfonySessionLockTest.php Tests lock acquisition and release.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Server/Protocol.php
'session_id' => $sessionId->toRfc4122(),
]);
// Taken under the lock, from a fresh read, before the transport resumes the fiber with it.
$responseData = $this->locked($sessionId, fn (): mixed => $this->consumeResponse($requestId, $sessionId));
Comment thread src/Server/Protocol.php
Comment on lines +59 to +63
if (null !== $this->changes) {
$data = $this->load();
foreach (array_keys($this->changes) as $key) {
$this->apply($data, (string) $key);
}
Comment thread src/Server/Session/SymfonySessionLock.php
@chr-hertel

Copy link
Copy Markdown
Member Author

Closed in favor of #584

@chr-hertel chr-hertel closed this Oct 12, 2026
@chr-hertel
chr-hertel deleted the feat-session-lock branch October 12, 2026 23:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working Server Issues & PRs related to the Server component

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Server] Parallel requests on one session overwrite each other's session writes

2 participants