Skip to main content
Glama

Rollbar MCP Server

by hiyorineko
rollbar.ts20.1 kB
import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { CallToolRequestSchema, ListToolsRequestSchema, Tool } from "@modelcontextprotocol/sdk/types.js"; import axios, { AxiosError } from "axios"; import { DeployResponse, ItemResponse, ListDeploysResponse, ListEnvironmentsResponse, ListItemsResponse, ListOccurrencesResponse, ListProjectsResponse, ListUsersResponse, OccurrenceResponse, ProjectResponse, RollbarProject, UserResponse, } from "./types.js"; // Check for project access token and account access token // Project Access Token is used for project-specific APIs (items, deploys, etc. within a project) // Account Access Token is used for account-wide APIs (project list, user list, etc.) const ROLLBAR_PROJECT_TOKEN = process.env.ROLLBAR_PROJECT_TOKEN; const ROLLBAR_ACCOUNT_TOKEN = process.env.ROLLBAR_ACCOUNT_TOKEN; // Verify the required tokens based on the APIs this project will use // For current functionality, at least one of these tokens is required if (!ROLLBAR_PROJECT_TOKEN && !ROLLBAR_ACCOUNT_TOKEN) { console.error("At least one of ROLLBAR_PROJECT_TOKEN or ROLLBAR_ACCOUNT_TOKEN is required"); process.exit(1); } // List of supported APIs const SUPPORTED_APIS = { // APIs that use Project Token projectApis: [ "rollbar_list_items", "rollbar_get_item", "rollbar_get_item_by_counter", "rollbar_list_occurrences", "rollbar_get_occurrence", "rollbar_list_environments", "rollbar_list_deploys", "rollbar_get_deploy", ], // APIs that use Account Token accountApis: ["rollbar_list_projects", "rollbar_get_project", "rollbar_list_users", "rollbar_get_user"], }; // Warning if using Project APIs but Project Token is not set if (!ROLLBAR_PROJECT_TOKEN) { console.warn("ROLLBAR_PROJECT_TOKEN is not set, the following APIs will not be available:"); console.warn(SUPPORTED_APIS.projectApis.join(", ")); } // Warning if using Account APIs but Account Token is not set if (!ROLLBAR_ACCOUNT_TOKEN) { console.warn("ROLLBAR_ACCOUNT_TOKEN is not set, the following APIs will not be available:"); console.warn(SUPPORTED_APIS.accountApis.join(", ")); } // Project name and ID environment variables (optional) const ROLLBAR_PROJECT_NAME = process.env.ROLLBAR_PROJECT_NAME; const ROLLBAR_PROJECT_ID = process.env.ROLLBAR_PROJECT_ID ? parseInt(process.env.ROLLBAR_PROJECT_ID, 10) : undefined; // Function to find project ID by name const findProjectIdByName = async (projectName: string): Promise<number | undefined> => { // Cannot execute if Account Token is not set if (!ROLLBAR_ACCOUNT_TOKEN || !accountClient) { console.error("ROLLBAR_ACCOUNT_TOKEN is not set, cannot search for project by name"); return undefined; } try { const response = await accountClient.get<ListProjectsResponse>("/projects"); const projects = response.data.result; const project = projects.find((p: RollbarProject) => p.name === projectName); return project?.id; } catch (error) { console.error("Error finding project by name:", error); return undefined; } }; // Function to get project ID from environment variables or project name const getEffectiveProjectId = async (providedId?: number): Promise<number | undefined> => { // Use provided ID if available if (providedId) return providedId; // Use project ID from environment variable if available if (ROLLBAR_PROJECT_ID) return ROLLBAR_PROJECT_ID; // Search by project name if (ROLLBAR_PROJECT_NAME) { const idFromName = await findProjectIdByName(ROLLBAR_PROJECT_NAME); if (idFromName) return idFromName; } return undefined; }; const API_BASE_URL = "https://api.rollbar.com/api/1"; // Client for project-specific APIs (only if set) const projectClient = ROLLBAR_PROJECT_TOKEN ? axios.create({ baseURL: API_BASE_URL, headers: { "X-Rollbar-Access-Token": ROLLBAR_PROJECT_TOKEN, "Content-Type": "application/json", }, }) : null; // Client for account-wide APIs (only if set) const accountClient = ROLLBAR_ACCOUNT_TOKEN ? axios.create({ baseURL: API_BASE_URL, headers: { "X-Rollbar-Access-Token": ROLLBAR_ACCOUNT_TOKEN, "Content-Type": "application/json", }, }) : null; const LIST_ITEMS_TOOL: Tool = { name: "rollbar_list_items", description: "List items (errors) from Rollbar", inputSchema: { type: "object", properties: { status: { type: "string", description: "Filter by status (active, resolved, muted, etc.)" }, level: { type: "string", description: "Filter by level (critical, error, warning, info, debug)" }, environment: { type: "string", description: "Filter by environment (production, staging, etc.)" }, limit: { type: "number", description: "Maximum number of items to return (default: 20)" }, page: { type: "number", description: "Page number for pagination (default: 1)" }, }, }, }; const GET_ITEM_TOOL: Tool = { name: "rollbar_get_item", description: "Get a specific item (error) from Rollbar using the internal item ID maintained by Rollbar's system.", inputSchema: { type: "object", properties: { id: { type: "number", description: "Item ID" }, }, required: ["id"], }, }; const GET_ITEM_BY_UUID_TOOL: Tool = { name: "rollbar_get_item_by_occurrence_uuid", description: "Get a specific item (error) from Rollbar using an occurrence UUID. The UUID must be from an occurrence that belongs to the item.", inputSchema: { type: "object", properties: { uuid: { type: "string", description: "Occurrence UUID" }, }, required: ["uuid"], }, }; const GET_ITEM_BY_COUNTER_TOOL: Tool = { name: "rollbar_get_item_by_counter", description: "Get a specific item by project counter from Rollbar. The counter is the visible ID that appears in the Rollbar UI.", inputSchema: { type: "object", properties: { counter: { type: "number", description: "Project counter for the item" }, }, required: ["counter"], }, }; const LIST_OCCURRENCES_TOOL: Tool = { name: "rollbar_list_occurrences", description: "List occurrences of errors from Rollbar", inputSchema: { type: "object", properties: { itemId: { type: "number", description: "Item ID to filter occurrences" }, limit: { type: "number", description: "Maximum number of occurrences to return (default: 20)" }, page: { type: "number", description: "Page number for pagination (default: 1)" }, }, }, }; const GET_OCCURRENCE_TOOL: Tool = { name: "rollbar_get_occurrence", description: "Get a specific occurrence of an error from Rollbar", inputSchema: { type: "object", properties: { id: { type: "string", description: "Occurrence ID" }, }, required: ["id"], }, }; const LIST_PROJECTS_TOOL: Tool = { name: "rollbar_list_projects", description: "List projects from Rollbar", inputSchema: { type: "object", properties: {}, }, }; const GET_PROJECT_TOOL: Tool = { name: "rollbar_get_project", description: "Get a specific project from Rollbar", inputSchema: { type: "object", properties: { id: { type: "number", description: "Project ID" }, }, required: ["id"], }, }; const LIST_ENVIRONMENTS_TOOL: Tool = { name: "rollbar_list_environments", description: "List environments from Rollbar", inputSchema: { type: "object", properties: { projectId: { type: "number", description: "Project ID" }, }, required: ["projectId"], }, }; const LIST_USERS_TOOL: Tool = { name: "rollbar_list_users", description: "List users from Rollbar", inputSchema: { type: "object", properties: {}, }, }; const GET_USER_TOOL: Tool = { name: "rollbar_get_user", description: "Get a specific user from Rollbar", inputSchema: { type: "object", properties: { id: { type: "number", description: "User ID" }, }, required: ["id"], }, }; const LIST_DEPLOYS_TOOL: Tool = { name: "rollbar_list_deploys", description: "List deploys from Rollbar", inputSchema: { type: "object", properties: { projectId: { type: "number", description: "Project ID" }, environment: { type: "string", description: "Environment name" }, limit: { type: "number", description: "Maximum number of deploys to return (default: 20)" }, page: { type: "number", description: "Page number for pagination (default: 1)" }, }, required: ["projectId"], }, }; const GET_DEPLOY_TOOL: Tool = { name: "rollbar_get_deploy", description: "Get a specific deploy from Rollbar", inputSchema: { type: "object", properties: { deployId: { type: "number", description: "Deploy ID" }, }, required: ["deployId"], }, }; export const createServer = () => { const server = new Server( { name: "rollbar-mcp-server", version: "1.0.0", }, { capabilities: { tools: {}, }, }, ); server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ LIST_ITEMS_TOOL, GET_ITEM_TOOL, GET_ITEM_BY_UUID_TOOL, GET_ITEM_BY_COUNTER_TOOL, LIST_OCCURRENCES_TOOL, GET_OCCURRENCE_TOOL, LIST_PROJECTS_TOOL, GET_PROJECT_TOOL, LIST_ENVIRONMENTS_TOOL, LIST_USERS_TOOL, GET_USER_TOOL, LIST_DEPLOYS_TOOL, GET_DEPLOY_TOOL, ], })); server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const { name, arguments: args = {} } = request.params; switch (name) { case "rollbar_list_items": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { status, level, environment, limit = 20, page = 1, } = args as { status?: string; level?: string; environment?: string; limit?: number; page?: number; }; const params: Record<string, string | number> = { page, limit }; if (status) params.status = status; if (level) params.level = level; if (environment) params.environment = environment; const response = await projectClient.get<ListItemsResponse>("/items", { params }); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_get_item": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { id } = args as { id: number }; const response = await projectClient.get<ItemResponse>(`/item/${id}`); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_get_item_by_occurrence_uuid": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { uuid } = args as { uuid: string }; const response = await projectClient.get<ItemResponse>(`/item/${uuid}`); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_get_item_by_counter": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { counter } = args as { counter: number }; const response = await projectClient.get<ItemResponse>(`/item_by_counter/${counter}`); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_list_occurrences": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { itemId, limit = 20, page = 1, } = args as { itemId?: number; limit?: number; page?: number; }; const params: Record<string, string | number> = { page, limit }; let endpoint = "/occurrences"; if (itemId) { endpoint = `/item/${itemId}/instances`; } const response = await projectClient.get<ListOccurrencesResponse>(endpoint, { params }); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_get_occurrence": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { id } = args as { id: string }; const response = await projectClient.get<OccurrenceResponse>(`/instance/${id}`); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_list_projects": { // Account Token is required if (!accountClient) { throw new Error("ROLLBAR_ACCOUNT_TOKEN is not set, cannot use this API"); } const response = await accountClient.get<ListProjectsResponse>("/projects"); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_get_project": { // Account Token is required if (!accountClient) { throw new Error("ROLLBAR_ACCOUNT_TOKEN is not set, cannot use this API"); } const { id } = args as { id: number }; // Use environment variable project ID as default value, or search by project name const effectiveProjectId = await getEffectiveProjectId(id); if (!effectiveProjectId) { throw new Error("Project ID is required but not provided in request or environment variables"); } const response = await accountClient.get<ProjectResponse>(`/project/${effectiveProjectId}`); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_list_environments": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { projectId } = args as { projectId: number }; // Use environment variable project ID as default value, or search by project name const effectiveProjectId = await getEffectiveProjectId(projectId); if (!effectiveProjectId) { throw new Error("Project ID is required but not provided in request or environment variables"); } const response = await projectClient.get<ListEnvironmentsResponse>( `/project/${effectiveProjectId}/environments`, ); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_list_users": { // Account Token is required if (!accountClient) { throw new Error("ROLLBAR_ACCOUNT_TOKEN is not set, cannot use this API"); } const response = await accountClient.get<ListUsersResponse>("/users"); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_get_user": { // Account Token is required if (!accountClient) { throw new Error("ROLLBAR_ACCOUNT_TOKEN is not set, cannot use this API"); } const { id } = args as { id: number }; const response = await accountClient.get<UserResponse>(`/user/${id}`); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_list_deploys": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { projectId, environment, limit = 20, page = 1, } = args as { projectId: number; environment?: string; limit?: number; page?: number; }; // Use environment variable project ID as default value, or search by project name const effectiveProjectId = await getEffectiveProjectId(projectId); if (!effectiveProjectId) { throw new Error("Project ID is required but not provided in request or environment variables"); } const params: Record<string, string | number> = { page, limit }; if (environment) params.environment = environment; const response = await projectClient.get<ListDeploysResponse>(`/project/${effectiveProjectId}/deploys`, { params, }); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } case "rollbar_get_deploy": { // Project Token is required if (!projectClient) { throw new Error("ROLLBAR_PROJECT_TOKEN is not set, cannot use this API"); } const { deployId } = args as { deployId: number }; const response = await projectClient.get<DeployResponse>(`/deploy/${deployId}`); return { content: [ { type: "text", text: JSON.stringify(response.data, null, 2), }, ], }; } default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { if (axios.isAxiosError(error)) { const axiosError = error as AxiosError; return { content: [ { type: "text", text: JSON.stringify( { error: "API Error", message: axiosError.message, status: axiosError.response?.status, data: axiosError.response?.data, }, null, 2, ), }, ], }; } // Return error to client (not throw as regular response) return { content: [ { type: "text", text: JSON.stringify( { error: "Server Error", message: error instanceof Error ? error.message : String(error), }, null, 2, ), }, ], }; } }); return { server }; };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hiyorineko/mcp-rollbar-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server