UNPKG

@emmahyde/thought-patterns

Version:

MCP server combining systematic thinking, mental models, debugging approaches, and stochastic algorithms for comprehensive cognitive pattern support

147 lines (146 loc) 4.58 kB
import { z } from 'zod'; /** * Abstract base class for all tool servers * Provides standardized validation, error handling, and response formatting */ export class BaseToolServer { /** * Constructor that accepts a Zod schema for input validation * @param schema - Zod schema for validating input data */ constructor(schema) { this.schema = schema; } /** * Validates input using the provided Zod schema * @param input - Raw input data to validate * @returns Validated and typed input data * @throws Error if validation fails */ validate(input) { try { return this.schema.parse(input); } catch (error) { if (error instanceof z.ZodError) { const errorMessages = error.errors.map(err => `${err.path.join('.')}: ${err.message}`).join(', '); throw new Error(`Validation failed: ${errorMessages}`); } throw error; } } /** * Standardized process method for unified server interface * Default implementation delegates to handle method for backward compatibility * Servers can override this to provide standardized processing interface * @param validInput - Validated input data * @returns Processed output data */ process(validInput) { return this.handle(validInput); } /** * Main entry point that wraps validation, processing, and error handling * Provides standardized {content, isError} envelope response * @param rawInput - Raw input data from MCP request * @returns Standardized MCP response */ run(rawInput) { try { // Validate input using schema const validatedInput = this.validate(rawInput); // Process with concrete implementation const result = this.handle(validatedInput); // Format successful response return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] }; } catch (error) { // Format error response return { content: [{ type: "text", text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), status: 'failed', timestamp: new Date().toISOString() }, null, 2) }], isError: true }; } } /** * Optional method for servers that need custom response formatting * @param result - Result from handle method * @returns Formatted response content */ formatResponse(result) { return [{ type: "text", text: JSON.stringify(result, null, 2) }]; } /** * Optional method for servers that need custom error formatting * @param error - Error that occurred during processing * @returns Formatted error response content */ formatError(error) { return [{ type: "text", text: JSON.stringify({ error: error.message, status: 'failed', timestamp: new Date().toISOString() }, null, 2) }]; } } /** * Tool registry for managing all available tools */ export class ToolRegistry { /** * Register a new tool * @param entry - Tool registry entry */ static register(entry) { this.tools.push(entry); } /** * Find a tool by name * @param name - Tool name * @returns Tool registry entry or undefined */ static findTool(name) { return this.tools.find(tool => tool.name === name); } /** * Get all registered tools * @returns Array of all tool registry entries */ static getAllTools() { return [...this.tools]; } /** * Get tool names for MCP ListTools response * @returns Array of tool definitions for MCP */ static getToolDefinitions() { return this.tools.map(tool => ({ name: tool.name, description: tool.description || `Tool for ${tool.name} operations`, inputSchema: { type: "object", properties: {}, required: [] } })); } } ToolRegistry.tools = [];