chrysalis-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@chrysalis-mcp remember that the staging database runs on port 5433, then recall it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
chrysalis-bridge
One MCP tool that gives a frozen, small, local LLM graph memory, continual learning outside the weights, SMT reasoning, and evidence-based advice on when to use them.
This is a research prototype with preliminary evidence. Every number below comes from small experiments on a single model; seeLimitations before drawing conclusions.
Table of contents
Related MCP server: mcp-engram
What it is and why
Small local models (here Gemma 4 E4B served by llama.cpp) are cheap, private and fast, but they forget everything between sessions, have a short window, and are unreliable at multi-constraint logic. Retraining or fine-tuning them for each of those gaps is expensive and, for a user running on a laptop or an iGPU, usually out of reach.
chrysalis-bridge augments a frozen model from the outside, over MCP, without retraining:
Memory that survives sessions and scales beyond the context window.
Learning that happens in an external store, not in the weights.
Reasoning delegated to an exact solver (Z3) for problems the model gets wrong.
Advice about when each capability helps or hurts that particular model on that particular task, derived from measured results and not from intuition.
The package is called chrysalis-mcp; the repository is chrysalis-bridge.
Key ideas
Idea | What it means here |
Graph memory (HippoRAG-style PPR) | Knowledge goes in as triples. Recall seeds a Personalized PageRank walk over the graph, so multi-hop questions reach facts that a nearest-neighbour lookup misses. Dense vectors live in sqlite-vec. |
Fly-inspired continual learning outside the weights | A FlyHash sparse code (random expansion plus winner-take-all) indexes nodes; |
Z3 reasoning via a JSON DSL |
|
Model-aware, task-conditioned, evidence-based advisories | The server holds |
Anti-chatty single-tool design | One tool, |
Architecture
Components
flowchart LR
CLIENT["MCP client / LLM"] -->|"stdio"| SERVER["server.py: tool chrysalis"]
SERVER --> REG["core/registry: domain and action dispatch"]
SERVER --> ENV["core/envelope: typed response"]
REG --> META["domain meta"]
REG --> MEM["domain memory"]
REG --> REASON["domain reason"]
META --> ADV["core/advisory and profile"]
META --> BATCH["core/batch and session cache"]
ADV --> EVID[("data/evidence.json")]
MEM --> SUB["substrate: SQLite and sqlite-vec"]
MEM --> ALG["algorithms: FlyHash and PPR"]
REASON --> DSL["constraint_dsl"]
REASON --> Z3W["isolated Z3 worker process"]Session flow
sequenceDiagram
participant C as Client
participant S as chrysalis server
participant A as Advisor
C->>S: initialize
S-->>C: instructions (startup-profile hint) and tool description
C->>S: chrysalis meta.handshake (model, params_b, thinking), session_id
S->>A: resolve profile and rules
A-->>S: plain-language hints
S-->>C: profile and prompt_hint
Note over C: client pastes prompt_hint into the system prompt
C->>S: chrysalis meta.batch (steps with $cache refs, return_only)
S->>S: run steps server-side, cache intermediate results
S-->>C: projected result in a typed envelopeAdvisory decision
flowchart TD
P["Model profile: class, thinking flag, forced or declared or calibrated"] --> M["Match rules"]
T["Task features: n_vars, n_atoms, goal, facts_exceed_ctx"] --> M
E[("evidence.json: each rule cites a measurement")] --> M
M --> L{"Level"}
L -->|"recommended"| H["Plain-language hint"]
L -->|"discouraged"| H
L -->|"experimental"| H
L -->|"neutral"| N["No hint"]
H --> SP["System prompt via MCP instructions and prompt_hint"]
H --> TD["Tool description line"]
H --> AN["advisory field on the call response"]The single tool contract
The server exposes exactly one MCP tool:
chrysalis(domain, action, params={}, verbosity="summary",
session_id=None, store_as=None, telemetry=None, agent_id=None)Call meta.schema for the full machine-readable contract, or meta.discover for a compact map.
Domain | Action | Purpose |
|
| Full contract: every domain, action, params and an example. |
|
| Compact orientation, optionally for one |
|
| Declare the calling model ( |
|
| Session-specific probes checked by the server; measured profile overrides a declared one. |
|
| Advisory level of a |
|
| Calls, errors, bytes, |
|
| Chain up to 25 steps server-side. |
|
| Add knowledge triples (nodes, edges, FlyHash code, dense vector). |
|
| Associative recall: |
|
| Reinforce the association between a query and a node; stores up to 3 teach examples per node. |
|
| Soft-invalidate the edges of a |
|
| Decay learned associations and prune weak ones; drops orphan examples. |
|
| List or restore verified rotating backups taken before |
|
| Solve an SMT-LIB 2 problem ( |
|
| Check whether an |
Envelope. Every response is one typed object with status, severity (INFO, WARN, ERROR),
summary, next_action, truncated, cursor, and a telemetry block (request_id, ms, bytes,
est_tokens). Oversized payloads are clamped; the telemetry block is omitted in brief and terse
unless requested.
Verbosity. detail, summary (default), brief, terse. Lower levels cap list and string
sizes; error text and advisory hints are never truncated.
Batch with $ref and return_only. Intermediate results stay on the server:
{
"domain": "meta", "action": "batch", "session_id": "run-1",
"params": {
"steps": [
{"id": "a", "domain": "memory", "action": "recall",
"params": {"query": "who owns the lab?", "k": 3}, "store_as": "hits"},
{"id": "b", "domain": "meta", "action": "stats", "params": {"scope": "all"}}
],
"return_only": "last",
"select_fields": ["status"]
}
}A step can reference an earlier result as $cache.<key>.<field> (the key is a step id or its
store_as). return_only is all, last or summary; select_fields projects dot-paths. A batch
stops at the first error unless continue_on_error is set, and nested batches are rejected.
session_id. Scopes the in-process result cache (store_as, $cache), the model profile set by
handshake/calibrate, and per-session stats. State is in memory and per process.
Quickstart
Requires Python 3.14 and uv.
git clone <this repository>
cd chrysalis-bridge
uv sync
uv run chrysalis-mcp # stdio MCP serverMCP client configuration (stdio):
{
"mcpServers": {
"chrysalis": {
"command": "uv",
"args": ["run", "--directory", "/path/to/chrysalis-bridge", "chrysalis-mcp"],
"env": {
"CHRYSALIS_DB": "/path/to/chrysalis/substrate.db"
}
}
}
}Environment variables:
Variable | Effect |
| SQLite path. Default |
| Force the model profile for every session (overrides any handshake). |
|
|
Example handshake (first call of a session):
{
"domain": "meta", "action": "handshake", "session_id": "run-1",
"params": {"model": "gemma-4-e4b", "family": "gemma", "params_b": 4, "thinking": false}
}The response includes a prompt_hint: paste it into the system prompt of the model.
Development:
uv run pytest
uv run ruff check . && uv run ruff format --check .Validation and results
Results are generated from validation/results/*.json by python -m validation.report. They are
reported as measured, including the ones that did not support the hypothesis.
Hypothesis | Verdict | Result |
H-b: continual learning does not forget (synthetic) | Supported | Accuracy on old associations after 1000 new updates: retention 1.00 with the sparse store vs 0.00 with an overwrite baseline. |
H-a: two-hop retrieval | Supported | recall@5 0.45 (PPR) vs 0.40 (seeds); one call instead of two. |
H-b-e2e: learned aliases, model in the loop | Supported | Gemma 4 E4B, 12 learned invented aliases, 300 interference updates. |
H-a: end to end | Supported | Accuracy 0.0 alone vs 0.6 with memory. |
H-a-ctx: memory vs full context | Not supported | 0.6 with memory vs 0.9 with the full context when the facts fit in the window. |
H-a-scale: facts beyond the window | Supported | 0.35 with memory vs 0.0 with context (+0.35). |
H-a': FlyHash vs exact cosine | Not supported | At N=1000, FlyHash cluster precision is worse than cosine (about 0.54 x cosine at the shipped setting, best swept 0.69 x). FlyHash retrieval is therefore experimental. |
H-c: solver on small puzzles | Not supported | 0.8 alone vs 0.6 with the solver (thinking off). |
H-c-hard: solver on hard puzzles | Supported | +0.12 accuracy with the solver in both thinking modes (off 0.18 to 0.29; on 0.82 to 0.94). |
H-adv held-out, thinking on | Supported | Advised arm 16/16 vs best fixed arm 15/16 (n=16). |
H-adv held-out, thinking off | Not supported | Advised 0.25 vs best fixed 0.375; the model rarely acts on the hint with thinking off. |
H-mcp: batching cost | Supported | Estimated tokens: batch 921, sequential 2127, granular tools 7977 (granular is simulated). |
Additional finding: an unconditional "reply with ONLY the JSON object" reminder in the prompt suppressed tool calls (solver use fell to 0 in the ablation), so the project only appends a format reminder conditionally.
Fixes found by the evaluation
The validation loop found two real defects in the learning path, both fixed:
Boost leak. The learned boost was unbounded, so unrelated updates destroyed recall (1.0 to 0.06 after 10 updates). Fixed by normalizing the boost to the KC overlap fraction (
BOOST_SCALE).Invisible learned associations. The first LLM run scored fly 0/12 because the model never saw why a node was recalled. Fixed with
learned_asprovenance facts; the result became 9/12.
Limitations
Small n. Held-out sets have 16 items; hard sets 17. Differences of one or two items are within noise and no statistical significance is claimed.
A single model. All live results use Gemma 4 E4B. Nothing here shows the effects transfer.
Synthetic memory benchmarks. H-a, H-a', H-b and H-a-scale use generated fictional facts.
Thinking off is not supported. The advisory path works with thinking on and not yet with it off.
Tool-call parsing. Gemma 4 tool calls are sometimes returned as plain content by llama.cpp (issue 22786); the harness has to tolerate this.
Common-word aliases. On realistic aliases such as "the big apple", false
learned_asfacts appear 17-58% of the time.Interference. Recall degrades at 300 high-overlap interference updates.
Snapshots. Substrate v4 cannot restore v3 snapshots.
Advisories are self-referential. The evidence rules come from the same benchmarks that report them.
Reproduce
uv run pytest # unit and contract tests (no model needed)
uv run pytest -m bench # offline benchmarks; write validation/results
python -m validation.eval_llm --hyp hc,hard,adv --thinking both # needs a live OpenAI-compatible model
python -m validation.report # merge results into a verdict tableeval_llm talks to an OpenAI-compatible endpoint at CHRYSALIS_LLM_URL. For local runs,
validation/llm_server.py --profile e4b is a resource-guarded launcher for llama.cpp (admission
control, RAM caps, watchdog); read its docstring first, since it manages a GPU-backed process.
Hypothesis groups: ha, ctx, hc, hard, adv, cal, hascale, heldout, hbe2e.
Related work and what is different
HippoRAG 2 (arXiv:2502.14802): graph-based non-parametric continual learning with Personalized PageRank. The recall path here follows the same idea at a much smaller scale; it is not a reproduction and has not been compared on their benchmarks.
FlyHash (Dasgupta et al., Science 2017, doi:10.1126/science.aam9868): a fly-olfaction-inspired similarity-search code. In this project's tests it underperforms exact cosine.
Larimar (arXiv:2403.11901): episodic memory for LLMs with fast updates. Different mechanism: here the memory is an external SQLite graph.
Logic-LM (arXiv:2305.12295): LLM plus symbolic solver for logical reasoning.
reasonis in the same family, exposed as an MCP action.SMART (arXiv:2502.11435) and When2Tool (arXiv:2605.09252): work on when an agent should or should not call a tool. Closest to the advisory idea; they are about the agent's own decision.
Dispatch-level instrumentation (arXiv:2608.28439): tool-dispatch measurement for agent pipelines; related to the envelope telemetry only loosely.
Code Mode (Cloudflare) and code execution with MCP (Anthropic): motivation for keeping intermediate results out of the model context.
meta.batchis a restricted, declarative analogue, not general code execution.
Plausibly novel (not established): server-side, training-free, model-aware and task-conditioned tool advisories, learned from evals and delivered through the system prompt. The evidence for this is preliminary (one model, small n, one positive held-out result with thinking on) and no exhaustive literature search was done, so treat the claim as a hypothesis.
Roadmap
A better
learned_asgate (global df, stoplist, coverage; boost share from the query's own KCs) and a realistic common-word alias dataset.More tasks per hypothesis, with confidence intervals.
Small model families: Gemma 4 E4B plus a small Qwen. No large models (local hardware) and no Gemma 3.
Rival baselines on the original benchmarks: SMART, When2Tool, HippoRAG 2, Logic-LM.
A better answer for thinking off, where the hint is currently not acted upon.
Project layout
chrysalis-bridge/
├── src/chrysalis_mcp/
│ ├── server.py # FastMCP app, the single tool, stdio entry point
│ ├── core/ # registry, envelope, batch, session, profile, advisory, task_features
│ ├── domains/ # meta, memory, reason, constraint_dsl, isolated Z3 worker
│ ├── algorithms/ # FlyHash, Personalized PageRank
│ ├── substrate/ # SQLite store, read/write paths, rotating backups, sqlite-vec
│ └── data/evidence.json # advisory rules, each citing a measurement
├── tests/ # unit, contract and stdio end-to-end tests
├── validation/ # benchmarks, LLM harness, guarded llama.cpp launcher, results/*.json
├── pyproject.toml
├── uv.lock
├── LICENSE
└── NOTICEContributing
Issues and pull requests are welcome. Before opening a PR, run uv run pytest and
uv run ruff check . && uv run ruff format --check .. Keep the single-tool contract: new capabilities
are new domain.action registrations (the schema is generated from the registry), not new MCP tools.
Claims about behaviour should come with a result under validation/.
License
Apache License 2.0. See LICENSE and NOTICE.
Runtime dependencies (versions from uv.lock; licenses from package metadata, all compatible with
Apache-2.0 distribution):
Package | License |
| MIT |
| BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0 |
| MIT or Apache-2.0 (dual) |
| MIT |
| MIT |
| MIT |
Model weights are not distributed. Gemma weights are used only if you download them yourself, and your use is governed by the Gemma Terms of Use, not by this repository's license. Likewise llama.cpp is a separate project under its own license.
Acknowledgements
Several infrastructure patterns (typed envelope, domain/action dispatcher,
$cachebatching, session cache, rotating verified backups, version stamp, tier-to-advisory precedence) were reverse-engineered, not imported, from the author's agent-execution-plane (Apache-2.0); see NOTICE.Inspiration: HippoRAG 2, the FlyHash work of Dasgupta et al., Logic-LM, and the Code Mode and code-execution-with-MCP write-ups cited above.
Built on the Model Context Protocol, Z3, sqlite-vec, NumPy and llama.cpp.
Available Tools
1 toolchrysalisC
Single dispatcher: chrysalis(domain, action, params). Call domain='meta', action='schema' for the full contract, or action='discover' for a compact map. Chain steps in one call with meta.batch. verbosity: detail|summary|brief|terse. Advisory memory.recall: rec:facts_exceed_ctx=true. In words: worth using when the facts do not fit in your context window.
Inputs: action (required), domain (required), params, agent_id, +4 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 1 tool
With a single tool there is no inter-tool overlap, so classic misselection risk is eliminated. However, the ambiguity is pushed inward: the domain/action/params space is opaque from the tool listing, so an agent cannot tell what operations exist or which action to pick without first making an exploratory meta.schema or meta.discover call.
The lone tool name 'chrysalis' matches the server and is not inconsistent with anything, but it is an opaque noun with no verb_noun convention to establish predictability. The actual naming surface (domain and action identifiers) is not visible here, so consistency cannot be verified from the tool set.
One tool is intentionally thin as a dispatcher pattern, which is a legitimate design, but by the rubric a single entry point is borderline and forces a discovery round-trip before any real work. It is not a trivial tool, so it avoids the worst score, but the surface is not self-evident from the count alone.
The tool advertises schema discovery, batching, verbosity levels, and advisory memory, which suggests a broad internal surface, but none of the actual domains or actions are enumerated so coverage cannot be assessed. Completeness is deferred to a runtime meta.schema call, leaving a potential dead end if discovery fails or is skipped.
Maintenance
Related MCP Connectors
Persistent memory and knowledge management for AI agents with semantic search and 50+ tools.
Persistent memory and knowledge graphs for AI agents. Hybrid search, context checkpoints, and more.
Evidence-grounded, graph-connected, correctable memory for agents.
Memory that reasons: continual learning for stateful agents. Better context, fewer tokens.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceLong-term memory for AI agents over MCP — episodic + semantic memory, a temporal knowledge graph, and a dialectic user model, exposed as 32 tools (recall, remember, context, graph, dreaming, peers). Zero dependencies, runs fully offline; leads the LoCoMo benchmark at ~35x fewer LLM calls.2Apache 2.0
- AlicenseNot gradedqualityCmaintenanceEnables LLMs to build and explore a cognitive neuroscience-inspired knowledge graph with SQLite, supporting search, graph traversal, temporal sequences, and structured reasoning.24MIT
- AlicenseNot gradedqualityDmaintenanceProvides persistent memory for AI tools by building a local knowledge graph from conversations, enabling cross-session recall and context awareness without cloud dependencies.9MIT
- AlicenseNot gradedqualityFmaintenanceProvides LLM agents with hallucination-free external memory and knowledge tools, including ask, remember, forget, math, and code reasoning, with deterministic, traceable outputs.MIT