branch-thinking
Organize and analyze complex thoughts by creating branches, linking ideas, extracting tasks, and generating insights to structure thinking processes.
Instructions
Branch-Thinking Tool
Purpose: Use branching commands to create, navigate, and analyze thought branches and tasks.
Usage: Provide a JSON payload with 'type' and relevant parameters in 'args' object. The tool returns an array of items in the format { type: string, text: string }.
Supported Commands:
create-branch: { type: 'create-branch', branchId }
focus: { type: 'focus', branchId }
add-thought: { type: 'add-thought', branchId, content }
semantic-search: { type: 'semantic-search', query, topN? }
extract-tasks: { type: 'extract-tasks', branchId? }
visualize: { type: 'visualize', branchId?, options? }
list-branches: { type: 'list-branches' }
history: { type: 'history', branchId }
insights: { type: 'insights', branchId }
crossrefs: { type: 'crossrefs', branchId }
hub-thoughts: { type: 'hub-thoughts', branchId }
link-thoughts: { type: 'link-thoughts', fromThoughtId, toThoughtId, linkType, reason? }
add-snippet: { type: 'add-snippet', content, tags, author? }
snippet-search: { type: 'snippet-search', query, topN? }
summarize-branch: { type: 'summarize-branch', branchId? }
doc-thought: { type: 'doc-thought', thoughtId }
review-branch: { type: 'review-branch', branchId? }
ask: { type: 'ask', question }
summarize-tasks: { type: 'summarize-tasks', branchId? }
advance-task: { type: 'advance-task', taskId, status }
assign-task: { type: 'assign-task', taskId, assignee }
reset-session: { type: 'reset-session' }
clear-cache: { type: 'clear-cache' }
get-cache-stats: { type: 'get-cache-stats' }
Visualization Options:
clustering: { type: 'clustering', algorithm? }
centrality: { type: 'centrality', metric? }
overlays: { type: 'overlays', features? }
analytics: { type: 'analytics', metrics? }
Example Calls and Expected Responses:
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| content | No | Thought content (string) or batch of thoughts (array of objects). | |
| branchId | No | Branch ID to associate with the thought(s). If omitted, a new branch may be created or the active branch used. | |
| parentBranchId | No | Optional: ID of the parent branch for hierarchical organization. | |
| type | No | Thought type: e.g., 'analysis', 'hypothesis', 'observation', 'task', etc. Used for filtering and scoring. | |
| confidence | No | Optional: Confidence score (0-1) for the thought, for ranking or filtering. | |
| keyPoints | No | Optional: Key points or highlights extracted from the thought. | |
| relatedInsights | No | Optional: IDs of related insights, for semantic linking. | |
| crossRefs | No | Optional: Array of cross-references to other branches, with type, reason, and strength. | |
| command | No | Optional: Navigation or workflow command. Used for agentic/AI interactions. |
Implementation Reference
- src/index.ts:779-790 (handler)MCP CallToolRequestSchema request handler that checks for 'branch-thinking' tool name and delegates to the processThought method on the BranchingThoughtServer instance.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 }; });
- src/index.ts:87-136 (handler)processThought method: the primary execution logic for the branch-thinking tool. Handles tool arguments by either adding thoughts via BranchManager or processing commands.// Made async to allow awaiting handleCommand async processThought(input: unknown): Promise<{ content: Array<{ type: string; text: string }>; isError?: boolean }> { try { const inputData = input as any; // Handle commands if present if (inputData.command) { // Await handleCommand since it is now async return await this.handleCommand(inputData.command); } // Handle regular thought input (single or batch) let lastThought; let branch; if (Array.isArray(inputData)) { lastThought = this.branchManager.addThought(inputData); branch = this.branchManager.getBranch(lastThought.branchId)!; } else { const thoughtInput = input as BranchingThoughtInput; lastThought = this.branchManager.addThought(thoughtInput); branch = this.branchManager.getBranch(lastThought.branchId)!; } // Format the response with the branch status const formattedStatus = await this.branchManager.formatBranchStatus(branch); console.error(formattedStatus); // Display in the console return { content: [{ type: "text", text: JSON.stringify({ thoughtId: lastThought.id, branchId: lastThought.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) }] }; } }
- src/index.ts:225-511 (handler)_executeAtomicCommand: switch-based dispatcher for all supported command types (e.g., 'add-thought', 'insights', 'extract-tasks'), delegating to BranchManager instance methods.private async _executeAtomicCommand(type: string, params: any): Promise<{ content: Array<{ type: string; text: string }> }> { switch (type) { case 'create-branch': { if (!params.branchId) throw new Error('branchId required for create-branch'); const branch = this.branchManager.createBranch(params.branchId, params.parentBranchId); const content: Array<{ type: string; text: string }> = [{ type: "text", text: `Created branch '${branch.id}'${params.parentBranchId ? ` with parent '${params.parentBranchId}'` : ''}.` }]; if (params.autoVisualize) { const options = { branchId: branch.id } as VisualizationOptions; const vizData = this.branchManager.visualizeBranch(options); content.push({ type: "text", text: JSON.stringify({ visualization: vizData }, null, 2) }); } return { content }; } case 'insights': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; if (!branchId) { throw new Error('No active branch and no branchId provided'); } const insights = this.branchManager.getCachedInsights(branchId); return { content: [{ type: "text", text: JSON.stringify({ branchId, insights }, null, 2) }] }; } 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 (!params.branchId) { throw new Error('branchId required for focus command'); } this.branchManager.setActiveBranch(params.branchId); const branch = this.branchManager.getBranch(params.branchId)!; const formattedStatus = await this.branchManager.formatBranchStatus(branch); console.error(formattedStatus); return { content: [{ type: "text", text: JSON.stringify({ status: 'success', message: `Now focused on branch: ${params.branchId}`, activeBranch: params.branchId }, null, 2) }] }; } case 'history': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; if (!branchId) { throw new Error('No active branch and no branchId provided'); } const history = await this.branchManager.getBranchHistory(branchId); return { content: [{ type: "text", text: history }] }; } case 'crossrefs': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; if (!branchId) throw new Error('No active branch and no branchId provided'); const branch = this.branchManager.getBranch(branchId)!; const crossRefs = branch.crossRefs || []; return { content: [{ type: "text", text: JSON.stringify({ branchId, crossReferences: crossRefs }, null, 2) }] }; } case 'hub-thoughts': { // List thoughts with the highest cross-branch connections/scores const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; if (!branchId) throw new Error('No active branch and no branchId provided'); const branch = this.branchManager.getBranch(branchId)!; const thoughts = branch.thoughts || []; // Sort by number of crossRefs and score const sorted = [...thoughts].sort((a, b) => { const aScore = (a.crossRefs?.length || 0) + (typeof a.score === 'number' ? a.score : 0); const bScore = (b.crossRefs?.length || 0) + (typeof b.score === 'number' ? b.score : 0); return bScore - aScore; }); return { content: [{ type: "text", text: JSON.stringify({ branchId, hubThoughts: sorted.slice(0, 10) }, null, 2) }] }; } case 'semantic-search': { if (!('query' in params) || typeof params.query !== 'string') { throw new Error('semantic-search requires a query string'); } const query = params.query; const topN = typeof params.topN === 'number' ? params.topN : 5; // Perform semantic search const results = await this.branchManager.semanticSearch(query, topN); return { content: [{ type: "text", text: JSON.stringify({ query, topN, results }, null, 2) }] }; } case 'link-thoughts': { if (!('fromThoughtId' in params) || !('toThoughtId' in params) || !('linkType' in params)) { throw new Error('link-thoughts requires fromThoughtId, toThoughtId, and linkType'); } const { fromThoughtId, toThoughtId, linkType, reason } = params; const validLinkType = linkType as 'supports' | 'contradicts' | 'related' | 'expands' | 'refines'; const success = this.branchManager.linkThoughts(fromThoughtId!, toThoughtId!, validLinkType, reason); return { content: [{ type: "text", text: JSON.stringify({ status: success ? 'linked' : 'failed', fromThoughtId, toThoughtId, linkType, reason }, null, 2) }] }; } case 'add-snippet': { if (!('content' in params) || typeof params.content !== 'string' || !('tags' in params) || !Array.isArray(params.tags)) throw new Error('add-snippet requires content (string) and tags (array)'); const snippet = this.branchManager.addSnippet(params.content, params.tags, typeof params.author === 'string' ? params.author : undefined); return { content: [{ type: "text", text: JSON.stringify(snippet, null, 2) }] }; } case 'snippet-search': { if (!('query' in params) || typeof params.query !== 'string') throw new Error('snippet-search requires a query string'); const results = this.branchManager.searchSnippets(params.query, typeof params.topN === 'number' ? params.topN : 5); return { content: [{ type: "text", text: JSON.stringify({ results }, null, 2) }] }; } case 'summarize-branch': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; if (!branchId) throw new Error('No branchId provided and no active branch.'); return { content: [{ type: "text", text: await this.branchManager.summarizeBranch(branchId) }] }; } case 'doc-thought': { if (!('thoughtId' in params) || typeof params.thoughtId !== 'string') throw new Error('doc-thought requires a thoughtId (string)'); return { content: [{ type: "text", text: await this.branchManager.summarizeThought(params.thoughtId) }] }; } case 'extract-tasks': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; const tasks = await this.branchManager.extractTasks(branchId); return { content: [{ type: "text", text: JSON.stringify({ branchId, tasks }, null, 2) }] }; } case 'list-tasks': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; const status = params.status; const assignee = params.assignee; const due = params.due; const tasks = await this.branchManager.queryTasks({ branchId, status, assignee, due }); return { content: [{ type: "text", text: JSON.stringify({ branchId, status, assignee, due, tasks }, null, 2) }] }; } case 'update-task-status': { const taskId = params.taskId; const status = params.status; if (!taskId || !status) throw new Error('update-task-status requires taskId and status'); const updated = await this.branchManager.updateTaskStatus(taskId, status as 'open' | 'in_progress' | 'closed'); return { content: [{ type: "text", text: updated ? `Task ${taskId} updated to status ${status}` : `Task ${taskId} not updated (stateless mode)` }] }; } case 'summarize-tasks': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; const summary = await this.branchManager.summarizeTasks(branchId); return { content: [{ type: "text", text: summary }] }; } case 'review-branch': { const branchId = params.branchId || this.branchManager.getActiveBranch()?.id; if (!branchId) throw new Error('No branchId provided and no active branch.'); const reviews = await this.branchManager.reviewBranch(branchId); return { content: [{ type: "text", text: JSON.stringify({ branchId, reviews }, null, 2) }] }; } case 'visualize': { // Pass full visualization options const options = params as VisualizationOptions; const data = this.branchManager.visualizeBranch(options); return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] }; } case 'ask': { if (!('question' in params) || typeof params.question !== 'string') throw new Error('ask requires a question string'); const question = params.question; const answer = await this.branchManager.askQuestion(question); return { content: [{ type: "text", text: answer }] }; } case 'reset-session': { // already transitioned return { content: [{ type: "text", text: 'Session has been reset.' }] }; } case 'clear-cache': { this.branchManager.clearCache(); return { content: [{ type: "text", text: 'Cache cleared.' }] }; } case 'get-cache-stats': { const stats = this.branchManager.getCacheStats(); return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] }; } } // Default return for unknown command types return { content: [{ type: "text", text: `Unknown command type: ${type}` }] }; }
- src/index.ts:514-759 (schema)BRANCHING_THOUGHT_TOOL constant: defines the tool schema including name, description of all commands, and comprehensive inputSchema for validation of thoughts and commands.const BRANCHING_THOUGHT_TOOL: Tool = { name: "branch-thinking", description: ` # Branch-Thinking Tool **Purpose:** Use branching commands to create, navigate, and analyze thought branches and tasks. **Usage:** Provide a JSON payload with 'type' and relevant parameters in 'args' object. The tool returns an array of items in the format { type: string, text: string }. **Supported Commands:** - create-branch: { type: 'create-branch', branchId } - focus: { type: 'focus', branchId } - add-thought: { type: 'add-thought', branchId, content } - semantic-search: { type: 'semantic-search', query, topN? } - extract-tasks: { type: 'extract-tasks', branchId? } - visualize: { type: 'visualize', branchId?, options? } - list-branches: { type: 'list-branches' } - history: { type: 'history', branchId } - insights: { type: 'insights', branchId } - crossrefs: { type: 'crossrefs', branchId } - hub-thoughts: { type: 'hub-thoughts', branchId } - link-thoughts: { type: 'link-thoughts', fromThoughtId, toThoughtId, linkType, reason? } - add-snippet: { type: 'add-snippet', content, tags, author? } - snippet-search: { type: 'snippet-search', query, topN? } - summarize-branch: { type: 'summarize-branch', branchId? } - doc-thought: { type: 'doc-thought', thoughtId } - review-branch: { type: 'review-branch', branchId? } - ask: { type: 'ask', question } - summarize-tasks: { type: 'summarize-tasks', branchId? } - advance-task: { type: 'advance-task', taskId, status } - assign-task: { type: 'assign-task', taskId, assignee } - reset-session: { type: 'reset-session' } - clear-cache: { type: 'clear-cache' } - get-cache-stats: { type: 'get-cache-stats' } **Visualization Options:** - clustering: { type: 'clustering', algorithm? } - centrality: { type: 'centrality', metric? } - overlays: { type: 'overlays', features? } - analytics: { type: 'analytics', metrics? } **Example Calls and Expected Responses:** ~~~json // Add a thought { "name": "branch-thinking", "args": { "type": "add-thought", "branchId": "research", "content": "Define MCP best practices" } } // → [{"type":"text","text":"Thought added to branch research."}] ~~~ ~~~json // Get insights { "name": "branch-thinking", "args": { "type": "insights", "branchId": "research" } } // → [{"type":"text","text":"Insights for branch research: ['Best practices cluster around workflow safety and semantic search.', 'Cross-references indicate high reuse of planning patterns.']"}] ~~~ ~~~json // Get cross-references { "name": "branch-thinking", "args": { "type": "crossrefs", "branchId": "research" } } // → [{"type":"text","text":"Cross-references for branch research: [{ from: 't1', to: 't3', type: 'supports', reason: 't1 evidence for t3' }, { from: 't2', to: 't4', type: 'related' }]"}] ~~~ ~~~json // Extract tasks { "name": "branch-thinking", "args": { "type": "extract-tasks", "branchId": "research" } } // → [{"type":"text","text":"Tasks extracted: [{ id: 'task-123', content: 'Document MCP safety rules', status: 'open' }]"}] ~~~ ~~~json // Summarize tasks { "name": "branch-thinking", "args": { "type": "summarize-tasks", "branchId": "research" } } // → [{"type":"text","text":"Task summary: 1 open, 2 in progress, 0 closed."}] ~~~ ~~~json // Advance a task { "name": "branch-thinking", "args": { "type": "advance-task", "taskId": "task-123", "status": "in_progress" } } // → [{"type":"text","text":"Task task-123 status updated to in_progress."}] ~~~ ~~~json // Assign a task { "name": "branch-thinking", "args": { "type": "assign-task", "taskId": "task-123", "assignee": "alice" } } // → [{"type":"text","text":"Task task-123 assigned to alice."}] ~~~ ~~~json // Semantic search { "name": "branch-thinking", "args": { "type": "semantic-search", "query": "workflow planning", "topN": 3 } } // → [{"type":"text","text":"Top 3 semantic matches for 'workflow planning' returned."}] ~~~ ~~~json // Link thoughts { "name": "branch-thinking", "args": { "type": "link-thoughts", "fromThoughtId": "t1", "toThoughtId": "t2", "linkType": "supports" } } // → [{"type":"text","text":"Linked thought t1 to t2 as 'supports'."}] ~~~ ~~~json // Summarize branch { "name": "branch-thinking", "args": { "type": "summarize-branch", "branchId": "research" } } // → [{"type":"text","text":"Summary for branch research: ..."}] ~~~ ~~~json // Review branch { "name": "branch-thinking", "args": { "type": "review-branch", "branchId": "research" } } // → [{"type":"text","text":"Branch research reviewed. 2 suggestions found."}] ~~~ `, inputSchema: { type: "object", properties: { content: { oneOf: [ { type: "string", description: "Single thought content as a string." }, { type: "array", items: { type: "object" }, description: "Batch mode: array of thought objects, each with content, branchId, and optional metadata." } ], description: "Thought content (string) or batch of thoughts (array of objects)." }, branchId: { type: "string", description: "Branch ID to associate with the thought(s). If omitted, a new branch may be created or the active branch used." }, parentBranchId: { type: "string", description: "Optional: ID of the parent branch for hierarchical organization." }, type: { type: "string", description: "Thought type: e.g., 'analysis', 'hypothesis', 'observation', 'task', etc. Used for filtering and scoring." }, confidence: { type: "number", description: "Optional: Confidence score (0-1) for the thought, for ranking or filtering." }, keyPoints: { type: "array", items: { type: "string" }, description: "Optional: Key points or highlights extracted from the thought." }, relatedInsights: { type: "array", items: { type: "string" }, description: "Optional: IDs of related insights, for semantic linking." }, crossRefs: { type: "array", items: { type: "object", properties: { toBranch: { type: "string", description: "Target branch ID for the cross-reference." }, type: { type: "string", description: "Type of cross-reference (e.g., 'related', 'supports', 'contradicts', etc.)." }, reason: { type: "string", description: "Optional: Reason or context for the cross-reference." }, strength: { type: "number", description: "Optional: Numeric strength/confidence of the cross-reference (0-1)." } }, required: ["toBranch", "type"] }, description: "Optional: Array of cross-references to other branches, with type, reason, and strength." }, command: { type: "object", description: "Optional: Navigation or workflow command. Used for agentic/AI interactions.", properties: { type: { type: "string", enum: ["create-branch","list","focus","history","insights","crossrefs","hub-thoughts","semantic-search","link-thoughts","add-snippet","snippet-search","summarize-branch","doc-thought","extract-tasks","review-branch","visualize","ask"], description: "Command type (see tool description for complete list and semantics)." }, branchId: { type: "string", description: "Branch ID for commands that operate on a specific branch." }, tags: { type: "array", items: { type: "string" }, description: "Tags for add-snippet or snippet-search commands." }, author: { type: "string", description: "Optional: Author or agent for add-snippet command." }, content: { type: "string", description: "Content for add-snippet, search, or ask commands." }, thoughtId: { type: "string", description: "Thought ID for doc-thought, link-thoughts, or review commands." }, question: { type: "string", description: "Free-form question for the ask command (AI/LLM query)." }, query: { type: "string", description: "Query string for semantic-search, snippet-search, or other search commands." }, topN: { type: "number", description: "Number of top results to return for semantic-search or snippet-search." }, fromThoughtId: { type: "string", description: "Source thought ID for link-thoughts or cross-linking commands." }, toThoughtId: { type: "string", description: "Target thought ID for link-thoughts or cross-linking commands." }, linkType: { type: "string", description: "Type of link for link-thoughts command (e.g., supports, contradicts, related, expands, refines)." }, reason: { type: "string", description: "Optional: Reason or context for linking thoughts." }, parentBranchId: { type: "string", description: "Optional: Parent branch ID for hierarchical organization when creating a branch." }, autoVisualize: { type: "boolean", description: "Optional: Automatically visualize the branch after creation." }, }, required: ["type"] } }, anyOf: [ { required: ["content", "type"] }, { required: ["command"] } ] } };
- src/index.ts:775-777 (registration)ListToolsRequestSchema handler that registers and returns the branch-thinking tool definition.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [BRANCHING_THOUGHT_TOOL], }));