Skip to main content
Glama

Enhanced Architecture MCP

cot_server.js14.2 kB
#!/usr/bin/env node const fs = require('fs'); const path = require('path'); const readline = require('readline'); // Data storage paths const DATA_DIR = path.join(__dirname, 'data'); const COT_STRANDS_FILE = path.join(DATA_DIR, 'cot_strands.json'); // Ensure data directory exists if (!fs.existsSync(DATA_DIR)) { fs.mkdirSync(DATA_DIR, { recursive: true }); } // Initialize CoT data file if (!fs.existsSync(COT_STRANDS_FILE)) { fs.writeFileSync(COT_STRANDS_FILE, JSON.stringify({ active_strands: {}, completed_strands: {}, strand_counter: 0 })); } // Helper functions function loadCotStrands() { try { return JSON.parse(fs.readFileSync(COT_STRANDS_FILE, 'utf8')); } catch (e) { return { active_strands: {}, completed_strands: {}, strand_counter: 0 }; } } function saveCotStrands(strands) { fs.writeFileSync(COT_STRANDS_FILE, JSON.stringify(strands, null, 2)); } // MCP Protocol Handler const rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false }); rl.on('line', (line) => { try { const trimmed = line.trim(); if (!trimmed) return; const request = JSON.parse(trimmed); handleRequest(request); } catch (e) { if (line.trim()) { process.stderr.write(`Parse error: ${e.message}\n`); } } }); function handleRequest(request) { switch (request.method) { case 'initialize': handleInitialize(request); break; case 'tools/list': handleToolsList(request); break; case 'tools/call': handleToolCall(request); break; case 'resources/list': handleResourcesList(request); break; default: sendError(request.id || 0, -32601, 'Method not found'); } } function handleInitialize(request) { const response = { jsonrpc: "2.0", id: request.id, result: { protocolVersion: "2024-11-05", capabilities: { tools: {} }, serverInfo: { name: "cot-server", version: "1.0.0" } } }; console.log(JSON.stringify(response)); } function handleResourcesList(request) { const response = { jsonrpc: "2.0", id: request.id, result: { resources: [] } }; console.log(JSON.stringify(response)); } function handleToolsList(request) { const tools = [ { name: "create_cot_strand", description: "Create new Chain of Thought reasoning strand", inputSchema: { type: "object", properties: { topic: { type: "string", description: "Topic or problem being analyzed" }, initial_thought: { type: "string", description: "Initial reasoning step" } }, required: ["topic", "initial_thought"] } }, { name: "add_to_strand", description: "Add reasoning step to existing CoT strand", inputSchema: { type: "object", properties: { strand_id: { type: "string", description: "ID of the strand to extend" }, thought: { type: "string", description: "Next reasoning step" } }, required: ["strand_id", "thought"] } }, { name: "get_strand", description: "Retrieve specific CoT strand", inputSchema: { type: "object", properties: { strand_id: { type: "string", description: "ID of strand to retrieve" } }, required: ["strand_id"] } }, { name: "complete_strand", description: "Mark CoT strand as completed with conclusion", inputSchema: { type: "object", properties: { strand_id: { type: "string", description: "ID of strand to complete" }, conclusion: { type: "string", description: "Final conclusion or result" } }, required: ["strand_id", "conclusion"] } }, { name: "list_strands", description: "List all CoT strands with optional filters", inputSchema: { type: "object", properties: { limit: { type: "number", description: "Maximum number of strands to return (default: 20)" }, status: { type: "string", enum: ["active", "completed", "all"], description: "Filter by strand status (default: all)" } } } }, { name: "search_strands", description: "Search CoT strands by topic or content keywords", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query for topics and content" }, limit: { type: "number", description: "Maximum results to return (default: 10)" } }, required: ["query"] } }, { name: "branch_strand", description: "Create new reasoning branch from existing strand", inputSchema: { type: "object", properties: { source_strand_id: { type: "string", description: "ID of strand to branch from" }, branch_topic: { type: "string", description: "Topic for the new branch" }, branch_thought: { type: "string", description: "Initial thought for the branch" } }, required: ["source_strand_id", "branch_topic", "branch_thought"] } } ]; const response = { jsonrpc: "2.0", id: request.id, result: { tools: tools } }; console.log(JSON.stringify(response)); } function handleToolCall(request) { const { name, arguments: args } = request.params; switch (name) { case 'create_cot_strand': handleCreateCotStrand(request, args); break; case 'add_to_strand': handleAddToStrand(request, args); break; case 'get_strand': handleGetStrand(request, args); break; case 'list_strands': handleListStrands(request, args); break; case 'search_strands': handleSearchStrands(request, args); break; case 'complete_strand': handleCompleteStrand(request, args); break; case 'branch_strand': handleBranchStrand(request, args); break; default: sendError(request.id, -32601, 'Tool not found'); } } function handleCreateCotStrand(request, args) { const { topic, initial_thought } = args; const strands = loadCotStrands(); strands.strand_counter++; const strand_id = `strand_${strands.strand_counter}`; strands.active_strands[strand_id] = { id: strand_id, topic: topic, thoughts: [initial_thought], created: new Date().toISOString(), last_updated: new Date().toISOString() }; saveCotStrands(strands); const response = { jsonrpc: "2.0", id: request.id, result: { content: [ { type: "text", text: `CoT strand '${strand_id}' created for topic: ${topic}` } ] } }; console.log(JSON.stringify(response)); } function handleAddToStrand(request, args) { const { strand_id, thought } = args; const strands = loadCotStrands(); const strand = strands.active_strands[strand_id]; if (!strand) { sendError(request.id, -32602, `Strand ${strand_id} not found`); return; } strand.thoughts.push(thought); strand.last_updated = new Date().toISOString(); saveCotStrands(strands); const response = { jsonrpc: "2.0", id: request.id, result: { content: [ { type: "text", text: `Added thought to strand ${strand_id}. Total thoughts: ${strand.thoughts.length}` } ] } }; console.log(JSON.stringify(response)); } function handleGetStrand(request, args) { const { strand_id } = args; const strands = loadCotStrands(); const strand = strands.active_strands[strand_id] || strands.completed_strands[strand_id]; if (!strand) { sendError(request.id, -32602, `Strand ${strand_id} not found`); return; } const response = { jsonrpc: "2.0", id: request.id, result: { content: [ { type: "text", text: `Strand ${strand_id}: ${strand.topic}\n\nThoughts:\n${strand.thoughts.map((t, i) => `${i + 1}. ${t}`).join('\n')}\n\n${strand.conclusion ? `Conclusion: ${strand.conclusion}` : 'Status: Active'}` } ] } }; console.log(JSON.stringify(response)); } function handleListStrands(request) { const strands = loadCotStrands(); let output = ''; if (Object.keys(strands.active_strands).length > 0) { output += 'Active Strands:\n'; for (const [id, strand] of Object.entries(strands.active_strands)) { output += `${id}: ${strand.topic} (${strand.thoughts.length} thoughts)\n`; } } if (Object.keys(strands.completed_strands).length > 0) { output += '\nCompleted Strands:\n'; for (const [id, strand] of Object.entries(strands.completed_strands)) { output += `${id}: ${strand.topic} (COMPLETED)\n`; } } if (!output) { output = 'No strands found.'; } const response = { jsonrpc: "2.0", id: request.id, result: { content: [ { type: "text", text: output.trim() } ] } }; console.log(JSON.stringify(response)); } function handleCompleteStrand(request, args) { const { strand_id, conclusion } = args; const strands = loadCotStrands(); const strand = strands.active_strands[strand_id]; if (!strand) { sendError(request.id, -32602, `Strand ${strand_id} not found`); return; } strand.conclusion = conclusion; strand.completed = new Date().toISOString(); strands.completed_strands[strand_id] = strand; delete strands.active_strands[strand_id]; saveCotStrands(strands); const response = { jsonrpc: "2.0", id: request.id, result: { content: [ { type: "text", text: `Strand ${strand_id} completed with conclusion: ${conclusion}` } ] } }; console.log(JSON.stringify(response)); } function handleBranchStrand(request, args) { const { source_strand_id, branch_topic, branch_thought } = args; const strands = loadCotStrands(); const sourceStrand = strands.active_strands[source_strand_id] || strands.completed_strands[source_strand_id]; if (!sourceStrand) { sendError(request.id, -32602, `Source strand ${source_strand_id} not found`); return; } strands.strand_counter++; const branch_id = `strand_${strands.strand_counter}`; strands.active_strands[branch_id] = { id: branch_id, topic: branch_topic, thoughts: [...sourceStrand.thoughts, branch_thought], created: new Date().toISOString(), last_updated: new Date().toISOString(), branched_from: source_strand_id }; saveCotStrands(strands); const response = { jsonrpc: "2.0", id: request.id, result: { content: [ { type: "text", text: `Created branch '${branch_id}' from '${source_strand_id}' with topic: ${branch_topic}` } ] } }; console.log(JSON.stringify(response)); } function handleSearchStrands(request, args) { const { query, limit = 10 } = args; const strands = loadCotStrands(); const searchTerm = query.toLowerCase(); let results = []; // Search active strands for (const [id, strand] of Object.entries(strands.active_strands)) { const topicMatch = strand.topic.toLowerCase().includes(searchTerm); const thoughtsMatch = strand.thoughts.some(thought => thought.toLowerCase().includes(searchTerm)); if (topicMatch || thoughtsMatch) { results.push({ id, topic: strand.topic, status: 'Active', thoughts: strand.thoughts.length, created: strand.created, match_type: topicMatch ? 'topic' : 'content' }); } } // Search completed strands for (const [id, strand] of Object.entries(strands.completed_strands)) { const topicMatch = strand.topic.toLowerCase().includes(searchTerm); const thoughtsMatch = strand.thoughts.some(thought => thought.toLowerCase().includes(searchTerm)); const conclusionMatch = strand.conclusion && strand.conclusion.toLowerCase().includes(searchTerm); if (topicMatch || thoughtsMatch || conclusionMatch) { results.push({ id, topic: strand.topic, status: 'Completed', thoughts: strand.thoughts.length, created: strand.created, match_type: topicMatch ? 'topic' : (conclusionMatch ? 'conclusion' : 'content') }); } } // Sort by relevance (topic matches first, then by date) results.sort((a, b) => { if (a.match_type === 'topic' && b.match_type !== 'topic') return -1; if (b.match_type === 'topic' && a.match_type !== 'topic') return 1; return new Date(b.created) - new Date(a.created); }); // Limit results results = results.slice(0, limit); let output = `Search results for "${query}" (${results.length} found):\n\n`; if (results.length === 0) { output = `No strands found matching "${query}".`; } else { results.forEach(result => { output += `${result.id}: ${result.topic} (${result.status}, ${result.thoughts} thoughts, ${result.match_type} match)\n`; }); } const response = { jsonrpc: "2.0", id: request.id, result: { content: [ { type: "text", text: output.trim() } ] } }; console.log(JSON.stringify(response)); } function sendError(id, code, message) { const response = { jsonrpc: "2.0", id: id, error: { code: code, message: message } }; console.log(JSON.stringify(response)); } process.stderr.write('CoT Server v1.0 started\n'); process.stderr.write('Chain of Thought reasoning tools active\n'); process.stderr.write(`Data directory: ${DATA_DIR}\n`);

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/autoexecbatman/arch-mcp'

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