Centralized memory system for AI development tools
Project description
mem-mesh
Persistent memory for AI agents — hybrid vector + FTS5 search, pin-based session tracking, and NLI conflict detection. Zero external dependencies.
한국어 · Quick Start · MCP Setup · MCP Tools · Session & Pins · Architecture · Docker · Contributing
Why mem-mesh?
Most MCP memory servers are glorified key-value stores. mem-mesh is built for how AI agents actually work — sessions with multiple steps, decisions that need to survive reboots, and cross-machine context that has to stay coherent.
| Differentiator | What it means |
|---|---|
| Pin lifecycle | Lightweight kanban inside every session: pin_add → pin_complete → pin_promote. No other MCP memory server has this. |
| Hybrid search | sqlite-vec vector embeddings + FTS5 full-text fused with Reciprocal Rank Fusion (RRF). Korean n-gram optimized out of the box. |
| NLI conflict detection | 2-stage pipeline: vector similarity pre-filter → mDeBERTa NLI model catches contradictory memories before they're stored. |
| 4-Tier Smart Expand | session_resume(expand="smart") uses an importance × status matrix to load only what matters — ~60% token savings. |
| Zero external services | Single SQLite file. pip install mem-mesh and you're running. No Postgres, no Redis, no cloud. |
| Dual MCP transport | stdio (Cursor, Claude Desktop, Kiro) + Streamable HTTP/SSE (MCP spec 2025-03-26). |
| 25+ client auto-detection | Identifies the calling IDE/AI platform from MCP handshake or User-Agent. |
| Batch operations | Pack multiple memory ops into one round-trip: 30–50% token savings. |
Features
- Memory CRUD —
add,search,context,update,delete - Hybrid search — sentence-transformers vectors + FTS5 RRF fusion, Korean n-gram support
- Session & pins — short-lived work tracking with importance-based promotion to permanent memory
- Memory relations —
link,unlink,get_linksacross 7 relation types - Conflict detection — mDeBERTa NLI prevents storing contradictory facts
- Batch operations — 30–50% fewer tokens per multi-op workflow
- Web dashboard — FastAPI REST API + real-time UI at
localhost:8000
Quick Start
Recommended: uvx (zero Python management)
One tool to install — uv — and mem-mesh handles the rest. No virtualenv, no pyenv tweaks, no sqlite-vec compile errors. Your MCP client spawns a cached, isolated mem-mesh on-demand.
# 1. Install uv (one-time, ~15 seconds)
curl -LsSf https://astral.sh/uv/install.sh | sh
# 2. Run the onboarding wizard — writes MCP config for detected tools,
# offers to install hooks, warms the uv cache.
uvx mem-mesh
That's it. Restart Cursor / Claude Desktop / Kiro and mem-mesh MCP tools are live.
uvx mem-mesh(bare) runs onboarding — no--from "mem-mesh[server]"needed, since the lightweight base package is all the wizard requires (it still writes config that runs the server via the[server]extra).uvx mem-mesh installis the explicit equivalent.
For agents / CI: uvx mem-mesh --json runs onboarding non-interactively and prints a single JSON result (per-step status + next_actions). Non-TTY invocations (pipes, agents) auto-run non-interactively even without --json. Onboarding writes the config single-source-of-truth — ~/.mem-mesh/api_url and ~/.mem-mesh/hook_token — which every tool's hooks read at runtime (reachable from GUI- and terminal-launched tools alike). The MEM_MESH_API_URL / MEM_MESH_HOOK_TOKEN env vars seed those files (and act as a per-session override; mem-mesh doctor flags any that shadow the files). The token must also stay exported for HTTP hooks / authenticated MCP, which read the shell env and have no file fallback. Example: MEM_MESH_API_URL=https://memory.example.com MEM_MESH_HOOK_TOKEN=… uvx mem-mesh --json.
Install or repair hooks directly through the same uvx entrypoint:
uvx mem-mesh hooks install --target codex
uvx mem-mesh hooks status
Want the web dashboard too? uvx --from "mem-mesh[server]" mem-mesh serve — open http://localhost:8000.
Alternative: pip install
If you prefer managing Python environments yourself:
pip install "mem-mesh[server]"
mem-mesh # onboarding wizard (or: mem-mesh install)
mem-mesh serve # web server + SSE MCP at localhost:8000
Prerequisites (only if NOT using uvx)
mem-mesh loads the sqlite-vec extension at runtime, so Python's sqlite3 module must support loadable extensions.
- uvx users — uv's managed Python builds already have extension loading enabled. Nothing to do.
- Linux —
pysqlite3-binarywheel installs automatically as a fallback. - macOS — system Python and Homebrew Python both work. Only pyenv's default build is broken.
- Windows — system Python works; install
pysqlite3-binarymanually if needed.
macOS + pyenv users who hit Migration failed: no such module: vec0:
# Option A: rebuild Python against Homebrew sqlite3
brew install sqlite3
SQLITE_PREFIX="$(brew --prefix sqlite3)"
PYTHON_CONFIGURE_OPTS="--enable-loadable-sqlite-extensions" \
LDFLAGS="-L${SQLITE_PREFIX}/lib" \
CPPFLAGS="-I${SQLITE_PREFIX}/include" \
CFLAGS="-I${SQLITE_PREFIX}/include" \
pyenv install 3.13 --force
pyenv rehash
# Option B (simplest): just use uvx — it bypasses system Python entirely
Linux distro Python, Docker images, and conda Python ship with extension loading enabled — no extra steps needed.
MCP Setup
mem-mesh install writes these entries for you automatically. The snippets below are what gets written, for reference.
uvx (recommended)
Zero Python-env management. The MCP client spawns a cached mem-mesh process per call; the first run downloads it, subsequent runs are instant.
{
"mcpServers": {
"mem-mesh": {
"command": "uvx",
"args": ["--from", "mem-mesh[server]", "mem-mesh-mcp-stdio"],
"env": { "MEM_MESH_CLIENT": "cursor" }
}
}
}
Stdio (local Python)
Use your own Python install. Good if you need -e . dev installs.
{
"mcpServers": {
"mem-mesh": {
"command": "python",
"args": ["-m", "app.mcp_stdio"],
"cwd": "/absolute/path/to/mem-mesh",
"env": { "MCP_LOG_LEVEL": "INFO" }
}
}
}
HTTP (streamable, shared running server)
For web clients or when multiple tools share one process. Requires mem-mesh serve running. Use "type": "http" — type: "sse" is legacy and hangs after a server restart.
{
"mcpServers": {
"mem-mesh": {
"url": "http://localhost:8000/mcp/sse",
"type": "http"
}
}
}
Config file locations by tool:
| Tool | Config file |
|---|---|
| Cursor | .cursor/mcp.json |
| Claude Desktop | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Kiro | ~/.kiro/settings/mcp.json |
Mode comparison
| uvx | Stdio | HTTP | |
|---|---|---|---|
| Prereq | uv only |
Python env with mem-mesh[server] |
Running mem-mesh serve |
| First call | ~15s (cache warm) | Instant | Instant |
| Server to manage | None | None | Yes |
| Dashboard | Optional (uvx … serve) |
Optional | Included |
| Hooks support | Requires separate server | Yes (local mode) | Yes (api mode) |
MCP Tools (15)
| Tool | Description | Key parameters |
|---|---|---|
add |
Store a memory | content, project_id, category, tags |
search |
Hybrid vector + FTS5 search | query, project_id, category, limit, recency_weight, response_format |
context |
Retrieve memories surrounding a given memory | memory_id, depth, project_id |
update |
Edit a memory | memory_id, content, category, tags |
delete |
Remove a memory | memory_id |
stats |
Usage statistics | project_id, start_date, end_date |
link |
Create a typed relation between memories | source_id, target_id, relation_type |
unlink |
Remove a relation | source_id, target_id |
get_links |
Query relations | memory_id, relation_type, direction |
pin_add |
Add a short-lived work-tracking pin | content, project_id, importance, tags |
pin_complete |
Mark a pin done; optionally promote to permanent memory | pin_id, promote, category |
pin_promote |
Promote an already-completed pin to permanent memory | pin_id, category |
session_resume |
Restore context from the previous session | project_id, expand, limit |
session_end |
Close a session with a summary | project_id, summary, auto_complete_pins |
batch_operations |
Execute multiple ops in one call | operations (array of add/search/pin_add/pin_complete) |
search response formats: minimal | compact | standard | full
Search
mem-mesh runs two retrieval engines in parallel and merges results with Reciprocal Rank Fusion:
- Vector —
dragonkue/snowflake-arctic-embed-l-v2.0-ko(1024-dim, Korean retrieval SOTA, MTEB-ko #1) by default; KURE, E5 and MiniLM models supported - FTS5 — SQLite full-text search with n-gram tokenization for CJK languages
- RRF fusion — balances semantic similarity and keyword precision
- Quality filters — noise removal, intent analysis, vector pre-filter overfetch to improve recall
Session & Pins
Session lifecycle
session_resume(project_id, expand="smart") → work → session_end(project_id, summary)
session_resumerestores incomplete pins and context from the previous session. Stale pins are auto-closed.expand="smart"applies an importance × status matrix that cuts token usage by ~60%.session_endrecords a summary and closes the session. If the session terminates abnormally, the nextsession_resumeautomatically recovers open pins.
Pin lifecycle
Pins are the unit of work inside a session. Track code changes, implementations, and configuration work as pins — not in permanent memory.
pin_add(content, project_id) → do the work → pin_complete(pin_id, promote=True)
# promote=True completes and promotes in one call
Status flow: open (planned, not started) → in_progress (active; default on pin_add) → completed
Multi-step work can pre-register later steps as open pins, then activate them one at a time.
Auto-stale cleanup (triggered on session_resume):
in_progresspins older than 7 days → auto-completedopenpins older than 30 days → auto-completed
When to pin: only when files change. Questions, explanations, and read-only lookups do not need pins. Multi-step tasks get one pin per step.
Importance levels:
| Level | Use for |
|---|---|
5 |
Architecture decisions, core design changes |
3–4 |
Feature implementations, significant fixes |
1–2 |
Minor edits, typo fixes |
| omit | Auto-inferred from content |
Promote: pin_complete(pin_id, promote=True) completes and promotes to permanent memory in one call. To promote after the fact: pin_promote(pin_id).
Client detection: In HTTP mode, the calling client is identified from the MCP initialize handshake or User-Agent header (25+ IDE/AI platforms supported). In stdio mode, set MEM_MESH_CLIENT in the environment.
AI agent checklist
1. Session start → session_resume(project_id, expand="smart")
2. Past context → search() before coding if referencing previous decisions
3. Track work → pin_add → pin_complete (promote=True to merge into memory)
4. Permanent store → decision / bug / incident / idea / code_snippet only
5. Session end → session_end(project_id, summary, auto_complete_pins=True)
6. Never store → API keys / tokens / passwords / PII
Principle: Hooks are read-only signals. All pin creation, completion, and promotion decisions are made by the LLM with full context.
Memory Relations
Seven relation types: related | parent | child | supersedes | references | depends_on | similar
get_links direction: outgoing | incoming | both
Configuration
| Variable | Description | Default |
|---|---|---|
MEM_MESH_DATABASE_PATH |
SQLite database path | XDG per-user path (see app/core/config.py _default_db_path) |
MEM_MESH_EMBEDDING_MODEL |
Embedding model name | dragonkue/snowflake-arctic-embed-l-v2.0-ko |
MEM_MESH_EMBEDDING_DIM |
Vector dimensions | 1024 |
MEM_MESH_SERVER_PORT |
Web server port | 8000 |
MEM_MESH_SEARCH_THRESHOLD |
Minimum similarity score | 0.5 |
MEM_MESH_USE_UNIFIED_SEARCH |
Enable hybrid search | true |
MEM_MESH_ENABLE_KOREAN_OPTIMIZATION |
Korean n-gram FTS | true |
MEM_MESH_LOG_LEVEL |
Server log level | INFO |
MEM_MESH_LOG_FILE |
Log output file | (none) |
See .env.example for the full list.
Pointing hooks at a remote mem-mesh server
Bash hooks (Stop, SessionStart, SubagentStop, …) resolve the API URL in this order:
MEM_MESH_API_URLenvironment variableAPI_URLenvironment variable~/.mem-mesh/api_url— single-line file with the server URL- The URL baked into the hook at install time
http://localhost:8000
Use the config file when you want one installed hook bundle to talk to a remote server (e.g. https://mem.example.com) without editing settings.json and without relying on env-var inheritance — Claude Code does not export settings.json.env retroactively to already-running sessions, so an env var added mid-session won't reach hooks until you restart.
mkdir -p ~/.mem-mesh
echo 'https://mem.example.com' > ~/.mem-mesh/api_url
mem-mesh doctor # confirms the resolved URL and its source
Per machine — the file is not synced. Delete it (or set MEM_MESH_API_URL) to fall back to the baked default.
Web Dashboard
- Dashboard: http://localhost:8000
- API docs (Swagger): http://localhost:8000/docs
- Health check: http://localhost:8000/health
Architecture
flowchart LR
subgraph Clients
Cursor[Cursor]
Claude[Claude Desktop]
Kiro[Kiro]
Web[Web Client]
end
subgraph Transport
Stdio[Stdio MCP]
SSE[SSE / Streamable HTTP]
end
subgraph Core
MCP[mcp_common]
Storage[Storage Service]
end
subgraph Data
SQLite[(SQLite + sqlite-vec + FTS5)]
end
Cursor --> Stdio
Claude --> Stdio
Kiro --> Stdio
Web --> SSE
Stdio --> MCP
SSE --> MCP
MCP --> Storage
Storage --> SQLite
Directory structure
mem-mesh/
├── app/
│ ├── core/ # DB, embeddings, services, schemas
│ ├── mcp_common/ # Shared MCP tools, dispatcher, batch
│ ├── mcp_stdio/ # FastMCP stdio server
│ ├── mcp_stdio_pure/ # Pure MCP stdio server
│ └── web/ # FastAPI (dashboard, SSE MCP, OAuth, WebSocket)
├── static/ # Frontend (Vanilla JS, Web Components)
├── tests/ # pytest
├── scripts/ # Migration and benchmark scripts
├── docs/rules/ # AI agent rule modules
├── data/ # memories.db
└── logs/
Docker
# Build and start
make quickstart
# or step by step:
make docker-build && make docker-up
# Open http://localhost:8000
First-run setup (dashboard auth)
When the server starts with no dashboard auth configured, anyone who can reach the port can read/write/delete all memories. To let you close this from the browser (no shell-only config), mem-mesh mints a one-time setup token on first boot and prints it to the server console:
============================================================
FIRST-RUN SETUP — dashboard auth is NOT configured
============================================================
Open : /setup
Token: <one-time-token>
(one-time — consumed the moment you finish setup)
============================================================
Open shows the bare path /setup by default — open it on whatever host:port you bound the server to. Set MEM_MESH_PUBLIC_URL to have the banner print a full URL (e.g. https://your-host/setup).
The token is also written next to the DB (/app/data/setup_token), so it survives a mid-onboarding restart. Retrieve it any time:
docker exec mem-mesh-prod cat /app/data/setup_token
# or scan the logs
docker compose logs mem-mesh | grep -A1 "Token:"
Open /setup, enter the token plus an admin username (default admin) and password (≥ 8 chars). On submit mem-mesh saves the credential, enables Basic Auth, consumes the token (single-use), and logs you straight into the dashboard. On a fresh server the first page load auto-redirects to /setup.
Once auth is configured the token is deleted on every startup, so a leftover token can never reconfigure an already-secured server.
Reset the token (lost it, and auth is not configured yet) — delete the file and restart; ensure_setup_token() is idempotent, so a plain restart keeps the same value:
docker exec mem-mesh-prod rm -f /app/data/setup_token
docker restart mem-mesh-prod
docker logs mem-mesh-prod 2>&1 | grep -A1 "Token:"
Development
# Install dev dependencies
pip install -e ".[dev]"
# Run tests
python -m pytest tests/ -v
# Format and lint
black app/ tests/
ruff check app/ tests/
# Check embedding migration status
python scripts/migrate_embeddings.py --check-only
Documentation
- CLAUDE.md — AI tool checklist (MUST/SHOULD/MAY rules, security policy)
- AGENTS.md — Project context, Golden Rules, Context Map, session management details
AI agent rules
| File | Purpose |
|---|---|
| DEFAULT_PROMPT.md | Standalone behavior rules for projects without installed hooks |
| modules/ | Optional Rule Manager modules: core, search, memory-log, pins, relations, batch, security |
Generated hook rules share the installed hook prompt version:
mem-mesh hooks rules --project-id <project-id> --format plain
mem-mesh hooks rules --project-id <project-id> --format claude
Architecture docs
- app/core/AGENTS.md — Core service internals
- app/mcp_common/AGENTS.md — MCP common layer
Contributing
- Open an issue or pull request
- Follow
blackandruffformatting - Add tests for any new behavior
See CONTRIBUTING.md for details and CHANGELOG.md for release history.
License
Project details
Release history Release notifications | RSS feed
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 mem_mesh-1.24.0.tar.gz.
File metadata
- Download URL: mem_mesh-1.24.0.tar.gz
- Upload date:
- Size: 1.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01f4b43b192bbd5da2e105449191ab178b3fde3303a2a38eff78dd6aace059f0
|
|
| MD5 |
ac858b713f15f21541adeefb4daa54b0
|
|
| BLAKE2b-256 |
f369cfa35ace047494f246db1faefc6705e7b1da5f92e3ea7a9950387c6f7639
|
Provenance
The following attestation bundles were made for mem_mesh-1.24.0.tar.gz:
Publisher:
release.yml on x-mesh/mem-mesh
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mem_mesh-1.24.0.tar.gz -
Subject digest:
01f4b43b192bbd5da2e105449191ab178b3fde3303a2a38eff78dd6aace059f0 - Sigstore transparency entry: 2043455823
- Sigstore integration time:
-
Permalink:
x-mesh/mem-mesh@80dbb01c2c3a39237127fc363f7c512381fd90c4 -
Branch / Tag:
refs/tags/v1.24.0 - Owner: https://github.com/x-mesh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@80dbb01c2c3a39237127fc363f7c512381fd90c4 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mem_mesh-1.24.0-py3-none-any.whl.
File metadata
- Download URL: mem_mesh-1.24.0-py3-none-any.whl
- Upload date:
- Size: 1.0 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3f69059438934b2e28e2716fa73fd1d8d735136d5fb258dda36ba4d887a3dfc
|
|
| MD5 |
f527d58b83643022568d18b106cf9bbc
|
|
| BLAKE2b-256 |
10b399e260a829f011a70c69c87010a859efdbae3b53c022d0197fa35bdf1743
|
Provenance
The following attestation bundles were made for mem_mesh-1.24.0-py3-none-any.whl:
Publisher:
release.yml on x-mesh/mem-mesh
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mem_mesh-1.24.0-py3-none-any.whl -
Subject digest:
f3f69059438934b2e28e2716fa73fd1d8d735136d5fb258dda36ba4d887a3dfc - Sigstore transparency entry: 2043455846
- Sigstore integration time:
-
Permalink:
x-mesh/mem-mesh@80dbb01c2c3a39237127fc363f7c512381fd90c4 -
Branch / Tag:
refs/tags/v1.24.0 - Owner: https://github.com/x-mesh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@80dbb01c2c3a39237127fc363f7c512381fd90c4 -
Trigger Event:
push
-
Statement type: