UNPKG

@sei-js/mcp-server

Version:

Model Context Protocol (MCP) server for interacting with EVM-compatible networks

79 lines (78 loc) 3.12 kB
import express from 'express'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { createCorsMiddleware, validateSecurityConfig } from './security.js'; import { getServer } from '../server.js'; export class StreamableHttpTransport { constructor(port = 8080, host = 'localhost', path = '/mcp', walletMode = 'disabled') { this.mode = 'streamable-http'; this.port = port; this.host = host; this.path = path; this.walletMode = walletMode; } // Note: server parameter ignored for now as this is a stateless server // TODO: allow creating both stateless and stateful remote MCP servers async start(_server) { // Block wallet mode on HTTP transports validateSecurityConfig(this.mode, this.walletMode); this.app = express(); this.app.use(express.json()); // Secure CORS - no cross-origin allowed by default this.app.use(createCorsMiddleware()); // Health check endpoint this.app.get('/health', (_req, res) => { res.json({ status: 'ok', timestamp: new Date().toISOString() }); }); this.app.post(this.path, async (req, res) => { try { // Create fresh MCP server for this request (stateless design) const mcpServer = await getServer(); const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined // For stateless servers }); res.on('close', () => { console.log('Request closed'); transport.close(); mcpServer.close(); }); await mcpServer.connect(transport); await transport.handleRequest(req, res, req.body); } catch (error) { console.error('Error handling MCP request:', error); if (!res.headersSent) { res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: 'Internal server error' }, id: null }); } } }); this.server = this.app.listen(this.port, this.host, () => { console.error(`MCP Server ready (streamable-http transport on ${this.host}:${this.port}${this.path})`); }); this.server.on('error', (error) => { console.error('Error starting server:', error); }); } async stop() { if (this.server) { return new Promise((resolve) => { if (this.server) { this.server.close(() => { this.server = undefined; this.app = undefined; resolve(); }); } else { resolve(); } }); } } }