Skip to main content
Glama

branch-thinking

Organize and manage complex thoughts and tasks using branching commands. Create, navigate, and analyze branches, extract tasks, link related ideas, and generate insights through semantic search and visualization.

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:

// 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."}]
// 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.']"}]
// 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' }]"}]
// 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' }]"}]
// Summarize tasks { "name": "branch-thinking", "args": { "type": "summarize-tasks", "branchId": "research" } } // → [{"type":"text","text":"Task summary: 1 open, 2 in progress, 0 closed."}]
// 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."}]
// Assign a task { "name": "branch-thinking", "args": { "type": "assign-task", "taskId": "task-123", "assignee": "alice" } } // → [{"type":"text","text":"Task task-123 assigned to alice."}]
// 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."}]
// 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'."}]
// Summarize branch { "name": "branch-thinking", "args": { "type": "summarize-branch", "branchId": "research" } } // → [{"type":"text","text":"Summary for branch research: ..."}]
// Review branch { "name": "branch-thinking", "args": { "type": "review-branch", "branchId": "research" } } // → [{"type":"text","text":"Branch research reviewed. 2 suggestions found."}]

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
branchIdNoBranch ID to associate with the thought(s). If omitted, a new branch may be created or the active branch used.
commandNoOptional: Navigation or workflow command. Used for agentic/AI interactions.
confidenceNoOptional: Confidence score (0-1) for the thought, for ranking or filtering.
contentNoThought content (string) or batch of thoughts (array of objects).
crossRefsNoOptional: Array of cross-references to other branches, with type, reason, and strength.
keyPointsNoOptional: Key points or highlights extracted from the thought.
parentBranchIdNoOptional: ID of the parent branch for hierarchical organization.
relatedInsightsNoOptional: IDs of related insights, for semantic linking.
typeNoThought type: e.g., 'analysis', 'hypothesis', 'observation', 'task', etc. Used for filtering and scoring.

Implementation Reference

  • src/index.ts:775-777 (registration)
    Registers the 'branch-thinking' tool in the MCP server's ListToolsRequestSchema handler.
    server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [BRANCHING_THOUGHT_TOOL], }));
  • Defines the input schema for the 'branch-thinking' tool, supporting thought content or command objects with various sub-types (e.g., 'add-thought', 'insights').
    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"] } ] }
  • MCP CallToolRequestSchema handler that routes 'branch-thinking' tool calls to the BranchingThoughtServer's processThought method.
    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 }; });
  • Core handler method in BranchingThoughtServer that dispatches to handleCommand for tool args with 'command' or processes thought content directly.
    // 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) }] }; } }
  • Implements the switch for all 'branch-thinking' sub-commands (e.g., create-branch, insights, extract-tasks), delegating to BranchManager 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}` }] }; }

Other Tools

Related Tools

Latest Blog Posts

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/ssdeanx/branch-thinking-mcp'

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