PMLL Memory MCP Server v2 — persistent memory logic loop with short-term KV cache (peek pattern), Q-promise deduplication, Context+ long-term semantic memory graph, and solution engine. Four-way benchmarked: Combined Context+ + PMLL/peek delivers 36ms (TS) / 78ms (PY) total — fastest configuration. 15 tools, agent_instructions workflow included. 99% accuracy in Claude Sonnet/Opus agent tasks.
Project description
PMLL Memory MCP Server v2.0.0
Persistent memory logic loop with short-term KV cache (peek pattern), Q-promise deduplication, and Context+ long-term semantic memory graph for 99% accuracy in Claude Sonnet/Opus agent tasks.
v2.0.0 — Four-way benchmarked, agent_instructions workflow, combined Context+ + PMLL/peek.
What's New in v2.0.0
- Four-way speed benchmarks — baseline, Context+-only, PMLL/peek-only, and combined (Context+ + PMLL/peek) configurations benchmarked in both TypeScript and Python with 5-run averages
- Combined speed tests — new
combined-speed.test.ts(14 tests) andtest_combined_speed.py(14 tests) proving both layers work together - Context+ standalone speed tests — isolated
contextplus-speed.test.ts(27 tests) andtest_contextplus_speed.py(27 tests) benchmarking pure graph operations - agent_instructions.md — mandatory agent workflow documentation defining the
peek()pattern, tool priority, and Context+ tool reference for all 15 tools - Expanded test suites — 197 TypeScript tests (8 files), 104 Python tests (6 files)
- npm + PyPI dual publishing — automated CI/CD for both registries on release
Benchmark Results (v2.0.0)
Four-way speed comparison across both languages. Full details in benchmarks/three-way-speed-comparison.md (updated from 3-way to 4-way in v2.0.0).
TypeScript — Average Test Execution (5 runs)
| Configuration | Avg Test Time | Tests | Per-test |
|---|---|---|---|
| Baseline (full suite) | 302ms | 197 | 1.53ms |
| Context+ only (no peek) | 63ms | 27 | 2.33ms |
| PMLL/peek only | 26ms | 32 | 0.81ms |
| ⭐ Combined (Context+ + PMLL/peek) | 36ms | 14 | 2.57ms |
Python — Total Duration Averages (5 runs)
| Configuration | Avg Duration | Tests | Per-test |
|---|---|---|---|
| Baseline (full suite) | 250ms | 104 | 2.40ms |
| Context+ only (no peek) | 142ms | 27 | 5.26ms |
| PMLL/peek only | 92ms | 32 | 2.88ms |
| ⭐ Combined (Context+ + PMLL/peek) | 78ms | 14 | 5.57ms |
Per-Operation Highlights
| Operation | TypeScript | Python | Layer |
|---|---|---|---|
peek cache hit |
0ms | <1ms | PMLL/KV |
set + peek round-trip |
≤2ms | ≤3ms | PMLL/KV |
upsert_memory_node (100 nodes) |
6–7ms | ~8ms | Context+ graph |
search_memory_graph (100 nodes, depth-2) |
7–8ms | ~10ms | Context+ graph |
| ⭐ Graph search + cache + 50 peeks | ≤8ms total | ≤10ms total | Combined |
Key Findings
- Combined is the fastest total in Python at 78ms — beating PMLL/peek-only (92ms) and Context+-only (142ms)
- In TypeScript, combined (36ms) finishes nearly as fast as PMLL/peek-only (26ms) despite doing far more work per test
- The cache elimination pattern works: 1 graph search (2–8ms) + 50 peek hits (0ms each) = 8ms total vs 50 × 8ms = 400ms without caching
- Both languages benefit equally from the combined approach
Agent Instructions (agent_instructions.md)
Every agent using this server must follow the workflow defined in agent_instructions.md. Key requirements:
The peek() Pattern (Mandatory)
initonce at task start to set up the session silopeekbefore every expensive MCP tool call — if hit, use cached valuesetafter a cache miss to populate the siloresolveto check Q-promise continuationsflushat task end to clear session slots
Tool Priority (Mandatory)
Agents MUST use Context+ tools instead of native equivalents:
| Instead of… | MUST use… | Why |
|---|---|---|
grep, rg |
semantic_code_search |
Finds by meaning, not string match |
find, ls |
get_context_tree |
Structure with symbols + line ranges |
cat, read file |
get_file_skeleton first |
Signatures without wasting context |
| manual symbol tracing | get_blast_radius |
Traces all usages across codebase |
Execution Rules
- Think less, execute sooner: smallest safe change, validate quickly
- Batch independent reads/searches in parallel
- If a command fails, diagnose once, pivot strategy, cap retries to 1–2
- Start every task with
get_context_treeorget_file_skeleton - Run
get_blast_radiusBEFORE modifying or deleting any symbol - Use
search_memory_graphat task start,upsert_memory_nodeafter completing work
See the full agent_instructions.md for the complete 15-tool reference and anti-patterns.
pmll-memory-mcp is a Model Context Protocol (MCP) server that gives Claude Sonnet/Opus agents a persistent memory logic loop with two complementary memory layers:
- Short-term KV cache (5 tools) — session-isolated key-value memory with Q-promise deduplication, mirroring
PMLL.c::memory_silo_t. - Long-term memory graph (6 tools) — adapted from Context+ by @ForLoopCodes, providing a persistent property graph with typed nodes, weighted edges, temporal decay scoring (e^(-λt)), and semantic search via TF-IDF embeddings.
- Solution engine (3 tools) — bridges both layers with unified context resolution (short-term → long-term → miss), auto-promotion of frequently accessed entries, and unified memory status views.
The server is designed to be the 3rd initializer alongside Playwright and other MCP tools — loaded once at the start of every agent task. Agents call init once at task start, then use peek before any expensive MCP tool invocation to avoid redundant calls. Frequently accessed entries are promoted to the long-term memory graph for persistent semantic retrieval.
The server exposes 15 tools total across four categories.
Why it's a premium 3rd initializer
Modern Claude agent tasks routinely call Playwright, file-system tools, and other MCP servers. Without a shared memory layer, every subtask re-initializes the same context from scratch. pmll-memory-mcp eliminates this overhead with two complementary memory layers:
Agent task start
├── 1st init: Playwright MCP
├── 2nd init: Unstoppable Domains MCP (see unstoppable-domains/)
└── 3rd init: pmll-memory-mcp ← this server
├── Short-term: all tool calls go through peek() first
└── Long-term: frequently accessed entries auto-promote to graph
The peek() pattern
Before every expensive MCP tool invocation, agents call peek to check the cache:
// Pseudocode — what the agent does automatically via MCP tool calls
// 1. Check cache before navigating
const result = mcp.call("pmll-memory-mcp", "peek", { session_id: sid, key: "https://example.com" });
if (result.hit) {
const pageContent = result.value; // ← served from PMLL silo, no browser needed
} else {
// 2. Cache miss — do the real work
const pageContent = mcp.call("playwright", "navigate", { url: "https://example.com" });
// 3. Populate the cache for future agents / subtasks
mcp.call("pmll-memory-mcp", "set", {
session_id: sid,
key: "https://example.com",
value: pageContent,
});
}
Tools reference (15 tools)
Short-term KV memory (5 tools)
| Tool | Input | Output | Description |
|---|---|---|---|
init |
session_id: str, silo_size: int = 256 |
{status, session_id, silo_size} |
Set up PMLL silo + Q-promise chain for session |
peek |
session_id: str, key: str |
{hit, value?, index?} or {hit, status, promise_id} |
Non-destructive cache + promise check |
set |
session_id: str, key: str, value: str |
{status: "stored", index} |
Store KV pair in the silo |
resolve |
session_id: str, promise_id: str |
{status: "resolved"|"pending", payload?} |
Check/resolve a Q-promise continuation |
flush |
session_id: str |
{status: "flushed", cleared_count} |
Clear all silo slots at task completion |
GraphQL (1 tool)
| Tool | Input | Output | Description |
|---|---|---|---|
graphql |
query: str, variables?: object, operationName?: str |
{data} or {errors} |
Execute GraphQL queries/mutations against the memory store |
Long-term memory graph (6 tools — adapted from Context+)
These tools are adapted from Context+ by @ForLoopCodes, providing persistent semantic memory with graph traversal, decay scoring, and cosine similarity search.
| Tool | Input | Output | Description |
|---|---|---|---|
upsert_memory_node |
session_id, type, label, content, metadata? |
{node} |
Create or update a memory node with auto-generated TF-IDF embeddings |
create_relation |
session_id, source_id, target_id, relation, weight?, metadata? |
{edge} |
Create typed edges (relates_to, depends_on, implements, references, similar_to, contains) |
search_memory_graph |
session_id, query, max_depth?, top_k?, edge_filter? |
{direct, neighbors, totalNodes, totalEdges} |
Semantic search with graph traversal — direct matches + neighbor walk |
prune_stale_links |
session_id, threshold? |
{removed, remaining} |
Remove decayed edges (e^(-λt) below threshold) and orphan nodes with low access |
add_interlinked_context |
session_id, items[], auto_link? |
{nodes, edges} |
Bulk-add nodes with auto-similarity linking (cosine ≥ 0.72 creates edges) |
retrieve_with_traversal |
session_id, start_node_id, max_depth?, edge_filter? |
[{node, depth, pathRelations, relevanceScore}] |
Walk outward from a node — returns reachable neighbors scored by decay & depth |
Solution engine (3 tools)
| Tool | Input | Output | Description |
|---|---|---|---|
resolve_context |
session_id, key |
{source, value, score} |
Unified context lookup: short-term KV → long-term graph → miss |
promote_to_long_term |
session_id, key, value, node_type?, metadata? |
{promoted, nodeId} |
Promote a short-term KV entry to the long-term memory graph |
memory_status |
session_id |
{shortTerm, longTerm, promotionThreshold} |
Unified view of short-term KV and long-term graph memory status |
Installation
Via npx (recommended — no install needed)
npx pmll-memory-mcp
Via npm
npm install -g pmll-memory-mcp
pmll-memory-mcp # starts the stdio MCP server
Claude Desktop / MCP config (claude_desktop_config.json)
NPX
{
"mcpServers": {
"pmll-memory-mcp": {
"command": "npx",
"args": ["pmll-memory-mcp"]
}
}
}
Docker
{
"mcpServers": {
"pmll-memory-mcp": {
"command": "docker",
"args": [
"run", "-i",
"-v", "pmll_data:/app/data",
"-e", "MEMORY_FILE_PATH=/app/data/memory.jsonl",
"--rm", "pmll-memory-mcp"
]
}
}
}
Docker
The MCP server ships as a multi-stage Docker image modelled on the
upstream memory server
Dockerfile.
Build
# From the repository root
docker build -f mcp/Dockerfile -t pmll-memory-mcp .
Run
docker run --rm -i pmll-memory-mcp:latest
Run (persistent KV memory via volume)
docker run --rm -i \
-v pmll_data:/app/data \
-e MEMORY_FILE_PATH=/app/data/memory.jsonl \
pmll-memory-mcp:latest
VS Code MCP configuration
Add to .vscode/mcp.json (or open MCP: Open User Configuration from the Command Palette):
NPX
{
"servers": {
"pmll-memory-mcp": {
"command": "npx",
"args": ["-y", "pmll-memory-mcp"]
}
}
}
Docker
{
"servers": {
"pmll-memory-mcp": {
"command": "docker",
"args": [
"run", "-i",
"-v", "pmll_data:/app/data",
"-e", "MEMORY_FILE_PATH=/app/data/memory.jsonl",
"--rm", "pmll-memory-mcp"
]
}
}
}
Differences from the upstream memory Dockerfile
Upstream src/memory |
This mcp/ |
|
|---|---|---|
| Build source | COPY src/memory /app + COPY tsconfig.json |
COPY mcp /app only |
| tsconfig.json | Extends root via ../../tsconfig.json |
Self-contained standalone |
| Build command | npm install + npm ci --omit-dev in builder |
npm install + npm run build |
| Persistence volume | ❌ | ✅ VOLUME ["/app/data"] |
| Entry point | node dist/index.js |
node dist/index.js ✓ |
Architecture
┌─────────────────────────────────────────────────────┐
│ pmll-memory-mcp v2.0.0 │
│ │
│ ┌────────── Short-term (5 tools) ────────────┐ │
│ │ index.ts ──► peekContext() ──► kv-store.ts│ │
│ │ │ │ │
│ │ └────────► q-promise-bridge│ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌──── Long-term — Context+ (6 tools) ────────┐ │
│ │ memory-graph.ts ──► embeddings.ts │ │
│ │ (nodes, edges, decay scoring, similarity) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌──── Solution Engine (3 tools) ─────────────┐ │
│ │ solution-engine.ts │ │
│ │ (resolve_context, promote, memory_status) │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ ┌──── GraphQL (1 tool) ─────────────────────┐ │
│ │ graphql.ts │ │
│ └────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
│ │
▼ ▼
PMLL.c / PMLL.h Q_promise_lib/
(memory_silo_t) (QMemNode chain)
The server is pure TypeScript — no C compilation is required at runtime. The KV store (kv-store.ts) mirrors the semantics of PMLL.c::init_silo() and update_silo() in TypeScript, and the promise registry (q-promise-bridge.ts) mirrors the QMemNode chain from Q_promise_lib/Q_promises.h.
The long-term memory graph (memory-graph.ts) is adapted from Context+ by @ForLoopCodes, providing an in-memory property graph with typed nodes, weighted edges, temporal decay scoring (e^(-λt)), and semantic search via TF-IDF embeddings. The solution engine (solution-engine.ts) bridges both layers, enabling unified context resolution and auto-promotion of frequently accessed short-term entries to the long-term graph.
C foundations & Context+ integration
| TypeScript module | Mirrors / Adapted from | Key primitives |
|---|---|---|
kv-store.PMMemoryStore |
PMLL.h::memory_silo_t |
init_silo(), update_silo() |
q-promise-bridge |
Q_promises.h::QMemNode |
q_mem_create_chain(), q_then() |
peek.peekContext() |
Recursive conflict check in PMLL | check_conflict(), pml_refine() |
memory-graph.ts |
Context+ memory graph | Nodes, edges, decay, traversal |
embeddings.ts |
Context+ embeddings | TF-IDF, cosine similarity |
solution-engine.ts |
Bridges short-term KV + Context+ long-term | resolveContext(), promoteToLongTerm() |
Registry submission
This server is structured for submission to the Anthropic official MCP registry. See mcp_manifest.json for the registry manifest.
Companion servers & integrations
| Server / Integration | Directory / Source | Transport | Description |
|---|---|---|---|
| Unstoppable Domains | unstoppable-domains/ |
HTTP (remote) | Search, purchase, and manage Web3 domain names via natural conversation. |
| Context+ | github.com/ForLoopCodes/contextplus | Integrated | Long-term semantic memory graph, adapted into memory-graph.ts and solution-engine.ts. By @ForLoopCodes. |
Use all integrations together for the best agent experience: Unstoppable Domains handles domain operations, Context+ provides long-term semantic memory, and pmll-memory-mcp caches API responses to eliminate redundant network calls. See unstoppable-domains/claude_desktop_config.json for a combined Claude Desktop config.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pmll_memory_mcp-2.0.0.tar.gz.
File metadata
- Download URL: pmll_memory_mcp-2.0.0.tar.gz
- Upload date:
- Size: 97.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7dc323fd5965db1855da74974f537e41693775ddcf90ab262785227b82a90f68
|
|
| MD5 |
a088f09f0ceee45223495a7efba5c431
|
|
| BLAKE2b-256 |
6c3ecb16488d257c19b549a7100ad361676535e511a71aed80f88ef0e23f0783
|
Provenance
The following attestation bundles were made for pmll_memory_mcp-2.0.0.tar.gz:
Publisher:
pypi-publish.yml on drQedwards/PPM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pmll_memory_mcp-2.0.0.tar.gz -
Subject digest:
7dc323fd5965db1855da74974f537e41693775ddcf90ab262785227b82a90f68 - Sigstore transparency entry: 1231790663
- Sigstore integration time:
-
Permalink:
drQedwards/PPM@27820235eaec59d3e991555f664e67eac15f21fb -
Branch / Tag:
refs/tags/V2.0.0 - Owner: https://github.com/drQedwards
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@27820235eaec59d3e991555f664e67eac15f21fb -
Trigger Event:
release
-
Statement type:
File details
Details for the file pmll_memory_mcp-2.0.0-py3-none-any.whl.
File metadata
- Download URL: pmll_memory_mcp-2.0.0-py3-none-any.whl
- Upload date:
- Size: 25.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19d92dd4f98f8f53e4fe0efc9cf5898ef4cc4a1fb5596428525fe304b00c3ffe
|
|
| MD5 |
b67c2559bbee7a3c124589ee51a4be0c
|
|
| BLAKE2b-256 |
d2438e7b219372f30345190a06a5055343e0642bba489e3eb5cb2be51950b332
|
Provenance
The following attestation bundles were made for pmll_memory_mcp-2.0.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on drQedwards/PPM
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pmll_memory_mcp-2.0.0-py3-none-any.whl -
Subject digest:
19d92dd4f98f8f53e4fe0efc9cf5898ef4cc4a1fb5596428525fe304b00c3ffe - Sigstore transparency entry: 1231790759
- Sigstore integration time:
-
Permalink:
drQedwards/PPM@27820235eaec59d3e991555f664e67eac15f21fb -
Branch / Tag:
refs/tags/V2.0.0 - Owner: https://github.com/drQedwards
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@27820235eaec59d3e991555f664e67eac15f21fb -
Trigger Event:
release
-
Statement type: