A persistent memory MCP server for AI coding agents — stores, searches, and retrieves atomic learnings per repository.
Mind Keg exhibits poor definition quality overall. While 8 consolidated tools have clear, actionable descriptions (50-150 chars), 19 deprecated aliases dilute the API surface and create confusion. Core issues: (1) Descriptions are present but minimal, many hover around 80-120 chars without explaining WHEN to use the tool or WHAT it returns; (2) Input schemas are visible in the tool list but lack explicit JSON Schema definitions in the source code (only descriptions and type hints are shown); (3) NO output schemas are documented anywhere, LLMs cannot predict what fields they'll receive; (4) Parameter descriptions are generic and lack constraints (e.g., 'Query' for query param gives no hints about format or valid values); (5) Error handling is mentioned in code (via recordToolMetrics) but not exposed to LLMs, no recovery guidance in tool descriptions; (6) 19 deprecated aliases muddy the API, they coexist with new tools, forcing LLMs to reason about which to use. The server excels at clarity of intent (verb-noun naming, single responsibility per consolidated tool) but fails at LLM-optimizable descriptions and output contracts.
Complete a run and store a run summary
Deprecated: Delete a learning permanently. Use update({ action: 'deprecate' }) instead.
Deprecated: Mark a learning as deprecated. Use update({ action: 'deprecate' }) instead.
Deprecated: Mark a learning as potentially stale. Use update({ action: 'flag_stale' }) instead.
Retrieve prior knowledge and context from persistent memory at session start or for topic-specific lookups
Deprecated: Retrieve decisions. Use query({ type: 'decisions' }) instead.
Deprecated: Retrieve gotchas. Use query({ type: 'gotchas' }) instead.
No output schemas documented. LLMs cannot predict what fields tools return (e.g., does get_context return {learnings: [], metadata: {}}? {results: [], count: 0}?). This forces LLMs to guess and handle ambiguous responses.
Parameter descriptions lack specificity and constraints. 'Query' in get_context gives no hint about format (free text? keywords?). 'Type' in store is ambiguous (does it accept any string or only gotcha|decision|finding|learning?). No enums or ranges documented.
19 deprecated aliases (store_learning, search_learnings, deprecate_learning, etc.) coexist with 8 canonical tools. The API surface is confusing, LLMs must reason about which version to call. Deprecated tools should be removed or clearly marked as such in tool descriptions.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 43 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 45 | - | v1 |
Deprecated: Retrieve open findings. Use query({ type: 'findings' }) instead.
Deprecated: Get relevant context for a topic. Use get_context({ query }) instead.
Deprecated: Retrieve run history. Use query({ type: 'run_history' }) instead.
Deprecated: List all repositories. Use list_scopes() instead.
List all repositories, workspaces, and global scopes that have learnings
Deprecated: List all workspaces. Use list_scopes() instead.
Deprecated: Merge duplicate learnings into one.
Query entities (decisions, findings, gotchas, run history) across scopes
Create relationships between learnings
Mark findings or other entities as resolved
Deprecated: Mark a finding as resolved. Use resolve() instead.
Deprecated: Search learnings by text or tags. Use get_context() instead.
Proactively preserve new insights (gotchas, decisions, findings, learnings) to Mind Keg with optional scope specification
Deprecated: Store an architectural decision. Use store({ type: 'decision' }) instead.
Deprecated: Store a code review finding. Use store({ type: 'finding' }) instead.
Deprecated: Store a gotcha (non-obvious behavior or library quirk). Use store({ type: 'gotcha' }) instead.
Deprecated: Store a new learning. Use store() instead.
Deprecated: Mark a decision as superseded.
Update existing learnings with actions like deprecate, flag_stale, or modify content
Deprecated: Update an existing learning. Use update() instead.
Descriptions are bare-minimum. Many are 35-65 chars and lack context about WHEN to use the tool, WHAT it returns, or WHAT the LLM should expect. Baseline for A-grade tools is 50-200 chars with explicit use-case guidance.
No error handling guidance exposed to LLMs. recordToolMetrics logs errors internally, but tool descriptions do not tell LLMs what can go wrong, how to recover, or whether to retry. Missing recovery guidance (pattern:recovery-guide).
Input schemas are inferred from parameter lists but not explicitly shown in JSON Schema format in the source. Cannot verify whether schemas include minLength, maxLength, pattern, enum, or other constraints that would guide LLM input.
No mention of pagination support or limits. Tools like 'query' may return large result sets. Baseline pattern requires limit/offset parameters and documented result caps (e.g., ≤50 items per page).
delete_learning is marked DESTRUCTIVE and has a deprecated notice, yet still coexists with the canonical update() tool. Irreversible operations should require confirmation or dry-run support per pattern:confirmation-request. Current implementation exposes a footgun.
No tool annotations. Tools like store(), update(), and delete_learning are not annotated with readOnlyHint, destructiveHint, or idempotentHint. MCP 2026-07-28 spec supports these; LLMs need them to reason safely about side effects.