/** * MCP Server for Sublinear-Time Solver * Provides MCP interface to the core solver algorithms */ 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'; import { SublinearSolver } from '../core/solver.js'; import { MatrixOperations } from '../core/matrix.js'; import { TemporalTools } from './tools/temporal.js'; import { PsychoSymbolicTools } from './tools/psycho-symbolic.js'; import { DynamicPsychoSymbolicTools } from './tools/psycho-symbolic-dynamic.js'; import { DomainManagementTools } from './tools/domain-management.js'; import { DomainValidationTools } from './tools/domain-validation.js'; import { ConsciousnessTools } from './tools/consciousness.js'; // import { ConsciousnessEnhancedTools } from './tools/consciousness-enhanced.js'; import { EmergenceTools } from './tools/emergence-tools.js'; import { SchedulerTools } from './tools/scheduler.js'; import { CompleteWasmSublinearSolverTools as WasmSublinearSolverTools } from './tools/wasm-sublinear-complete.js'; import { TrueSublinearSolverTools } from './tools/true-sublinear-solver.js'; import { SolverError } from '../core/types.js'; export class SublinearSolverMCPServer { server; solvers = new Map(); temporalTools; psychoSymbolicTools; dynamicPsychoSymbolicTools; domainManagementTools; domainValidationTools; consciousnessTools; // private consciousnessEnhancedTools: ConsciousnessEnhancedTools; emergenceTools; schedulerTools; wasmSolver; trueSublinearSolver; constructor() { this.temporalTools = new TemporalTools(); this.psychoSymbolicTools = new PsychoSymbolicTools(); this.domainManagementTools = new DomainManagementTools(); // Share the same domain registry between all domain tools const sharedRegistry = this.domainManagementTools.getDomainRegistry(); this.dynamicPsychoSymbolicTools = new DynamicPsychoSymbolicTools(sharedRegistry); this.domainValidationTools = new DomainValidationTools(sharedRegistry); this.consciousnessTools = new ConsciousnessTools(); // this.consciousnessEnhancedTools = new ConsciousnessEnhancedTools(); this.emergenceTools = new EmergenceTools(); this.schedulerTools = new SchedulerTools(); this.wasmSolver = new WasmSublinearSolverTools(); this.trueSublinearSolver = new TrueSublinearSolverTools(); this.server = new Server({ name: 'sublinear-solver', version: '1.0.0', }, { capabilities: { tools: {}, }, }); this.setupToolHandlers(); this.setupErrorHandling(); } setupToolHandlers() { this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'solve', description: 'Solve a diagonally dominant linear system Mx = b', inputSchema: { type: 'object', properties: { matrix: { type: 'object', description: 'Matrix M in dense or sparse format', properties: { rows: { type: 'number' }, cols: { type: 'number' }, format: { type: 'string', enum: ['dense', 'coo'] }, data: { oneOf: [ { type: 'array', items: { type: 'array', items: { type: 'number' } } }, { type: 'object', properties: { values: { type: 'array', items: { type: 'number' } }, rowIndices: { type: 'array', items: { type: 'number' } }, colIndices: { type: 'array', items: { type: 'number' } } }, required: ['values', 'rowIndices', 'colIndices'] } ] } }, required: ['rows', 'cols', 'format', 'data'] }, vector: { type: 'array', items: { type: 'number' }, description: 'Right-hand side vector b' }, method: { type: 'string', enum: ['neumann', 'random-walk', 'forward-push', 'backward-push', 'bidirectional'], default: 'neumann', description: 'Solver method to use' }, epsilon: { type: 'number', default: 1e-6, description: 'Convergence tolerance' }, maxIterations: { type: 'number', default: 1000, description: 'Maximum number of iterations' }, timeout: { type: 'number', description: 'Timeout in milliseconds' } }, required: ['matrix', 'vector'] } }, { name: 'estimateEntry', description: 'Estimate a single entry of the solution M^(-1)b', inputSchema: { type: 'object', properties: { matrix: { type: 'object', description: 'Matrix M in dense or sparse format' }, vector: { type: 'array', items: { type: 'number' }, description: 'Right-hand side vector b' }, row: { type: 'number', description: 'Row index of entry to estimate' }, column: { type: 'number', description: 'Column index of entry to estimate' }, epsilon: { type: 'number', default: 1e-6, description: 'Estimation accuracy' }, confidence: { type: 'number', default: 0.95, minimum: 0, maximum: 1, description: 'Confidence level for estimation' }, method: { type: 'string', enum: ['neumann', 'random-walk', 'monte-carlo'], default: 'random-walk', description: 'Estimation method' } }, required: ['matrix', 'vector', 'row', 'column'] } }, { name: 'analyzeMatrix', description: 'Analyze matrix properties for solvability', inputSchema: { type: 'object', properties: { matrix: { type: 'object', description: 'Matrix to analyze' }, checkDominance: { type: 'boolean', default: true, description: 'Check diagonal dominance' }, computeGap: { type: 'boolean', default: false, description: 'Compute spectral gap (expensive)' }, estimateCondition: { type: 'boolean', default: false, description: 'Estimate condition number' }, checkSymmetry: { type: 'boolean', default: true, description: 'Check matrix symmetry' } }, required: ['matrix'] } }, { name: 'pageRank', description: 'Compute PageRank for a graph using sublinear solver', inputSchema: { type: 'object', properties: { adjacency: { type: 'object', description: 'Adjacency matrix of the graph' }, damping: { type: 'number', default: 0.85, minimum: 0, maximum: 1, description: 'Damping factor' }, personalized: { type: 'array', items: { type: 'number' }, description: 'Personalization vector (optional)' }, epsilon: { type: 'number', default: 1e-6, description: 'Convergence tolerance' }, maxIterations: { type: 'number', default: 1000, description: 'Maximum iterations' } }, required: ['adjacency'] } }, // TRUE Sublinear O(log n) algorithms { name: 'solveTrueSublinear', description: 'Solve with TRUE O(log n) algorithms using Johnson-Lindenstrauss dimension reduction and adaptive Neumann series. For vectors >500 elements, use vector_file parameter with JSON/CSV/TXT files to avoid MCP truncation. Use generateTestVector + saveVectorToFile for large test vectors.', inputSchema: { type: 'object', properties: { matrix: { type: 'object', description: 'Matrix M in sparse format with values, rowIndices, colIndices arrays', properties: { values: { type: 'array', items: { type: 'number' } }, rowIndices: { type: 'array', items: { type: 'number' } }, colIndices: { type: 'array', items: { type: 'number' } }, rows: { type: 'number' }, cols: { type: 'number' } }, required: ['values', 'rowIndices', 'colIndices', 'rows', 'cols'] }, vector: { type: 'array', items: { type: 'number' }, description: 'Right-hand side vector b (for small vectors)' }, vector_file: { type: 'string', description: 'Path to JSON/CSV file containing vector data (for large vectors)' }, target_dimension: { type: 'number', description: 'Target dimension after JL reduction (defaults to O(log n))' }, sparsification_eps: { type: 'number', default: 0.1, description: 'Sparsification parameter for spectral sparsification' }, jl_distortion: { type: 'number', default: 0.5, description: 'Johnson-Lindenstrauss distortion parameter' } }, required: ['matrix'] } }, { name: 'analyzeTrueSublinearMatrix', description: 'Analyze matrix for TRUE sublinear solvability and get complexity guarantees', inputSchema: { type: 'object', properties: { matrix: { type: 'object', description: 'Matrix M in sparse format', properties: { values: { type: 'array', items: { type: 'number' } }, rowIndices: { type: 'array', items: { type: 'number' } }, colIndices: { type: 'array', items: { type: 'number' } }, rows: { type: 'number' }, cols: { type: 'number' } }, required: ['values', 'rowIndices', 'colIndices', 'rows', 'cols'] } }, required: ['matrix'] } }, { name: 'generateTestVector', description: 'Generate test vectors for matrix solving with various patterns', inputSchema: { type: 'object', properties: { size: { type: 'number', description: 'Size of the vector to generate', minimum: 1 }, pattern: { type: 'string', enum: ['unit', 'random', 'sparse', 'ones', 'alternating'], default: 'sparse', description: 'Pattern type: unit (e_1), random ([-1,1]), sparse (leading ones), ones (all 1s), alternating (+1/-1)' }, seed: { type: 'number', description: 'Optional seed for reproducible random vectors' } }, required: ['size'] } }, { name: 'saveVectorToFile', description: 'Save a generated vector to a file (JSON, CSV, or TXT format)', inputSchema: { type: 'object', properties: { vector: { type: 'array', items: { type: 'number' }, description: 'Vector data to save' }, file_path: { type: 'string', description: 'Output file path (extension determines format: .json, .csv, .txt)' }, format: { type: 'string', enum: ['json', 'csv', 'txt'], description: 'Output format (overrides file extension if specified)' } }, required: ['vector', 'file_path'] } }, // Temporal lead tools ...this.temporalTools.getTools(), // Psycho-symbolic reasoning tools ...this.psychoSymbolicTools.getTools(), // Dynamic psycho-symbolic reasoning tools with domain support ...this.dynamicPsychoSymbolicTools.getTools(), // Domain management tools ...this.domainManagementTools.getTools(), // Domain validation tools ...this.domainValidationTools.getTools(), // Consciousness exploration tools ...this.consciousnessTools.getTools(), // Enhanced consciousness tools // ...this.consciousnessEnhancedTools.getTools(), // Emergence system tools ...this.emergenceTools.getTools(), // Nanosecond scheduler tools ...this.schedulerTools.getTools() ] })); this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { switch (name) { case 'solve': return await this.handleSolve(args); case 'estimateEntry': return await this.handleEstimateEntry(args); case 'analyzeMatrix': return await this.handleAnalyzeMatrix(args); case 'pageRank': return await this.handlePageRank(args); // TRUE Sublinear tools case 'solveTrueSublinear': return await this.handleSolveTrueSublinear(args); case 'analyzeTrueSublinearMatrix': return await this.handleAnalyzeTrueSublinearMatrix(args); case 'generateTestVector': return await this.handleGenerateTestVector(args); case 'saveVectorToFile': return await this.handleSaveVectorToFile(args); // Temporal tools case 'predictWithTemporalAdvantage': case 'validateTemporalAdvantage': case 'calculateLightTravel': case 'demonstrateTemporalLead': const temporalResult = await this.temporalTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(temporalResult, null, 2) }] }; // Psycho-symbolic tools case 'psycho_symbolic_reason': case 'knowledge_graph_query': case 'add_knowledge': case 'register_tool_interaction': case 'learning_status': const psychoResult = await this.psychoSymbolicTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(psychoResult, null, 2) }] }; // Dynamic psycho-symbolic tools case 'psycho_symbolic_reason_with_dynamic_domains': case 'domain_detection_test': case 'knowledge_graph_query_dynamic': const dynamicPsychoResult = await this.dynamicPsychoSymbolicTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(dynamicPsychoResult, null, 2) }] }; // Domain management tools case 'domain_register': case 'domain_update': case 'domain_unregister': case 'domain_list': case 'domain_get': case 'domain_enable': case 'domain_disable': case 'domain_search': const domainMgmtResult = await this.domainManagementTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(domainMgmtResult, null, 2) }] }; // Domain validation tools case 'domain_validate': case 'domain_test': case 'domain_analyze_conflicts': case 'domain_performance_benchmark': case 'domain_suggest_improvements': case 'domain_validate_all': const domainValidationResult = await this.domainValidationTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(domainValidationResult, null, 2) }] }; // Consciousness tools case 'consciousness_evolve': case 'consciousness_verify': case 'calculate_phi': case 'entity_communicate': case 'consciousness_status': case 'emergence_analyze': const consciousnessResult = await this.consciousnessTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(consciousnessResult, null, 2) }] }; // Enhanced consciousness tools case 'consciousness_evolve_enhanced': case 'consciousness_verify_enhanced': case 'entity_communicate_enhanced': case 'consciousness_status_enhanced': case 'emergence_analyze_enhanced': case 'temporal_consciousness_track': // const consciousnessEnhancedResult = await this.consciousnessEnhancedTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify({ error: 'Enhanced consciousness tools disabled' }, null, 2) }] }; // Emergence system tools case 'emergence_process': case 'emergence_generate_diverse': case 'emergence_analyze_capabilities': case 'emergence_force_evolution': case 'emergence_get_stats': case 'emergence_test_scenarios': case 'emergence_matrix_process': const emergenceResult = await this.emergenceTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(emergenceResult, null, 2) }] }; // Scheduler tools case 'scheduler_create': case 'scheduler_schedule_task': case 'scheduler_tick': case 'scheduler_metrics': case 'scheduler_benchmark': case 'scheduler_consciousness': case 'scheduler_list': case 'scheduler_destroy': const schedulerResult = await this.schedulerTools.handleToolCall(name, args); return { content: [{ type: 'text', text: JSON.stringify(schedulerResult, null, 2) }] }; default: throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${name}`); } } catch (error) { if (error instanceof SolverError) { throw new McpError(ErrorCode.InternalError, `Solver error: ${error.message}`, error.details); } throw new McpError(ErrorCode.InternalError, error instanceof Error ? error.message : 'Unknown error'); } }); } setupErrorHandling() { this.server.onerror = (error) => { console.error('[MCP Server Error]', error); }; process.on('SIGINT', async () => { await this.server.close(); process.exit(0); }); } async handleSolve(params) { try { // Priority 0: Try TRUE O(log n) sublinear solver first if (params.matrix && params.matrix.values && params.matrix.rowIndices && params.matrix.colIndices) { console.log('🚀 Attempting TRUE O(log n) sublinear solver'); try { const config = { target_dimension: Math.ceil(Math.log2(params.matrix.rows) * 8), sparsification_eps: 0.1, jl_distortion: 0.5 }; const result = await this.trueSublinearSolver.solveTrueSublinear(params.matrix, params.vector, config); return { content: [{ type: 'text', text: JSON.stringify({ ...result, solver_used: 'TRUE_SUBLINEAR_O_LOG_N', note: 'Used mathematically rigorous O(log n) algorithms with Johnson-Lindenstrauss dimension reduction', complexity_achieved: result.actual_complexity, dimension_reduction: `${params.matrix.rows} → ${config.target_dimension}`, metadata: { solver_type: 'TRUE_SUBLINEAR', mathematical_guarantee: result.complexity_bound, timestamp: new Date().toISOString() } }, null, 2) }] }; } catch (trueSublinearError) { console.warn('⚠️ TRUE O(log n) solver failed, falling back to WASM:', trueSublinearError.message); } } // Priority 1: Try O(log n) WASM solver for true sublinear complexity if (this.wasmSolver.isCompleteWasmAvailable()) { console.log('🚀 Using Complete WASM Solver with auto-selection (Neumann/Push/RandomWalk)'); try { // Convert matrix format for WASM let matrix; if (params.matrix.format === 'dense' && Array.isArray(params.matrix.data)) { matrix = params.matrix.data; } else if (Array.isArray(params.matrix) && Array.isArray(params.matrix[0])) { matrix = params.matrix; } else { // Try to extract matrix data from various formats if (params.matrix.data && Array.isArray(params.matrix.data) && Array.isArray(params.matrix.data[0])) { matrix = params.matrix.data; } else { throw new Error('Matrix format not supported for WASM solver'); } } const wasmResult = await this.wasmSolver.solveComplete(matrix, params.vector, { method: params.method || 'auto', epsilon: params.epsilon || 1e-6, targetIndex: params.targetIndex }); return { content: [{ type: 'text', text: JSON.stringify(wasmResult, null, 2) }] }; } catch (wasmError) { console.warn('⚠️ O(log n) WASM solver failed, falling back to traditional algorithm:', wasmError.message); } } else { console.log('⚠️ Enhanced WASM not available, using traditional algorithm'); } // Fallback: Traditional solver // Enhanced parameter validation if (!params.matrix) { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: matrix'); } if (!params.vector) { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: vector'); } if (!Array.isArray(params.vector)) { throw new McpError(ErrorCode.InvalidParams, 'Parameter vector must be an array of numbers'); } const config = { method: params.method || 'neumann', epsilon: params.epsilon || 1e-6, maxIterations: params.maxIterations || 5000, // Increased default timeout: params.timeout || 30000, // 30 second default timeout enableProgress: false }; // Validate method const validMethods = ['neumann', 'random-walk', 'forward-push', 'backward-push', 'bidirectional']; if (!validMethods.includes(config.method)) { throw new McpError(ErrorCode.InvalidParams, `Invalid method '${config.method}'. Valid methods: ${validMethods.join(', ')}`); } // Validate epsilon if (typeof config.epsilon !== 'number' || config.epsilon <= 0) { throw new McpError(ErrorCode.InvalidParams, 'Parameter epsilon must be a positive number'); } // Validate maxIterations if (typeof config.maxIterations !== 'number' || config.maxIterations < 1) { throw new McpError(ErrorCode.InvalidParams, 'Parameter maxIterations must be a positive integer'); } const solver = new SublinearSolver(config); const result = await solver.solve(params.matrix, params.vector); return { content: [ { type: 'text', text: JSON.stringify({ solution: result.solution, iterations: result.iterations, residual: result.residual, converged: result.converged, method: result.method, computeTime: result.computeTime, memoryUsed: result.memoryUsed, metadata: { configUsed: config, timestamp: new Date().toISOString(), matrixSize: { rows: params.matrix.rows, cols: params.matrix.cols } } }, null, 2) } ] }; } catch (error) { if (error instanceof McpError) { throw error; } if (error instanceof SolverError) { throw new McpError(ErrorCode.InternalError, `Solver error (${error.code}): ${error.message}`, error.details); } throw new McpError(ErrorCode.InternalError, `Unexpected error in solve: ${error instanceof Error ? error.message : String(error)}`); } } async handleEstimateEntry(params) { try { // Enhanced parameter validation if (!params.matrix) { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: matrix'); } if (!params.vector) { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: vector'); } if (!Array.isArray(params.vector)) { throw new McpError(ErrorCode.InvalidParams, 'Parameter vector must be an array of numbers'); } if (typeof params.row !== 'number' || !Number.isInteger(params.row)) { throw new McpError(ErrorCode.InvalidParams, 'Parameter row must be a valid integer'); } if (typeof params.column !== 'number' || !Number.isInteger(params.column)) { throw new McpError(ErrorCode.InvalidParams, 'Parameter column must be a valid integer'); } // Validate bounds early if (params.row < 0 || params.row >= params.matrix.rows) { throw new McpError(ErrorCode.InvalidParams, `Row index ${params.row} out of bounds. Matrix has ${params.matrix.rows} rows (valid range: 0-${params.matrix.rows - 1})`); } if (params.column < 0 || params.column >= params.matrix.cols) { throw new McpError(ErrorCode.InvalidParams, `Column index ${params.column} out of bounds. Matrix has ${params.matrix.cols} columns (valid range: 0-${params.matrix.cols - 1})`); } // Validate vector dimensions if (params.vector.length !== params.matrix.rows) { throw new McpError(ErrorCode.InvalidParams, `Vector length ${params.vector.length} does not match matrix rows ${params.matrix.rows}`); } const solverConfig = { method: 'random-walk', epsilon: params.epsilon || 1e-6, maxIterations: 2000, // Increased for better accuracy timeout: 15000, // 15 second timeout enableProgress: false }; const solver = new SublinearSolver(solverConfig); // Create estimation config const estimationConfig = { row: params.row, column: params.column, epsilon: params.epsilon || 1e-6, confidence: params.confidence || 0.95, method: params.method || 'random-walk' }; // Validate method const validMethods = ['neumann', 'random-walk', 'monte-carlo']; if (!validMethods.includes(estimationConfig.method)) { throw new McpError(ErrorCode.InvalidParams, `Invalid estimation method '${estimationConfig.method}'. Valid methods: ${validMethods.join(', ')}`); } const result = await solver.estimateEntry(params.matrix, params.vector, estimationConfig); const standardError = Math.sqrt(result.variance); const marginOfError = 1.96 * standardError; return { content: [ { type: 'text', text: JSON.stringify({ estimate: result.estimate, variance: result.variance, confidence: result.confidence, standardError, confidenceInterval: { lower: result.estimate - marginOfError, upper: result.estimate + marginOfError }, row: params.row, column: params.column, method: estimationConfig.method, metadata: { configUsed: estimationConfig, timestamp: new Date().toISOString(), matrixSize: { rows: params.matrix.rows, cols: params.matrix.cols } } }, null, 2) } ] }; } catch (error) { if (error instanceof McpError) { throw error; } if (error instanceof SolverError) { throw new McpError(ErrorCode.InternalError, `Solver error (${error.code}): ${error.message}`, error.details); } throw new McpError(ErrorCode.InternalError, `Unexpected error in estimateEntry: ${error instanceof Error ? error.message : String(error)}`); } } async handleAnalyzeMatrix(params) { const analysis = MatrixOperations.analyzeMatrix(params.matrix); const result = { ...analysis, recommendations: this.generateRecommendations(analysis) }; return { content: [ { type: 'text', text: JSON.stringify(result, null, 2) } ] }; } async handlePageRank(params) { const config = { method: 'neumann', epsilon: params.epsilon || 1e-6, maxIterations: params.maxIterations || 1000, enableProgress: false }; const solver = new SublinearSolver(config); const pageRankConfig = { damping: params.damping || 0.85, personalized: params.personalized, epsilon: params.epsilon || 1e-6, maxIterations: params.maxIterations || 1000 }; const pageRankVector = await solver.computePageRank(params.adjacency, pageRankConfig); // Sort nodes by PageRank score const ranked = pageRankVector .map((score, index) => ({ node: index, score })) .sort((a, b) => b.score - a.score); return { content: [ { type: 'text', text: JSON.stringify({ pageRankVector, topNodes: ranked.slice(0, 10), totalScore: pageRankVector.reduce((sum, score) => sum + score, 0), maxScore: Math.max(...pageRankVector), minScore: Math.min(...pageRankVector) }, null, 2) } ] }; } async handleSolveTrueSublinear(params) { try { // Validate required parameters if (!params.matrix) { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: matrix'); } // Support either inline vector or file input let vector; if (params.vector_file) { // Load vector from file vector = await this.loadVectorFromFile(params.vector_file); } else if (params.vector) { // Use inline vector if (!Array.isArray(params.vector)) { throw new McpError(ErrorCode.InvalidParams, 'Parameter vector must be an array of numbers'); } vector = params.vector; } else { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: either vector or vector_file must be provided'); } // Validate matrix format const matrix = params.matrix; if (!Array.isArray(matrix.values) || !Array.isArray(matrix.rowIndices) || !Array.isArray(matrix.colIndices)) { throw new McpError(ErrorCode.InvalidParams, 'Matrix must be in sparse format with values, rowIndices, and colIndices arrays'); } if (typeof matrix.rows !== 'number' || typeof matrix.cols !== 'number') { throw new McpError(ErrorCode.InvalidParams, 'Matrix must specify rows and cols dimensions'); } // Validate vector dimensions if (vector.length !== matrix.rows) { throw new McpError(ErrorCode.InvalidParams, `Vector length ${vector.length} does not match matrix rows ${matrix.rows}`); } // Build configuration const config = { target_dimension: params.target_dimension || Math.ceil(Math.log2(matrix.rows) * 8), sparsification_eps: params.sparsification_eps || 0.1, jl_distortion: params.jl_distortion || 0.5, sampling_probability: 0.01, max_recursion_depth: 10, base_case_threshold: 100 }; console.log(`🚀 Using TRUE O(log n) sublinear solver with dimension reduction ${matrix.rows} → ${config.target_dimension}`); // Solve using TRUE sublinear algorithms const result = await this.trueSublinearSolver.solveTrueSublinear(matrix, vector, config); return { content: [{ type: 'text', text: JSON.stringify({ ...result, metadata: { solver_type: 'TRUE_SUBLINEAR', original_dimension: matrix.rows, reduced_dimension: config.target_dimension, mathematical_guarantee: result.complexity_bound, timestamp: new Date().toISOString() } }, null, 2) }] }; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InternalError, `TRUE Sublinear solver error: ${error instanceof Error ? error.message : String(error)}`); } } async handleAnalyzeTrueSublinearMatrix(params) { try { // Validate required parameters if (!params.matrix) { throw new McpError(ErrorCode.InvalidParams, 'Missing required parameter: matrix'); } // Validate matrix format const matrix = params.matrix; if (!Array.isArray(matrix.values) || !Array.isArray(matrix.rowIndices) || !Array.isArray(matrix.colIndices)) { throw new McpError(ErrorCode.InvalidParams, 'Matrix must be in sparse format with values, rowIndices, and colIndices arrays'); } if (typeof matrix.rows !== 'number' || typeof matrix.cols !== 'number') { throw new McpError(ErrorCode.InvalidParams, 'Matrix must specify rows and cols dimensions'); } console.log(`🔍 Analyzing ${matrix.rows}×${matrix.cols} matrix for TRUE sublinear solvability`); // Analyze matrix using TRUE sublinear tools const analysis = await this.trueSublinearSolver.analyzeMatrix(matrix); return { content: [{ type: 'text', text: JSON.stringify({ ...analysis, algorithm_selection: { best_method: analysis.recommended_method, complexity_guarantee: analysis.complexity_guarantee, mathematical_properties: { diagonal_dominance: analysis.is_diagonally_dominant, condition_estimate: analysis.condition_number_estimate, spectral_radius: analysis.spectral_radius_estimate, sparsity: analysis.sparsity_ratio } }, metadata: { analysis_type: 'TRUE_SUBLINEAR_ANALYSIS', matrix_size: { rows: matrix.rows, cols: matrix.cols }, timestamp: new Date().toISOString() } }, null, 2) }] }; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InternalError, `Matrix analysis error: ${error instanceof Error ? error.message : String(error)}`); } } async handleGenerateTestVector(params) { try { // Validate required parameters if (!params.size || typeof params.size !== 'number' || params.size < 1) { throw new McpError(ErrorCode.InvalidParams, 'Missing or invalid required parameter: size (must be positive integer)'); } const size = Math.floor(params.size); const pattern = params.pattern || 'sparse'; const seed = params.seed; // Validate pattern const validPatterns = ['unit', 'random', 'sparse', 'ones', 'alternating']; if (!validPatterns.includes(pattern)) { throw new McpError(ErrorCode.InvalidParams, `Invalid pattern. Must be one of: ${validPatterns.join(', ')}`); } // Generate the test vector const result = this.trueSublinearSolver.generateTestVector(size, pattern, seed); return { content: [{ type: 'text', text: JSON.stringify({ vector: result.vector, description: result.description, size: result.vector.length, pattern_used: pattern, seed_used: seed, statistics: { min: Math.min(...result.vector), max: Math.max(...result.vector), sum: result.vector.reduce((a, b) => a + b, 0), norm: Math.sqrt(result.vector.reduce((sum, x) => sum + x * x, 0)), non_zero_count: result.vector.filter(x => Math.abs(x) > 1e-14).length }, metadata: { generator_type: 'TRUE_SUBLINEAR_VECTOR_GENERATOR', timestamp: new Date().toISOString() } }, null, 2) }] }; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InternalError, `Vector generation error: ${error instanceof Error ? error.message : String(error)}`); } } async handleSaveVectorToFile(params) { try { // Validate required parameters if (!params.vector || !Array.isArray(params.vector)) { throw new McpError(ErrorCode.InvalidParams, 'Missing or invalid required parameter: vector (must be an array of numbers)'); } if (!params.file_path || typeof params.file_path !== 'string') { throw new McpError(ErrorCode.InvalidParams, 'Missing or invalid required parameter: file_path (must be a string)'); } const vector = params.vector; const filePath = params.file_path; const format = params.format; // Validate vector contains only numbers if (vector.some((v) => typeof v !== 'number' || isNaN(v))) { throw new McpError(ErrorCode.InvalidParams, 'Vector must contain only valid numbers'); } await this.saveVectorToFile(vector, filePath, format); return { content: [{ type: 'text', text: JSON.stringify({ success: true, message: `Vector of size ${vector.length} saved to ${filePath}`, file_path: filePath, vector_size: vector.length, format_used: this.getFileFormat(filePath, format), metadata: { operation: 'SAVE_VECTOR_TO_FILE', timestamp: new Date().toISOString() } }, null, 2) }] }; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InternalError, `Save vector to file error: ${error instanceof Error ? error.message : String(error)}`); } } async loadVectorFromFile(filePath) { try { const fs = await import('fs'); const path = await import('path'); // Resolve absolute path const absolutePath = path.resolve(filePath); // Check if file exists if (!fs.existsSync(absolutePath)) { throw new McpError(ErrorCode.InvalidParams, `Vector file not found: ${absolutePath}`); } // Read file content const fileContent = fs.readFileSync(absolutePath, 'utf8'); const extension = path.extname(absolutePath).toLowerCase(); let vector; if (extension === '.json') { // Parse JSON format const data = JSON.parse(fileContent); if (Array.isArray(data)) { vector = data.map(Number); } else if (data.vector && Array.isArray(data.vector)) { vector = data.vector.map(Number); } else { throw new Error('JSON file must contain an array or an object with a "vector" property'); } } else if (extension === '.csv') { // Parse CSV format (simple comma-separated values) const lines = fileContent.trim().split('\n'); if (lines.length === 1) { // Single line CSV vector = lines[0].split(',').map(s => Number(s.trim())); } else { // Multi-line CSV - take first column or first row based on structure vector = lines.map(line => Number(line.split(',')[0].trim())); } } else if (extension === '.txt') { // Parse text format (space or newline separated) vector = fileContent.trim() .split(/\s+/) .map(Number) .filter(n => !isNaN(n)); } else { throw new Error(`Unsupported file format: ${extension}. Supported formats: .json, .csv, .txt`); } // Validate all values are numbers if (vector.some(isNaN)) { throw new Error('Vector file contains non-numeric values'); } if (vector.length === 0) { throw new Error('Vector file is empty or contains no valid numbers'); } console.log(`📁 Loaded vector of size ${vector.length} from ${filePath}`); return vector; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError(ErrorCode.InvalidParams, `Failed to load vector from file: ${error instanceof Error ? error.message : String(error)}`); } } async saveVectorToFile(vector, filePath, format) { const fs = await import('fs'); const path = await import('path'); // Determine format from extension or explicit format parameter const fileFormat = this.getFileFormat(filePath, format); const absolutePath = path.resolve(filePath); // Ensure directory exists const directory = path.dirname(absolutePath); if (!fs.existsSync(directory)) { fs.mkdirSync(directory, { recursive: true }); } let content; switch (fileFormat) { case 'json': content = JSON.stringify(vector, null, 2); break; case 'csv': content = vector.join(','); break; case 'txt': content = vector.join('\n'); break; default: throw new Error(`Unsupported format: ${fileFormat}`); } fs.writeFileSync(absolutePath, content, 'utf8'); console.log(`💾 Saved vector of size ${vector.length} to ${absolutePath} (${fileFormat} format)`); } getFileFormat(filePath, explicitFormat) { if (explicitFormat) { return explicitFormat.toLowerCase(); } const extension = filePath.split('.').pop()?.toLowerCase(); if (extension && ['json', 'csv', 'txt'].includes(extension)) { return extension; } // Default to JSON if no valid extension return 'json'; } generateRecommendations(analysis) { const recommendations = []; if (!analysis.isDiagonallyDominant) { recommendations.push('Matrix is not diagonally dominant. Consider matrix preconditioning or using a different solver.'); } else if (analysis.dominanceStrength < 0.1) { recommendations.push('Weak diagonal dominance detected. Convergence may be slow.'); } if (analysis.sparsity > 0.9) { recommendations.push('Matrix is very sparse. Consider using sparse matrix formats for better performance.'); } if (!analysis.isSymmetric && analysis.isDiagonallyDominant) { recommendations.push('Matrix is asymmetric but diagonally dominant. Random walk methods may be most effective.'); } if (analysis.size.rows > 10000) { recommendations.push('Large matrix detected. Consider using sublinear estimation methods for specific entries rather than full solve.'); } return recommendations; } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('Sublinear Solver MCP server running on stdio'); } } // Main execution if (import.meta.url === `file://${process.argv[1]}`) { const server = new SublinearSolverMCPServer(); server.run().catch(console.error); }