UNPKG

@crazyrabbitltc/railway-mcp

Version:

Railway MCP Server - 146+ tools with 100% Railway API coverage, comprehensive MCP testing framework, and real infrastructure management through AI assistants. Enhanced version with enterprise features, based on original work by Jason Tan.

152 lines (151 loc) 6.33 kB
import { BaseService } from '../services/base.service.js'; import { createSuccessResponse, createErrorResponse, formatError } from '../utils/responses.js'; export class ServiceService extends BaseService { constructor() { super(); } async listServices(projectId) { try { const services = await this.client.services.listServices(projectId); if (services.length === 0) { return createSuccessResponse({ text: "No services found in this project.", data: [] }); } // Get latest deployment status for each service const serviceDetails = await Promise.all(services.map(async (service) => { try { const deployments = await this.client.deployments.listDeployments({ projectId, serviceId: service.id, limit: 1 }); const latestDeployment = deployments[0]; if (latestDeployment) { return `🚀 ${service.name} (ID: ${service.id}) Status: ${latestDeployment.status} URL: ${latestDeployment.url || 'Not deployed'}`; } return `🚀 ${service.name} (ID: ${service.id}) Status: No deployments`; } catch { return `🚀 ${service.name} (ID: ${service.id})`; } })); return createSuccessResponse({ text: `Services in project:\n\n${serviceDetails.join('\n\n')}`, data: services }); } catch (error) { return createErrorResponse(`Error listing services: ${formatError(error)}`); } } async getServiceInfo(projectId, serviceId, environmentId) { try { const [serviceInstance, deployments] = await Promise.all([ this.client.services.getServiceInstance(serviceId, environmentId), this.client.deployments.listDeployments({ projectId, serviceId, environmentId, limit: 5 }) ]); if (!serviceInstance) { return createErrorResponse(`Service instance not found.`); } const deploymentStatus = deployments.length > 0 ? `\nLatest Deployment: ${deployments[0].status} (${deployments[0].id})` : '\nNo recent deployments'; const info = `🚀 Service: ${serviceInstance.serviceName} ID: ${serviceInstance.serviceId} Region: ${serviceInstance.region || 'Not set'} Replicas: ${serviceInstance.numReplicas || 1} Root Directory: ${serviceInstance.rootDirectory || '/'} Build Command: ${serviceInstance.buildCommand || 'Not set'} Start Command: ${serviceInstance.startCommand || 'Not set'} Health Check Path: ${serviceInstance.healthcheckPath || 'Not set'} Sleep Mode: ${serviceInstance.sleepApplication ? 'Enabled' : 'Disabled'}${deploymentStatus}`; return createSuccessResponse({ text: info, data: { serviceInstance, deployments } }); } catch (error) { return createErrorResponse(`Error getting service details: ${formatError(error)}`); } } async createServiceFromRepo(projectId, repo, name) { try { const service = await this.client.services.createService({ projectId, name: name || 'service-' + Date.now(), source: { repo, } }); return createSuccessResponse({ text: `Created new service "${service.name}" (ID: ${service.id}) from GitHub repo "${repo}"`, data: service }); } catch (error) { return createErrorResponse(`Error creating service: ${formatError(error)}`); } } async createServiceFromImage(projectId, image, name) { try { const service = await this.client.services.createService({ projectId, name: name || 'service-' + Date.now(), source: { image, } }); return createSuccessResponse({ text: `Created new service "${service.name}" (ID: ${service.id}) from Docker image "${image}"`, data: service }); } catch (error) { return createErrorResponse(`Error creating service: ${formatError(error)}`); } } async updateService(projectId, serviceId, environmentId, config) { try { const updated = await this.client.services.updateServiceInstance(serviceId, environmentId, config); if (!updated) { return createErrorResponse(`Error updating service: Failed to update service instance of ${serviceId} in environment ${environmentId}`); } return createSuccessResponse({ text: `Service configuration updated successfully` }); } catch (error) { return createErrorResponse(`Error updating service: ${formatError(error)}`); } } async deleteService(projectId, serviceId) { try { await this.client.services.deleteService(serviceId); return createSuccessResponse({ text: `Service deleted successfully` }); } catch (error) { return createErrorResponse(`Error deleting service: ${formatError(error)}`); } } async restartService(serviceId, environmentId) { try { await this.client.services.restartService(serviceId, environmentId); await new Promise(resolve => setTimeout(resolve, 5000)); // TEMPORARY UNTIL WEBHOOKS ARE IMPLEMENTED: Wait for 5 seconds to ensure the service is restarted return createSuccessResponse({ text: `Service restarted successfully` }); } catch (error) { return createErrorResponse(`Error restarting service: ${formatError(error)}`); } } } // Initialize and export the singleton instance export const serviceService = new ServiceService();