MonkeyLLM forest navigation MCP server — the 9 primitives + harvest + view as MCP tools. A knowledge engine for AI agents: your documents become a git-versioned markdown knowledge graph an agent navigates over MCP, instead of flat vector search.
MonkeyLLM Vine is a well-designed knowledge graph navigation server with domain-specific, well-documented tool definitions. All 17 tools have clear names following verb_noun patterns (harvest, locate, look, move, pick, sniff, scan, plant, graft, tend, prune, query, calendar, history, coverage, transplant), appropriate for agentic use. Tool descriptions are substantial (100-400 chars) and domain-aware, explaining what each tool does, when to use it, and how results chain together. Input schemas are consistently present across all tools with properly typed parameters and descriptions. Output schemas are documented inline within tool descriptions rather than as separate schema definitions. Error handling is implicit through the domain design (read-only vs write operations marked with Risk levels) but lacks explicit recovery guidance. Security considerations are addressed through risk classification but lack formal permission declaration patterns. Schema completeness is strong overall, all tools declare their inputs with types and descriptions, but output structures are described narratively rather than as formal JSON schemas. The server demonstrates production-quality engineering with git-versioned knowledge management, Docker-based deployment, and clear separation of concerns (engine vs. host). Composition is excellent, tools chain naturally (locate→pick→graft) and each performs a single responsibility. A few tools could benefit from explicit error case documentation and recovery patterns.
The time map (C.13.3, v0.52): a read like any other — catalog only, no body opened, and scoped by the same policy.
What the forest holds — catalog only, scoped, budgeted (C.17, v0.59).
List the forests this server can navigate (spec C.0).
Rewrite a node: its title, type, body, or frontmatter (C.5). Pass only the fields you want to change. A move (A.2, C.9) is a graft that relocates the node in the forest. Moving a branch moves its entire subtree.
One-shot retrieval (zero LLM server-side): ranked notes with body or matched sections + exact snippets. Use it when you want evidence in a single call and will reason over it yourself; use the primitives below when you want to navigate step by step. A result that a live node `supersedes` is left out and the seat refilled — `superseded_excluded` says which and by what; `include_superseded=True` brings the history back (spec C.6c.4). `lang` (a BCP-47 tag) filters BOTH halves of the sweep, so the evidence is in the language the response says it is.
The document's past is a listing — a read (C.16, v0.58).
Output schemas are documented narratively in tool descriptions rather than as formal, machine-parseable JSON Schema definitions. LLMs must infer the structure of responses (e.g., harvest returns 'ranked notes with body or matched sections + exact snippets') rather than having explicit field types and structure.
Error handling and recovery guidance are implicit (Risk classification: READ_ONLY, WRITE, DESTRUCTIVE) but not explicit in descriptions. Tools like prune (DESTRUCTIVE) lack a confirmation pattern or dry-run capability. No error messages describe what to do if a query fails or a node is not found.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 68 | 2026-07-28+ | v2 |
Find entry points (the helicopter). scope: all|branches|notes. Results carry `body_tokens`; include=["outline"] adds outline sections.
Peek at a node: summary + digest (the cheap one), or the full index when id='_index'. Looking at a node never opens its body or runs a query.
Neighbors of a node in the forest graph. Results are sorted by the node's explicit links (A.3) and then by updated time. A node's own links come first; the children of a branch come before its siblings.
Open a node and read its body. Use this only when the summary says the body is the answer — picking every result is wasteful.
Write a new node to the forest. The id is generated; the return says what it is. title and body are both required. The body is markdown; frontmatter is optional. schema= births a new dataset (C.4).
Delete a node from the forest. Pruning a branch deletes its entire subtree. The deletion is written to the forest immediately.
Read from a dataset with a SELECT statement (C.3). The result is the row list; an empty result is a successful query that returned no rows.
List all nodes in the forest that match the filter (spec C.2).
Grep the forest's bodies for exact terms the summaries miss.
Write dataset rows. id is the dataset node; sql is a single INSERT, UPDATE or DELETE statement (C.3). The result says how many rows changed.
Move a node to a new parent (C.15, v0.58): a move that edits every pointing node — it is a write, on the writer lane.
No permission scopes declared for tools. Each tool should declare what permissions are required (e.g., 'read:forest', 'write:forest', 'delete:forest') for least-privilege agent configuration and audit clarity.
Some parameter descriptions lack explicit constraints. For example, 'k' (number of results) has no min/max specified; 'lang' accepts 'BCP-47 language tag' but doesn't validate the format; 'sql' in tend and query accepts INSERT, UPDATE, DELETE, SELECT respectively but doesn't state what types are allowed or what will be rejected.
Tool names 'tend' and 'transplant' are domain-specific jargon from the MonkeyLLM gardening metaphor. While internally consistent and thematically coherent, 'tend' (write dataset rows) and 'transplant' (move node to new parent) may require explanation for LLMs unfamiliar with the metaphor. Consider: 'tend' could be clearer as 'update_dataset', 'transplant' as 'move_node'.