Skip to content

fix: isolate instrumentation data per request - #668

Merged
koic merged 1 commit into
modelcontextprotocol:mainfrom
atesgoral:fix/instrumentation-data-per-request
Nov 7, 2026
Merged

koic merged 1 commit into
modelcontextprotocol:mainfrom
atesgoral:fix/instrumentation-data-per-request

Conversation

@atesgoral

@atesgoral atesgoral commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Motivation and Context

Concurrent requests overwrote each other's instrumentation data, because instrument_call kept one record on the shared host. The record is now built inside instrument_call and passed explicitly through the SDK's request handlers. Each writer updates that record, and both hooks receive the same hash for the request. There is no ambient request context.

add_instrumentation_data(**kwargs) stays as a soft-deprecated compatibility shim with its existing behavior. It still uses a shared record and is not safe for concurrent application calls. Both hook signatures are unchanged.

Fixes #657.

How Has This Been Tested?

test/mcp/instrumentation_test.rb and test/mcp/server_test.rb cover overlapping requests, distinct clients and arguments, late errors, nested calls, callback failures and hook identity.

The five isolation regressions use APIs that already exist on main. Against its production code, all five fail with duplicate method or tool records, with no errors. The compatibility test passes there. Against the current published head, all six cases pass (61 assertions). The compatibility test includes updates after a request returns.

The focused tests pass (304 runs, 901 assertions), and so does the full suite (2,506 runs, 8,325 assertions). RuboCop is clean on the changed files.

Breaking Changes

None. Both hook signatures and add_instrumentation_data(**kwargs) keep their behavior, and the helper is now marked @deprecated. The instrument_call block also receives the record as an argument, which blocks that ignore it do not notice.

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 diff touches the private handler signatures, since passing the record explicitly replaces the implicit context. I found no smaller change that is correct without ambient state, because the old helper has no request identity to select a record.

@atesgoral
atesgoral force-pushed the fix/instrumentation-data-per-request branch 2 times, most recently from d323aa7 to 43614b4 Compare November 6, 2026 07:14
@atesgoral
atesgoral marked this pull request as ready for review November 6, 2026 07:18
@atesgoral
atesgoral marked this pull request as draft November 6, 2026 07:54
@atesgoral
atesgoral force-pushed the fix/instrumentation-data-per-request branch from 43614b4 to 2121369 Compare November 6, 2026 13:58
@atesgoral
atesgoral marked this pull request as ready for review November 6, 2026 14:14
@koic
koic merged commit 2cbc16c into modelcontextprotocol:main Nov 7, 2026
13 checks passed
@atesgoral
atesgoral deleted the fix/instrumentation-data-per-request branch November 7, 2026 15:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Concurrent requests overwrite each other's instrumentation data

2 participants