Are you the author? Sign in to claim
Local-first MCP server for durable agent memory
Local-first durable memory for MCP agents, backed by SQLite and FTS5.
Why · How it works · Installation · Quick start · Tools · Evaluation · Validation · Security
server-memory is an open-source Model Context Protocol server for durable AI-agent memory. It stores project facts, decisions, observations, relations, preferences, and activity in local SQLite databases, then returns compact, scoped context when an agent needs continuity across sessions.
It is designed for agents that repeatedly work on the same repositories, systems, incidents, or long-running tasks and need to remember what was already learned without replaying an entire conversation or loading the full knowledge graph every turn.
It is intentionally boring where memory should be boring: local storage, explicit tools, inspectable data, bounded output, and predictable failure modes.
Data remains local unless it is explicitly exported. The default transport is stdio. An optional shared HTTP daemon binds to localhost and uses local bearer-token authentication by default.
LLM agents commonly lose useful state between sessions. Common workarounds have real costs:
server-memory addresses those problems with durable, queryable memory that can be read selectively instead of replayed wholesale.
The project is intended to improve:
These are design goals, not performance claims. Verified results will be published only after controlled benchmark runs are complete.
The server stores:
Routine recall uses memory_context:
The goal is to return the smallest useful memory slice for the current task, not to place the entire database in model context.
| Capability | Implementation |
|---|---|
| Storage | SQLite with WAL mode and FTS5 search |
| Memory model | Entities, observations, relations, tags, and activity |
| MCP interface | 20 tools; no MCP resources or prompts |
| Routine recall | Compact memory_context output |
| Broader recall | memory_context_full, graph reads, node search, and timeline queries |
| Retrieval | FTS5, ranking signals, fuzzy fallback, and optional embeddings |
| Scopes | Workspace memory and optional global preference memory |
| Default transport | stdio |
| Shared mode | Localhost HTTP daemon with a stdio proxy |
| Data paths | Platform-native user data and runtime directories through platformdirs |
| License | MIT |
scope="all".┌────────────┐ stdio ┌─────────────────────┐
│ MCP client │ ────────────────────> │ server-memory │
└────────────┘ │ FastMCP server │
├─────────────────────┤
│ Workspace SQLite DB │
│ │
│ Global preferences │
│ DB, when enabled │
└─────────────────────┘
┌────────────┐ stdio ┌─────────────────────┐
│ MCP client │ ───────────────> │ server-memory-proxy │
└────────────┘ └──────────┬──────────┘
│
│ HTTP
│ 127.0.0.1:8765/mcp
▼
┌─────────────────────┐
│ server-memory-serve │
│ FastMCP daemon │
└─────────────────────┘
Use shared mode when multiple local clients should access one database process rather than opening the same database independently.
pip for installation from the repositoryCheck FTS5 support:
python -c "import sqlite3; c=sqlite3.connect(':memory:'); c.execute('CREATE VIRTUAL TABLE t USING fts5(content)'); c.close(); print('FTS5 available')"
No hosted CI status is used as proof of compatibility. Validate the package locally on the operating system and Python version where it will run.
python -m pip install "server-memory @ git+https://github.com/MK-986123/server-memory.git"
python -m pip install "server-memory[embeddings] @ git+https://github.com/MK-986123/server-memory.git"
Embeddings are optional. Core storage and FTS5 retrieval work without them.
git clone https://github.com/MK-986123/server-memory.git
cd server-memory
python -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
On Windows PowerShell:
.venv\Scripts\Activate.ps1
Install development and embedding dependencies together:
python -m pip install -e ".[dev,embeddings]"
AI coding agents working in this repository should follow AGENTS.md. Contributors should also read CONTRIBUTING.md.
server-memory
Equivalent module form:
python -m server_memory
MEMORY_DB_PATH=<PROJECT_ROOT>/memory.db server-memory
Use the equivalent environment-variable syntax for your shell on Windows.
server-memory-serve \
--host 127.0.0.1 \
--port 8765 \
--transport streamable-http
server-memory-proxy --url http://127.0.0.1:8765/mcp
{
"mcpServers": {
"server-memory": {
"command": "server-memory",
"env": {
"MEMORY_PROJECT": "<PROJECT_NAME>"
}
}
}
}
Start server-memory-serve separately, then configure the MCP client to launch the proxy:
{
"mcpServers": {
"server-memory": {
"command": "server-memory-proxy",
"args": [
"--url",
"http://127.0.0.1:8765/mcp"
]
}
}
}
Use memory only when prior state may materially improve the task.
memory_context(hint="current topic", limit=3-5) when earlier decisions, project facts, preferences, or unresolved work may matter.log_activity after meaningful changes, fixes, or decisions.pinned.server-memory registers MCP tools only. It does not register resources or prompts.
| Scope | Behavior |
|---|---|
workspace | Operates on the current workspace database and is the default for project memory |
global | Operates on the global preference database |
all | Combines supported workspace and global results with source labels |
Preference-tagged writes can automatically route to the global database when global preference routing is enabled.
[!IMPORTANT] Destructive operations require an explicit
workspaceorglobalscope. They rejectscope="all"to prevent accidental cross-database deletion, merging, or tag removal.
| Tool | Purpose | Main inputs |
|---|---|---|
memory_context | Compact scoped recall for ordinary agent context | hint, project, limit, scope |
memory_context_full | Larger bootstrap context with pinned and recent items | project, budget, scope |
create_entities | Add entities and optional initial observations | entities, scope |
add_observations | Add observations to existing entities | observations, scope |
create_relations | Connect existing entities | relations, scope |
read_graph | Read graph data, compressed by default | tags, entity_types, limit, include_deleted, compress, scope |
search_nodes | FTS5 search with filters | query, tags, entity_types, time_range, limit, compress, scope |
open_nodes | Open named entities and optional neighbors | names, depth, scope |
log_activity | Record a durable development or session event | action, summary, entity_names, tags, metadata, scope |
query_timeline | Query activity history | time_range, start, end, actions, entity_name, session_id, limit, scope |
manage_tags | List, create, delete, apply, remove, or clean tags | action, name, entity_name, tag_name, scope |
merge_entities | Merge one entity into another | source, target, strategy, scope |
export_graph | Export graph as JSON or JSONL | format, scope |
import_graph | Import JSON or JSONL graph data | data, scope |
memory_stats | Return counts and storage statistics | scope |
backup_memory | Copy a SQLite database | dest_path, scope |
get_observation_history | Show observation versions for an entity | entity_name, content_prefix, scope |
delete_entities | Soft-delete or hard-delete entities | entityNames, hard, scope |
delete_observations | Delete selected observations | deletions, scope |
delete_relations | Delete relations | relations, scope |
Write tools modify the selected SQLite database. backup_memory writes a database backup. export_graph may expose sensitive memory content, so review exports before sharing them.
Configuration is environment-driven. Empty path overrides in .env.example use platform defaults.
| Variable | Default | Meaning |
|---|---|---|
MEMORY_DB_PATH | Platform user-data directory, workspace-namespaced when detected | Workspace SQLite database |
MEMORY_PROJECT | Empty | Default project scope |
MEMORY_GLOBAL_DB_ENABLED | true | Enable the global preference database |
MEMORY_GLOBAL_DB_PATH | Platform user-data directory | Global preference database |
MEMORY_GLOBAL_PREFERENCE_ROUTING_ENABLED | true | Route preference-tagged writes to global memory |
MEMORY_WORKSPACE_ROOT | Unset | Explicit workspace root for default database placement |
MEMORY_WORKSPACE_ID | Unset | Explicit workspace identifier for default database placement |
| Variable | Default | Meaning |
|---|---|---|
MEMORY_COMPRESSION_LEVEL | 4 | Compression level from 0 through 4; 4 is automatic |
MEMORY_TOKEN_BUDGET | 2000 | Maximum approximate token budget for compressed graph output |
MEMORY_EMBEDDING_MODEL | all-MiniLM-L6-v2 | Optional embedding model |
MEMORY_EMBEDDING_ENABLED | true | Enable embedding search and backfill when dependencies are available |
MEMORY_WRITE_EMBEDDING_BUDGET_MS | 10000 | Write-path embedding time budget |
MEMORY_DEDUP_THRESHOLD | 0.92 | Semantic deduplication threshold |
| Variable | Default | Meaning |
|---|---|---|
MEMORY_IMPORT_JSONL | Unset | Import JSONL on startup |
MEMORY_SESSION_ID | Unset | Session identifier for activity logging |
MEMORY_HTTP_AUTH_ENABLED | true | Require bearer authentication for the shared HTTP daemon |
MEMORY_AUTH_TOKEN_PATH | Platform runtime directory | Local HTTP daemon token file |
The repository includes deterministic retrieval scenarios for memory_context, including exact-name lookup, importance ranking, pinned facts, access recency, activity links, file-path hints, stale-fact demotion, lexical fallback, and duplicate suppression.
Those tests validate expected ranking behavior, but they do not establish real-world improvements in agent completion rate or token use.
A separate controlled protocol is provided in docs/BENCHMARK_PROTOCOL.md. It compares:
server-memoryThe protocol measures:
[!NOTE] No performance numbers are claimed in this README yet. Verified results should include raw run records, exact model revisions, repository commits, configurations, task fixtures, evaluator rubrics, acceptance-test logs, and confidence intervals.
Hosted GitHub Actions are not currently treated as an active validation source for this repository. Workflow definitions may remain under .github/workflows for future use, but this README does not claim that those jobs are running or passing.
Install development dependencies:
python -m pip install -e ".[dev]"
Run the required local checks:
python -m compileall -q src tests scripts
python -m ruff check .
python -m pytest -q
Run the full package and supply-chain checks before a release or substantial pull request:
rm -rf dist build
python -m build
python -m twine check dist/*
python scripts/inspect_wheel.py dist
python -m pip_audit
python scripts/smoke_stdio.py server-memory
server-memory-serve --help
server-memory-proxy --help
On PowerShell, remove build artifacts with:
Remove-Item -Recurse -Force dist, build -ErrorAction SilentlyContinue
The stdio smoke test sends an MCP initialize request to the installed entry point and fails if stdout contains non-protocol output.
When reporting validation, include the exact commands, Python version, operating system, and full failure output. Do not describe a check as passing unless it was actually executed.
See CONTRIBUTING.md for contribution guidance and AGENTS.md for repository-specific agent instructions.
[!IMPORTANT] Memory databases, exports, backups, and activity logs can contain sensitive user data.
127.0.0.1 and local bearer-token authentication.MEMORY_AUTH_TOKEN_PATH is set.Report vulnerabilities through GitHub private vulnerability reporting when available. Do not include secrets or private memory exports in public issues.
See SECURITY.md for the project security policy.
| Symptom | Check |
|---|---|
no such module: fts5 | Use a Python build linked against SQLite with FTS5 enabled. |
| MCP client hangs at startup | Run python scripts/smoke_stdio.py server-memory and inspect stderr. |
| Multiple clients lock the database | Run one server-memory-serve process and connect clients through server-memory-proxy. |
| Proxy returns an authentication failure | Restart the daemon and client so both read the same MEMORY_AUTH_TOKEN_PATH. |
| Memory is stored in an unexpected location | Set MEMORY_DB_PATH, MEMORY_WORKSPACE_ROOT, or MEMORY_WORKSPACE_ID explicitly. |
Licensed under the MIT License.
Run Claude Code as an MCP server so any agent can delegate coding tasks to it
Browser automation using accessibility snapshots instead of screenshots
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases
Official GitHub integration for repos, issues, PRs, and CI/CD workflows