-
Notifications
You must be signed in to change notification settings - Fork 1.4k
RFC: Tool call middleware hook for authorization and cross-cutting concerns #2870
Description
Is this related to an existing feature request or issue?
No response
Summary
Add a standard middleware interface that intercepts tool calls before handler execution, enabling authorization, audit logging, and argument validation to be implemented once and applied across all AWS MCP servers without modifying tool handlers or forking the repo.
Use case
Teams deploying AWS MCP servers in multi-tenant or regulated environments need to enforce per-tool authorization policies, log tool invocations for compliance, and validate arguments against external constraints. Today there is no hook to do this without either modifying each tool handler individually or maintaining a fork. - Both approaches break on upstream updates and produce non-interoperable implementations — every team reimplements the same interception logic independently.
Concrete examples:
- Enforcing that an agent can only call
s3_get_objecton a specific bucket prefix before the handler executes - Logging every tool invocation with caller identity and arguments to a compliance audit trail
- Rejecting tool calls whose arguments fail an external policy check
Proposal
A single middleware interface registered at server startup, applied to every tool call before the handler runs:
type ToolMiddleware interface {
BeforeToolCall(
ctx context.Context,
toolName string,
arguments map[string]any,
meta map[string]any,
) (map[string]any, error) // return modified args, or non-nil error to deny
}Registered at server startup:
server.Use(myAuthMiddleware, myAuditMiddleware)Middleware runs in registration order. A non-nil error short-circuits the chain and returns an MCP error response without invoking the tool handler. The meta parameter exposes params._meta so middleware can read authorization context (tokens, signatures) passed by the client without those fields reaching the tool handler.
Out of scope
- Built-in authorization implementations — the interface is the primitive; implementations are external
- Changes to the MCP wire protocol
- Modifications to individual tool handler signatures or behavior
Potential challenges
Middleware ordering matters when multiple middlewares modify arguments. The proposed return signature (map[string]any, error) passes modified arguments to the next middleware in the chain, which requires each middleware to be aware it may receive arguments already transformed by a predecessor. This is the same pattern mcp-go uses and is well understood.
Panic recovery in middleware should be handled consistently with how the server handles panics in tool handlers today.
Dependencies and Integrations
The GitHub MCP server merged equivalent middleware support in github/github-mcp-server#2026. The official Go MCP SDK ships AddReceivingMiddleware with the same semantics. mcp-go supports WithToolHandlerMiddleware. This proposal aligns awslabs/mcp with the pattern already established across the ecosystem.
No external dependencies required. The interface is pure Go with no new imports.
Alternative solutions
- Fork per team: teams maintain their own patched version of each AWS MCP server.
- Breaks on upstream updates, no interoperability.
- Tool handler modification: authorization logic added to each individual tool handler. Duplicates logic across tools, tightly couples security policy to application code.
- Proxy server: a separate process sits in front of the MCP server and intercepts calls. Adds deployment complexity and a network hop.
A standard middleware hook eliminates all three workarounds.
Happy to submit a draft PR for discussion.Metadata
Metadata
Assignees
Labels
Type
Projects
Status