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 registerUserTools(server: McpServer) {
// Delete User Account
server.tool(
"delete_user",
"Initiates the deletion process for the currently authenticated User",
{
reasons: z.array(
z.object({
slug: z.string().describe("Reason identifier"),
description: z.string().describe("Detailed description of the reason")
})
).optional().describe("Optional array of objects that describe the reason why the User account is being deleted")
},
async ({ reasons }) => {
const response = await fetch(`${BASE_URL}/v1/user`, {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`,
},
...(reasons && { body: JSON.stringify({ reasons }) })
});
const data = await handleResponse(response);
return {
content: [
{ type: "text", text: `User deletion initiated:\n${JSON.stringify(data, null, 2)}` },
],
};
}
);
// Get User Information
server.tool(
"get_user",
"Retrieves information related to the currently authenticated User",
{},
async () => {
const response = await fetch(`${BASE_URL}/v2/user`, {
headers: {
Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`,
},
});
const data = await handleResponse(response);
return {
content: [
{ type: "text", text: `User information:\n${JSON.stringify(data, null, 2)}` },
],
};
}
);
// List User Events
server.tool(
"list_user_events",
"Retrieves a list of events generated by the User on Vercel",
{
limit: z.number().optional().describe("Maximum number of items which may be returned"),
since: z.string().optional().describe("Timestamp to only include items created since then (e.g. 2019-12-08T10:00:38.976Z)"),
until: z.string().optional().describe("Timestamp to only include items created until then (e.g. 2019-12-09T23:00:38.976Z)"),
types: z.string().optional().describe("Comma-delimited list of event types to filter the results by (e.g. login,team-member-join,domain-buy)"),
userId: z.string().optional().describe("When retrieving events for a Team, filter events by a specific member"),
withPayload: z.string().optional().describe("When set to true, includes the payload field for each event"),
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 ({ limit, since, until, types, userId, withPayload, teamId, slug }) => {
const url = new URL(`${BASE_URL}/v3/events`);
if (limit) url.searchParams.append("limit", limit.toString());
if (since) url.searchParams.append("since", since);
if (until) url.searchParams.append("until", until);
if (types) url.searchParams.append("types", types);
if (userId) url.searchParams.append("userId", userId);
if (withPayload) url.searchParams.append("withPayload", withPayload);
if (teamId) url.searchParams.append("teamId", teamId);
if (slug) url.searchParams.append("slug", slug);
const response = await fetch(url.toString(), {
headers: {
Authorization: `Bearer ${DEFAULT_ACCESS_TOKEN}`,
},
});
const data = await handleResponse(response);
return {
content: [
{ type: "text", text: `User events:\n${JSON.stringify(data, null, 2)}` },
],
};
}
);
}