Skip to main content
Glama
jakedx6
by jakedx6
index-minimal.ts10.4 kB
#!/usr/bin/env node import { Server } from '@modelcontextprotocol/sdk/server/index.js' import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js' import { CallToolRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js' import dotenv from 'dotenv' import { logger } from './lib/logger.js' import { authManager } from './lib/auth.js' import { projectTools, projectHandlers } from './tools/projects.js' // Constants const HELIOS_VERSION = '1.0.0' const MCP_PROTOCOL_VERSION = '2024-11-05' // Load environment variables dotenv.config() class HeliosMCPServer { private server: Server private readonly allTools: any[] private readonly allHandlers: Record<string, Function> constructor() { // Initialize server this.server = new Server( { name: 'helios9-mcp', version: HELIOS_VERSION, }, { capabilities: { tools: { listChanged: false, // Tools don't change dynamically }, resources: { subscribe: false, listChanged: false, }, prompts: { listChanged: false, }, }, } ) // Combine all tools and handlers this.allTools = [ ...Object.values(projectTools), ] this.allHandlers = { ...projectHandlers, } this.setupHandlers() logger.info('Helios-9 MCP Server initialized', { version: HELIOS_VERSION, protocol_version: MCP_PROTOCOL_VERSION, tools_count: this.allTools.length }) } private setupHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { logger.debug('Listing available tools') return { tools: this.allTools.map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema, })), } }) // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params logger.info('Tool call received', { tool: name, args: Object.keys(args || {}) }) try { // Check if tool exists if (!this.allHandlers[name]) { throw new Error(`Unknown tool: ${name}`) } // Call the tool handler const result = await this.allHandlers[name](args || {}) logger.info('Tool call completed successfully', { tool: name }) return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) logger.error('Tool call failed', { tool: name, error: errorMessage }) return { content: [ { type: 'text', text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), tool: name, timestamp: new Date().toISOString(), }, null, 2), }, ], isError: true, } } }) // List available resources this.server.setRequestHandler(ListResourcesRequestSchema, async () => { logger.debug('Listing available resources') return { resources: [ { uri: 'helios9://projects', name: 'All Projects', description: 'List of all user projects', mimeType: 'application/json', }, { uri: 'helios9://project/{project_id}/context', name: 'Project Context', description: 'Comprehensive project context for AI agents', mimeType: 'application/json', }, ], } }) // Read resources this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => { const { uri } = request.params logger.info('Resource read requested', { uri }) try { const content = await this.handleResourceRead(uri) return { contents: [ { uri, mimeType: 'application/json', text: typeof content === 'string' ? content : JSON.stringify(content, null, 2), }, ], } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) logger.error('Resource read failed', { uri, error: errorMessage }) throw error } }) // List available prompts this.server.setRequestHandler(ListPromptsRequestSchema, async () => { logger.debug('Listing available prompts') return { prompts: [ { name: 'project_kickoff', description: 'Generate project structure from natural language description', arguments: [ { name: 'description', description: 'Natural language description of the project', required: true, }, { name: 'team_size', description: 'Number of team members', required: false, }, { name: 'duration', description: 'Expected project duration', required: false, }, ], }, ], } }) // Handle prompt requests this.server.setRequestHandler(GetPromptRequestSchema, async (request) => { const { name, arguments: args } = request.params logger.info('Prompt requested', { prompt: name, args }) try { const prompt = await this.handlePromptRequest(name, args || {}) return { description: `Generated ${name} prompt`, messages: [ { role: 'user', content: { type: 'text', text: prompt, }, }, ], } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error) logger.error('Prompt generation failed', { prompt: name, error: errorMessage }) throw error } }) } private async handleResourceRead(uri: string): Promise<any> { // Parse URI and route to appropriate handler if (uri === 'helios9://projects') { return await this.allHandlers.list_projects({}) } const projectContextMatch = uri.match(/^helios9:\/\/project\/([^\/]+)\/context$/) if (projectContextMatch) { return await this.allHandlers.get_project_context({ project_id: projectContextMatch[1] }) } throw new Error(`Unknown resource URI: ${uri}`) } private async handlePromptRequest(name: string, args: Record<string, any>): Promise<string> { switch (name) { case 'project_kickoff': return this.generateProjectKickoffPrompt(args) default: throw new Error(`Unknown prompt: ${name}`) } } private async generateProjectKickoffPrompt(args: Record<string, any>): Promise<string> { const { description, team_size = 3, duration = '2-3 months' } = args return `# Project Kickoff Planning Based on this project description: "${description}" Please help me create a comprehensive project plan including: ## 1. Project Structure - Break down the project into logical phases and milestones - Identify key deliverables and dependencies - Suggest appropriate project timeline given ${duration} duration ## 2. Team Organization - Define roles and responsibilities for ${team_size} team members - Suggest task assignments and collaboration patterns - Identify skills and expertise needed ## 3. Documentation Strategy - Recommend essential documents to create (README, specs, etc.) - Suggest documentation templates and standards - Plan knowledge sharing and onboarding materials ## 4. Initial Tasks - Create a prioritized backlog of initial tasks - Define acceptance criteria and definition of done - Set up project tracking and communication tools Please provide specific, actionable recommendations that I can implement immediately.` } public async start() { // Setup authentication if API key is provided const apiKey = process.env.MCP_API_KEY const accessToken = process.env.SUPABASE_ACCESS_TOKEN if (apiKey) { try { await authManager.authenticate('api_key', apiKey) logger.info('Authenticated with API key') } catch (error) { logger.error('API key authentication failed:', error) process.exit(1) } } else if (accessToken) { try { await authManager.authenticate('token', accessToken) logger.info('Authenticated with access token') } catch (error) { logger.error('Token authentication failed:', error) process.exit(1) } } else { logger.warn('No authentication provided - some operations may fail') } // Start the server const transport = new StdioServerTransport() await this.server.connect(transport) logger.info('Helios-9 MCP Server started and ready for connections') } public async stop() { logger.info('Shutting down Helios-9 MCP Server') await this.server.close() } } // Main execution async function main() { const server = new HeliosMCPServer() // Handle graceful shutdown process.on('SIGINT', async () => { logger.info('Received SIGINT, shutting down gracefully') await server.stop() process.exit(0) }) process.on('SIGTERM', async () => { logger.info('Received SIGTERM, shutting down gracefully') await server.stop() process.exit(0) }) // Start the server try { await server.start() } catch (error) { logger.error('Failed to start server:', error) process.exit(1) } } // Run if this is the main module if (import.meta.url === `file://${process.argv[1]}`) { main().catch((error) => { logger.error('Unhandled error in main:', error) process.exit(1) }) } export { HeliosMCPServer }

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/jakedx6/helios9-MCP-Server'

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