Skip to main content
Glama

ARC Config MCP Server

by tsviz
index.tsβ€’6.63 kB
#!/usr/bin/env node /** * ARC Config MCP Server * * A comprehensive TypeScript MCP server for GitHub Actions Runner Controller (ARC) management * with AI-powered automation for Kubernetes-based GitHub Actions runners. */ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import express, { Request, Response } from 'express'; import cors from 'cors'; import { config } from 'dotenv'; import { createLogger, format, transports } from 'winston'; import { ArcInstaller } from './services/arc-installer.js'; import { KubernetesService } from './services/kubernetes.js'; import { KubernetesEnhancedService } from './services/kubernetes-enhanced.js'; import { GitHubService } from './services/github.js'; import { PolicyService } from './services/policy.js'; import { registerArcTools } from './tools/index.js'; import { ArcServerInfo } from './types/arc.js'; // Load environment variables config(); // Configure logger const logger = createLogger({ level: process.env.LOG_LEVEL || 'info', format: format.combine( format.timestamp(), format.errors({ stack: true }), format.json() ), transports: [ new transports.Console({ format: format.combine( format.colorize(), format.simple() ) }) ] }); /** * Server configuration and implementation */ const SERVER_INFO: ArcServerInfo = { name: 'arc-config-mcp', version: '1.0.0', description: 'GitHub Actions Runner Controller (ARC) management with AI-powered automation', author: 'tsviz' }; /** * Create and configure the MCP server */ function createMcpServer(): McpServer { const server = new McpServer( { name: SERVER_INFO.name, version: SERVER_INFO.version, description: SERVER_INFO.description, icons: [ { src: './assets/arc-logo.svg', sizes: ['512x512'], mimeType: 'image/svg+xml' } ], websiteUrl: 'https://github.com/tsviz/arc-config-mcp' }, { capabilities: { tools: { listChanged: true }, resources: { subscribe: true, listChanged: true }, prompts: { listChanged: true }, logging: {} } } ); // Initialize services const kubernetesService = new KubernetesEnhancedService(logger); const githubService = new GitHubService(logger); const policyService = new PolicyService(logger); const arcInstaller = new ArcInstaller(kubernetesService, githubService, logger); // Register all ARC management tools registerArcTools(server, { kubernetes: kubernetesService, github: githubService, policy: policyService, installer: arcInstaller, logger }); logger.info('ARC MCP Server initialized with comprehensive tooling', { server: SERVER_INFO.name, version: SERVER_INFO.version, toolsRegistered: 'comprehensive ARC management tools' }); return server; } /** * Run server with stdio transport (for local MCP clients) */ async function runStdioServer(): Promise<void> { logger.info('Starting ARC MCP Server with stdio transport'); const server = createMcpServer(); const transport = new StdioServerTransport(); await server.connect(transport); logger.info('ARC MCP Server running on stdio transport'); } /** * Run server with HTTP transport (for remote MCP clients) */ async function runHttpServer(port: number = 3000): Promise<void> { logger.info(`Starting ARC MCP Server with HTTP transport on port ${port}`); const app = express(); app.use(express.json()); app.use(cors({ origin: '*', exposedHeaders: ['Mcp-Session-Id'] })); const server = createMcpServer(); // Health check endpoint app.get('/health', (req, res) => { res.json({ status: 'healthy', server: SERVER_INFO.name, version: SERVER_INFO.version, timestamp: new Date().toISOString() }); }); // MCP endpoint app.post('/mcp', async (req: Request, res: Response) => { try { const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined, enableJsonResponse: true }); res.on('close', () => { transport.close(); }); await server.connect(transport); await transport.handleRequest(req, res, req.body); } catch (error: any) { logger.error('Error handling MCP request:', error); if (!res.headersSent) { res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: 'Internal server error' }, id: null }); } } }); app.listen(port, () => { logger.info(`ARC MCP Server running on http://localhost:${port}/mcp`); }).on('error', (error: Error) => { logger.error('Server error:', error); process.exit(1); }); } /** * Main entry point */ async function main(): Promise<void> { const args = process.argv.slice(2); const transport = args.includes('--http') ? 'http' : 'stdio'; const port = parseInt(args.find(arg => arg.startsWith('--port='))?.split('=')[1] || '3000'); try { if (transport === 'http') { await runHttpServer(port); } else { await runStdioServer(); } } catch (error: any) { logger.error('Fatal error starting ARC MCP Server:', error); process.exit(1); } } // Handle graceful shutdown process.on('SIGINT', () => { logger.info('Received SIGINT, shutting down gracefully...'); process.exit(0); }); process.on('SIGTERM', () => { logger.info('Received SIGTERM, shutting down gracefully...'); process.exit(0); }); // Start the server if (import.meta.url === `file://${process.argv[1]}`) { main().catch((error) => { logger.error('Fatal error:', error); process.exit(1); }); }

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/tsviz/arc-config-mcp'

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