An AI-first archive server for Claude, ChatGPT, LM Studio, and any other MCP-compatible client.
Persistent archive that the AI owns: store, retrieve, organize, curate, and forget across sessions. The Archive is the collection; an entry is what a session writes into it. Built natively in Objective-C with Core Data, on-device multilingual Core ML embeddings, and optional CloudKit sync. Designed and optimized for Claude; Claude Desktop, ChatGPT desktop, and LM Studio all connect to the same server over stdio, each as its own persona, in one shared archive.
ES Archive was known as ES Memory through version 3.3.3. The rename was a clean cut, no aliases: the MCP tools (memory_* → archive_*), bundle identifiers, and app group all changed. The CloudKit container and sync schema did not, so a synced archive re-downloads on first launch, and legacy .esmemory backups still open.
Read more about the technology and philosophy behind ES Archive on alpharecursion.com.
ES Archive is one engine that ships in two forms, built as two targets in this repository:
- ES Archive MCP — a stdio server, and the recommended install. Any client that can launch a stdio MCP server spawns it directly: Claude Desktop, Claude Code, ChatGPT desktop, LM Studio, Codex. No localhost port, no network listener. Concurrent sessions — across all of those clients at once — share one in-process engine over a local UNIX-domain socket: the first to start hosts it, the rest relay, so N sessions cost one engine, not N (see Architecture). Each session declares its persona at launch with --author, so Claude, ChatGPT, and a local model each write as themselves into the same archive.
- ES Archive Server — the HTTP app. Hosts the same engine behind a hardened localhost web server for clients that speak MCP-over-HTTP or SSE (curl, a cloudflared tunnel, HTTP-only clients), with port-bound personas and per-port authentication. Use this when you need/sseor HTTP clients, or remote access.
Both read and write the same kind of archive; each keeps its own local store.
- macOS 26 (Tahoe) or later
- ES Archive MCP: any client that launches stdio MCP servers — tested with Claude Desktop, Claude Code, ChatGPT desktop, LM Studio, and Codex
- ES Archive Server: any MCP-over-HTTP or SSE client
- Install ES Archive MCP from the Mac App Store.
- Connect the client(s) you use — see below. Each is a one-time step.
That's all. The client launches the server on demand and the archive tools appear automatically — no separate app to keep running, nothing listening on a port. While it's running the host presents the app's UI — a Dock app by default (Archive Scope, persona management, backup/restore), or a menu-bar item if you switch to Minimal mode in Settings.
Every client points at the same executable:
/Applications/ES Archive MCP.app/Contents/MacOS/ES Archive MCP
and passes --author <name> to say who is writing. The name is the persona: it is stamped on every entry the session stores and scopes what the session reads, so each assistant keeps to its own slice of the shared archive. Without the flag the session writes as Claude.
In ES Archive MCP, choose Help ▸ Connect ES Archive… and click Connect to Claude. That builds a connector pointing at this copy of the app and hands it to Claude Desktop, which asks you to approve the install. (Equivalently: Claude Desktop → Settings → Extensions → install the .mcpb from a release.)
ChatGPT's desktop app can launch stdio MCP servers directly. In ChatGPT, open Settings → Plugins → MCPs → Add. The Connect to a custom MCP dialog opens with the Type toggle already on STDIO (the other option, Streamable HTTP, is for the Server app). Fill in:
Save, then start a new conversation; the archive_* tools appear as a plugin. Use whatever persona name you like in place of ChatGPT — that is the name entries will carry. To change the arguments later, open the server from the MCPs tab; switching between STDIO and Streamable HTTP requires an uninstall and re-add. Note that this is a recent ChatGPT feature and much of the older advice online (HTTP-only connectors, developer mode) no longer applies.
In ES Archive MCP, choose Help ▸ Connect ES Archive… and click Copy MCP Configuration, then in LM Studio choose Program ▸ Edit mcp.json and paste. Add an author for the model you run, and load a model that supports tool use:
{
"mcpServers": {
"es-archive": {
"command": "/Applications/ES Archive MCP.app/Contents/MacOS/ES Archive MCP",
"args": ["--author", "Gemma"]
}
}
}claude mcp add es-archive -- "/Applications/ES Archive MCP.app/Contents/MacOS/ES Archive MCP" --author ClaudeThe LM Studio snippet is plain MCP-over-stdio. Any client that can launch a command with arguments (Codex, editors, agent frameworks) uses the same executable path and --author.
ES Archive MCP is distributed through the Mac App Store, sandboxed like every App Store app. All data stays on your Mac; if you're signed into iCloud it syncs through your own private CloudKit database, and nothing else leaves the machine.
The repository uses git submodules for the on-device embedder and the two dependency projects, so clone with them:
git clone --recurse-submodules https://github.com/apocryphx/ES-Archive.gitIf you already have a clone without them:
git submodule update --initThe embedder submodule pulls ~220 MB of model weights and tokenizer through Git LFS, so install it once beforehand (brew install git-lfs && git lfs install).
Open ES-Archive.xcworkspace (not the bare .xcodeproj — it cannot resolve the dependency projects on its own) and build the ES Archive MCP or ES Archive Server scheme. A build phase verifies the embedder model landed in the bundle and fails red if a submodule is missing.
To keep the submodules moving with the main repo on every pull, set once per clone:
git config submodule.recurse trueES Archive exposes 22 MCP tools. Most retrieval and curation runs through archive_cli, a Unix-pipeline surface — compose operations with | the way you would in a shell (lfind --tag "X" | w2vgrep "concept" | head 5); run archive_cli("man") for the full vocabulary. The rest are direct tools:
- Storage — archive_store,archive_read,archive_update,archive_erase
- Retrieval — archive_search(semantic, with optional recency weighting),archive_grep(line-level pattern search — the matching passages with context, not just which entries contain a string),archive_timeline,archive_tagged
- Pipeline — archive_cli(composable surface),archive_pipeline(its underlying executor)
- Discovery — archive_discover(hubs, orphans, forgotten, and other archive structures)
- Graph — archive_link,archive_unlink,archive_links,archive_tag,archive_untag,archive_tags
- Annotation & history — archive_comment,archive_reference,archive_revisions
- Identity & upkeep — archive_author_list,archive_maintenance
Tags are deliberately curated — every tag's existence is an authorial judgment, not an automatic extraction. On archive_store, the server returns similarity scores against existing entries as a behavioral cue against duplication.
The tools are the instrument; the skills are how an assistant learns to play it. The repository carries two complete suites in skills/, each documenting the same tool surface in its own voice, and each owned and edited only by the assistant it is written for:
They cover the same ground — when and what to store, how to research with archive_cli pipelines, how to curate tags and links, how to listen to the archive's shape — but they are not translations of each other. The Claude suite was written with Claude over a year of daily use; the Codex suite was written by Codex for itself, including a visitor skill for reading an archive that belongs to a different persona without curating it.
The skills are versioned next to the code they describe so that a tool change and its skill change land in the same commit. Both apps bundle the Claude suite at build time and install it from the Install Claude Skills… card of the Connect window (Help ▸ Connect ES Archive…): each skill has a Read button to see its text and an Install button that hands it to Claude Desktop for confirmation and shows a checkmark once done. For a developer machine, scripts/sync-skills.sh copies the Claude suite to ~/.claude/skills and packs .skill files for claude.ai, and copies the Codex suite to ~/.codex/skills, where both Codex and ChatGPT desktop (Settings → Plugins → Skills) pick it up. See skills/README.md.
Entries are stored locally in Core Data. Vector embeddings are computed on-device with EmbeddingGemma — Google's embeddinggemma-300m, quantized to int4 (768-dimensional) — via Core ML. It is multilingual across 100+ languages, so a query in one language reaches entries written in another; each entry is embedded with its title alongside its summary for sharper retrieval. CloudKit sync across your devices is optional — without iCloud, ES Archive works fully offline, and with it, data stays within your iCloud account. No third-party services, no telemetry.
Both apps include a visual layer that renders the Archive as a force-directed graph. Nodes are entries, edges are explicit links and similarity connections, color encodes access frequency. Each entry draws one similarity edge to its single nearest neighbor, and small clusters that would otherwise float free are bridged into the main body, so the graph reads as one connected whole rather than scattered fragments. A second tab shows tags as an Archimedean spiral, sized by frequency. The views update live as the Archive changes and as tools are called — you can watch new entries find their place, and see when sustained engagement with a topic produces a hub.
An ES Archive persona is an author: a name that is stamped on everything a session writes and that scopes everything it reads. Several assistants can share one archive without seeing or overwriting each other's entries, and the tags, links, and Archive Scope graph stay one shared structure.
The stdio ES Archive MCP scopes a persona per connection: each session declares its author with --author at launch. That is how Claude Desktop, ChatGPT, and LM Studio coexist on one machine — three clients, three personas, one engine, one archive. Its Settings pane lists the Archive's personas to delete or merge them (merge renames an author across all of its records, which is how you fold a misnamed persona into the right one).
The HTTP ES Archive Server binds personas to ports instead: the port a request arrives on is its identity, so authorship is stamped from the channel rather than asserted by the client, and misattribution is structurally impossible. Personas are managed in Settings → Personas — every author already in the Archive is listed with its record count; from there you can assign a port to serve a persona, create a new one, rename or merge an author, or delete a persona along with its records. Each port can independently require a Cloudflare Access JWT, so a persona exposed over a cloudflared tunnel sits behind edge authentication while a local-only persona stays open. A read-only GET /personas directory lets a client discover which port serves which persona before connecting. Port-bound personas, persona creation, and per-port JWT stay exclusive to the Server app.
The engine — the Core Data stack, the on-device embedder, vector search, and every MCP tool implementation — is shared by both targets. What differs is the transport:
- ES Archive MCP speaks MCP as newline-delimited JSON-RPC over stdio, and N concurrent sessions — whichever clients spawned them — share one engine rather than N. The first session to start binds a UNIX-domain socket in the shared App Group container and hosts the engine in-process; every other session connects to that host, declares its --author, and relays its requests over the socket, never loading its own Core Data stack or embedder (≈30 MB per relay vs. ≈550 MB for the one host). The election is thebind()itself — kernel-arbitrated, no daemon, App-Store-safe (seedesign-decisions/socket-election.md). The host also owns the single GUI; relays stay headless and exit when their host does, so nothing lingers. There is no HTTP listener anywhere in the target. Shutdown is stdin EOF or SIGTERM, draining cleanly before the store is saved.
- ES Archive Server hosts the same engine behind a localhost HTTP server — GCDWebServer (a submodule), hardened with security fixes documented in CHANGES-2026-05-09.md and CHANGES-2026-04-25.md — binding to 127.0.0.1only, one listener per persona. It accepts no external connections; remote access, when wanted, is delegated to a cloudflared tunnel with per-port Cloudflare Access authentication.
Packaging of the stdio .mcpb for Claude Desktop lives in packaging/.
ES Archive is written in Objective-C throughout — a deliberate choice, not a legacy constraint. Core Data, CloudKit, and GCDWebServer compose cleanly in Objective-C in ways that Swift's strict type system makes awkward; the dynamic dispatch model fits a server that routes heterogeneous MCP tool calls at runtime. The codebase has no Swift dependencies and no bridging headers.
The practical consequence: the contributor surface is small by design. This is not a project looking for pull requests. It is a working instrument, published so that developers who want to understand the architecture can read it.
ES Archive has been in active development for over a year (as ES Memory until August 2026), used by its author daily and built in collaboration with Claude across many sessions. It is released publicly as part of the alpharecursion research program. The current release is 3.3.12 for both ES Archive MCP (stdio) and ES Archive Server (HTTP); ES Archive MCP is on the Mac App Store, approved September 22, 2026. The tool API listed above is stable; new tools may be added but existing ones will not be removed without notice.
Questions, bug reports and feature requests go to the Issues page. Search first — the answer may already be there — then open a new issue with the app (MCP or Server), its version from the About panel, and what you expected to happen. The in-app help book (Help ▸ ES Archive Help) covers setup, connecting clients, personas and troubleshooting. Your archive stays on your Mac and in your iCloud account; see PRIVACY.md.
MIT. See LICENSE for full text. The GCDWebServer submodule retains its original BSD 3-Clause license; see its README.
Kolja Wawrowsky — alpharecursion.com · twilighttales.art