redraft
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PYTHONPATH | No | Set to empty string to clear inherited PYTHONPATH. | |
| REDRAFT_DIR | Yes | Absolute path to the graph directory. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| extensions | {
"io.modelcontextprotocol/ui": {}
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| create_nodeA | Create a new node. Does not attach it anywhere -- call create_edge next. |
| update_nodeA | Update a node's body/status/properties. Cannot change title or edges
(use rename_node / create_edge / delete_edge for those) -- pin R5.
|
| create_edgeA | Create a directed edge. STRICT (pin R2): dst must already exist -- raises not_found otherwise, no dangling-edge creation via this tool. A part_of edge when src already has a different part_of parent raises collision; call delete_edge first to re-parent. |
| create_edgesA | Create many edges in ONE atomic operation (GraphStore.create_edges): every edge is validated together -- including part_of single-parent/cycle rules considering the OTHER edges in this same batch -- before anything is written. On any hard error the whole call fails, with the store's own message, and NOTHING from this batch is applied (no partial report). Prefer this over looping create_edge when linking several edges from one dump (organizing-protocol.md §3.4). |
| delete_edgeD | Remove an edge. |
| delete_nodeB | Remove a node's file (Git retains history). Inbound edges from other nodes are left dangling by design -- surfaced here, not silently dropped. |
| merge_nodesA | Dedup: repoint drop's inbound edges to keep, migrate drop's outbound edges onto keep (deduped; a part_of conflict is a warning, never a failure), delete drop's file. Body is NOT auto-merged -- inspect dropped_body_preview and update_node(keep_id, ..., mode='append') first if unique content from drop should survive (pin R3). |
| rename_nodeA | Rename a node, rewriting every inbound frontmatter wikilink to the new id. Inline [[wikilinks]] in Markdown body prose are NOT rewritten (the index only tracks frontmatter edges) -- flagged in body_references_not_updated, not silently left unmentioned. |
| get_nodeB | Fetch a node. neighbor_depth > 0 also returns nodes reachable within that many hops (any edge type, any direction) and the node's own direct edges. |
| neighborsC | Single-hop edges touching |
| get_subgraphB | Everything connected to root_id within |
| reindexA | Rebuild the derived index from graph/nodes/*.md. Run after a manual git pull/merge, or to recover from a deleted/corrupted index/ dir. |
| snapshotC | git add (pathspec-scoped) + commit; push only if push=True (defaults off to avoid a surprise network operation). |
| search_nodesA | Hybrid FTS+vector search, fused by Reciprocal Rank Fusion. types/status filter each branch's candidates before fusion (a filtered-out result never consumes a fusion rank slot it wasn't really competing within). Prefer this over grepping graph files for ANY lookup -- it matches paraphrase, filters by type/status, and returns typed nodes, which grep cannot. |
| find_similarA | Vector-only near-duplicate search -- the dedup primitive. text_or_id may be an existing node's id (reuses its cached vector, excludes it from its own results) or free text (embedded fresh). Prefer this over grepping graph files to check "is this already recorded" -- it matches paraphrase across different wording, which grep cannot. |
| decisions_without_rationaleA | Decisions (any status) with no inbound |
| open_questionsC | Question nodes with status='open'. |
| orphansA | Nodes with zero edges in any direction/type (a legitimate root-level concept with no part_of parent is NOT flagged for that alone). |
| contradictionsA | {a, b} node pairs linked by a |
| staleB | Nodes untouched since before_iso. types/statuses omitted (None) use the default non-terminal question/decision/milestone set; an explicit [] matches nothing (not reinterpreted as 'omitted'). |
| dangling_edgesB | Edges whose src and/or dst no longer resolves to a node. |
| case_collisionsB | Groups of >=2 node ids identical under Unicode NFC+casefold. |
| assemble_reportA | Collapse root_id's part_of subtree into a report bundle: nested sections with attached cross-links, decision_tables grouped by driver question/requirement (any status, cross-branch — see report-bundle-v2.md), and per-section gaps (open questions, decisions lacking rationale). The agent writes the narrative; this never summarizes. |
| briefingA | One-call topic guidance: hybrid search hits, their 1-hop neighborhood, open questions, and unjustified decisions scoped to the topic. Prefer this over grepping graph files for "what do we know about X" -- it returns the matched nodes together with their neighborhood and open gaps, which grep cannot assemble. |
| overviewA | Cheap, shallow map of the project's shape: every spine root, each root's direct part_of children as branches with per-subtree tallies (descendants, open questions, decisions by status, unjustified decisions), whole-graph totals, and the top open questions. Prefer this over grepping graph files for the project's shape -- it returns the spine structure and tallies in one cheap call, which grep cannot compute. Call this (or read graph://project/overview) at the start of a session, before anything else, to load the project's shape and make your first real call targeted instead of blind. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| organizing_protocol | The redraft organizing protocol for turning freeform dumps into graph mutations. |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| ProjectGraphRoot | Root-level nodes (no part_of parent) plus type/status counts. |
| graph_stats_resource | Counts by type/status, orphan count, dangling-edge count. |
| ProjectOverview | Spine roots, each root's direct branches with per-subtree tallies, whole-graph totals, and the top open questions -- see report.overview(). |
TDQS
Scored across 25 tools
Most tools target distinct resources/actions, and descriptions explicitly differentiate the potentially overlapping ones (create_edge vs atomic create_edges, search_nodes vs find_similar vs briefing). The search/discovery cluster (search_nodes, find_similar, briefing, overview) and get_node(neighbor_depth) vs get_subgraph/neighbors carry mild overlap, but guidance mitigates it.
Core mutators follow a clean verb_noun pattern (create_node, update_node, delete_node, rename_node, merge_nodes, create_edge, delete_edge). Read-only analytics/report tools use bare-noun forms (orphans, stale, contradictions, overview, briefing), which is a consistent secondary convention rather than random mixing.
25 tools sits at the heavy end of the acceptable band. Each is distinct, but the seven separate audit queries (decisions_without_rationale, open_questions, orphans, contradictions, stale, dangling_edges, case_collisions) suggest the surface could be consolidated somewhat.
Full node lifecycle (create/get/update/rename/merge/delete), edge create-batch/delete, search/dedup, maintenance (reindex/snapshot), and rich reporting/audit coverage are all present. Only minor gaps (no in-place edge update, though delete+recreate covers it) leave it just shy of complete.