Skip to main content
Glama
application.entry.ts6.11 kB
#!/usr/bin/env node /** * Application Entry Module * ====================== * * This is the main entry point for the GitHub MCP server application. * It initializes the MCP server, registers tools, and handles connections. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js'; import { getApplicationConfiguration } from './configuration/index.export.js'; import { StructuredLoggingUtility } from './utilities/structured.logging.utility.js'; import { ApplicationErrorHandlingUtility } from './utilities/error.handling.utility.js'; import { ToolRegistry } from './dependencyInjection/tool.registry.js'; /** * Main GitHub MCP Server class that handles initialization and request processing */ class GitHubServer { private server: Server; private toolRegistry: ToolRegistry; /** * Initialize the GitHub MCP Server */ constructor() { const config = getApplicationConfiguration(); this.server = new Server( { name: config.serverName, version: config.serverVersion, }, { capabilities: { tools: {}, }, } ); this.toolRegistry = new ToolRegistry(); this.setupRequestHandlers(); // Error handling this.server.onerror = (error) => { StructuredLoggingUtility.recordErrorEntry('[MCP Error]', { error }); }; process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); StructuredLoggingUtility.recordInfoEntry('GitHub MCP server initialized'); } /** * Set up MCP request handlers for tool listing and execution */ private setupRequestHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { StructuredLoggingUtility.recordDebugEntry('Listing available tools'); return { tools: this.toolRegistry.getToolDefinitions(), }; }); // Handle tool execution this.server.setRequestHandler(CallToolRequestSchema, async (request) => { try { StructuredLoggingUtility.recordDebugEntry('Tool execution requested', { toolName: request.params.name, }); // Find and execute the requested tool const tool = this.toolRegistry.findTool(request.params.name); if (!tool) { StructuredLoggingUtility.recordErrorEntry('Unknown tool requested', { toolName: request.params.name, }); throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } // Execute the tool and return the result const result = await tool.execute(request.params.arguments); StructuredLoggingUtility.recordDebugEntry('Tool execution completed', { toolName: request.params.name, success: true, }); return result; } catch (error) { // Handle MCP errors directly if (error instanceof McpError) throw error; // Get error details const errorMessage = error instanceof Error ? error.message : String(error); const errorCategory = this.determineErrorCategory(error, request.params.name); StructuredLoggingUtility.recordErrorEntry('Tool execution failed', { toolName: request.params.name, error: errorMessage }); // Create appropriate error message based on category const errorText = errorMessage.length > 200 ? errorMessage.substring(0, 200) + '...' : errorMessage; throw new McpError( ErrorCode.InternalError, `${errorCategory} error: ${errorText}` ); } }); } /** * Determine the appropriate error category based on the error * * @param error - The error that occurred * @param toolName - The name of the tool that was being executed * @returns Appropriate error category string */ private determineErrorCategory(error: unknown, toolName: string): string { // Check for specific error types if (error instanceof Error) { // Network or connection errors if (error.message.includes('network') || error.message.includes('ECONNREFUSED') || error.message.includes('timeout')) { return 'Network'; } // Authentication or authorization errors if (error.message.includes('authentication') || error.message.includes('authorization') || error.message.includes('401') || error.message.includes('403')) { return 'Authentication'; } // Validation errors if (error.message.includes('validation') || error.message.includes('invalid') || error.message.includes('required')) { return 'Validation'; } // Known GitHub API errors if (error.message.includes('GitHub') || error.message.includes('API')) { return 'GitHub API'; } } // Default to system error if can't determine category return 'System'; } /** * Run the MCP server using stdio transport */ async run() { try { const transport = new StdioServerTransport(); await this.server.connect(transport); StructuredLoggingUtility.recordInfoEntry('GitHub MCP server running on stdio'); } catch (error) { StructuredLoggingUtility.recordFatalEntry('Failed to start MCP server', { error: error instanceof Error ? error.message : String(error), }); process.exit(1); } } } // Create and run the server const server = new GitHubServer(); server.run().catch((error) => { StructuredLoggingUtility.recordFatalEntry('Unhandled server error', { error: error instanceof Error ? error.message : String(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/cyanheads/github-mcp-server'

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