Skip to main content
Glama
expressjs-mcp.ts5.78 kB
#!/usr/bin/env node /** * Express MCP CLI * * Native MCP server implementation using the official SDK. * This connects to an Express MCP server and exposes its tools as MCP tools. * * Usage: * expressjs-mcp [options] * * Options: * --url <url> Express MCP URL (default: http://localhost:3000/mcp) * --debug Enable debug logging * --help Show help * * Environment Variables: * EXPRESS_MCP_URL - URL of Express MCP server * DEBUG - Enable debug mode */ 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"; interface ExpressMCPServerOptions { baseUrl?: string; debug?: boolean; } class ExpressMCPServer { private server: Server; private baseUrl: string; private debug: boolean; private tools: any[] = []; constructor(options: ExpressMCPServerOptions = {}) { this.baseUrl = options.baseUrl || "http://localhost:3000/mcp"; this.debug = options.debug || false; this.server = new Server( { name: "expressjs-mcp", version: "1.0.0", }, { capabilities: { tools: {}, resources: {}, }, }, ); this.setupHandlers(); this.log("Express MCP Server initialized"); } private log(...args: any[]) { if (this.debug) { console.error("[Express MCP]", ...args); } } private async loadTools(): Promise<any[]> { try { const response = await fetch(`${this.baseUrl}/tools`); const data = await response.json(); this.tools = data.tools || []; this.log(`Loaded ${this.tools.length} tools from ${this.baseUrl}`); return this.tools; } catch (error) { this.log("Failed to load tools:", error); this.tools = []; return []; } } private async invokeTool(toolName: string, args: any): Promise<any> { this.log(`Invoking tool: ${toolName}`, args); try { const response = await fetch(`${this.baseUrl}/invoke`, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ toolName, args: args || {}, }), }); if (!response.ok) { const errorText = await response.text(); throw new Error(`HTTP ${response.status}: ${errorText}`); } const result = await response.json(); return result; } catch (error) { this.log("Tool invocation error:", error); throw new McpError( ErrorCode.InternalError, `Tool execution failed: ${error instanceof Error ? error.message : "Unknown error"}`, ); } } private setupHandlers() { // Handle tool listing this.server.setRequestHandler(ListToolsRequestSchema, async () => { await this.loadTools(); return { tools: this.tools.map((tool) => ({ name: tool.name || tool.title, description: tool.description || `Invoke ${tool.title}`, inputSchema: tool.inputSchema || { type: "object", properties: {}, additionalProperties: true, }, })), }; }); // Handle tool invocation this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; this.log(`Invoking tool: ${name}`, args); try { const result = await this.invokeTool(name, args || {}); if (result.ok) { return { content: [ { type: "text", text: typeof result.result === "string" ? result.result : JSON.stringify(result.result, null, 2), }, ], }; } throw new McpError( ErrorCode.InternalError, result.error || "Tool execution failed", ); } catch (error: any) { this.log("Tool invocation error:", error); if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `Tool execution failed: ${error.message}`, ); } }); this.log("Request handlers configured"); } async start() { const transport = new StdioServerTransport(); await this.server.connect(transport); this.log("MCP Server connected via stdio"); console.error("Express MCP Server ready"); console.error(`Connected to: ${this.baseUrl}`); } } // Parse command line arguments const args = process.argv.slice(2); const options: ExpressMCPServerOptions = { baseUrl: process.env.EXPRESS_MCP_URL || "http://localhost:3000/mcp", debug: process.env.DEBUG === "true", }; for (let i = 0; i < args.length; i++) { switch (args[i]) { case "--url": options.baseUrl = args[++i]; break; case "--debug": options.debug = true; break; case "--help": case "-h": console.log(`Express MCP Server Usage: expressjs-mcp [options] Options: --url <url> Express MCP URL (default: http://localhost:3000/mcp) --debug Enable debug logging --help Show help Environment Variables: EXPRESS_MCP_URL - URL of Express MCP server DEBUG - Enable debug mode Examples: expressjs-mcp expressjs-mcp --url http://localhost:8080/mcp expressjs-mcp --debug EXPRESS_MCP_URL=http://api.example.com/mcp expressjs-mcp `); process.exit(0); break; default: if (args[i].startsWith("-")) { console.error(`Unknown option: ${args[i]}`); console.error("Use --help for usage information"); process.exit(1); } } } // Create and start server const server = new ExpressMCPServer(options); server.start().catch((error) => { console.error("Failed to start MCP server:", error); process.exit(1); }); // Handle graceful shutdown process.on("SIGINT", () => { console.error("\nShutting down..."); process.exit(0); }); process.on("SIGTERM", () => { console.error("\nShutting down..."); process.exit(0); });

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/bowen31337/expressjs_mcp'

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