70 tools organized into 10 groups. Each tool is a separate module in src/api/tools/.
Tools are conditionally registered based on which graphs are enabled:
| Group | Count | Registered when | On mutation server |
|---|---|---|---|
| Context | 1 | always | no |
| Docs | 5 | docs graph enabled | no |
| Code blocks | 4 | docs graph enabled | no |
| Cross-graph | 1 | docs + code both enabled | no |
| Code | 5 | code graph enabled | no |
| File index | 3 | file index enabled | no |
| Knowledge | 12 | knowledge graph enabled | yes (mutations) |
| Tasks | 17 | task graph enabled | yes (mutations) |
| Epics | 8 | task graph enabled | yes (mutations) |
| Skills | 14 | skill graph enabled | yes (mutations) |
Read tools (list, get, search) run freely without queueing — they read graph state directly.
Mutation tools (create, update, delete, move, link) are registered on a mutation server proxy that wraps every handler in a PromiseQueue. This ensures serial execution of all graph writes, even from parallel MCP sessions.
All tools return { content: [{ type: 'text', text: JSON.stringify(result) }] }. Error cases return { isError: true }.
Returns the current project and workspace context. Use this first to understand what's available.
Input: none
Output:
{
"projectId": "my-app",
"workspaceId": "backend",
"workspaceProjects": ["api-gateway", "catalog-service"],
"hasWorkspace": true
}When to use: At the start of a session to discover available graphs and workspace context.
List all indexed markdown files.
Input: optional filter, limit
Output: [{ fileId, title, chunks }]
When to use: To get an overview of available documentation.
Table of contents for a specific documentation file.
Input: fileId (e.g. "docs/auth.md")
Output: [{ id, title, level }]
When to use: Before diving into a doc file — see its structure first.
Semantic search over documentation with BFS expansion.
Input:
| Param | Default | Description |
|---|---|---|
query |
(required) | Search query |
topK |
5 | Seed results for BFS |
bfsDepth |
1 | BFS expansion hops |
maxResults |
5 | Max results |
minScore |
0.5 | Minimum relevance |
bfsDecay |
0.8 | Score decay per hop |
searchMode |
hybrid |
hybrid, vector, keyword |
Output: [{ id, fileId, title, content, level, score }]
When to use: Finding relevant documentation sections by meaning. Always prefer this over reading files directly.
Full content of a specific doc chunk.
Input: nodeId (e.g. "docs/auth.md::JWT Tokens")
Output: { id, fileId, title, content, level, mtime }
When to use: After search finds a relevant chunk — get the full text.
File-level semantic search (by path + title).
Input: query, optional limit (default 10), minScore (default 0.3)
Output: [{ fileId, title, chunks, score }]
When to use: Finding which documentation files are relevant before drilling into sections.
Find code blocks in documentation that contain a specific symbol.
Input: symbol (required), optional limit
Output: [{ id, fileId, language, symbols, content, parentId, parentTitle }]
When to use: "Show me examples of how UserService is used in the docs."
Semantic search over code blocks extracted from documentation.
Input: query, optional limit, minScore, language
Output: [{ id, fileId, language, symbols, content, score }]
When to use: Finding code examples by what they do, not just what symbols they contain.
List code blocks with optional filters.
Input: optional fileId, language, filter (substring)
Output: [{ id, fileId, language, symbols, preview }]
When to use: Browsing all code examples in docs, optionally filtered by language.
Find a code example and its surrounding text explanation.
Input: symbol (required), optional fileId
Output: { codeBlock, explanation, fileId }
When to use: Understanding how a symbol works — gets both the code example and the prose that explains it.
Full picture: code definitions + documentation examples + explanations for a symbol.
Input: symbol (required)
Output: { definitions, documentation, examples }
When to use: Getting complete context — the code definition from CodeGraph, plus examples and explanations from DocGraph. Requires both docs and code to be enabled.
List all indexed source files.
Input: none
Output: [{ fileId, symbolCount }]
List all symbols in a source file, sorted by line number.
Input: fileId (e.g. "src/auth.ts")
Output: [{ id, kind, name, signature, startLine, endLine, isExported }]
When to use: Getting an overview of a file's structure — like an IDE outline.
Semantic search over code symbols with BFS expansion.
Input: query + optional search params (same as docs_search)
Output: [{ id, fileId, kind, name, signature, docComment, startLine, endLine, score }]
When to use: Finding code by what it does. "Find the function that handles password hashing."
Full source body of a specific symbol.
Input: nodeId (e.g. "src/auth.ts::hashPassword")
Output: { id, fileId, kind, name, signature, docComment, body, startLine, endLine, isExported }
When to use: Reading the full implementation of a specific function, class, or method.
File-level semantic search over source files (by path).
Input: query, optional limit, minScore
Output: [{ fileId, score }]
When to use: Finding relevant source files before diving into symbols.
List all project files and directories with filters.
Input:
| Param | Default | Description |
|---|---|---|
directory |
— | Filter by parent directory |
extension |
— | Filter by extension (e.g. ".ts") |
language |
— | Filter by language (e.g. "typescript") |
filter |
— | Substring match on path |
limit |
50 | Max results |
Output: [{ filePath, kind, fileName, extension, language, mimeType, size, fileCount }]
Semantic search over files by path.
Input: query, optional limit (default 10), minScore (default 0.3)
Output: [{ filePath, fileName, extension, language, size, score }]
When to use: "Find files related to database configuration."
Full metadata for a file or directory.
Input: filePath (e.g. "src/lib/embedder.ts")
Output: { filePath, kind, fileName, directory, extension, language, mimeType, size, fileCount, mtime }
Create a note with title, content, and tags. Auto-generates slug ID, embeds content, writes mirror file.
Input: title (required), content (required), optional tags
Output: { noteId }
Partial update — only send fields to change. Re-embeds if title or content changes.
Input: noteId + optional title, content, tags
Output: { noteId, updated }
Deletes the note, all relations, orphaned proxy nodes, and mirror directory.
Input: noteId
Output: { noteId, deleted }
Fetch a note by ID. Returns null for proxy nodes.
Input: noteId
Output: { id, title, content, tags, createdAt, updatedAt }
List notes with optional filters. Excludes proxy nodes.
Input: optional filter (substring), tag, limit
Output: [{ id, title, tags, updatedAt }]
Hybrid search with BFS expansion. Excludes proxy nodes.
Input: query + optional search params
Output: [{ id, title, content, tags, score }]
Create a relation between notes, or from a note to an external node.
Input: fromId, toId, kind, optional targetGraph
Output: { fromId, toId, kind, targetGraph?, created }
When targetGraph is set, validates the target exists in the external graph and creates a phantom proxy node.
Delete a relation. Cleans up orphaned proxy nodes.
Input: fromId, toId, optional targetGraph
Output: { fromId, toId, deleted }
List all relations for a note (incoming + outgoing). Resolves proxy IDs to original node IDs transparently.
Input: noteId
Output: [{ fromId, toId, kind, targetGraph? }]
Reverse lookup: find all notes that link to a specific external node.
Input: targetId, targetGraph
Output: [{ noteId, kind }]
When to use: Before modifying code — check if any notes document it. "What notes reference src/auth.ts::login?"
Add or remove file attachments.
Input: noteId, filename, content (base64 for add)
Output: { noteId, filename, added/removed }
Input: title (required) + optional description, status, priority, tags, dueDate, estimate, assignee
Output: { taskId }
Partial update. Also handles completedAt automation if status changes.
Deletes task, all relations, proxies, and mirror directory.
Returns enriched data: subtasks, blockedBy, blocks, related, crossLinks.
Filtered list sorted by priority (critical→low) then dueDate (earliest first, nulls last).
Input: optional status, priority, tag, filter, assignee, limit
Hybrid search over tasks.
Change status with automatic completedAt management.
Input: taskId, status
- →
done/cancelled: setscompletedAt - → any other: clears
completedAt
When to use: Always use tasks_move instead of tasks_update for status changes.
Create task↔task relation: subtask_of, blocks, related_to.
Same-graph (task↔task) or cross-graph links to docs/code/files/knowledge/skills nodes. targetGraph is optional — omit for task-to-task links.
Reverse lookup: find tasks linking to a specific node.
When to use: Before modifying a file — "are there open tasks related to this code?"
Reposition a task within its status column using gap-based ordering.
Input: taskId (required), optional beforeId, afterId
Output: { taskId, order }
When to use: When the user wants to reorder tasks within a column. Place a task between two others by specifying beforeId and/or afterId.
File attachments on tasks.
Epics group related tasks into larger units of work. They live in the same TaskGraph using a nodeType: "epic" discriminator and connect to tasks via belongs_to edges.
Input: title (required) + optional description, status, priority, tags
Output: { epicId }
Partial update of epic fields.
Input: epicId + optional title, description, status, priority, tags, expectedVersion
Output: { epicId, updated }
Deletes the epic and its belongs_to edges. Linked tasks are not deleted.
Input: epicId
Output: { epicId, deleted }
Returns the epic with its linked tasks list.
Input: epicId
Output: { id, title, description, status, priority, tags, tasks, createdAt, updatedAt }
List epics with optional filters, sorted by priority then creation date.
Input: optional status, priority, tag, filter, limit
Output: [{ id, title, description, status, priority, tags, taskCount, createdAt, updatedAt }]
Semantic search over epics.
Input: query + optional topK, maxResults, minScore, searchMode
Output: [{ id, title, description, status, priority, tags, score }]
Link a task to an epic (creates a belongs_to edge from task to epic).
Input: epicId, taskId
Output: { epicId, taskId, linked }
When to use: Grouping tasks under a larger initiative.
Remove the belongs_to edge between a task and an epic.
Input: epicId, taskId
Output: { epicId, taskId, unlinked }
Input: title (required) + optional description, steps, triggers, inputHints, filePatterns, source, confidence, tags
Output: { skillId }
Standard CRUD + search (same patterns as knowledge/tasks).
Search with lower minScore (0.3 vs 0.5) for higher recall.
When to use: At the start of a complex task — "what recipes might be relevant?" Cast a wider net than skills_search.
Increment usageCount + set lastUsedAt.
When to use: After successfully applying a skill's recipe.
Same relation patterns as knowledge/tasks. skills_create_link and skills_delete_link support optional targetGraph — omit for skill-to-skill links.
File attachments on skills.
- Search before reading files —
code_searchanddocs_searchare faster and more targeted - Use
get_contextfirst — know what graphs are available - Create notes for decisions — persist architectural choices and non-obvious context
- Use
skills_recallbefore complex tasks — there might be a saved recipe - Use
tasks_movefor status changes, nottasks_update— managescompletedAtautomatically - Use
docs_cross_referencesfor complete symbol context — bridges code and docs - Use
tasks_find_linkedbefore changing code — see related tasks - Bump skill usage after applying a recipe — surfaces frequently used skills
- Link everything — connect notes to code, tasks to files, skills to docs