Skip to main content

Centralized memory system for AI development tools

Project description

mem-mesh

PyPI version CI Python 3.9+ License: MIT MCP Protocol

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_addpin_completepin_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 CRUDadd, 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 relationslink, unlink, get_links across 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 install is 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.
  • Linuxpysqlite3-binary wheel 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-binary manually 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:

  • Vectordragonkue/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_resume restores 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_end records a summary and closes the session. If the session terminates abnormally, the next session_resume automatically 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_progress pins older than 7 days → auto-completed
  • open pins 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:

  1. MEM_MESH_API_URL environment variable
  2. API_URL environment variable
  3. ~/.mem-mesh/api_url — single-line file with the server URL
  4. The URL baked into the hook at install time
  5. 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


Contributing

  1. Open an issue or pull request
  2. Follow black and ruff formatting
  3. Add tests for any new behavior

See CONTRIBUTING.md for details and CHANGELOG.md for release history.


License

MIT

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

mem_mesh-1.21.1.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mem_mesh-1.21.1-py3-none-any.whl (964.3 kB view details)

Uploaded Python 3

File details

Details for the file mem_mesh-1.21.1.tar.gz.

File metadata

  • Download URL: mem_mesh-1.21.1.tar.gz
  • Upload date:
  • Size: 1.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mem_mesh-1.21.1.tar.gz
Algorithm Hash digest
SHA256 ffa2bedf59fcc327a227285e964634a06a4438b71b9c7b8c0efe19950a269000
MD5 ddcc874ae0895bb9afeecc108d2da7d9
BLAKE2b-256 9ff1b512e303f24bb1b7fd8f7373622f6b8696d4f0f65e81ae2a0fecbd88eb54

See more details on using hashes here.

Provenance

The following attestation bundles were made for mem_mesh-1.21.1.tar.gz:

Publisher: release.yml on x-mesh/mem-mesh

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file mem_mesh-1.21.1-py3-none-any.whl.

File metadata

  • Download URL: mem_mesh-1.21.1-py3-none-any.whl
  • Upload date:
  • Size: 964.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for mem_mesh-1.21.1-py3-none-any.whl
Algorithm Hash digest
SHA256 d2981ee6fdc9a68a07492131c7db7137e5eed7699c40e4fbee55186f2f71ff0e
MD5 f7532b793290bc8703de9f42a24f7482
BLAKE2b-256 e1235c3128de8d3af72ee73de9e5a30a4893faed3875f3b64df86d00879f9deb

See more details on using hashes here.

Provenance

The following attestation bundles were made for mem_mesh-1.21.1-py3-none-any.whl:

Publisher: release.yml on x-mesh/mem-mesh

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page