You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[v2] Expose the JSON-RPC request id to callers of request() (onRequestId) #3061
Protocol.request() assigns the JSON-RPC id internally (this._requestMessageId++) and never exposes it to the caller. An extension that opens a long-lived request, and then receives notifications correlated to that request, can't tell which request a given notification belongs to.
Why it matters
In the Events extension (SEP-3415, see #2945), a client may hold several events/stream requests open at once. Each stream starts with a notifications/events/active that confirms the subscription. On transports without per-request streams (stdio), the client needs the request id to match that notification to the open that produced it.
In @mastra/mcp we first bound each open to the first unclaimed active notification. That can mismatch subscriptions when one confirmation arrives late after a timeout. We now work around it by wrapping transport.send to observe the outgoing message and read its id. That relies on internal envelope details.
Proposal
Expose the id through a RequestOptions callback, for example onRequestId?: (id: RequestId) => void, invoked synchronously before the message is sent. An alternative would be a lower-level API that returns { id, result } for the request.
Versions
We hit this on @modelcontextprotocol/client@2.2.0. It's still present on main (c05225a6), in _requestWithSchemaViaCodec in packages/core-internal/src/shared/protocol.ts.
I'd like to take this on for v2. Could a maintainer confirm the direction and assign #3061 to @Arham-Begani?
I propose an optional RequestOptions.onRequestId callback, called once with the actual allocated JSON-RPC ID before transport dispatch. This would let callers correlate concurrent extension requests without wrapping transport.send; request allocation would remain inside the protocol.
Planned coverage:
ID zero, distinct concurrent IDs and notifications arriving out of order.
Callback ordering, plus unchanged behavior when the option is absent.
Abort, timeout and send-failure cleanup; relevant protocol/client tests, type checks, lint and docs checks.
One API detail to settle: if the callback throws, should the request reject before sending? That seems preferable to dispatching a request the caller could not correlate.
I found no matching open PR in issue-number or onRequestId searches. No implementation has started; I'll wait for approval and assignment.
This proposal was prepared with AI assistance for research and drafting. Any resulting AI-assisted changes will be disclosed and personally reviewed before submission.
Activity
Arham-Begani commentedon Oct 24, 2026
I'd like to take this on for v2. Could a maintainer confirm the direction and assign #3061 to @Arham-Begani?
I propose an optional
RequestOptions.onRequestIdcallback, called once with the actual allocated JSON-RPC ID before transport dispatch. This would let callers correlate concurrent extension requests without wrappingtransport.send; request allocation would remain inside the protocol.Planned coverage:
One API detail to settle: if the callback throws, should the request reject before sending? That seems preferable to dispatching a request the caller could not correlate.
I found no matching open PR in issue-number or
onRequestIdsearches. No implementation has started; I'll wait for approval and assignment.This proposal was prepared with AI assistance for research and drafting. Any resulting AI-assisted changes will be disclosed and personally reviewed before submission.