Are you the author? Sign in to claim
Self-hosted MCP server that gives Claude persistent memory across conversations — entities, observations, history, and t
Self-hosted MCP server that gives Claude persistent memory across conversations — entities, observations, history, and time-based reminders, in a lightweight Node/SQLite backend you run yourself.
Point Claude at it as an MCP connector and it can remember what you're working on from one conversation to the next: ongoing projects, decisions and their rationale, facts about you and your setup, and things to resurface on a future date.
Claude forgets everything when a conversation ends. Atlas is a small, boring, durable memory layer you own end to end — no third-party service, no vendor lock-in. It's a single Node process backed by one SQLite file. Run it on a home server, a VPS, or your laptop.
| Concept | What it is |
|---|---|
| Entity | A topic or project you want Claude to track (e.g. "Home Network", "Q3 Planning"). Has a name and a one-line summary. |
| Observation | A single fact attached to an entity ("switched the router to the 6E band on 2026-06-01"). The atomic unit of memory. Can be edited in place or marked protected against accidental deletion. |
| History event | A notable thing that happened, logged to the timeline for later recall. |
| Reminder | A note with a trigger_date. Once the date arrives it auto-surfaces at the start of a conversation and stays until dismissed. |
| Section | A top-level namespace — one of three fixed values, work, personal, and shared. Every tool call takes a section argument. shared is a handoff channel both work- and personal-scoped tokens can read/write; get_landscape automatically merges it into whichever section you pull. |
The server exposes 16 MCP tools:
Reading
get_landscape — everything in a section (with shared auto-merged in): all entities with their observations, plus any due reminders. Call at the start of a conversation to get oriented.search — keyword search across entities, observations, and history.get_entity — one entity and its observations by name.get_history — the timeline of logged events.Writing
upsert_entity — create or update an entity's name/summary.add_observation — attach a fact to an entity.update_observation — edit a fact in place; the ID and its history stay stable. Works on protected rows.remove_observation — drop a fact that's stale or done (refuses if protected).protect_observation / unprotect_observation — mark a fact as protected from deletion, or lift that protection.remove_entity — delete an entity and its observations (refuses if any observation is protected).log_event — record a notable event to history.Reminders
create_reminder — a note with a trigger_date (and optional entity link).list_reminders — all reminders, or just those currently due.dismiss_reminder — mark a reminder handled (it stops surfacing).remove_reminder — delete a reminder outright.Every tool response also carries a small time footer — current server time (America/New_York) plus elapsed time since that token's last call — so the model never has to guess or do date math from a stale mental clock.
src/groom.js is a standalone script meant to run on a schedule (cron, or
docker exec <container> node src/groom.js). It's intentionally report-only
and mechanical — no LLM calls, no deletion of your data:
audit_log (90+ days) — the only thing it actually deletesFindings land in a per-section "Groom Report" entity for you (or Claude) to act on.
node:sqlite) — Node 22+.There are no native dependencies — storage is the built-in node:sqlite module, so there's nothing to compile.
git clone https://github.com/dcazman/Claude-Atlas-MCP.git
cd Claude-Atlas-MCP
cp .env.example .env # set a token
docker compose up -d --build
The server listens on port 7784. Data persists to ./data (a single SQLite file) via the mounted volume.
Requires Node 22+ (for built-in node:sqlite).
npm install
cp .env.example .env # set a token
npm start # or: node src/server.js
Atlas speaks MCP over streamable HTTP at POST /atlas-mcp. Add it as a connector using the server's URL with your token:
https://<your-host>/atlas-mcp?token=<your-secret>
The token is the secret half of an ATLAS_TOKEN caller:secret pair (see below). You can also pass it as an X-Atlas-Token header or a Bearer token instead of the query string.
There's no section in the URL — every tool takes a section argument (work, personal, or shared), and which one a given conversation should default to is best set in your Claude project's custom instructions (e.g. "Your Atlas section is personal"). A GET /health endpoint is available for liveness checks.
For real use you'll want it behind HTTPS — a reverse proxy or a tunnel (Cloudflare Tunnel, Tailscale, nginx, etc.) in front of the container. The token is the only auth, so do not expose the port publicly without TLS.
Once connected, a good habit is to have Claude call get_landscape at the start of each conversation and keep entries updated (upsert_entity / add_observation / log_event / remove_observation) as things change — you can encode that in the connector's instructions field or your project's custom instructions.
Atlas's built-in auth is a single shared token — fine behind a private network or tunnel, but thin if you're exposing it to the internet. For real access control, put a dedicated auth gateway in front rather than hardening this server yourself.
mcp-auth-proxy is a drop-in OAuth 2.1 / OIDC gateway for MCP servers — no code changes to Atlas:
*@yourcompany.com).Roughly, you'd point it at Atlas's HTTP endpoint:
./mcp-auth-proxy \
--external-url https://<your-domain> \
--tls-accept-tos \
-- http://localhost:7784/atlas-mcp
See its documentation for IdP setup and configuration. (Not affiliated — just a clean fit for self-hosted MCP servers like this one.)
Set via .env (see .env.example):
| Variable | Purpose |
|---|---|
ATLAS_TOKEN | Required. One or more caller:secret:scope triples, comma-separated. Scope is mandatory — work (reaches work+shared), personal (reaches personal+shared), or shared (reaches shared only). Enforced server-side on every call; out-of-scope requests get a 403 and are logged. Generate a secret with node -e "console.log(require('crypto').randomBytes(24).toString('hex'))". |
PORT | Listen port (defaults to 7784). |
ATLAS_DB_PATH | Path to the SQLite file (defaults to ../data/atlas.db relative to src/; the Docker image uses /app/data/atlas.db). |
See SECURITY.md for the threat model, deployment hardening notes, and how to report a vulnerability.
MIT — see LICENSE.
Google's universal MCP server supporting PostgreSQL, MySQL, MongoDB, Redis, and 10+ databases
Official MongoDB integration — query collections, run aggregations, inspect schemas
Secure MCP server for MySQL database interaction, queries, and schema management
Run Claude Code as an MCP server so any agent can delegate coding tasks to it