Consider a scenario where the same MCP tool can be called from different clients (for example, an AI agent and a UI application). In some of those clients, there is additional context that would be useful to pass alongside the tool call, such as a session or entity identifier. This information doesn't change the tool's response at all, it's purely for logging and observability purposes on the server side.
The question is: is there a way to pass this kind of context to the tool handler without adding it as a tool parameter? Adding it as a parameter would force a change to the tool's schema with information that doesn't belong there. The tool interface would end up reflecting the caller's context rather than the tool's actual contract.
What would be ideal is the ability to pass this context via HTTP headers on the tool call request, so that:
- The tool schema remains completely unmodified
- The tool handler can access the context through the transport/request layer, not through its arguments
- Clients that don't need to pass this context are completely unaffected
For example, on the calling side:
const result = await client.callTool(
{ name: "my_tool", arguments: { arg1: "value" } },
{ headers: { "x-session-id": "abc123" } }
);
And on the handler side:
server.registerTool(
"my_tool",
{ inputSchema: z.object({ arg1: z.string() }) },
async (args, ctx) => {
const sessionId = ctx.mcpReq.headers["x-session-id"];
// used for logging/observability only, not part of tool logic
}
);
Looked at the _meta field in request.params, but that still lives in the message body and is visible as part of the protocol contract. It doesn't achieve the same clean separation.
Is there already a mechanism in the protocol or the SDKs that supports this? If not, are there any plans to add something like this?
Consider a scenario where the same MCP tool can be called from different clients (for example, an AI agent and a UI application). In some of those clients, there is additional context that would be useful to pass alongside the tool call, such as a session or entity identifier. This information doesn't change the tool's response at all, it's purely for logging and observability purposes on the server side.
The question is: is there a way to pass this kind of context to the tool handler without adding it as a tool parameter? Adding it as a parameter would force a change to the tool's schema with information that doesn't belong there. The tool interface would end up reflecting the caller's context rather than the tool's actual contract.
What would be ideal is the ability to pass this context via HTTP headers on the tool call request, so that:
For example, on the calling side:
And on the handler side:
Looked at the
_metafield inrequest.params, but that still lives in the message body and is visible as part of the protocol contract. It doesn't achieve the same clean separation.Is there already a mechanism in the protocol or the SDKs that supports this? If not, are there any plans to add something like this?