Vercel MCP Server

import { z } from "zod"; import { handleResponse } from "../utils/response.js"; import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { BASE_URL, DEFAULT_ACCESS_TOKEN } from "../config/constants.js"; export function registerAuthTools(server: McpServer) { // Create Auth Token server.tool( "create_auth_token", "Creates and returns a new authentication token for the currently authenticated User", { name: z.string().describe("Name of the token"), expiresAt: z.number().optional().describe("Token expiration timestamp"), teamId: z.string().optional().describe("The Team identifier to perform the request on behalf of"), slug: z.string().optional().describe("The Team slug to perform the request on behalf of") }, async ({ name, expiresAt, teamId, slug }) => { const url = new URL(`${BASE_URL}/v3/user/tokens`); if (teamId) url.searchParams.append("teamId", teamId); if (slug) url.searchParams.append("slug", slug); const response = await fetch(url.toString(), { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`, }, body: JSON.stringify({ name, expiresAt }), }); const data = await handleResponse(response); return { content: [{ type: "text", text: `Auth token created:\n${JSON.stringify(data, null, 2)}` }], }; } ); // Delete Auth Token server.tool( "delete_auth_token", "Invalidate an authentication token", { tokenId: z.string().describe("The identifier of the token to invalidate. Use 'current' for the current token"), }, async ({ tokenId }) => { const response = await fetch(`${BASE_URL}/v3/user/tokens/${tokenId}`, { method: "DELETE", headers: { Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`, }, }); const data = await handleResponse(response); return { content: [{ type: "text", text: `Auth token deleted:\n${JSON.stringify(data, null, 2)}` }], }; } ); // Get Auth Token Metadata server.tool( "get_auth_token", "Retrieve metadata about an authentication token", { tokenId: z.string().describe("The identifier of the token to retrieve. Use 'current' for the current token"), }, async ({ tokenId }) => { const response = await fetch(`${BASE_URL}/v5/user/tokens/${tokenId}`, { headers: { Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`, }, }); const data = await handleResponse(response); return { content: [{ type: "text", text: `Auth token metadata:\n${JSON.stringify(data, null, 2)}` }], }; } ); // List Auth Tokens server.tool( "list_auth_tokens", "Retrieve a list of the current User's authentication tokens", {}, async () => { const response = await fetch(`${BASE_URL}/v5/user/tokens`, { headers: { Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`, }, }); const data = await handleResponse(response); return { content: [{ type: "text", text: `Auth tokens list:\n${JSON.stringify(data, null, 2)}` }], }; } ); // SSO Token Exchange server.tool( "sso_token_exchange", "Exchange OAuth code for OIDC token during SSO authorization", { code: z.string().describe("The sensitive code received from Vercel"), state: z.string().optional().describe("The state received from the initialization request"), clientId: z.string().describe("The integration client id"), clientSecret: z.string().describe("The integration client secret"), redirectUri: z.string().optional().describe("The integration redirect URI") }, async ({ code, state, clientId, clientSecret, redirectUri }) => { const response = await fetch(`${BASE_URL}/v1/integrations/sso/token`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`, }, body: JSON.stringify({ code, state, client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri }), }); const data = await handleResponse(response); return { content: [{ type: "text", text: `SSO token exchange completed:\n${JSON.stringify(data, null, 2)}` }], }; } ); }