UseScraper MCP Server

  • src
#!/usr/bin/env node import { Server } from "@modelcontextprotocol/sdk/server/index.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { CallToolRequestSchema, ListToolsRequestSchema, Tool, } from "@modelcontextprotocol/sdk/types.js"; import { BranchManager } from './branchManager.js'; import { BranchingThoughtInput } from './types.js'; import chalk from 'chalk'; class BranchingThoughtServer { private branchManager = new BranchManager(); processThought(input: unknown): { content: Array<{ type: string; text: string }>; isError?: boolean } { try { const inputData = input as any; // Handle commands if present if (inputData.command) { return this.handleCommand(inputData.command); } // Handle regular thought input const thoughtInput = input as BranchingThoughtInput; const thought = this.branchManager.addThought(thoughtInput); const branch = this.branchManager.getBranch(thought.branchId)!; // Format the response with the branch status const formattedStatus = this.branchManager.formatBranchStatus(branch); console.error(formattedStatus); // Display in the console return { content: [{ type: "text", text: JSON.stringify({ thoughtId: thought.id, branchId: thought.branchId, branchState: branch.state, branchPriority: branch.priority, numInsights: branch.insights.length, numCrossRefs: branch.crossRefs.length, activeBranch: this.branchManager.getActiveBranch()?.id }, null, 2) }] }; } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), status: 'failed' }, null, 2) }], isError: true }; } } private handleCommand(command: { type: string; branchId?: string }): { content: Array<{ type: string; text: string }> } { try { switch (command.type) { case 'list': { const branches = this.branchManager.getAllBranches(); const activeBranchId = this.branchManager.getActiveBranch()?.id; const output = branches.map(b => { const isActive = b.id === activeBranchId; const prefix = isActive ? chalk.green('→') : ' '; return `${prefix} ${b.id} [${b.state}] - ${b.thoughts[b.thoughts.length - 1]?.content.slice(0, 50)}...`; }).join('\n'); return { content: [{ type: "text", text: `Current Branches:\n${output}` }] }; } case 'focus': { if (!command.branchId) { throw new Error('branchId required for focus command'); } this.branchManager.setActiveBranch(command.branchId); const branch = this.branchManager.getBranch(command.branchId)!; const formattedStatus = this.branchManager.formatBranchStatus(branch); console.error(formattedStatus); return { content: [{ type: "text", text: JSON.stringify({ status: 'success', message: `Now focused on branch: ${command.branchId}`, activeBranch: command.branchId }, null, 2) }] }; } case 'history': { const branchId = command.branchId || this.branchManager.getActiveBranch()?.id; if (!branchId) { throw new Error('No active branch and no branchId provided'); } const branch = this.branchManager.getBranch(branchId)!; const history = this.branchManager.getBranchHistory(branchId); return { content: [{ type: "text", text: history }] }; } default: throw new Error(`Unknown command: ${command.type}`); } } catch (error) { return { content: [{ type: "text", text: JSON.stringify({ error: error instanceof Error ? error.message : String(error), status: 'failed' }, null, 2) }] }; } } } const BRANCHING_THOUGHT_TOOL: Tool = { name: "branch-thinking", description: `A tool for managing multiple branches of thought with insights and cross-references. Each thought can: - Belong to a specific branch - Generate insights - Create cross-references to other branches - Include confidence scores and key points The system tracks: - Branch priorities and states - Relationships between thoughts - Accumulated insights - Cross-branch connections Commands: - list: Show all branches and their status - focus [branchId]: Switch focus to a specific branch - history [branchId?]: Show the history of thoughts in a branch (uses active branch if none specified)`, inputSchema: { type: "object", properties: { content: { type: "string", description: "The thought content" }, branchId: { type: "string", description: "Optional: ID of the branch (generated if not provided)" }, parentBranchId: { type: "string", description: "Optional: ID of the parent branch" }, type: { type: "string", description: "Type of thought (e.g., 'analysis', 'hypothesis', 'observation')" }, confidence: { type: "number", description: "Optional: Confidence score (0-1)" }, keyPoints: { type: "array", items: { type: "string" }, description: "Optional: Key points identified in the thought" }, relatedInsights: { type: "array", items: { type: "string" }, description: "Optional: IDs of related insights" }, crossRefs: { type: "array", items: { type: "object", properties: { toBranch: { type: "string" }, type: { type: "string" }, reason: { type: "string" }, strength: { type: "number" } } }, description: "Optional: Cross-references to other branches" }, command: { type: "object", description: "Optional: Navigation command", properties: { type: { type: "string", enum: ["list", "focus", "history"], description: "Command type" }, branchId: { type: "string", description: "Branch ID for commands that require it" } }, required: ["type"] } }, anyOf: [ { required: ["content", "type"] }, { required: ["command"] } ] } }; const server = new Server( { name: "branch-thinking-server", version: "0.1.0", }, { capabilities: { tools: {}, }, } ); const thinkingServer = new BranchingThoughtServer(); server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [BRANCHING_THOUGHT_TOOL], })); server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name === "branch-thinking") { return thinkingServer.processThought(request.params.arguments); } return { content: [{ type: "text", text: `Unknown tool: ${request.params.name}` }], isError: true }; }); async function runServer() { const transport = new StdioServerTransport(); await server.connect(transport); console.error("Branch Thinking MCP Server running on stdio"); } runServer().catch((error) => { console.error("Fatal error running server:", error); process.exit(1); });