Skip to main content
Glama

Dev Memory MCP Server

by TrackerXXX23
server.ts4.26 kB
import { McpRequest, McpResponse, ServerInfo, ListToolsRequest, ListResourcesRequest, CallToolRequest, ReadResourceRequest, Tool, Resource } from './types.js'; import { McpError, Errors } from './errors.js'; import { randomUUID } from 'crypto'; export type RequestHandler<T = any, R = any> = (request: McpRequest<T>) => Promise<R>; export class Server { private handlers: Map<string, RequestHandler> = new Map(); private info: ServerInfo; private transport: Transport | null = null; constructor(info: ServerInfo) { this.info = info; this.setupDefaultHandlers(); } private setupDefaultHandlers() { // List available tools this.setRequestHandler('list_tools', async () => ({ tools: Array.from(this.handlers.entries()) .filter(([method]) => method.startsWith('tool:')) .map(([method]) => ({ name: method.replace('tool:', ''), description: 'Tool description', inputSchema: {} })) })); // List available resources this.setRequestHandler('list_resources', async () => ({ resources: Array.from(this.handlers.entries()) .filter(([method]) => method.startsWith('resource:')) .map(([method]) => ({ uri: method.replace('resource:', ''), name: 'Resource name', description: 'Resource description' })) })); } public setRequestHandler<T = any, R = any>(method: string, handler: RequestHandler<T, R>) { this.handlers.set(method, handler); } public async handleRequest(request: McpRequest): Promise<McpResponse> { try { if (!request.jsonrpc || request.jsonrpc !== '2.0') { throw Errors.InvalidRequest('Invalid JSON-RPC version'); } if (!request.method || typeof request.method !== 'string') { throw Errors.InvalidRequest('Invalid method'); } // Generate a request ID if none provided const requestId = request.id ?? randomUUID(); const handler = this.handlers.get(request.method); if (!handler) { throw Errors.MethodNotFound(`Method not found: ${request.method}`); } const result = await handler(request); return { jsonrpc: '2.0', result, id: requestId }; } catch (error) { if (McpError.isInstance(error)) { return { jsonrpc: '2.0', error: error.toJSON(), id: request.id ?? randomUUID() }; } return { jsonrpc: '2.0', error: Errors.InternalError(error instanceof Error ? error.message : 'Internal error').toJSON(), id: request.id ?? randomUUID() }; } } public async connect(transport: Transport) { this.transport = transport; await transport.connect(this.handleRequest.bind(this)); } public async close() { if (this.transport) { await this.transport.close(); this.transport = null; } } } export interface Transport { connect(handler: (request: McpRequest) => Promise<McpResponse>): Promise<void>; close(): Promise<void>; } export class StdioTransport implements Transport { private handler: ((request: McpRequest) => Promise<McpResponse>) | null = null; private requestId = 0; async connect(handler: (request: McpRequest) => Promise<McpResponse>) { this.handler = handler; process.stdin.setEncoding('utf8'); process.stdin.on('data', async (data) => { try { const request = JSON.parse(data.toString()) as McpRequest; const response = await this.handler!(request); process.stdout.write(JSON.stringify(response) + '\n'); } catch (error) { const response: McpResponse = { jsonrpc: '2.0', error: Errors.ParseError(error instanceof Error ? error.message : 'Parse error').toJSON(), id: String(this.requestId++) }; process.stdout.write(JSON.stringify(response) + '\n'); } }); // Handle process termination process.on('SIGINT', () => this.close()); process.on('SIGTERM', () => this.close()); } async close() { this.handler = null; process.stdin.removeAllListeners(); process.removeAllListeners('SIGINT'); process.removeAllListeners('SIGTERM'); } }

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/TrackerXXX23/dev_memory_mcp'

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