Ability to pass custom context to tool handlers
Opened this issue · 3 comments
Is your feature request related to a problem? Please describe.
It would be helpful if it were possible to pass arbitrary context to all tools containing information that was derived from the original request.
For my use case, I need to run an additional check to get the current role for a user within my application, but I imagine there would also be other use cases that would be best served by a generic mechanism.
Describe the solution you'd like
Frameworks like GraphQL and TRPC support creating a context object per-request, which is then passed to all methods. A similar implementation for McpServer could look like:
const mcpServer = new McpServer(
{ name: "my-server", version: "1.0.0" },
{
async getContext({ req, res }) {
const role = await getUserRole(req.auth);
return { role };
},
}
);
mcpServer.registerTool("get_info", {}, (input, { ctx }) => {
if (ctx.role !== "admin") {
throw new Error("Unauthorized");
}
return await getInfo(input);
});Describe alternatives you've considered
#166 added support for accessing AuthInfo from a tool call, however this is limited to what is returned from the bearer token middleware.
Additional context
Add any other context or screenshots about the feature request here.
Today you could achieve this with some design patterns - e.g. if you provided your own class for tool registration which wraps the SDK registration, you could pass any additional data you want to your callback.
There's a few open source implementations out there that do this, happy to send you a few - drop me a DM if you wish some concrete examples.
The key requirement I have is I need the context to be unique per request. For my use case I need to make a call to a DB every time a tool is called and I'd like to avoid repeating the logic in every callback if possible.
Context in other frameworks works as a sort of middleware, except more portable as it's agnostic of the transport.
AsyncLocalStorage can solve this. Initialize the store in Express middleware prior to registering the MCP route then you should be able to access the store from within functions that are part of a requests call stack.