Skip to main content
Glama
chrisleekr

MCP Server Boilerplate

by chrisleekr
handlers.ts3.69 kB
import { CallToolRequest, CallToolRequestSchema, CallToolResult, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { toolLoader } from '@/tools/loader'; import { ToolContext } from '@/tools/types'; import { loggingContext } from '../http/context'; export function setupToolHandlers(toolContext: ToolContext): void { const server = toolContext.server; if (!server) { throw new Error('Server not found'); } // List available tools server.setRequestHandler(ListToolsRequestSchema, () => { const tools = toolLoader.getToolDefinitions(); return Promise.resolve({ tools: tools.map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema, })), }); }); // Handle tool execution server.setRequestHandler( CallToolRequestSchema, async (request: CallToolRequest) => { return handleToolCall(request, toolContext); } ); } async function handleToolCall( request: CallToolRequest, toolContext: ToolContext ): Promise<CallToolResult> { const server = toolContext.server; if (!server) { throw new Error('Server not found'); } const { name, arguments: args } = request.params; loggingContext.log('info', 'Handling tool call', { data: { toolName: name, arguments: args }, }); const tool = toolLoader.getTool(name); if (!tool) { throw new Error(`Tool not found: ${name}`); } try { // Add progress token to context if provided const requestWithMeta = request as CallToolRequest & { _meta?: { progressToken?: string | number }; }; // If no progress token is provided, generate a random one const progressToken = requestWithMeta._meta?.progressToken ?? Math.random().toString(36).substring(2, 15); loggingContext.setContextValue('progressToken', progressToken); // Add progress token to tool context const toolContextWithProgressToken: ToolContext = { ...toolContext, progressToken, }; const generator = tool.execute(args ?? {}, toolContextWithProgressToken); let finalResult: { success: boolean; [key: string]: unknown } | null = null; // Get the result from the generator and assign it to the final result for await (const result of generator) { finalResult = result; } // Ensure we have at least one result finalResult ??= { success: false, error: 'No results generated', }; return { content: [ { type: 'text', text: JSON.stringify(finalResult), }, ], }; } catch (error: unknown) { loggingContext.log('error', 'Tool call failed', { data: { toolName: name, error: error instanceof Error ? error.message : 'Unknown error', stack: error instanceof Error ? error.stack : undefined, }, }); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error', timestamp: new Date().toISOString(), }, null, 2 ), }, ], isError: true, }; } } export function loadTools(): void { try { toolLoader.loadAllTools(); loggingContext.log('info', 'All tools loaded successfully'); } catch (error) { loggingContext.log('error', 'Failed to load tools', { error: { message: error instanceof Error ? error.message : 'Unknown error', stack: error instanceof Error ? error.stack : undefined, }, }); throw error; } }

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/chrisleekr/mcp-server-boilerplate'

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