.dai, an open plain-text format for AI memory. Reference engine plus MCP server for Claude Desktop, Claude Code and any MCP client.
The daidocs server exposes 3 tools with domain-specific descriptions that explain the .dai memory system well. However, there are critical gaps in schema formalization, parameter constraints, and error guidance. Tool descriptions are verbose (200-400+ chars) and narrative rather than optimized for LLM consumption. Input schemas are visible but lack proper JSON Schema structure with type definitions for several parameters. No output schemas are documented. Error handling is mentioned in descriptions but no structured guidance is provided. The tools are well-named and address a clear domain (memory retrieval/storage/project linking), but the implementation falls short of production standards for LLM agent consumption.
Declare the relationship between two folders (both running daidocs) so recall_memory can search across them. Call this once, and stores are remembered: later recalls with scope:"all" will search both. Both folders must exist and be initialized with daidocs setup. Folders are identified by their storeDir (the daidocs config file location). If you have a parent folder (the main project) and want to search it from a subfolder, pass reads:["self", "parent"]. Pass reads:["self", "peer"] for two sibling folders or folders with no hierarchy.
Retrieve relevant material from the user's .dai memory store for a question about their past conversations, documents, facts, preferences, or history. Returns assembled context: answer the user's question from it. Call this whenever the user references something from the past that is not in the current conversation. By default it reads only the current project store. If that has no memories, it says so and names any other stores reachable from here: ask the user before calling again with scope:"all", which searches those too. A store that needs permission is named; ask the user, then call again with allow or refuse, and the answer is remembered. If the user asks to include the main project (the project in the folder above this one) and it is not reachable yet, call declare_project with reads: ["self", "parent"] first, then recall again with scope:"all". Confidential stores are never included in a wider search.
Convert one conversation/document into one .dai file plus append-only index rows; originals kept verbatim in _raw/. Caller must pass the session content: text, or if session came from Claude Code, the path to its .jsonl (the hook reads the file). Save_memory calls the observer to extract an Understanding from the session, returning the .dai filename and size so you can tell the user. The observer is the LLM configured at setup: this call is never billed when run under Claude (conversion happens inside your session, where your assistant writes it), and costs nothing when the observer is local (ollama). Under ChatGPT or any other host, set DAIDOCS_USE_API=1 to bill the observer; without that flag, nothing calls an external API and the call says "will cost" instead.
Input schemas lack proper JSON Schema type definitions. The 'scope' parameter in recall_memory is described as an enum ('project', 'all', 'wider', or collection name) but has no 'enum' constraint in schema; 'allow' parameter lacks type specification entirely.
No output schemas are documented for any tool. Callers cannot predict what fields will be returned, making it impossible for LLMs to plan downstream operations. Descriptions mention 'assembled context', '.dai filename and size', and 'stores are remembered' but without structured response definitions.
Descriptions are verbose (300-400+ chars for recall_memory) and narrative, mixing procedural logic with documentation. They read like user guides rather than LLM-optimized tool summaries. Best practice is 50-200 chars stating WHAT, WHEN, and RESULT. Current style forces LLMs to parse implementation details instead of intent.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 52 | 2026-07-28+ | v2 |
The 'session' parameter in save_memory is described as accepting EITHER session id OR text, but the schema does not enforce mutual exclusivity. Documentation says 'Only one of session or text may be passed' but there is no oneOf constraint or validation hint in the schema structure.
Error handling is mentioned descriptively (e.g., recall_memory says 'A store that needs permission is named') but no structured error response format is defined. LLMs cannot distinguish between actionable errors (ask user for permission), retryable errors (temporary outage), or fatal errors (store not found). No recovery guidance pattern implemented.
The 'allow' parameter in recall_memory references store labels but does not explain what format labels take, whether they are free-form strings, or how to discover valid labels. An LLM cannot invoke this parameter without ambiguity.
declare_project 'reads' parameter accepts arrays like ["self", "parent"] or ["self", "peer"], and description mentions 'folder paths may be supplied', but no schema defines the array element type, valid values, or whether folder paths are absolute/relative. This creates ambiguity for LLM invocation.