levh
Optional integration for LLM-powered query answering, enabling natural-language questions against stored memories with source citations when an OpenAI API key is configured.
Click on "Install 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., "@levhremember that the API key is stored in the secrets manager"
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.
# LEVHWhat is LEVH?
LEVH gives AI agents and people a persistent, searchable memory across sessions, projects, and tools. Instead of starting from scratch every time, shared context preserves what you discussed, decisions you made, and what matters in each workspace.
Most memory tools optimize for perfect recall — store everything, retrieve everything, let noise pile up forever. LEVH instead models memory the way human memory actually works: every memory has its own decay curve; unused memories fade; memories you actually rely on get reinforced and become durable, automatically, with no manual curation. Signal rises to the top on its own.
It works as an MCP (Model Context Protocol) server — plug it into Claude Desktop, Cursor, Claude Code, VS Code (Cline), Windsurf, or any MCP-compatible client. It also exposes a REST API + WebSocket for custom integrations and ships with a built-in dashboard with a real-time activity feed.
Key insight: Your AI tools (Claude, Cursor, Copilot) are stateless. LEVH makes them stateful — and self-curating.
Related MCP server: exocortex
The memory model
This is the core mechanic, not a footnote:
Every memory has its own half-life. New memories start at a default (168h) — like short-term memory, they fade fast unless something happens.
Recalling a memory resets its clock and reinforces it. Each time a memory is retrieved (or explicitly reinforced), its half-life grows — modeled on spaced repetition / the testing effect, the same mechanism flashcard apps like Anki use to build long-term retention.
Importance accelerates consolidation, like emotional salience in human memory: a
0.9-importance memory becomes durable much faster per recall than a0.1one.Outcome feedback closes the loop.
memory_feedback(helpful=false)cuts a memory's stability so wrong or stale information fades out fast instead of resurfacing;helpful=truereinforces it. Your AI can call this whenever you correct it.New information interferes with old. Storing a memory near-identical to an existing one weakens the older version (retroactive interference) — "the deploy branch is prod" naturally supersedes "the deploy branch is main" without anyone deleting anything.
Pinning is permanent encoding — for rules and facts that must never be forgotten, skip decay entirely. Pinned memories are also immune to interference and never auto-deduped.
Fading memories surface for review. The dashboard (and the
list_fading_memoriestool) shows memories whose predicted retention has dropped below 35% — rescue what still matters with one click, let the rest go.Every memory's curve is visible in the dashboard: open any memory to see its predicted retention over the next 30 days, its current strength, and one-click Reinforce / Stale actions.
retention(t) = 0.5 ^ (hours_since_last_recall / stability_hours)
stability_hours(after recall) = min(stability × (1 + gain·(0.5+importance)), max_stability)
stability_hours(negative feedback) = max(stability × weaken_factor, 1h)Features
Adaptive memory decay: per-memory half-life, reinforced by recall, weakened by negative feedback and interference, visualized as a forgetting curve — see The memory model
3-Layer Memory: ShortTerm (FIFO deque, max 50) → Episodic (SQLite) → Vector Store (NumPy cosine similarity)
H(x,ψ) Scoring: Multi-factor ranking:
α·(1-similarity) + β·(1-decay) + γ·(1-importance) + δ·(1-frequency)— every weight env-configurable, every score explainable in the UIAsk your memory:
ask_memory/POST /api/ask/ dashboard "Ask" panel — a natural-language question returns a synthesized answer that cites the exact memories it drew from (with dates). LLM-powered whenOPENAI_API_KEYis set, deterministic ranked-evidence fallback offline. Read-only: asking never reinforces memories.People graph: everyone you interact with, extracted automatically from calendar attendees, email senders/recipients, and transcript speakers —
/api/people,list_people/about_personMCP tools, and a dashboard People page ("what do I know about X?"). No manual tagging.Timeline: episodic memories grouped by the day they actually happened — "what happened this/last week" —
/api/timeline, thetimelineMCP tool, and a dashboard Timeline page.Daily Briefing: memory as an active assistant — today's events, open commitments detected from your own words ("I'll send…", "yapacağım…"), and what you may be forgetting. Fully offline/deterministic (no LLM key).
/api/briefing, thebriefingMCP tool, and a dashboard Briefing page.Organizations: the people graph rolled up by email domain — the companies you actually interact with, who from them, and how often. Personal email providers excluded.
/api/organizations,list_organizations/about_organizationMCP tools, and a dashboard Organizations page.Decisions: decision statements detected from memory content ("we decided", "agreed to", "karar verdik") — what was decided, and when/where. Deterministic, no LLM.
/api/decisions, thelist_decisionsMCP tool, and a dashboard Decisions page.Encrypted Backup & Restore: full portable snapshot (every memory with its decay state + every session), optionally encrypted at rest with a passphrase (PBKDF2 + Fernet/AES).
/api/backup+/api/restore,create_backup/restore_backupMCP tools, and a Settings → Backup & Restore panel with merge/replace.Meeting Prep: the proactive "before you walk in" brief — your next meeting, who's attending, what you last discussed with each of them, plus relevant open commitments and decisions. Deterministic, offline.
/api/meeting-prep, themeeting_prepMCP tool, and a dashboard Meeting Prep page.Memory Consolidation: sleep-like compression — clusters of related, aged, unpinned memories collapse into one durable summary each (the raw episodes archived inside it, not lost).
/api/memories/consolidate-similar, theconsolidate_similarMCP tool, and Settings → Data Management buttons.Spaced-Repetition Review: the fading queue as an active review flow — keep / reinforce / weaken / pin / snooze / forget each memory losing strength, every decision recorded in its history. Closes the lifecycle loop.
/api/memories/review,list_review_memories/review_memoryMCP tools,levh reviewCLI, and a dashboard Review page.Memory Admission Gate: decides what happens to an incoming memory before it's stored — admit / review / reject (duplicates) / redact (strips secrets like API keys & passwords; keeps emails). Deterministic, offline.
/api/memories/admit+/api/memories/evaluate-admission,admit_memory/evaluate_admissionMCP tools,levh admitCLI, and a Settings preview card.Connector Framework v2: gate-integrated, incremental ingest — every fetched item is routed through the admission gate (dedupe + secret redaction) with per-item error isolation, and each run is recorded so re-syncing is incremental and reportable.
/api/connectors/sync+/api/connectors/sync-state,sync_connector/connector_sync_statusMCP tools,levh syncCLI, and a Settings gate toggle + sync history.Hard-delete Audit & Redaction: deletes a memory from the tracked primary stores and reports any detected residue (
purge_memory), and finds + strips secrets stored before the gate existed (audit_secrets/redact_secrets, logged to each memory's redaction history). Full derived-state cascade is verified by the 2.26.x privacy-hardening gates before public RC./api/memories/audit-secrets+/redact-all+/{id}/redact+/{id}/purge, matching MCP tools,levh audit-secrets/redact-secrets/purgeCLI, and a Settings Privacy & Redaction card.Entity Knowledge Graph: memories indexed into persistent
entities+memory_entitiestables — person / organization / event / document / task — so "which memories mention X" and "which entities co-occur with X" are real joins./api/entities(reindex / stats / list / detail),reindex_entities/list_entities/about_entityMCP tools,levh entitiesCLI, and a dashboard Graph page.Provenance / Trust Score: a deterministic, explainable reliability signal per memory — source type + entity-graph corroboration (how many independent sources back it) + review lifecycle + recency − risk flags → a
confidencewith a label and a human-readable breakdown. Separate from the H-score; never changes recall ranking; not a "truth" claim./api/memories/{id}/trust+/trust/recompute+/low-trust,memory_trust/recompute_trust_scores/list_low_trust_memoriesMCP tools,levh trustCLI, and a Settings Trust & provenance card.Conflict Candidates: deterministic flagging of memories that might disagree (share an entity + an opposing surface pattern: antonym / negation / same-attribute-different-value) — a review signal, never a verdict, never auto-deletes; an open candidate adds a small risk to the trust score. Not LLM contradiction detection.
/api/conflicts(detect / list / review),detect_conflict_candidates/list_conflict_candidates/review_conflict_candidateMCP tools,levh conflictsCLI, and a dashboard Conflicts page.59 MCP Tools: Store, admit, evaluate-admission, recall, ask, forget, purge, audit-secrets, redact-secrets, search, update, list, stats, consolidate, consolidate-similar, sessions, export/import, backup/restore, connectors, connector-sync, pinning, reinforcement, feedback, fading review, spaced-repetition review, projects, people, organizations, decisions, timeline, briefing, meeting prep, context files, dedupe, related memories, session summarization
Auto-Capture Summaries:
summarize_sessiondistills a session's memories into one durable memory — LLM-powered whenOPENAI_API_KEYis set, deterministic offline fallback otherwise; can run automatically onend_session(AUTO_SUMMARIZE_SESSIONS=true)Related Memories: live nearest-neighbour "see also" for any memory, computed from embedding similarity — no manual linking, no extra schema
Recall Quality Benchmark:
levh benchmark/ Settings panel reports hit@1/hit@3/hit@5/MRR on a labelled query set, so recall quality is measurable, not just claimedProject Memory: Namespace memories per repo/workspace; filter recall by project
Source Tracking: Know which AI client (claude-code, cursor, ...) stored each memory
Pinned Memories: Rules and decisions that never decay and always surface
Context File Generation: Compile memories into
CLAUDE.md/.cursorrulesso every session starts pre-loaded — from the UI, the CLI, or an MCP toolAuto-Capture:
levh hook installcaptures every git commit message as a memory;levh capturefor one-liners (auto-detects your repo as the project)4 Embedding Modes: OpenAI
text-embedding-3-small, localall-MiniLM-L6-v2, Ollama (fully offline), or deterministic hash fallback — the system always worksApp Connectors: Import from Calendar (.ics), Email (.mbox/.eml), Meeting transcripts (.vtt/.srt), Notion, Obsidian, GitHub repos, local files
Live Dashboard: Next.js dashboard served by the API itself (one process, one port) with a real-time WebSocket activity feed, semantic search, insights charts, and full memory management
Zero Infrastructure: SQLite (no MongoDB, no Redis, no external services); old v1 databases migrate automatically
Quick Start
1. Install
git clone https://github.com/ali-ulu/levh.git
cd levh
pip install -e ".[dev]"
pip install levh2. Configure
cp .env.example .env
# Defaults work out of the box; set EMBEDDER_MODE=local for semantic searchFirst run: choose demo or real data
Try the demo
pip install levh
levh setup --demo --client claude --profile work
levh serveStart with real data
pip install levh
levh setup --real --client claude --profile work
levh capture "Atlas uses PostgreSQL in production."
levh serveThe first-run dashboard offers the same two paths, shows real readiness state, generates focused MCP configs, and explains the local/off-by-default dogfood measurement. See Getting Started and the 5-minute demo.
3. Run
levh serve # or: uvicorn server.api:app --port 8000
# Dashboard + API on http://localhost:8000
# MCP SSE stream endpoint: http://localhost:8000/api/mcp/sseThe dashboard is served by the API. Source checkouts serve frontend/out/; built
wheels include a packaged static export under server/dashboard/. To rebuild the
dashboard after changes: cd frontend && npm ci && npm run build.
Try it in 5 minutes
Empty store? Load a deterministic demo corpus — 4 people, 2 organizations, a few decisions and tasks, meetings, and one real conflict candidate — so every view has something to show:
levh seed-demo # or click "Load demo data" on the empty dashboardThen open the dashboard and explore Briefing (daily digest), Meeting Prep
(who/what before a call), Conflicts (review the disputed Atlas deadline), and
Insights (watch low-importance memories fade while pinned ones persist). The
seed refuses to touch a non-empty store unless you pass --force.
4. Connect Your AI Client
Open Settings in the dashboard for copy-paste MCP configs, or see Platform Setup below.
5. (Optional) Auto-capture your work
levh hook install # capture every git commit message
levh capture "we use pnpm, not npm" --pin
levh context -o CLAUDE.md # compile memory into a context filePlatform Setup
All clients use the same stdio server. Generate any config with
levh mcp config <claude|claude_code|cursor|windsurf|vscode|cline>.
Claude Desktop
Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"levh": {
"command": "python",
"args": ["-m", "server.mcp_stdio"],
"cwd": "/path/to/levh-new",
"env": {
"EMBEDDER_MODE": "local"
}
}
}
}Cursor IDE
Same server block in .cursor/mcp.json in your project root.
Claude Code (CLI)
Same server block in ~/.claude.json.
VS Code (Cline Extension)
Same server block (under a servers key) in .vscode/mcp.json.
Windsurf
Same server block in ~/.codeium/windsurf/mcp_config.json.
Architecture
┌─────────────────────────────────────────────┐
│ LEVH Server │
│ │
Claude Desktop ───┤ ┌─────────┐ ┌──────────┐ ┌──────┐ │
Cursor IDE ───┤ │ MCP │ │ Memory │ │Embed │ │
Claude Code ───┤ │ Server ├───▶│ Engine ├───▶│OpenAI│ │
VS Code/Cline ───┤ │(stdio + │ │ 3-Layer │ │Local │ │
Windsurf ───┤ │ SSE) │ │ H(x,ψ) │ │Ollama│ │
│ └─────────┘ └────┬─────┘ └──────┘ │
REST API ───┤ one shared │ │
WebSocket ───┤ engine ┌─────▼──────┐ │
Dashboard (/) ───┤ instance │ SQLite │ │
│ │ (aiosqlite)│ │
─────────────────┤ └────────────┘ │
App Connectors: │ │
Notion / Obsidian │ import_from_app() → store → recall │
GitHub / Files ───┤ │
└─────────────────────────────────────────────┘All transports share one engine instance — a memory stored via MCP is instantly visible in the dashboard's live feed, and vice versa.
59 MCP Tools
Tool profiles. Advertising all 59 tools to a client hurts tool-selection accuracy, so LEVH groups them into cumulative profiles —
minimal(5) ⊂work(15) ⊂admin(54) ⊂full(59). Generated configs default towork; runlevh mcp profilesto see the bands, or setLEVH_MCP_PROFILE/mcp config --profile <name>to change it. The full table below is thefullsurface. Profiles only filter which tools a client sees — they are not an authentication or authorization boundary; every profile talks to the same engine instance with the same access.
# | Tool | Description |
1 |
| Store a memory with importance, tags, project, source, pin |
2 |
| Recall memories ranked by H(x,ψ) score (filter by session/project) |
3 |
| Delete from all 3 layers |
4 |
| Semantic search with detailed results |
5 |
| Update content/importance/tags |
6 |
| List with type/tag/session/project/source/pinned filters |
7 |
| System statistics and metrics |
8 |
| Promote short-term → episodic |
9 |
| Clear the live FIFO deque |
10 |
| Set importance (0.0-1.0) |
11 |
| Build context window (short-term + pinned + important) |
12 |
| Start a named session |
13 |
| End session + consolidate its memories |
14 |
| Export all memories as JSON |
15 |
| Import memories from JSON |
16 |
| Import from Calendar/Email/Transcripts/Notion/Obsidian/GitHub/local files |
17 |
| List available app connectors |
18 |
| Get config help for a connector |
19 |
| Pin a memory — exempt from decay, always in context files |
20 |
| Restore normal decay |
21 |
| Workspaces with memory counts |
22 |
| Which AI clients stored memories |
23 |
| Compile memories into CLAUDE.md / .cursorrules |
24 |
| Find/remove near-duplicates (dry-run by default) |
25 |
| Manually strengthen a memory — resets decay clock, grows stability |
26 |
| helpful=true reinforces; helpful=false makes wrong/stale info fade fast |
27 |
| Review queue of memories about to be forgotten |
28 |
| Nearest-neighbour "see also" for a memory (live, embedding-based) |
29 |
| Distill a session's memories into one durable summary memory |
30 |
| Ask your memory a question → synthesized, cited answer (read-only) |
31 |
| People across your memories (calendar/email/transcript), by frequency |
32 |
| One person's profile + the memories mentioning them |
33 |
| Recent memories grouped by day (what happened this/last week) |
34 |
| Daily briefing — today's events, open commitments, and what you may be forgetting |
35 |
| Organizations across your memories (people grouped by email domain) |
36 |
| One organization's profile + the memories mentioning it |
37 |
| Decisions detected in recent memories — what was decided, when/where |
38 |
| Write a full backup (memories + sessions) to a file, optionally passphrase-encrypted |
39 |
| Restore memories + sessions from a backup file (merge or replace) |
40 |
| Pre-meeting brief — next meeting, attendees, what you last discussed, open items |
41 |
| Compress clusters of related aged memories into durable summaries (sleep-like) |
42 |
| Memories due for spaced-repetition review (fading, unpinned, un-snoozed) |
43 |
| Apply a review decision — keep / reinforce / weaken / pin / forget / snooze |
44 |
| Preview the admission verdict for candidate text (admit/review/reject/redact) |
45 |
| Store through the admission gate — dedupe + secret redaction |
46 |
| Connector v2 — fetch + gate-filtered incremental ingest |
47 |
| Per-source sync bookkeeping (last synced, totals, run count) |
48 |
| Scan stored memories for secrets (credentials, tokens) |
49 |
| Strip secrets from stored memories (preview or apply) |
50 |
| Hard-delete a memory and report residue across tracked storage layers |
51 |
| Rebuild the persistent entity graph from all memories |
52 |
| List graph entities by type, most-mentioned first |
53 |
| One entity's profile — its memories and co-occurring entities |
54 |
| A memory's provenance/trust breakdown (confidence + explainable evidence) |
55 |
| Recompute provenance/trust scores for all memories |
56 |
| Memories below a confidence threshold, least-trusted first |
57 |
| Flag memory pairs that might disagree (shared entity + opposing pattern) |
58 |
| List conflict candidates by status (open/confirmed/…) |
59 |
| Human review — dismiss / confirm / keep-A / keep-B / both-valid |
CLI
levh serve # API + dashboard on :8000
levh doctor # health checks
levh setup --status # computed first-run readiness
levh setup --demo --client claude --profile work
levh setup --real --client cursor --profile minimal
levh seed-demo # load a demo corpus into an empty store
levh capture "note" --pin # store a memory (auto-detects git repo as project)
levh context -o CLAUDE.md # generate a context file from memories
levh hook install # git post-commit auto-capture
levh summarize <session_id> # distill a session into one summary memory
levh benchmark # recall-quality harness (hit@k / MRR)
levh mcp config cursor # print MCP config for a client
levh mcp stdio # run the MCP stdio server
levh eval run # golden-fixture memory evaluation → eval_report.json
levh eval report # print the last written evaluation report
levh dogfood status # aggregate view of the local usage journal
levh dogfood export -o out.json # write the aggregate dogfood report (explicit)H(x,ψ) Scoring Algorithm
Memories are ranked by a multi-factor score (lower = more relevant):
H(x,ψ) = α·(1-similarity) + β·(1-decay_factor) + γ·(1-importance) + δ·(1-frequency)
α = 0.4 (semantic relevance) — HSCORE_ALPHA
β = 0.2 (time decay) — HSCORE_BETA
γ = 0.3 (user-marked importance) — HSCORE_GAMMA
δ = 0.1 (access frequency) — HSCORE_DELTASimilarity: Cosine similarity between query and memory embeddings
Decay: Exponential decay measured from last access (not creation) at the memory's own
stability_hourshalf-life — default 168h, but it grows every time the memory is recalled or reinforced (see The memory model). Pinned memories never decay.Importance: User-assigned importance (0.0-1.0) — also accelerates stability growth on reinforcement
Frequency: How often the memory has been accessed — only memories actually returned by a recall are counted
Explainability: every score can be broken into its four components — in the dashboard's detail drawer or via
GET /api/memories/{id}/score-breakdown; the forgetting curve itself is available viaGET /api/memories/{id}/forgetting-curve
REST API Endpoints
Method | Endpoint | Description |
POST |
| Store a memory |
GET |
| List with filters ( |
GET |
| Get single memory |
PUT |
| Update memory |
PATCH |
| Pin / unpin |
POST |
| Manually strengthen a memory |
POST |
| helpful=true/false — learn from recall outcomes |
GET |
| Memories about to be forgotten (review queue) |
DELETE |
| Delete memory |
POST |
| Recall by query (optional project filter) |
POST |
| Short-term → episodic |
POST |
| Find or remove near-duplicates |
POST |
| Export all as JSON |
POST |
| Import from JSON |
GET |
| Explain a memory's H(x,ψ) score |
GET |
| Predicted retention curve over time |
GET |
| Nearest-neighbour "see also" memories |
POST |
| Create session |
GET |
| List sessions |
GET |
| Get session |
PATCH |
| End session (consolidates) |
POST |
| Distill a session into one summary memory |
GET |
| Projects with counts |
GET |
| AI clients with counts |
GET |
| Tags with counts |
GET |
| People across memories, by frequency |
GET |
| A person's profile + their memories |
GET |
| Memories grouped by day |
GET |
| Current context window |
POST |
| Generate CLAUDE.md / .cursorrules |
GET |
| System statistics |
GET |
| Server configuration |
GET |
| Health check |
POST |
| Run the recall-quality benchmark (hit@k / MRR) |
WS |
| Real-time event stream + RPC actions |
SSE |
| MCP SSE stream endpoint |
POST |
| Import from app |
GET |
| List connectors |
GET |
| Connector config help |
App Connectors
Import data from your existing tools directly into LEVH's memory layer. Every import can be namespaced under a project.
import_from_app("calendar", config={"ics_path": "/path/to/calendar.ics"}) # or ics_url
import_from_app("email", config={"mbox_path": "/path/to/mail.mbox"}) # or eml_path / eml_dir
import_from_app("transcript", config={"transcript_path": "/path/to/meeting.vtt"}) # or transcript_dir
import_from_app("notion", config={"api_key": "ntn_xxx", "database_ids": ["..."]})
import_from_app("obsidian", config={"vault_path": "/path/to/vault"})
import_from_app("github", config={"token": "ghp_xxx", "repos": ["owner/repo"]})
import_from_app("local_files", config={"directory": "/path/to/project"})Calendar, Email & Transcripts — the work-life capture trio (roadmap Phase 1): when/who + correspondence + what was said. All parse the universal offline export formats with zero extra dependencies, so no OAuth, no API keys, nothing leaves your machine:
Calendar (
.ics): the format Google Calendar, Outlook, and Apple Calendar all export. Each event → a memory with title, time, attendees, and location — so you can ask "what did I discuss with X last week?". Optionalpast_days/future_dayswindow.Email (
.mbox/.eml): Gmail Takeout, Thunderbird, Apple Mail, Outlook export. Each message → a memory with sender, recipients, subject, date, and a body excerpt — ask "what did Dana email me about pricing?". Options:past_days,max_messages,body_chars,exclude_senders(skip no-reply/notification noise).Transcripts (
.vtt/.srt/.txt): Zoom, Google Meet, Teams, Otter, Fireflies, or Whisper output. Each meeting → one summarized memory (LLM ifOPENAI_API_KEYis set, offline extractive otherwise) with the speaker list and a transcript excerpt — ask "what did we decide in the roadmap call?". Options:summarize,max_chars.
Or use the Import from Apps panel in the dashboard's Settings page.
Docker
docker compose up -d
# Dashboard + API: http://localhost:8000
# MCP SSE stream: http://localhost:8000/api/mcp/sseOne container, one port. The image builds the dashboard and serves it from the API.
Configuration
Runtime settings use one precedence order across CLI, API, MCP and generated client configs:
explicit CLI/API override > environment > .stackmemory/config.json > defaultslevh init and levh setup create .stackmemory/config.json.
Relative database paths in that file are resolved from the working directory.
LEVH does not load .env implicitly; export environment variables in
the process that launches it when environment overrides are required.
Variable | Default | Description |
|
| SQLite database path |
|
|
|
| — | Used only when |
|
| Local embedding model |
|
| Ollama server (mode |
|
| Ollama embedding model |
|
| Max short-term memories |
|
| Starting half-life for new memories |
|
| Similarity weight |
|
| Decay weight |
|
| Importance weight |
|
| Frequency weight |
|
| Stability growth per recall (higher = faster consolidation) |
|
| Cap on how durable a memory can become (1 year) |
|
| Stability multiplier on negative feedback |
|
| Similarity above which new memories weaken old ones (1.0 = off) |
|
| Stability multiplier applied to superseded memories |
|
| Auto-summarize a session's memories on |
|
| OpenAI chat model used for session summaries |
| — | Optional shared-secret gate on |
| localhost only | Comma-separated allowed browser origins ( |
|
| Failed token attempts allowed per rate-limit window, per client/process |
|
| Authenticated API requests allowed per window, per client/process |
|
| In-process rate-limit window; not a distributed quota system |
|
| SQLite lock wait before failing; file databases use WAL mode |
| DB sibling | Location for automatic pre-replace SQLite safety backups |
Security
LEVH binds to loopback by default. levh serve --host 0.0.0.0
(or any non-loopback host) is refused unless LEVH_TOKEN is set. The
Docker Compose default publishes only 127.0.0.1:8000; deployments that widen
the bind must set a strong token. CORS is not an authorization boundary.
The default REST, WebSocket, MCP store_memory, CLI capture, and connector
import paths pass through the deterministic admission gate before persistence.
Rejected/review candidates are not stored; secrets are redacted. An explicit
admit_memory(force=true) operation is the audited administrative override.
LEVH is designed as a local, single-user tool — no accounts, no multi-tenancy. Two lightweight controls harden the default local deployment:
CORS defaults to localhost origins, not
*— without this, any website open in your browser couldfetch()your entire memory store from a service running onlocalhost:8000. Widen it withLEVH_CORS_ORIGINSonly if you know what you're exposing.Optional shared-secret token (
LEVH_TOKEN) gates every/api/*route and the WebSocket behind anX-LEVH-Tokenheader (or?token=for the socket). When enabled, failed token attempts and authenticated API traffic are limited in-process. Unset by default so local use stays zero-config.
This is not per-user auth or a substitute for running behind your own reverse proxy if you expose the service beyond localhost.
SQLite file databases use WAL mode, a 5-second busy timeout, numbered
PRAGMA user_version migrations, and an FTS5 text index when the local SQLite
build supports it. Full-text search falls back to LIKE if FTS5 is unavailable.
Before restore --replace changes an existing file database, LEVH creates
a consistent online SQLite safety backup in a local safety-backups/ directory.
Evaluation & Dogfood (2.25)
Two offline tools for judging whether the memory system is actually working, distinct from the H(x,ψ) recall benchmark above.
levh eval run [--fixtures DIR] [--embedder-mode hash|local|...] [--output FILE]runs the golden-fixture evaluation (tests/fixtures/evaluation/*.json) through the real admission → store → trust → conflict → recall → review pipeline and writes a JSON report (defaulteval_report.json). Deterministic for a fixed fixture set + embedder mode.levh eval report [--output FILE]prints the last written report.levh dogfood statusprints the aggregate view of the local usage journal (event counts, time-to-first-value, recall-feedback rate, review distribution).levh dogfood export --output report.jsonis an explicit user action that writes the aggregate journal report to a file.
Live instrumentation (2.25.1) is opt-in: set
LEVH_DOGFOOD_ENABLED=true and every transport that uses the shared
engine (REST API / serve, MCP stdio, MCP SSE) journals coarse usage events
automatically — store, recall, briefing opened, meeting prep opened, trust
viewed, review keep/reinforce/weaken/forget, conflict confirm/dismiss, seed
demo completed. The journal is a plain JSONL file next to the SQLite database
(override with DOGFOOD_JOURNAL_PATH). With the flag unset (the default)
nothing is journaled at all.
Privacy rules, both tools:
Local-only, no network. Neither module performs any network I/O; the evaluation report and the dogfood journal are plain local files.
No default telemetry. Nothing is collected or sent anywhere unless the user explicitly sets
LEVH_DOGFOOD_ENABLED=true; there is no opt-out because there's no opt-in by default.No raw memory content. The evaluation report contains fixture keys, scenario names, labels, and numbers only. The dogfood journal accepts only a whitelisted set of event types and scalar attributes (ids, counts, labels) — content and query text are rejected at the API boundary, not filtered after the fact.
Export is explicit.
dogfood exportwrites aggregates, never raw event lines; you decide if and when a report leaves the machine.
Do not quote evaluation numbers (hit@1, hit@3, MRR, precision/recall, etc.)
from anything other than a real levh eval run against a known
fixture set — every report is tagged with its evaluation_version
(currently memory-eval-v1) so a number is only meaningful alongside the
fixture set that produced it.
Testing
pip install -e ".[dev]"
EMBEDDER_MODE=hash python -m pytest -q125 tests covering memory lifecycle, H(x,ψ) scoring, adaptive decay/reinforcement, outcome feedback, retroactive interference, fading review queue, forgetting curves, sessions, consolidation, export/import, concurrent operations, edge cases, session isolation, project namespacing, source tracking, pinning, recall correctness (no side effects on non-returned candidates), env-configurable weights, mixed embedding dimensions, v1 → v2 schema migration, dedupe, context file generation, related memories, session summarization, the recall-quality benchmark harness, and the REST API.
Benchmark recall quality directly with levh benchmark. Source-tree users
can also run python scripts/benchmark_recall.py; the runtime implementation is
packaged under server.core.benchmark so wheel installs do not depend on the
non-package scripts/ directory. Run with EMBEDDER_MODE=local, ollama, or
openai for a meaningful semantic signal; the default hash embedder is
non-semantic and intended for deterministic smoke checks.
Tech Stack
Component | Technology |
MCP Server | Python |
API | FastAPI + Uvicorn |
Database | SQLite via |
Embeddings | OpenAI / sentence-transformers / Ollama / hash |
Vector Search | NumPy cosine similarity |
Frontend | Next.js 14 (static export) + shadcn/ui + Recharts |
Container | Docker (single image: API + dashboard) |
License
GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later)
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ali-ulu/levh'
If you have feedback or need assistance with the MCP directory API, please join our Discord server