Skip to main content
Glama

@pulumi/mcp-server

Official
by pulumi
server.ts4.93 kB
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import packageJSON from '../../package.json' with { type: 'json' }; import { registryCommands } from '../pulumi/registry.js'; import * as fs from 'node:fs'; import * as path from 'node:path'; import { fileURLToPath } from 'node:url'; import { cliCommands } from '../pulumi/cli.js'; import { logger } from '../logging/logging.js'; import { deployCommands, deployPrompts } from '../deploy/deploy.js'; import { convertPrompts } from '../pulumi/convert.js'; import { resourceSearchCommands } from '../insights/resource-search.js'; import { neoTaskLauncherCommands } from '../neo/neo-task-launcher.js'; // Get the directory of the current module const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Create cache directory if it doesn't exist const CACHE_DIR = path.join(__dirname, './.cache'); if (!fs.existsSync(CACHE_DIR)) { fs.mkdirSync(CACHE_DIR, { recursive: true }); } type TextContent = { type: 'text'; text: string; }; function handleError( error: unknown, toolName: string ): { description: string; content: TextContent[] } { logger.error(`Error in tool ${toolName}:`, error); const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return { description: `Error executing ${toolName}`, content: [ { type: 'text' as const, text: `Operation failed: ${errorMessage}` } ] }; } export class Server extends McpServer { constructor(description: string) { super({ name: packageJSON.name, version: packageJSON.version, description: description }); // Centralized error handling function // Register registry commands Object.entries(registryCommands(CACHE_DIR)).forEach(([commandName, command]) => { const toolName = `pulumi-registry-${commandName}`; // eslint-disable-next-line @typescript-eslint/no-explicit-any this.tool(toolName, command.description, command.schema, async (args: any) => { try { return await command.handler(args); } catch (error) { return handleError(error, toolName); } }); }); // Register CLI commands Object.entries(cliCommands).forEach(([commandName, command]) => { const toolName = `pulumi-cli-${commandName}`; // eslint-disable-next-line @typescript-eslint/no-explicit-any this.tool(toolName, command.description, command.schema, async (args: any) => { try { return await command.handler(args); } catch (error) { return handleError(error, toolName); } }); }); // Register deploy commands Object.entries(deployCommands).forEach(([commandName, command]) => { const toolName = commandName; this.tool(toolName, command.description, command.schema, async () => { try { return await command.handler(); } catch (error) { return handleError(error, toolName); } }); }); // Register resource search commands Object.entries(resourceSearchCommands).forEach(([commandName, command]) => { const toolName = `pulumi-${commandName}`; // eslint-disable-next-line @typescript-eslint/no-explicit-any this.tool(toolName, command.description, command.schema, async (args: any) => { try { return await command.handler(args); } catch (error) { return handleError(error, toolName); } }); }); // Register neo task launcher commands Object.entries(neoTaskLauncherCommands).forEach(([commandName, command]) => { const toolName = commandName; // eslint-disable-next-line @typescript-eslint/no-explicit-any this.tool(toolName, command.description, command.schema, async (args: any) => { try { return await command.handler(args); } catch (error) { return handleError(error, toolName); } }); }); // Register deploy prompts Object.entries(deployPrompts).forEach(([promptName, prompt]) => { this.prompt(promptName, prompt.description, async () => { try { return await prompt.handler(); } catch (error) { logger.error(`Error in prompt ${promptName}:`, error); throw error; } }); }); // Register convert prompts Object.entries(convertPrompts).forEach(([promptName, prompt]) => { this.prompt(promptName, prompt.description, prompt.args, async (args) => { try { return await prompt.handler(args); } catch (error) { logger.error(`Error in prompt ${promptName}:`, error); throw error; } }); }); } } export const createServer = () => { return new Server( 'An MCP server for querying Pulumi Registry information and running Pulumi CLI commands' ); };

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/pulumi/mcp-server'

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