Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
Your own AI agent, running 24/7 with QwikClaw logoYour own AI agent, running 24/7 with QwikClaw

QwikClaw sets up and runs an always-on OpenClaw agent for you. One click, no config files, no server setup.

Deploy now
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 47,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

Universal MCP Server with advanced AI memory capabilities and semantic search.

README.md

<div align="center"> <picture> <img src="https://raw.githubusercontent.com/Lyellr88/marm-memory/MARM-main/assets/marm-logo.png" alt="marm-memory - persistent local memory server for AI agents (Model Context Protocol)" width="900" height="250"> </picture> <h1 align="center">Give your AI Agents a permanent memory in 60 seconds.</h1>

![License](https://github.com/Lyellr88/marm-memory/blob/MARM-main/LICENSE) ![Python](https://www.python.org/) ![FastAPI](https://fastapi.tiangolo.com/) ![Docker Pulls](https://hub.docker.com/r/lyellr88/marm-mcp-server) ![PyPI Downloads](https://pepy.tech/projects/marm-mcp-server) ![PyPI Version](https://pypi.org/project/marm-mcp-server/) ![MCP Registry](https://registry.modelcontextprotocol.io/?q=marm-mcp)

![Discord](https://discord.gg/nhyJWPz2cf) ![Publish](https://github.com/Lyellr88/marm-memory/actions/workflows/publish-mcp.yml) ![CodeQL](https://github.com/Lyellr88/marm-memory/security/code-scanning) ![marm-memory MCP server](https://glama.ai/mcp/servers/Lyellr88/marm-memory)

Contributions welcome! Browse open issues to contribute, or join the MARM Discord to share workflows, get setup help, and connect with other builders.

</div>

Table of Contents

Quick Start

  1. Install and initialize with your preferred agent profiles:
pip install marm-mcp-server
marm-memory init --g-claude --g-codex --g-gemini

Also available: --g-qwen and --g-kiro. Run without flags to install into your current project folder instead of home

  1. Hand off to your AI companion. Tell your agent:

"Use the marm-init skill to set up MARM."

  1. Interact: Your agent will handle the entire setup (Python/Docker, HTTP/STDIO, keys, and client configs) interactively right inside your chat.

Manual setup

Prefer to wire it up yourself:

Replace "agent" with your client’s CLI command (for example, claude, gemini, or qwen). For Codex, use codex mcp add marm-memory --url http://localhost:8001/mcp instead.

| If you are... | Start the server | Connect your MCP client | | --------------- | ------------------ | ------------------------- | | Solo developer / researcher | marm-memory start | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp | | Private local STDIO user | marm-mcp-stdio | "agent" mcp add --transport stdio marm-memory-stdio marm-mcp-stdio | | Multiple agents sharing memory | marm-memory start --profile swarm | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp | | Private high-throughput swarm | marm-memory start --profile swarm-max | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp | | Trusted private lab/server | marm-memory start --profile trusted | "agent" mcp add --transport http marm-memory http://localhost:8001/mcp |

  • ⚡ Fastest HTTP Startup: Run marm-memory fast-start-http to spin up the local runtime, launch the console, and open it in your browser immediately.
  • 🖥️ Web Console: Run marm-memory console to view the local UI app instantly (no Node.js required).
  • ⚙️ Lifecycle Management: Manage the background daemon using status, logs --follow, restart, and stop.
  • 💡 Quick Flags: Use --no-console or --no-browser to restrict startups. Run marm-memory --help for full command lists.

Why MARM Memory

Your AI forgets everything. MARM Memory doesn't.

marm-memory gives your agents a private, shared memory for the context that normally gets lost between chats: decisions, research, fixes, notes, and project history. Switch from Claude Code to Codex or Gemini without losing the context already gathered.

It brings three things together:

  • 🧠 Core Memory (7 tools) stores conversations, notes, notebook entries, and summaries so they stay searchable.
  • 💻 Code Graph (5 tools) maps your repository so agents can find symbols, follow code paths, and understand the project without rereading it all.
  • 🧩 Concept Graph (2 tools) connects people, decisions, errors, and ideas from your stored memories, with links back to relevant code when available.

All 14 tools work over HTTP and STDIO. Your agents share the same local memory across sessions instead of starting from scratch each time. The built-in Console lets you see and manage what is saved.

How It Works

| Layer | What it does | Why it matters | | ------- | -------------- | ---------------- | | Memory model | Sessions, structured logs, notebooks, summaries, and semantic memories | Keeps project history searchable instead of trapped in one chat | | Scale layer | SQLite WAL mode, connection pooling, serialized write queue, and HTTP rate-limit presets | Lets one server support solo use, multi-agent work, and swarm-style bursts | | Intelligence layer | FTS filter, semantic re-rank, bounded semantic fallback, auto-classification, write-time consolidation, and compaction candidates | Keeps recall useful as memory grows instead of letting duplicates pile up | | Code graph layer | Repo indexing, symbol lookup, call tracing, architecture overview, and change-impact analysis | Gives agents project structure without rereading the whole codebase | | Concept graph layer | Entity and relationship extraction from stored memories, with links back into the code graph | Connects decisions, errors, tools, and people across sessions instead of leaving them as flat text | | Token layer | Lightweight 7-tool core surface (14 total with bundled graph tools), semantic re-rank before retrieval, and write-time deduplication | Reduces tokens sent to the model on every recall and cost stays predictable as memory scales | | Deployment layer | Pip, Docker, STDIO, HTTP, and managed swarm, swarm-max, and trusted profiles | Lets you run private local memory or shared multi-agent memory with the same MCP surface |

See Performance & Scaling Benchmarks for retrieval latency, concurrency, and write-cost numbers, and Architecture & Internals for the mechanisms behind each layer.

Runtime CLI Commands

marm-memory is the local runtime manager installed with the Python package. These are the normal operational commands; use marm-memory <command> --help for flags and command-specific examples.

Daily runtime work

marm-memory fast-start-http                # start HTTP, Console, and open the browser
marm-memory start                          # start or reuse the managed HTTP runtime
marm-memory start --profile swarm          # shared multi-agent preset
marm-memory stop                           # stop the managed runtime safely
marm-memory restart                        # restart the managed runtime
marm-memory status                         # inspect runtime, database, queue, and graph status
marm-memory logs --follow                  # follow bounded runtime logs
marm-memory console                        # start or reuse the bundled local Console

Transports and setup

marm-memory http                           # run HTTP in the foreground
marm-memory stdio                          # run the strict local MCP STDIO transport
marm-memory init                           # install the MARM skill into detected agents (project scan)
marm-memory init --g-claude                # install the skill into the home-folder claude directory
marm-memory doctor                         # diagnose the local install
marm-memory key init                       # create or reuse ~/.marm/.env without displaying the key
marm-memory key path                       # print the managed key-file path
marm-memory key reveal                     # explicitly display the managed key
marm-memory console --import-key           # open an authenticated local Console session
marm-memory upgrade --check                # compare the installed package with PyPI
marm-memory uninstall                      # preview package removal; always preserves ~/.marm

Knowledge, projects, and maintenance

marm-memory knowledge status               # Check available indexers and models
marm-memory knowledge build --all          # Build the concept graph from stored memories
marm-memory projects list                  # List all tracked workspaces
marm-memory projects index <path>          # Run deep codebase structural indexing
marm-memory projects status                # Inspect target repo graph readiness
marm-memory maintenance status             # Check internal database optimization state
marm-memory maintenance embeddings migrate # Upgrade old 384-dim vectors to 512-dim
marm-memory maintenance chunks rechunk     # Recalibrate long memory text splits

Docker commands are documented separately below because they require explicit data mounts, network exposure, and key-handling choices.

Performance & Scaling Benchmarks

MARM is tuned for fast recall first, even as memory grows and long memories are chunked behind the scenes.

These measurements use the fastembed-backed jinaai/jina-embeddings-v2-small-en encoder and a throwaway local SQLite database. Every timed path calls the shipped MARMMemory code, not a benchmark-local reimplementation. Sections 1-4 are timings from a single run of scripts/benchmarking/performance/bench_hotpath.py on local hardware; absolute milliseconds vary by machine, so treat the scaling shape as the signal. Section 5 is a separate accuracy benchmark (run_eval.py) and reports two runs, for the reason given there.

1. Retrieval Latency Scaling

End-to-end recall_similar latency (includes query encoding).

| Session Size ($N$) | Min Latency | Median Latency | p95 Latency | | :--- | :--- | :--- | :--- | | N = 100 | 7.4 ms | 7.9 ms | 9.4 ms | | N = 250 | 11.9 ms | 13.5 ms | 15.4 ms | | N = 500 | 10.9 ms | 11.8 ms | 13.4 ms | | N = 1,000 | 13.3 ms | 13.5 ms | 15.6 ms | | N = 2,000 | 17.5 ms | 18.2 ms | 19.6 ms | | N = 4,000 | 23.8 ms | 25.9 ms | 30.9 ms |

Run-to-run variance at small $N$ is larger than the gap between adjacent sizes, which is why N = 250 reads slower than N = 500 here. Treat the trend from N = 1,000 upward as the real signal.

2. Encoder + Concurrency

  • Cold model load: 893ms
  • Warm encode: median 3.8ms, p95 4.3ms
  • Concurrent recall: 10 gathered recalls completed in 151.5ms vs 176.0ms serial (gather/serial = 0.86). Do not read that as parallelism: repeated runs of this same benchmark land anywhere from 0.63 to 0.86, so the ratio is not stable enough to claim a speedup. The path is serialized around shared encoder and SQLite work by design, and any apparent gain is measurement noise.

3. Write-Time Ingestion Cost

  • Consolidation off: median 6.5ms, p95 7.6ms
  • Consolidation on: median 58.1ms, p95 106.5ms
  • Tradeoff: write-time dedupe/clustering adds 9.0x median cost so recall stays fast and the store stays cleaner over time. Consolidation is off by default.

4. Recall Scaling: Full Scan vs Production Hybrid

Why recall stays flat as memory grows: Instead of scanning every vector, production recall uses an FTS keyword pre-filter to narrow the candidate pool, then re-ranks using a blended semantic + BM25 + temporal score. Both benchmark columns represent authentic asynchronous code paths timed with precomputed vectors to isolate retrieval speed from raw encoding overhead. Tests alternate execution to ensure completely unbiased cache conditions.

| Session Size ($N$) | Full Semantic Scan | Production Hybrid | Speedup | FTS candidates | | :--- | :--- | :--- | :--- | :--- | | N = 100 | 3.3 ms | 6.6 ms | 0.5x | 85 / 200 | | N = 500 | 16.3 ms | 11.6 ms | 1.4x | 200 / 200 | | N = 1,000 | 31.1 ms | 14.7 ms | 2.1x | 200 / 200 | | N = 2,000 | 63.5 ms | 19.0 ms | 3.3x | 200 / 200 | | N = 4,000 | 127.2 ms | 29.1 ms | 4.4x | 200 / 200 | | N = 10,000 | 316.7 ms | 53.8 ms | 5.9x | 200 / 200 |

The full scan grows roughly linearly with $N$ while hybrid recall grows far more slowly, so the advantage still widens with session size. At very small $N$ the pre-filter is not worth its overhead and hybrid is slower.

5. LoCoMo Retrieval Accuracy

All 10 LoCoMo conversations are ingested through marm_log_entry (5,882 memories), then top-5 marm_smart_recall results are scored against 1,977 evidence-annotated questions. No answer-generation model or LLM judge is used.

| Configuration | Any evidence hit | All evidence hit | Mean evidence recall | | :--- | :--- | :--- | :--- | | MiniLM baseline | 37.5% | 29.5% | not published | | Jina v2 Small (v2.29.0) | 53.0% | 43.4% | 47.6% | | Recent (v2.33.1) | 62.9 - 63.5% | 53.1 - 53.5% | 57.4 - 57.9% |

Performance gains are isolated to the blended retrieval pipeline and localized vector space, ensuring high multi-hop recall accuracy without relying on cloud-hosted LLM judges. Reproduce the full benchmark using scripts/benchmarking/accuracy/locomo/run_eval.py.

6. vs Competitors: Architecture

MARM targets a specific niche: local-first memory for MCP-connected coding agents, not general personalization memory or a full agent runtime. Here's how it differs architecturally from established names in AI agent memory:

| | MARM | Mem0 | Letta (MemGPT) | Zep / Graphiti | agentmemory | | --- | --- | --- | --- | --- | --- | | Type | Memory engine, MCP-native | Memory layer API | Full agent runtime | Temporal knowledge graph | Memory engine, MCP-native | | Required infrastructure | No separate data service (embedded SQLite) | Vector DB (Qdrant/pgvector) | Postgres + vector DB | Neo4j | Separate iii-engine runtime | | Deployment | Local-first by default; Docker for shared/remote | Cloud API or self-hosted | Self-hosted or cloud | Cloud or self-hosted | Local-first | | Retrieval model | Hybrid: FTS5 BM25 exact lane + semantic rerank | Vector + graph + key-value | Vector archival store + agent-managed core memory | Temporal knowledge graph (fact validity windows) | BM25 + vector + graph (RRF fusion) | | Write capture | Explicit tool calls from the connected agent | Explicit add() calls (some integrations auto-extract) | Agent self-edits its own memory | Explicit API calls | Hook-based, automatic (no explicit calls needed) | | Code structure awareness | Bundled code graph + concept graph, fused with memory | Not built in | Not built in | Not built in | Not built in (pairs with a separate project) | | Framework lock-in | None (any MCP client) | None | High (must run within Letta) | None | None (any MCP client) |

Disclaimers & Accuracy: Competitor landscapes evolve rapidly. The matrix above reflects core architectural traits as of Q3 2026, based on public documentation and READMEs, not internal testing of each system. If any data point regarding an alternative framework has changed or is misrepresented, please open an issue or submit a Pull Request to update the table. We actively welcome corrections from peer maintainers.

MCP Client Setup for HTTP & STDIO

Manual pip install

pip install marm-mcp-server

Use this quick rule of thumb to choose your setup

  • Local HTTP/STDIO = fastest single-machine setup.
  • Docker HTTP = shared/always-on server (key required).
  • Docker STDIO = private containerized local use (no HTTP key).

Swarm / multi-agent note: The write queue is enabled by default to serialize memory writes through one worker. For shared HTTP deployments, use marm-memory start --profile swarm (200 RPM) or --profile swarm-max (600 RPM). --profile trusted disables rate limiting entirely for private deployments. STDIO is still best for private single-agent/local use. See Swarm & multi-agent presets for the full table.

<details> <summary><strong>Local pip HTTP </strong></summary>

"agent" refers to claude, gemini, grok, qwen, or any MCP client. Codex uses --url instead of --transport to add MCP tools.

pip install marm-mcp-server
marm-memory start
# Stuck on client setup? Open a Q&A thread: https://github.com/Lyellr88/marm-memory/discussions
# most agents use this --transport command
"agent" mcp add --transport http marm-memory http://localhost:8001/mcp
codex mcp add marm-memory --url http://localhost:8001/mcp

Default pip/local startup is zero-config: MARM binds to localhost and does not require a key unless you expose it with SERVER_HOST=0.0.0.0.

</details>

<details> <summary><strong>Local pip STDIO</strong></summary>

pip install marm-mcp-server
python -m marm_mcp_server.server_stdio
# most agents use this --transport command
"agent" mcp add --transport stdio marm-memory-stdio marm-mcp-stdio
codex mcp add marm-memory-stdio -- marm-mcp-stdio

Replace marm-mcp-stdio with python -m marm_mcp_server.server_stdio if using a virtualenv or a path-based setup. Works with Claude Code, Cursor, VS Code, Qwen, and Gemini CLI. STDIO stays a single local process with no port and no API key, and exposes the same 14 tools as HTTP.

</details>

<details> <summary><strong>Local Python swarm modes (HTTP & STDIO)</strong></summary>

Use HTTP when multiple agents need to share one live MARM server. STDIO is still best for private single-agent use because each client owns its own local process.

# HTTP shared server, normal multi-agent use
marm-memory start --profile swarm

# HTTP shared server, heavier private swarm
marm-memory start --profile swarm-max

# HTTP trusted private lab/server, rate limiting disabled
marm-memory start --profile trusted

# STDIO remains keyless/private and does not use swarm flags
marm-mcp-stdio

</details>

---

<details> <summary><strong>Docker HTTP (key required)</strong></summary>

Docker HTTP requires an API key because it exposes MARM as a network server; STDIO stays local to the client process and does not need one.

If you installed MARM through pip, the product CLI can safely preview or run the same setup. It uses a loopback port by default, preserves ~/.marm, stores the generated key in ~/.marm/.env rather than shell history, and refuses to replace an existing container.

marm-memory docker command                 # preview the exact HTTP command
marm-memory docker run                     # create the managed HTTP container
marm-memory docker stdio-command           # print a Docker STDIO client command
marm-memory docker status
marm-memory docker logs --follow
marm-memory docker stop

# Optional: mount repositories read-only for code indexing.
marm-memory docker run --repo /absolute/path/to/repository

# Optional: preview or explicitly write a Compose configuration.
marm-memory docker compose
marm-memory docker compose --yes

The HTTP run, command, and compose commands accept the same operational flags:

| Flag | Purpose | | --- | --- | | --data-dir <absolute path> | Persistent host directory mounted at /home/marm/.marm. Defaults to ~/.marm; this holds memory, indexes, logs, and the managed key file. | | --env-file <path> | Explicit Docker env file. It must already contain MARM_API_KEY; without this flag, MARM uses ~/.marm/.env and creates a key there only when docker run or docker compose --yes needs one. | | --port <number> | Host HTTP port. Default: 8001. | | --expose-network | Bind the host port to 0.0.0.0 instead of loopback. This is deliberate network exposure; configure a firewall and TLS proxy. | | --profile standard\|swarm\|swarm-max\|trusted | Select the same write-queue and rate-limit preset as native HTTP startup. | | --rate-limit-rpm <number> | Override the selected profile's HTTP rate limit. 0 disables rate limiting. | | --repo <absolute path> | Repeatable read-only repository mount for code indexing. MARM reports each corresponding /workspace/repo-N path to index inside the container. | | --tag <tag> | Official image tag. Default: latest. | | --pull | Pull the selected image before creating a new HTTP container. | | --name <name> | Managed container name. MARM refuses to replace an existing container with that name. | | --memory <limit> / --cpus <limit> | Optional Docker resource limits. | | --dry-run | docker run only: print the planned command without creating a container or key file. docker command is always a preview. |

For example:

# Shared local server with a custom data path and two repositories for indexing.
marm-memory docker command \
  --profile swarm \
  --data-dir /srv/marm-data \
  --repo /srv/projects/api \
  --repo /srv/projects/web

# Execute the reviewed command, pulling the image first.
marm-memory docker run --profile swarm --data-dir /srv/marm-data --pull

Docker STDIO is separate from Docker HTTP: marm-memory docker stdio-command uses docker run -i --rm, has no port and no bearer key, but still mounts the data directory so SQLite memory persists after the short-lived container exits. Use --data-dir and --tag with that command when needed. There are no separate docker key or docker mount commands; --env-file and --data-dir make those choices explicit in the generated HTTP command.

marm-memory docker pull only downloads an image. marm-memory docker maintenance embeddings migrate runs against the same data mount and refuses while the managed HTTP container is running. The helper is available only with the pip-installed marm-memory command; Docker-only users can use the raw commands below.

# Step 1: generate key (do not add < > around the key)
docker run --rm lyellr88/marm-mcp-server:latest --generate-key

# Step 2: run server
docker pull lyellr88/marm-mcp-server:latest
docker run -d --name marm-mcp-server \
  -p 127.0.0.1:8001:8001 \
  -e SERVER_HOST=0.0.0.0 \
  -e MARM_API_KEY=your-generated-key \
  -v ~/.marm:/home/marm/.marm \
  lyellr88/marm-mcp-server:latest

# Step 3: connect client
"agent" mcp add --transport http marm-memory http://localhost:8001/mcp --header "Authorization: Bearer your-generated-key"

# PowerShell: set this before starting/restarting Codex
$env:MARM_API_KEY="your-generated-key"
codex mcp add marm-memory --url http://localhost:8001/mcp --bearer-token-env-var MARM_API_KEY

# Quick auth smoke test
curl -i -H "Authorization: Bearer $env:MARM_API_KEY" http://127.0.0.1:8001/mcp

--bearer-token-env-var takes the environment variable name, not the raw key. Start or restart Codex from the same shell after setting $env:MARM_API_KEY. For local Docker smoke tests, MARM_API_KEY=test is fine and avoids shell escaping problems; use a generated key for real deployments. A 406 Not Acceptable from the smoke-test GET /mcp means auth reached the MCP endpoint; 401 Unauthorized means the key is missing or mismatched.

</details>

<details> <summary><strong>Docker HTTP swarm mode</strong></summary>

# --swarm: write queue on, 200 RPM - recommended for multi-agent shared servers
docker run -d --name marm-mcp-server \
  -p 127.0.0.1:8001:8001 \
  -e SERVER_HOST=0.0.0.0 \
  -e MARM_API_KEY=your-generated-key \
  -v ~/.marm:/home/marm/.marm \
  lyellr88/marm-mcp-server:latest --swarm

</details>

<details> <summary><strong>Docker graph indexing: mount the repo</strong></summary>

Docker graph tools run inside the container, so they cannot see host paths unless you mount them at docker run.

$env:MARM_API_KEY="test"

# The second -v line mounts your repo; adjust the host path to your project
docker run -d --name marm-mcp-server `
  -p 127.0.0.1:8001:8001 `
  -e SERVER_HOST=0.0.0.0 `
  -e MARM_API_KEY=$env:MARM_API_KEY `
  -v ~/.marm:/home/marm/.marm `
  -v C:\Users\lyell\Desktop\marm-memory:/workspace/marm-memory `
  lyellr88/marm-mcp-server:latest

Then index the container path, not the Windows host path:

marm_graph_index(repo_path="/workspace/marm-memory")

Graph tools must use the container path. Mounts cannot be added to an already-running container; stop and restart the container with the repo mount when you want Docker graph indexing.

</details>

<details> <summary><strong>Docker STDIO (no HTTP key)</strong></summary>

Docker STDIO includes the same built-in marm-graph tools; no extra image or install step is required.

docker run --rm -i \
  -v ~/.marm:/home/marm/.marm \
  --entrypoint python \
  lyellr88/marm-mcp-server:latest \
  -m marm_mcp_server.server_stdio

</details>

---

<details> <summary><strong>Support notes</strong></summary>

  • Docker HTTP requires a key; Docker STDIO does not.
  • If you get 401, verify key match and client restart after env var changes.
  • For full key setup, rotation, and troubleshooting: INSTALL-DOCKER.md

</details>

Connect your client

Start the server (python -m marm_mcp_server), then wire up your client below. Every block assumes the default local install (no key). For Docker or exposed servers, add the Authorization: Bearer header shown in each client's collapsible.

<details> <summary><strong>Claude Code</strong></summary>

claude mcp add --transport http marm-memory http://localhost:8001/mcp

Claude Code supports HTTP, SSE, and STDIO through claude mcp add; use HTTP for MARM. For STDIO: claude mcp add --transport stdio marm-memory-stdio marm-mcp-stdio.

</details>

<details> <summary><strong>VS Code / GitHub Copilot Agent</strong></summary>

Add to .vscode/mcp.json in your workspace. Use marm-memory-local for direct Python installs; marm-memory-docker for Docker or exposed/key mode.

{
  "inputs": [
    {
      "type": "promptString",
      "id": "marm-api-key",
      "description": "MARM API Key for Docker or exposed server mode",
      "password": true
    }
  ],
  "servers": {
    "marm-memory-local": {
      "type": "http",
      "url": "http://localhost:8001/mcp"
    },
    "marm-memory-docker": {
      "type": "http",
      "url": "http://localhost:8001/mcp",
      "headers": {
        "Authorization": "Bearer ${input:marm-api-key}"
      }
    }
  }
}

Open .vscode/mcp.json, click Start above the server you want, then use Copilot Agent or any extension that consumes VS Code's native MCP registry.

</details>

<details> <summary><strong>Cursor</strong></summary>

Add to .cursor/mcp.json in your workspace. Cursor uses mcpServers, not VS Code's servers root.

{
  "mcpServers": {
    "marm-memory-local": {
      "type": "http",
      "url": "http://localhost:8001/mcp"
    },
    "marm-memory-docker": {
      "type": "http",
      "url": "http://localhost:8001/mcp",
      "headers": {
        "Authorization": "Bearer ${env:MARM_API_KEY}"
      }
    }
  }
}

For Docker/key mode, launch Cursor with MARM_API_KEY set in the environment.

</details>

<details> <summary><strong>Codex CLI</strong></summary>

Codex uses codex mcp add or TOML config at ~/.codex/config.toml (%USERPROFILE%\.codex\config.toml on Windows).

# Direct Python install - no key needed
codex mcp add marm-memory --url http://localhost:8001/mcp

# Docker or SERVER_HOST=0.0.0.0 - key required (set MARM_API_KEY in your shell first)
codex mcp add marm-memory --url http://localhost:8001/mcp --bearer-token-env-var MARM_API_KEY
[mcp_servers."marm-memory"]
url = "http://localhost:8001/mcp"
enabled = true
bearer_token_env_var = "MARM_API_KEY"

</details>

<details> <summary><strong>Gemini CLI</strong></summary>

# Direct Python install - no key needed
gemini mcp add --transport http marm-memory http://localhost:8001/mcp

# Docker or SERVER_HOST=0.0.0.0 - key required
gemini mcp add --transport http marm-memory http://localhost:8001/mcp --header "Authorization: Bearer your-generated-key"

Equivalent ~/.gemini/settings.json (user scope) or project .gemini/settings.json:

{
  "mcpServers": {
    "marm-memory": {
      "httpUrl": "http://localhost:8001/mcp",
      "headers": {
        "Authorization": "Bearer your-generated-key"
      }
    }
  }
}

</details>

<details> <summary><strong>Qwen Code</strong></summary>

# Direct Python install - no key needed
qwen mcp add --transport http marm-memory http://localhost:8001/mcp

# Docker or SERVER_HOST=0.0.0.0 - key required
qwen mcp add --transport http marm-memory http://localhost:8001/mcp --header "Authorization: Bearer your-generated-key"

Equivalent .qwen/settings.json (project) or ~/.qwen/settings.json (user):

{
  "mcpServers": {
    "marm-memory": {
      "httpUrl": "http://localhost:8001/mcp",
      "headers": {
        "Authorization": "Bearer your-generated-key"
      }
    }
  }
}

</details>

<details> <summary><strong>xAI / Grok Remote MCP</strong></summary>

xAI connects from its own infrastructure, so localhost will not work. Expose MARM behind HTTPS and set MARM_API_KEY.

{
  "type": "mcp",
  "server_url": "https://your-marm-domain.example.com/mcp",
  "server_label": "marm-memory",
  "authorization": "Bearer your-generated-key"
}

</details>

Full platform walkthroughs, key setup, and OS-specific notes: Windows · Linux · Docker/key mode · Other platforms

Using a client that isn't listed? Open an issue and let us know; client adapters are a first-class feature request.

<details> <summary><strong>System requirements, data location & backup</strong></summary>

Requirements

  • Python: 3.10 or higher
  • SQLite3: Included with Python (no separate install needed)
  • Storage: ~100MB minimum for initial setup, scales with memory database size
  • RAM: 512MB minimum (varies by concurrent clients and database size)
  • OS: Windows, macOS, Linux

Data location

  • Location: ~/.marm/ (Linux/macOS) or %USERPROFILE%\.marm\ (Windows)
  • Contents: SQLite database with all memories, sessions, and notebooks; the concept graph lives in its own ~/.marm/index/ database
  • Backup: Copy the entire ~/.marm/ directory to preserve all data
  • Privacy: Everything stays on your machine, no cloud sync or external storage

Verify installation

Use the MCP server health endpoint for the fastest live check:

curl http://localhost:8001/health

Expected output includes server version, feature availability (semantic search status), database connection status, and service health status.

</details>

Complete MCP Tool Suite (14 Tools)

💡 Pro Tip: You don't need to manually call these tools! Just tell your AI agent what you want in natural language:

  • "Claude, log this session as 'Project Alpha' and add this conversation as 'database design discussion'"
  • "Remember this code snippet in your notebook for later"
  • "Search for what we discussed about authentication yesterday"

The AI agent will automatically use the appropriate tools. Manual tool access is available for power users who want direct control.

🧠 Core Memory (7 tools)

| Tool | What it does | Key parameters | | ------ | -------------- | ---------------- | | marm_smart_recall | Hybrid memory recall with an additive, bounded concept/code graph sidecar when a compatible graph exists | query, limit, session_name, search_all, detail=1/2/3, project, platform, exact_mode | | marm_log_entry | Add structured session log entries; each entry is also embedded into semantic memory so marm_smart_recall can find it | entry, session_name | | marm_log_show | Display all entries and sessions, with filtering | session_name | | marm_delete | Delete a log session, log entry, or notebook entry | type, target, session_name, project, platform | | marm_summary | Cached, paste-ready session summaries with intelligent truncation | session_name | | marm_notebook | Session-scoped scratch pad plus promotion to a permanent, graph-linked doc | action="add"\|"use"\|"show"\|"status"\|"clear"\|"save", name, data, session_name, project, platform | | marm_compaction | Agent-assisted memory cleanup with a reviewable audit trail | action="status"\|"candidates"\|"review"\|"stage"\|"apply"\|"discard" |

🕸️ Code Graph (5 tools)

| Tool | What it does | Key parameters | | ------ | -------------- | ---------------- | | marm_graph_index | Index a repo into the code-structure graph, check status, or list projects | repo_path, project | | marm_code_lookup | Find symbols, text patterns, or a symbol's source; use instead of grep/glob | kind="auto"\|"symbol"\|"text"\|"snippet" | | marm_graph_trace | Trace call paths and data flow from a function | direction, mode | | marm_graph_architecture | Architecture overview: modules, node/edge breakdown, schema | project | | marm_graph_impact | Blast radius of code changes: git diff → affected symbols + risk | since, base_branch, depth |

🧩 Concept Graph (2 tools)

| Tool | What it does | Key parameters | |------|--------------|----------------| | marm_concept_build | Extract entities and typed relationships from stored memories | session_name, project, or search_all=True (one required) | | marm_concept_recall | Explicitly query entities, relationships, and linked code symbols | query, depth (1-5), direction, project, platform |

All 14 tools are available on both HTTP and STDIO. Behind the tool surface, the server handles lifecycle setup, protocol refresh, docs indexing, date context, summary-cache maintenance, write queue handling, project/platform attribution, and health checks automatically; none of those consume the agent's attention or tokens. The two graph engines start lazily on first use and never block the 7 core memory tools if they fail to start. See Architecture & Internals for the mechanisms.

Using MARM: Talk, Don't Call Tools

MARM handles lifecycle work internally. Docs and session state initialize on the first real tool call, and packaged docs are indexed into the marm_system memory namespace with source-file hash tracking, so your agent can answer MARM usage questions from memory itself.

Example Workflow: Cross-AI Research Project

A realistic workflow showing MARM in action. Scenario: you're researching authentication patterns for a new project using multiple AI clients.

Phase 1: Route Session (Claude)

You: "Claude, create a MARM session called 'auth-research-2025-01'"
Claude calls: marm_log_entry(entry="Session: auth-research")
Result: Session routed to auth-research-[today]. MARM lifecycle/docs initialize automatically.

Phase 2: Capture Research (Claude)

You: "Summarize OAuth2 vs JWT for API authentication and save it"
Claude calls: marm_log_entry(entry="Research: OAuth2 is token-based with refresh cycles, better for delegated access. JWT is stateless, good for microservices...", session_name="auth-research-2025-01")
Result: Research captured in the active session log and marked for summary-cache refresh

Phase 3: Add Reusable Reference (Claude)

You: "Save a JWT validation code snippet to my notebooks as 'jwt-validation-pattern'"
Claude calls: marm_notebook(action="add", name="jwt-validation-pattern", data="def verify_jwt(token):\n  # validation logic...")
Result: Reusable snippet stored for future projects

Phase 4: Recall Context (Gemini)

You: "Gemini, what authentication approaches did we research? Activate the JWT pattern."
Gemini calls: marm_smart_recall("authentication patterns", search_all=True)
Gemini calls: marm_notebook(action="use", names="jwt-validation-pattern")
Result: Gemini sees previous research + has JWT code available as context

Phase 5: Synthesis & Summary (Qwen)

You: "Qwen, pull everything from the auth research and create a summary"
Qwen calls: marm_smart_recall("authentication", session_name="auth-research-2025-01", limit=20)
Qwen calls: marm_summary(session_name="auth-research-2025-01")
Result: Qwen generates an implementation guide from all captured research

Phase 6: End Session (Claude)

You: "Log final decision - we're using JWT for APIs, and OAuth2 for user auth"
Claude calls: marm_log_entry(entry="DECISION: JWT for API auth, OAuth2 for user flows. Rationale: stateless APIs + delegated user access", session_name="auth-research-2025-01")
Result: Decision logged and searchable by all future AI clients

Result: Three different AI clients collaboratively researched a topic, shared insights, and documented decisions. All without re-explaining the project to each new AI.

Advanced patterns

<details> <summary><strong>Project memory architecture & knowledge base development</strong></summary>

Project Structure:
├── project-name-planning/          # Initial design and requirements
├── project-name-development/       # Implementation details
├── project-name-testing/           # QA and debugging notes
├── project-name-deployment/        # Production deployment
└── project-name-retrospective/     # Lessons learned

Knowledge base loop:

  1. Capture: Use marm_log_entry for structured session learnings
  2. Organize: Create themed sessions for knowledge areas
  3. Synthesize: Regular marm_summary for knowledge consolidation
  4. Apply: Convert summaries to marm_notebook(action="add", ...) entries

Multi-AI collaboration: each AI works in dedicated sessions on its strengths, uses marm_smart_recall to build on the others' work, then a collaborative session combines the insights.

</details>

<details> <summary><strong>Pro tips & best practices</strong></summary>

  • Session naming: Include the LLM name for cross-referencing
  • Strategic logging: Focus on key decisions, solutions, discoveries, configurations
  • Global search: Use search_all=True to search across all sessions
  • Natural language search: "authentication problems with JWT tokens" beats "auth error"
  • Layered recall depth: detail=1 returns a short summary view (~200 chars), detail=2 a larger context view (~500 chars), detail=3 full memory content
  • Notebook stacking: Combine multiple entries for complex workflows
  • Compaction: Let MARM surface compaction candidates, then use marm_compaction to stage, review, apply, or discard summaries
  • Session lifecycle: Start → Work → Reference → Review staged compaction when MARM asks

</details>

Understanding MARM Memory

Two searches, two very different problems, one tool:

User: "I discussed machine learning algorithms yesterday"
MARM Search: Finds related memories about "ML models", "neural networks", "AI training"

User: "What was the COMPACTION_TRIGGER_COUNT setting?"
MARM Search: Finds the exact config memory even if the rest of the text differs

The first query is about meaning, so MARM reranks candidates with local vector embeddings — RAG-style semantic search without a hosted vector database. The second is syntax-shaped (a config key), so MARM detects that automatically and routes it through deterministic exact matching instead. This exact-retrieval lane is the difference between a memory system that works in demos and one that answers the questions developers actually ask: config keys, CLI flags, file paths, API names, error strings. Pure-semantic memory systems fail at exactly those queries.

<details> <summary><strong>How the recall pipeline works under the hood</strong></summary>

MARM uses filter→rerank hybrid recall plus an exact retrieval lane:

  1. Exact lane (exact_mode="auto", the default): config keys, CLI flags, file paths, API/tool names, dotted namespaces, HTTP routes, URLs, and quoted command strings are detected and routed through deterministic FTS5 BM25 with a LIKE fallback. No embeddings involved, so results are stable and literal.
  2. Filter→rerank lane: natural-language queries first pull a bounded candidate set from the FTS index (FTS_CANDIDATE_LIMIT, default 200), then semantic embeddings rerank those candidates by meaning. Conservative temporal weighting gives fresher memories a modest boost when matches are otherwise close.
  3. Bounded semantic fallback: when FTS coverage is weak or unusable, MARM falls back to a bounded semantic scan (RECALL_SCAN_LIMIT). If the response includes recall_scan_truncated=true, the fallback hit its cap; narrow the session/query or raise the env var for larger stores.
  4. Chunk-aware scoring: long memories (roughly 180+ words) are embedded as overlapping chunk rows internally, and recall collapses chunk scores back to one parent memory using the best-matching chunk. Both the rerank lane and the fallback lane are chunk-aware.

This is why recall latency stays nearly flat as the store grows (see benchmarks): the semantic rerank always scores a bounded set instead of scanning every embedding.

Exact recall control: exact_mode="auto" is usually right. Use exact_mode="exact" when a query must match literal text such as RECALL_SCAN_LIMIT, --generate-key, or settings.py. Use exact_mode="semantic" when a syntax-looking query should still be treated as meaning-based recall.

</details>

Memory types & classification

  1. Context Logs - Auto-classified conversation memories
  2. Manual Entries - Explicitly saved important information
  3. Notebook Entries - Reusable instructions and knowledge
  4. Session Summaries - Compressed conversation history

MARM automatically categorizes content on write: Code (programming snippets and technical discussions), Project (work conversations and planning), Book (literature, learning materials, research), and General (everything else).

Project & platform attribution

MARM stores nullable project and platform columns on memories, log entries, and notebook entries. The project is detected from the working directory and the platform from the connecting client (Claude Code, VS Code, Cursor, ...); MARM_PROJECT and MARM_PLATFORM override detection. marm_smart_recall(project=..., platform=...) scopes recall without changing the default unfiltered behavior, so one shared server can hold several projects without cross-contamination.

Knowledge Graphs: Code & Concepts

MARM ships two graph systems that complement the memory store: a code graph that understands your repository's structure, and a concept graph that understands what your stored memories are about. When both are indexed for the same project, concept entities cross-link to code symbols.

Code Graph: repo indexing and code lookup

marm-graph is bundled into both transports. It indexes a repository once, then lets agents ask code-structure questions without repeatedly scanning files:

Use marm_graph_index to index this repository.
Then use marm_code_lookup when you need symbols, files, or source snippets.
Use marm_graph_trace for call paths, marm_graph_architecture for an overview, and marm_graph_impact for change-risk checks.

The recommended agent workflow: index once, then marm_code_lookup before broad file reads, marm_graph_trace when callers/callees or data-flow context matters, marm_graph_architecture for orientation, and marm_graph_impact before risky refactors. Re-index after meaningful code changes. One graph query replaces dozens of grep/read cycles, which is where the token savings come from.

Under the hood, the engine is codebase-memory-mcp (MIT), a zero-dependency static binary that parses 158 languages through tree-sitter with Hybrid LSP type resolution for the major ones, indexes an average repository in seconds, and answers structural queries in under a millisecond. MARM pins a specific release, verifies its tool schema on startup, and routes its 14 upstream tools through 5 focused MCP tools so the model surface stays small. The graph backend starts lazily on first graph-tool use, so memory, logging, notebook, and summary tools still start fast. In Docker, the engine binary is baked into the image; local pip installs fetch it on first graph use (~269MB, one time).

Degraded mode: if the graph engine fails to start (no network for the first-run download, disk full, schema drift) or GRAPH_ENABLED=false is set, graph tools return {"status": "error", "message": "graph backend unavailable"} while the other 9 tools keep working normally. Graph failures can never take down memory.

Concept Graph: what your memories are about

MARM can extract a knowledge graph from the memories you've already stored. marm_concept_build runs entity and relationship extraction over stored memory content, producing typed entities (concepts, decisions, patterns, errors, tools, people, organizations) connected by typed relationships (fixes, implements, depends_on, uses, causes, replaces, extends). Once built, marm_smart_recall automatically adds bounded related entities, relationships, and linked code as a graph_context sidecar without changing primary memory ranking. marm_concept_recall remains available for explicit graph exploration:

marm_concept_recall(query="write queue")            → the entity, its relationships, linked code symbols
marm_concept_recall(query="related to SQLite", depth=3) → multi-hop traversal of everything connected

How to use it:

  • Build first: call marm_concept_build scoped to a session_name, project, or search_all=True. There is no data until a build has run at least once. Builds are explicit and on-demand, not a live hook into the write path; re-run after logging significant new memories.
  • Upgrade once: graphs built before platform attribution require marm_concept_build(search_all=True). A full build backs up and resets only the derived concept database; targeted builds refuse to guess platform ownership.
  • Bounded by design: each build is row-capped (CONCEPT_BUILD_ROW_CAP, default 500) so a huge store can't turn one tool call into a runaway job.
  • Recall fails open: a missing, empty, incompatible, or unavailable concept graph never blocks normal memory recall. The response reports graph status separately.
  • Code cross-linking: when the code graph has indexed the same project, concept entities that match code symbols get linked, connecting "what we decided" to "where it lives in the code."
  • Bundled extraction runtime: the spaCy runtime and English extraction model ship with MARM but load only on the first concept build. If a damaged or partial installation makes them unavailable, both concept tools degrade cleanly while core memory remains available; run marm-memory knowledge status, then reinstall MARM if needed.
  • Isolated storage: the concept graph lives in its own SQLite database (~/.marm/index/marm_index.db) with its own connection pool, so concept-graph writes can never block or corrupt the production memory database.
  • Console atlas: MARM Console renders the complete atlas up to 750 entities and 6,000 stored relationships. Larger graphs use a deterministic connected sample of up to 600 entities and 4,000 aggregated visual edges, clearly labelled as sampled.

This fills the cross-session structure gap that flat memory search leaves open: sessions organize memories, but the concept graph connects them, so "what depends on the write queue?" is answerable even when the answer spans five sessions from three different agents.

Architecture & Internals

Everything above runs on a small number of deliberate mechanisms. This section is the full map, so you (or your agent) never have to guess what the server is doing.

Storage engine

  • SQLite in WAL mode at ~/.marm/marm_memory.db with a connection pool (5 connections). WAL keeps readers unblocked during writes, which matters when several agents recall while one writes.
  • FTS5 full-text index (memories_fts) is maintained as an external-content table over the memories table and powers both the exact lane (BM25) and the filter stage of hybrid recall.
  • Chunk storage: memories past ~180 words are split into overlapping 150-token chunks (50-token overlap) in a memory_chunks table, each with its own embedding. Recall scores chunks and collapses to the parent memory.
  • Embeddings come from the fastembed-backed jinaai/jina-embeddings-v2-small-en encoder: 33M parameters, 512 dimensions, an 8,192-token context window, and an Apache-2.0 license. It does not require separate query/document text prefixes. The encoder is lazily loaded on first semantic use and serialized behind a lock so concurrent encodes can't corrupt each other. If it is unavailable, writes still succeed; memories are stored without embeddings until it loads. Semantic scoring runs as a single NumPy batch (matrix cosine) rather than a Python loop.
  • The concept graph gets its own database (~/.marm/index/marm_index.db) and its own pool, reusing the same pool implementation but never sharing connections with the memory store. Deliberate isolation: an experimental graph build must not be able to stall the production WAL.

Write path

  • Serialized write queue (enabled by default): all memory writes flow through one internal async worker, eliminating SQLite writer contention under multi-agent load. The queue is generic; compaction applies go through the same worker, so there is exactly one writer no matter which subsystem is writing. MAX_QUEUE_SIZE bounds it.
  • Write-time consolidation (opt-in, CONSOLIDATION_ENABLED=1) runs two layers before a memory lands:
  • Layer 1, exact dedup: a SHA-256 hash of normalized content is checked within the session; hash hits are verified against the actual content before deduplicating, so a hash collision stores a new row instead of silently merging different content.
  • Layer 2, semantic merge: near-duplicates above CONSOLIDATION_THRESHOLD cosine similarity are merged rather than accumulated. This never blocks a write; if the encoder isn't available, the write proceeds unconsolidated.
  • The tradeoff is measured and published: roughly 9x median write cost (58ms vs 6.5ms) in exchange for a store that stays clean, because reads dominate memory workloads. See section 3 of the benchmarks above.
  • Compaction (opt-in, COMPACTION_ENABLED=1) is Layer 3: after enough writes in a session, a background pass detects clusters of related memories using cosine similarity plus union-find connected components, gated by minimum cluster size, minimum age, and an active-session grace period so it never compacts work in flight. MARM then injects a bounded request asking the connected agent to summarize each cluster: candidatesstagereviewapply or discard. Source memory IDs are preserved on apply, so compacted summaries stay traceable to their originals. Staged summaries expire (COMPACTION_STAGING_TTL_HOURS), nudges are capped and cooldown-limited, and the injection has a byte budget. The design is honest about what LLMs are for: MARM detects, the agent summarizes, and a human-reviewable stage/apply/discard loop gates the destructive step.

Recall path

Covered in Understanding MARM Memory: exact lane (FTS5 BM25 + LIKE fallback), filter→rerank (bounded FTS candidates → batch semantic rerank → temporal blend), bounded semantic fallback with an explicit truncation flag, and chunk-collapse scoring. Recall depth (detail=1/2/3) controls how much of each memory is returned, and every MCP response passes through a 1MB response limiter that truncates content intelligently instead of breaking the protocol.

Code graph subprocess protocol

The bundled graph engine runs as a supervised child process, not an import:

  • Transport: newline-delimited JSON-RPC 2.0 over the child's stdio, with a verified handshake (initialize → capture server version → initialized notification).
  • Envelope care: responses are scanned for the first JSON-parseable content item rather than assuming index 0, because the upstream binary can prepend an update notice. Tool errors arrive as result.isError, not JSON-RPC errors, and are converted to clean {"status": "error"} dicts with the upstream's own remediation hint attached.
  • Serialization: one lock guards each write+read round trip on the single stdin pipe; async callers go through asyncio.to_thread so the event loop never blocks on subprocess IO.
  • Crash recovery: stderr is drained on a background thread, child EOF/crash is detected, and the process is transparently respawned on the next call. Timeouts are deliberately not treated as crashes; a long index run may still be working, and killing it would destroy in-flight work.
  • Supervision: a lazy singleton supervisor owns the client for the process lifetime. Startup is triggered by the first graph-tool call, never raises into the MCP layer, and verifies the pinned binary's tool schema so upstream drift is caught at startup instead of mid-call.

Security & rate limiting

  • Two-mode auth gate: keyless on loopback (127.0.0.1), MARM_API_KEY (Bearer) mandatory the moment the server is network-exposed (SERVER_HOST=0.0.0.0, Docker). --generate-key produces one. Safe by default, zero setup friction locally.
  • IP-based rate limiting with sliding windows and temporary blocks, tuned through CLI presets rather than a config maze (table below).
  • Local-first: everything lives under ~/.marm/; no cloud sync, no telemetry, no external storage.
  • Graceful shutdown: SIGTERM/SIGINT handlers drain and close the connection pool cleanly, and an internal event system runs automation callbacks with per-callback error isolation and timeouts so one bad hook can't wedge the server.

Swarm & multi-agent presets

| Flag | Rate Limit | Write Queue | Use When | | ------ | ------------ | ------------- | ---------- | | (none) | 80 RPM | enabled | Normal local use and small 3-5 agent setups | | --swarm | 200 RPM | enabled | Shared HTTP server, roughly 15-30 agents depending on write style | | --swarm-max | 600 RPM | enabled | Heavier local/private swarm, roughly 50-100 agents depending on write style | | --trusted | disabled | enabled | Private/trusted deployments only | | --rate-limit-rpm N | N RPM | unchanged | Custom override; 0 disables limiting |

The write queue serializes memory writes regardless of preset; swarm flags tune the HTTP rate limit on top of that. The queue controls write ordering; consolidation and compaction are separate memory-maintenance layers. This stack (WAL + pooling + one serialized writer + RPM presets) is intentionally scoped to "SQLite, many agents, one machine"; distributed multi-node memory is out of scope for the current design.

Self-maintaining documentation

Packaged docs are indexed into the marm_system memory namespace on startup and refreshed every 50 tool calls, with source-file hash tracking so unchanged docs are skipped and changed or deleted rows are re-indexed. Connected agents can answer MARM usage questions with marm_smart_recall instead of you pasting docs at them.

Configuration reference

<details> <summary><strong>Environment variables (defaults in parentheses)</strong></summary>

| Variable | Default | What it controls | | ---------- | --------- | ------------------ | | SERVER_HOST | 127.0.0.1 | Bind address; 0.0.0.0 exposes the server and makes MARM_API_KEY mandatory | | SERVER_PORT | 8001 | HTTP port | | MARM_API_KEY | (empty) | Bearer key for network-exposed deployments | | MARM_DB_PATH | ~/.marm/marm_memory.db | Memory database location | | MARM_CONCEPT_DB_PATH | ~/.marm/index/marm_index.db | Concept graph database location | | MARM_PROJECT / MARM_PLATFORM | (auto-detected) | Override project/platform attribution | | MARM_RATE_LIMIT_RPM | 80 | Requests per minute per IP (presets override) | | WRITE_QUEUE_ENABLED | 1 | Serialize writes through one worker | | FTS_CANDIDATE_LIMIT | 200 | BM25 candidates fetched before semantic reranking; raise for stores with weak keyword overlap, lower to tighten results to the closest keyword matches | | RECALL_SCAN_LIMIT | 10000 | Cap on the semantic fallback scan; recall_scan_truncated=true in responses means it was hit | | FTS_QUERY_MODE | or_nostop | How semantic recall builds its keyword query: or_nostop ignores filler words then matches any remaining term, or matches any term, and requires every term (the pre-2.31.0 behavior). The exact/lexical lane always requires every term. | | FTS_EXTRA_STOPWORDS | (empty) | Comma-separated extra words to ignore when building keyword queries, for terms so common in your store they carry no signal | | HYBRID_SEARCH_TEXT_WEIGHT | 0.05 | How much the keyword score influences ranking. Set from a benchmark sweep; accuracy peaks across 0.04-0.08 and falls off sharply above 0.10. At 0.0, keyword matching narrows which memories are considered but does not reorder them. | | FTS_LONE_HIT_SCORE | 1.0 | Keyword score used when only one memory matches, or when every match ties. Lower it on small stores if a single keyword match should not count as a perfect one. | | SEMANTIC_SEARCH_ENABLED | 1 | Set to 0 to run without the embedding model: nothing is loaded, no embeddings are written, and recall falls back to keyword matching. Useful on low-memory hosts, or to see how recall behaves when the model is unavailable. marm-memory doctor reports when it is off. | | TEMPORAL_WEIGHT / TEMPORAL_HALF_LIFE_DAYS | 0.1 / 30 | Strength and decay of the recency boost | | CONSOLIDATION_ENABLED | 0 | Write-time dedup + semantic merge | | CONSOLIDATION_THRESHOLD | 0.92 | Cosine similarity needed to merge near-duplicates. Compared against meaning-similarity alone, not the blended ranking score | | COMPACTION_ENABLED | 0 | Background cluster detection + agent-assisted compaction | | `COMPACTION_TRIGGER_

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use Vector & Memory servers.