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
Part of the hosted on-behalf-of MCP server proposal (#297).
Scope
Add a documented middleware (interceptor) chain around tool invocation, so cross-cutting concerns can be layered without swapping the server's internal request handlers.
Today the only way to observe or govern a tool call is to replace the low-level CallToolRequest handler on the server. That is a single private slot: it is undocumented, and the next feature that needs the same seam overwrites the previous one. Several accepted and proposed items all need this exact interception point:
Each of these is "run something around a tool invocation with the caller's validated identity in hand." A single ordered middleware chain turns all of them into registered middleware rather than internal extension.
Proposed shape (illustrative, not prescriptive):
asyncdefmiddleware(ctx: ToolCallContext, call_next):
# ctx exposes: tool name, arguments, the validated auth context# (subject, client id, scopes) from request-scoped identity, and a request idresult=awaitcall_next(ctx) # runs inner middleware, then the tool# after: result error flag, durationreturnresult
Middleware runs in registration order (outer to inner) around the handler, may short-circuit (for example, a quota middleware returning an error result without calling call_next), and has read access to the validated auth context so it never re-decodes the bearer.
Acceptance criteria
A public, documented way to register tool-call middleware; the internal request-handler dict is no longer the extension surface.
Middleware receives the tool name, arguments, validated caller identity (subject, client id, scopes), and a request id correlating to the HTTP request.
Middleware runs in a defined order and can short-circuit a call (return an error result without invoking the tool).
Registering middleware does not require importing or mutating server internals.
Dependencies
Builds on request-scoped identity (#302, closed) for the auth context passed to middleware. Unblocks the tool-call half of per-user observability and quotas (#309), rate limiting and abuse protection (#307), and is the seam #373 should be built on.
Part of the hosted on-behalf-of MCP server proposal (#297).
Scope
Add a documented middleware (interceptor) chain around tool invocation, so cross-cutting concerns can be layered without swapping the server's internal request handlers.
Today the only way to observe or govern a tool call is to replace the low-level
CallToolRequesthandler on the server. That is a single private slot: it is undocumented, and the next feature that needs the same seam overwrites the previous one. Several accepted and proposed items all need this exact interception point:Each of these is "run something around a tool invocation with the caller's validated identity in hand." A single ordered middleware chain turns all of them into registered middleware rather than internal extension.
Proposed shape (illustrative, not prescriptive):
Middleware runs in registration order (outer to inner) around the handler, may short-circuit (for example, a quota middleware returning an error result without calling
call_next), and has read access to the validated auth context so it never re-decodes the bearer.Acceptance criteria
Dependencies
Builds on request-scoped identity (#302, closed) for the auth context passed to middleware. Unblocks the tool-call half of per-user observability and quotas (#309), rate limiting and abuse protection (#307), and is the seam #373 should be built on.