Skip to main content
Glama
mcp-server.ts5.21 kB
#!/usr/bin/env node /** * MCP Server implementation using stdio and JSON-RPC protocol * Compatible with Model Context Protocol specification */ import { ToolRegistry } from './tools/ToolRegistry'; import { PolicyEngine } from './services/PolicyEngine'; interface MCPJsonRpcRequest { jsonrpc: '2.0'; id: number | string | null; method: string; params?: any; } interface MCPJsonRpcResponse { jsonrpc: '2.0'; id: number | string | null; result?: any; error?: { code: number; message: string; data?: any; }; } interface MCPServerCapabilities { tools?: { listChanged?: boolean; }; } interface MCPTool { name: string; description: string; inputSchema: { type: 'object'; properties: Record<string, any>; required?: string[]; }; } class MCPServer { private toolRegistry: ToolRegistry; private policyEngine: PolicyEngine; constructor() { // Initialize services this.toolRegistry = new ToolRegistry(); this.policyEngine = new PolicyEngine(); // Add default policy for development this.policyEngine.addPolicy(PolicyEngine.createDefaultPolicy()); } private getServerCapabilities(): MCPServerCapabilities { return { tools: { listChanged: true } }; } private async handleInitialize(params: any): Promise<any> { return { protocolVersion: '2024-11-05', capabilities: this.getServerCapabilities(), serverInfo: { name: 'fullstack-mcp', version: '1.0.0' } }; } private async handleToolsList(): Promise<MCPTool[]> { const tools = this.toolRegistry.getAllTools(); return tools.map(tool => ({ name: tool.name, description: tool.description, inputSchema: { type: 'object', properties: tool.parameters.reduce((acc, param) => { acc[param.name] = { type: param.type, description: param.description, default: param.default }; return acc; }, {} as Record<string, any>), required: tool.parameters.filter(p => p.required).map(p => p.name) } })); } private async handleToolsCall(params: { name: string; arguments?: any }): Promise<any> { const { name, arguments: args = {} } = params; try { // Check policy (simplified for MCP context) const tool = this.toolRegistry.getTool(name); if (!tool) { throw new Error(`Tool not found: ${name}`); } const result = await this.toolRegistry.executeTool(name, args); if (!result.success) { throw new Error(result.error || 'Tool execution failed'); } return result.data; } catch (error: any) { throw new Error(`Tool execution failed: ${error.message}`); } } private async handleMessage(request: MCPJsonRpcRequest): Promise<MCPJsonRpcResponse> { try { switch (request.method) { case 'initialize': return { jsonrpc: '2.0', id: request.id, result: await this.handleInitialize(request.params) }; case 'tools/list': return { jsonrpc: '2.0', id: request.id, result: { tools: await this.handleToolsList() } }; case 'tools/call': return { jsonrpc: '2.0', id: request.id, result: await this.handleToolsCall(request.params) }; default: return { jsonrpc: '2.0', id: request.id, error: { code: -32601, message: `Method not found: ${request.method}` } }; } } catch (error: any) { return { jsonrpc: '2.0', id: request.id, error: { code: -32000, message: error.message || 'Internal server error' } }; } } public async start(): Promise<void> { // Handle stdio communication process.stdin.setEncoding('utf8'); process.stdin.on('data', async (data) => { try { // Parse incoming JSON-RPC message const request: MCPJsonRpcRequest = JSON.parse(data.toString().trim()); // Handle the request const response = await this.handleMessage(request); // Send response back via stdout process.stdout.write(JSON.stringify(response) + '\n'); } catch (error) { // Send error response for malformed requests const errorResponse: MCPJsonRpcResponse = { jsonrpc: '2.0', id: null, error: { code: -32700, message: 'Parse error', data: error instanceof Error ? error.message : String(error) } }; process.stdout.write(JSON.stringify(errorResponse) + '\n'); } }); // Handle shutdown gracefully process.on('SIGINT', () => { process.exit(0); }); process.on('SIGTERM', () => { process.exit(0); }); } } // Start the MCP server if (require.main === module) { const server = new MCPServer(); server.start().catch((error) => { console.error('Failed to start MCP server:', error); process.exit(1); }); } export { MCPServer };

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/Nom-nom-hub/fullstack-mcp'

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