Skip to main content
Glama
stdio-server.ts5.39 kB
import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { McpError, ErrorCode, CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js"; import { WalletServiceError as MidnightMCPError } from './mcp/index.js'; import { ALL_TOOLS, handleToolCall } from './tools.js'; import { handleListResources, handleReadResource } from './resources.js'; /** * Simple logging function */ function log(...args: any[]) { const timestamp = new Date().toISOString(); console.error(`[${timestamp}]`, ...args); } /** * Format error for logging */ function formatError(error: unknown): string { if (error instanceof Error) { return `${error.name}: ${error.message}`; } /* istanbul ignore next */ return String(error); } /** * Create and configure MCP server */ export function createServer() { log("Creating Midnight MCP server"); // Get agent ID from environment const agentId = process.env.AGENT_ID; if (!agentId) { throw new Error('AGENT_ID environment variable is required'); } // Create server instance const server = new Server({ name: "midnight-mcp-server", version: "1.0.0" }, { capabilities: { resources: {}, tools: {} } }); // Set up request handlers setupRequestHandlers(server); // Create STDIO transport const transport = new StdioServerTransport(); return { start: async () => { try { await server.connect(transport); log("Server created successfully"); } catch (error) { log("Failed to start server:", error); throw error; } }, stop: async () => { try { await server.close(); log("Server stopped"); } catch (error) { log("Error stopping server:", error); } } }; } /** * Helper function to handle errors uniformly */ function handleError(context: string, error: unknown): never { log(`Error ${context}:`, error); if (error instanceof McpError) { throw error; } // Handle Midnight MCP errors if (error instanceof MidnightMCPError) { throw new McpError( ErrorCode.InternalError, `Midnight MCP Error (${error.type}): ${error.message}` ); } throw new McpError( ErrorCode.InternalError, `${context}: ${formatError(error)}` ); } /** * Set up server request handlers */ function setupRequestHandlers(server: Server) { // Handle tool calls server.setRequestHandler(CallToolRequestSchema, async (request) => { try { const toolName = request.params.name; const toolArgs = request.params.arguments; log(`Tool call received: ${toolName}`); return await handleToolCall(toolName, toolArgs, log); } catch (error) { /* istanbul ignore next */ return handleError("handling tool call", error); } }); // Handle resource listing server.setRequestHandler(ListResourcesRequestSchema, async () => { try { return { resources: handleListResources() }; } catch (error) { /* istanbul ignore next */ return handleError("listing resources", error); } }); // Handle resource reading server.setRequestHandler(ReadResourceRequestSchema, async (request) => { try { const resourceUri = request.params.uri; const resource = handleReadResource(resourceUri); /* istanbul ignore next */ return { contents: [{ uri: resourceUri, mimeType: resource.mimeType || "application/json", text: JSON.stringify(resource) }] }; } catch (error) { /* istanbul ignore next */ handleError("reading resource", error); } }); // Handle tool listing server.setRequestHandler(ListToolsRequestSchema, async () => { try { return { tools: ALL_TOOLS }; } catch (error) { /* istanbul ignore next */ return handleError("listing tools", error); } }); // Handle global errors process.on("uncaughtException", (error) => { log("Uncaught exception:", error); }); process.on("unhandledRejection", (reason) => { log("Unhandled rejection:", reason); }); } /** * Set up process exit signal handlers */ /* istanbul ignore next */ function setupExitHandlers(server: any) { const exitHandler = async () => { log("Shutting down server..."); await server.stop(); process.exit(0); }; // Handle various exit signals process.on("SIGINT", exitHandler); process.on("SIGTERM", exitHandler); process.on("SIGUSR1", exitHandler); process.on("SIGUSR2", exitHandler); } /** * Main function - Program entry point */ /* istanbul ignore next */ async function main() { try { log("Starting Midnight MCP server"); const server = createServer(); // Start server await server.start(); log("Server started successfully"); // Handle process exit signals setupExitHandlers(server); } catch (error) { log("Failed to start server:", error); process.exit(1); } } // Run the main function if this file is executed directly /* istanbul ignore next */ if (import.meta.url === `file://${process.argv[1]}`) { main().catch((error) => { log("Fatal error:", 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/evilpixi/pixi-midnight-mcp'

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