modelcontextprotocol / modelcontextprotocol/typescript-sdk

Is there a way to pass request-scoped context to tool handlers via HTTP headers without modifying the tool schema?

Open
#2,101 1 comment 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

potentially close question
Dominant language
TypeScript
Stars
13.4k
Forks
2.2k
Avg merge
3d 15h
Merged PRs (30d)
4

Description

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?

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the client.callTool and server.registerTool entry points, including how ctx.mcpReq and request.params._meta are handled in the TypeScript SDK. Determine whether request headers can reach tool handlers without changing the tool schema; done means documenting an existing mechanism or defining the required SDK and protocol behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend-api-design
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.