Persistent Memory Logic Loop (PMLL) MCP Server with short-term KV cache (peek pattern), Q-promise deduplication, SQLite-backed Context+ long-term semantic memory graph with stable hashing embeddings, and solution engine. Designed to improve context retention and retrieval for coding agents.
PMLL Memory MCP has 15 tools with schemas and descriptions visible in source, but exhibits multiple serious quality issues: (1) Naming inconsistencies, tools like 'resolve', 'set', 'init', 'peek', 'flush' are cryptic C-library style names that don't follow verb_noun convention; LLMs will struggle to infer intent. (2) Descriptions are terse (10 - 60 chars on average for critical tools), often referencing internal C structs (PMLL.c, memory_silo_t) that are meaningless to LLM agents. (3) Output schemas are almost entirely undocumented, no tool in the provided source shows return types or field definitions. (4) Parameters lack validation constraints: session_id accepts any string with no format guidance, silo_size has a default but no min/max bounds, decay_threshold is unranged. (5) Error handling is absent, no error examples, recovery guidance, or status fields in responses. (6) Composition is fragmented, peek + set + resolve + flush implement low-level KV operations that should be hidden behind higher-level query/cache abstractions. Average tool description length: ~45 chars (below 194-char baseline). Zero tools document return schema. 0% of parameters have validation constraints documented.
Bulk-add nodes with auto-similarity linking. Creates multiple related nodes and auto-links them based on semantic similarity.
Create a typed edge between two memory nodes in the long-term graph. Supported relation types: relates_to, depends_on, implements, references, similar_to, contains.
Clear all short-term KV slots for a session. Call at agent task completion to free memory. Mirrors the teardown of a memory_silo_t allocation (PMLL.c::free_pml).
Execute a GraphQL query or mutation against a remote endpoint, with optional PMLL cache integration. Supply `operation` as a GraphQL document string and `variables` as a JSON object. Pass `cache_key` to store/retrieve the result from the PMLL silo so redundant network calls are avoided on subsequent `peek` checks.
Initialise the PMLL memory silo for an agent session. Call this once at the start of every agent task, as the 3rd initializer alongside Playwright. Sets up the KV silo and prepares the Q-promise chain for the session.
Cryptic low-level naming (peek, set, resolve, flush, init) violates verb_noun convention and lacks clarity. LLMs cannot infer intent from single-word cryptic names. Should rename: peek→check_kv_exists, set→cache_kv_pair, resolve→await_promise, flush→clear_session_cache, init→initialize_session.
Output schemas completely undocumented across all 15 tools. No source code shows return types, field names, or response structures. LLMs cannot plan downstream calls or extract data without schema knowledge.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 58 | 2026-07-28+ | v2 |
Unified memory view. Returns combined statistics about both short-term KV silo and long-term graph utilization.
Non-destructive context check — the core deduplication primitive. Call this before any Playwright or other MCP tool invocation to check whether the required context already exists in the PMLL silo or is in-flight as a Q-promise.
Promote KV entries to the memory graph. Converts short-term context into persistent long-term nodes for future semantic retrieval.
Remove decayed edges and orphan nodes from the long-term graph. Helps maintain semantic coherence as the graph grows.
Check or resolve a Q-promise continuation. Mirrors the `QThenCallback` mechanism in Q_promise_lib/Q_promises.h — the callback is invoked when a QMemNode's payload becomes available. If the promise is already resolved, returns its payload immediately. If still pending, returns `{status: "pending", payload: null}`.
Unified short-term + long-term context lookup. Queries both the PMLL KV silo and the memory graph, returning the most relevant context.
Walk outward from a node. Returns the node and its connected neighbors up to a specified depth.
Semantic search with graph traversal. Query the memory graph for nodes matching a search string, with optional traversal depth and result limit.
Store a KV pair in the session's PMLL memory silo. Call after a successful (non-cached) MCP tool invocation to populate the silo so future `peek` calls return a cache hit. Mirrors PMLL.c::update_silo() writing a var/value pair into the silo.
Create or update a memory node in the long-term semantic graph. Nodes represent concepts, files, symbols, or notes with auto-generated stable hashing embeddings for semantic search (TF-IDF is legacy-only). Part of the Context+ solution engine for durable context retention and retrieval.
Descriptions reference internal C artifacts (PMLL.c, memory_silo_t, QThenCallback, QMemNode) that are meaningless to LLM agents. Average description length ~45 chars, well below 194-char baseline. Descriptions should focus on WHAT the tool does, WHEN to use it, and WHAT it returns, not internal implementation.
Parameters lack validation constraints. session_id accepts any string with no format guidance. silo_size has default=256 but no minimum/maximum bounds, could accept 0 or 999999. decay_threshold (0-1 implied) has no explicit range constraint. node_ids and promise_ids lack UUID/format guidance. Violates constrained-input pattern.
Composition: Five low-level tools (init, peek, set, resolve, flush) implement KV/promise primitives that should be hidden behind a higher-level query abstraction. 'Call peek before each expensive tool' is implementation-specific guidance that violates the chat-data-model principle. Agents should call resolve_context() once, not peek() repeatedly.
No error handling documentation. No examples of failure modes, error codes, or recovery guidance. Descriptions do not answer 'What happens if this fails?' Critical for tools that mutate state (upsert_memory_node, create_relation, promote_to_long_term, prune_stale_links).
Parameter descriptions use examples inline (e.g. 'e.g. a UUID', 'e.g. concept, file, symbol, or note') which LLMs may reuse literally. Should use enum constraints for fixed sets (node type, relation type, sort order) and formal format/pattern definitions for dynamic values.
Destructive/irreversible operations (flush, prune_stale_links, promote_to_long_term) lack confirmation or dry-run patterns. No tool offers a 'confirm' parameter or dry-run mode. Agents may accidentally clear caches or prune live graph edges.