Description
Scenario
A MCP server is using Microsoft Entra ID for authentication. It successfully acquires a token through the client. Said token needs to be used by tools implemented by the server to make sure that they can get user data (e.g., trigger OBO-based token exchanges to acquire user information).
Details
Following the authorization spec and the implementation in the TypeScript SDK, one of the gaps today seems the fact that the authentication context (i.e., the token) is not passed down to the tool/prompt request handlers. For example, if I have a tool that is responsible for getting data from Azure, and I am authenticating with Microsoft Entra ID as my IdP, I need to be able to pass the authentication token that the server uses downstream to the tool itself.
However, when using request handlers like this:
server.setRequestHandler(CallToolRequestSchema, async (request) => { }
The request doesn't seem to carry the auth context. As a hacky workaround, I end up passing the token through a custom-built context, like this:
app.post("/message", requireBearerAuth({
provider,
requiredScopes: ["SOME_SCOPE_I_USE"]
}), async (req, res) => {
console.log("Received message");
// Get the auth context
const authHeader = req.headers.authorization;
const token = authHeader?.split(' ')[1];
// Get the raw body first
const rawBody = await getRawBody(req, {
limit: '1mb',
encoding: 'utf-8'
});
// Amend the context to make sure that I am able
// to pass a token into the tool.
const messageBody = JSON.parse(rawBody.toString());
if (!messageBody.params) {
messageBody.params = {};
}
messageBody.params.context = { token };
await transport.handlePostMessage(req, res, messageBody);
});
This seems like something that the SDK can do natively rather than me amending the context.