Skip to main content
Glama
index.ts6.77 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { CoolifyConfig, CoolifyApiClient } from './client/coolify-api.js'; import { logger } from './utils/logger.js'; // Import tools import { listProjectsTool, createProjectTool, handleListProjects, handleCreateProject, } from './tools/projects.js'; import { listAppsTool, getAppTool, createAppTool, updateAppTool, deleteAppTool, handleListApps, handleGetApp, handleCreateApp, handleUpdateApp, handleDeleteApp, } from './tools/applications.js'; import { deployAppTool, getDeploymentStatusTool, getDeploymentLogsTool, handleDeployApp, handleGetDeploymentStatus, handleGetDeploymentLogs, } from './tools/deployments.js'; import { deployTemplateTool, listTemplatesTool, handleDeployTemplate, handleListTemplates, } from './tools/templates.js'; import { checkQuotaTool, checkNameConflictsTool, handleCheckQuota, handleCheckNameConflicts, } from './tools/safety.js'; // Load configuration from environment variables function loadConfig(): CoolifyConfig { const apiUrl = process.env.COOLIFY_API_URL; const apiToken = process.env.COOLIFY_API_TOKEN; if (!apiUrl) { throw new Error('COOLIFY_API_URL environment variable is required'); } if (!apiToken) { throw new Error('COOLIFY_API_TOKEN environment variable is required'); } return { apiUrl: apiUrl.replace(/\/$/, ''), // Remove trailing slash apiToken, defaultTeamId: process.env.COOLIFY_DEFAULT_TEAM_ID, maxAppsPerProject: process.env.COOLIFY_MAX_APPS_PER_PROJECT ? parseInt(process.env.COOLIFY_MAX_APPS_PER_PROJECT, 10) : undefined, }; } // Initialize the server async function main() { try { const config = loadConfig(); const apiClient = new CoolifyApiClient(config); const server = new Server( { name: 'coolify-mcp-server', version: '1.0.0', }, { capabilities: { tools: {}, }, } ); // List all available tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ // Projects listProjectsTool, createProjectTool, // Applications listAppsTool, getAppTool, createAppTool, updateAppTool, deleteAppTool, // Deployments deployAppTool, getDeploymentStatusTool, getDeploymentLogsTool, // Templates deployTemplateTool, listTemplatesTool, // Safety checkQuotaTool, checkNameConflictsTool, ], }; }); // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { // Projects case 'coolify.list_projects': return { content: [{ type: 'text', text: JSON.stringify(await handleListProjects(args, apiClient)) }] }; case 'coolify.create_project': return { content: [{ type: 'text', text: JSON.stringify(await handleCreateProject(args, apiClient)) }] }; // Applications case 'coolify.list_apps': return { content: [{ type: 'text', text: JSON.stringify(await handleListApps(args, apiClient)) }] }; case 'coolify.get_app': return { content: [{ type: 'text', text: JSON.stringify(await handleGetApp(args, apiClient)) }] }; case 'coolify.create_app': return { content: [{ type: 'text', text: JSON.stringify(await handleCreateApp(args, apiClient)) }] }; case 'coolify.update_app': return { content: [{ type: 'text', text: JSON.stringify(await handleUpdateApp(args, apiClient)) }] }; case 'coolify.delete_app': return { content: [{ type: 'text', text: JSON.stringify(await handleDeleteApp(args, apiClient)) }] }; // Deployments case 'coolify.deploy_app': return { content: [{ type: 'text', text: JSON.stringify(await handleDeployApp(args, apiClient)) }] }; case 'coolify.get_deployment_status': return { content: [{ type: 'text', text: JSON.stringify(await handleGetDeploymentStatus(args, apiClient)) }] }; case 'coolify.get_deployment_logs': return { content: [{ type: 'text', text: JSON.stringify(await handleGetDeploymentLogs(args, apiClient)) }] }; // Templates case 'coolify.deploy_template': return { content: [{ type: 'text', text: JSON.stringify(await handleDeployTemplate(args, apiClient)) }] }; case 'coolify.list_templates': return { content: [{ type: 'text', text: JSON.stringify(await handleListTemplates(args)) }] }; // Safety case 'coolify.check_quota': return { content: [{ type: 'text', text: JSON.stringify(await handleCheckQuota(args, apiClient)) }] }; case 'coolify.check_name_conflicts': return { content: [{ type: 'text', text: JSON.stringify(await handleCheckNameConflicts(args, apiClient)) }] }; default: throw new Error(`Unknown tool: ${name}`); } } catch (error: any) { logger.error(`Tool execution failed for ${name}`, { error: error.message }); return { content: [ { type: 'text', text: JSON.stringify({ success: false, error: { code: error.code || 'EXECUTION_ERROR', message: error.message, }, }), }, ], }; } }); // Start the server const transport = new StdioServerTransport(); await server.connect(transport); logger.info('Coolify MCP Server started successfully'); logger.info(`Connected to Coolify API at ${config.apiUrl}`); // Graceful shutdown process.on('SIGINT', async () => { logger.info('Shutting down Coolify MCP Server...'); await server.close(); process.exit(0); }); process.on('SIGTERM', async () => { logger.info('Shutting down Coolify MCP Server...'); await server.close(); process.exit(0); }); } catch (error: any) { logger.error('Failed to start server', { error: error.message }); process.exit(1); } } // Start the server main().catch((error) => { logger.error('Server startup error', { error }); process.exit(1); });

Latest Blog Posts

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/Thedurancode/Coolify-MCP'

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