-
Notifications
You must be signed in to change notification settings - Fork 65
Open
Description
I need to create the server that show the tools based on the user auth token's permission
in below example the adminTool should not be visible to regular user as if that tool doesn't exist
import type { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js";
import { createMcpHandler, withMcpAuth } from "mcp-handler";
import { z } from "zod";
const handler = createMcpHandler(
(server) => {
// Public tool: Accessible to everyone
server.tool("ping", "Returns a pong message", {}, async () => {
return {
content: [{ type: "text", text: "pong" }],
};
});
// Scoped tool: Accessible only with the 'admin' scope
server.tool(
"admin_action",
"Performs an administrative action",
{ action: z.string() },
async (args, extra) => {
const { action } = args as { action: string };
if (!extra.authInfo?.scopes?.includes("admin")) {
return {
content: [
{
type: "text",
text: "Unauthorized: Requires 'admin' scope",
},
],
};
}
return {
content: [
{
type: "text",
text: `Admin action '${action}' performed`,
},
],
};
}
);
},
{},
{
basePath: "/api",
maxDuration: 60,
verboseLogs: true,
}
);
const verifyToken = async (
req: Request,
bearerToken?: string
): Promise<AuthInfo | undefined> => {
if (!bearerToken) return undefined;
const isValid = bearerToken.startsWith("your");
if (!isValid) return undefined;
let scopes: string[] = [];
if (bearerToken.includes("admin")) {
scopes = ["admin", "read:stuff"];
} else {
scopes = ["read:stuff"];
}
return {
token: bearerToken,
scopes: scopes,
clientId: "user123",
extra: {
userId: "123",
},
};
};
const authHandler = withMcpAuth(handler, verifyToken, {
required: false, // Auth is optional, but scoped tools will still check scopes
requiredScopes: ["read:stuff"],
resourceMetadataPath: "/.well-known/oauth-protected-resource",
});
export { authHandler as GET, authHandler as POST };
// TEST USAGE
// npx mcp-remote http://localhost:3000/api/mcp --header "Authorization: Bearer $AUTH_TOKEN"Metadata
Metadata
Assignees
Labels
No labels