Mem Port
FreeNot checkedA local MCP server providing portable, long-term agentic memory through an embedded knowledge graph and semantic search, allowing multiple AI copilots to share
About
A local MCP server providing portable, long-term agentic memory through an embedded knowledge graph and semantic search, allowing multiple AI copilots to share isolated memory libraries via library-id without external services.
README
A local MCP (Model Context Protocol) server for portable, long-term agentic memory — a thumb drive for your AI context.
Every AI copilot (Claude Code, Cursor, Windsurf, ...) keeps its own memory, siloed to that tool. The usual workaround — copy-pasting context, summaries, or exported notes from one agent into another — only captures a snapshot frozen at the moment you made it. From there the copies drift: each agent keeps learning on its own, nothing keeps the copies in sync, and the longer you go the more your copilots disagree about what's actually true. mem-port runs as a single local daemon that any number of copilots can connect to, backed by an embedded knowledge graph (entities, episodes, memories, skills, and the relations between them) that survives restarts and can be exported to a portable file and moved anywhere. Every connected copilot reads and writes the same graph, so there's nothing to paste and nothing to drift.
Unlike other memory-for-agents projects, mem-port needs no external services — no Postgres, no Qdrant, no Neo4j. It's one process, one embedded SurrealDB instance combining graph storage and vector search, and zero-config local semantic search (no API key required).
Connecting a client (below) gives it the ability to use mem-port; for more detailed, tunable instructions on what it should actually save and when — including keeping personal/team/project memory in separate scopes — see MEMORY_GUIDE.md.
Quick start
npx @rsl-innovation/mem-port serve
This starts a daemon on http://127.0.0.1:8787/mcp. Point any MCP client at it over Streamable HTTP, with a library-id header identifying your workspace. Every copilot that connects with the same library-id shares the same memory; different library-ids are fully isolated from each other (each maps to its own SurrealDB namespace/database) — there's no cross-tenant leakage.
npx re-checks the registry on every invocation. If you'll be running mem-port commands often, install it globally instead so mem-port is a plain command on your PATH:
npm install -g @rsl-innovation/mem-port
mem-port serve
The rest of this README uses mem-port <command> for brevity. If you didn't install globally, substitute npx @rsl-innovation/mem-port <command> wherever you see that — it works identically, just slower to start.
Connecting from Claude Code
Easiest: use the CLI (--header accepts any number of Key: Value pairs). Add --scope user so the server is available in every project on this machine, not just the one you happen to be in when you run the command — the default local scope ties it to a single project directory:
claude mcp add --transport http mem-port http://127.0.0.1:8787/mcp \
--header "library-id: my-personal-workspace" \
--scope user
Or add it directly to ~/.claude.json (user scope, applies everywhere) or .mcp.json (project scope, shareable via version control with that repo's team). The type field is required — an entry with a url but no type is treated as a misconfigured stdio server:
{
"mcpServers": {
"mem-port": {
"type": "http",
"url": "http://127.0.0.1:8787/mcp",
"headers": { "library-id": "my-personal-workspace" }
}
}
}
Run /mcp inside Claude Code to confirm it shows mem-port as connected.
Connecting from the Claude Code VS Code extension
The extension shares the exact same MCP configuration as the CLI (.mcp.json / ~/.claude.json) — there's no separate settings UI to add a server from. Open the integrated terminal (Ctrl+` / Cmd+`) and run the same command as above:
claude mcp add --transport http mem-port http://127.0.0.1:8787/mcp \
--header "library-id: my-personal-workspace" \
--scope user
This requires the standalone claude CLI to be installed — the extension bundles its own private copy for the chat panel and does not put claude on your terminal PATH, so claude mcp add won't work in the integrated terminal until you install the CLI separately. Editing .mcp.json directly (the JSON block above) works too and doesn't need the CLI.
Once added, type /mcp in the chat panel to confirm mem-port shows as connected, or to enable/disable/reconnect it.
Connecting from other MCP clients
Any client that supports Streamable HTTP with custom headers can connect the same way. Clients that only support stdio-based servers (some Claude Desktop configurations, for example) need a stdio-to-HTTP bridge such as mcp-remote:
{
"mcpServers": {
"mem-port": {
"command": "npx",
"args": ["-y", "mcp-remote@latest", "http://127.0.0.1:8787/mcp", "--header", "library-id:my-personal-workspace"]
}
}
}
Getting your copilot to use it proactively
Connecting the server gives your copilot the ability to save/recall memory — the server's MCP instructions and tool descriptions already nudge any client toward using it proactively. For more explicit control (and for keeping personal/organizational/project memory in separate library-id scopes instead of one bucket), see MEMORY_GUIDE.md for instructions to paste into your copilot's own custom-instructions file.
Tools
| Tool | Purpose |
|---|---|
save_memory |
Save a fact/preference/decision/task/reference, optionally linked to entities |
search_memory |
Semantic (vector) search over memories |
save_episode |
Record a raw interaction/event that memories can be derived from |
list_episodes |
List recorded episodes, filterable by time range/source |
save_skill |
Save a reusable procedure, optionally linked to entities |
search_skills |
Semantic (vector) search over skills, by task/situation |
list_skills |
List saved skills, filterable by tag/source |
get_skill |
Look up a skill by exact name or id |
forget_skill |
Soft-archive (default) or permanently delete a skill |
get_entity |
Look up an entity plus everything that mentions or relates to it |
relate_entities |
Create a graph relation between two entities |
forget_memory |
Soft-archive (default) or permanently delete a memory |
export_library |
Export this library to a portable .memport.json bundle |
import_library |
Import a .memport.json bundle, merging or overwriting |
Skills memory
Alongside episodes and memories, mem-port stores skills — reusable procedures for recurring tasks (e.g. "how to debug a flaky test in this repo," "the deploy steps for checkout-service"). A skill has a name, a description (the trigger condition — when a copilot should reach for it, matched by search_skills), and content (the actual instructions).
Skills are what makes "porting common skills across AI" work with no extra machinery: since they live in the same shared knowledge graph as everything else, a skill saved by Claude Code is immediately visible to Cursor or Windsurf the moment they connect with the same library-id — no file format conversion needed. export_library/import_library carry skills between machines exactly like entities, episodes, and memories.
Porting memory between machines
Same-machine sharing across copilots needs no extra step — they just connect to the same daemon with the same library-id. export_library/import_library solve a different problem: moving to a new machine, backing up, versioning (the bundle is plain JSON — commit it to a private git repo if you like), or handing a curated slice of memory to someone else.
# on the old machine
mem-port export --library-id my-personal-workspace
# -> writes <data-dir>/exports/my-personal-workspace-<timestamp>.memport.json
# on the new machine, after copying the file over
mem-port import --library-id my-personal-workspace --in ./my-personal-workspace-....memport.json
import defaults to --mode merge (dedupes entities by name+type, memories/episodes by content hash — importing the same bundle twice is a no-op). Pass --mode overwrite to wipe the target library first, or --dry-run to see what would happen without writing anything.
Running persistently
mem-port serve runs in the foreground — it's a long-lived daemon, not a one-shot command, so it blocks whatever terminal started it and dies when that terminal closes. If your MCP client can't connect (ECONNREFUSED 127.0.0.1:8787), that's almost always the reason: nothing is actually listening. Check with lsof -i :8787.
For a quick session, background it: mem-port serve & (or nohup mem-port serve > ~/.mem-port.log 2>&1 & to survive closing the terminal). For something that survives reboots and restarts itself if it ever crashes, set it up as a proper background service.
macOS (launchd)
which node # note this path
which mem-port # note this path too, then resolve the symlink:
readlink -f "$(which mem-port)" # -> .../lib/node_modules/@rsl-innovation/mem-port/bin/mem-port.js
Write ~/Library/LaunchAgents/com.rsl-innovation.mem-port.plist, substituting the two paths above. Invoke node directly with the resolved script path — don't point ProgramArguments at the mem-port shim itself. launchd doesn't inherit your shell's PATH, so the shim's #!/usr/bin/env node shebang fails with env: node: No such file or directory when launchd runs it:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.rsl-innovation.mem-port</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/node</string>
<string>/usr/local/lib/node_modules/@rsl-innovation/mem-port/bin/mem-port.js</string>
<string>serve</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/Users/YOUR_USERNAME/Library/Logs/mem-port.log</string>
<key>StandardErrorPath</key>
<string>/Users/YOUR_USERNAME/Library/Logs/mem-port.error.log</string>
</dict>
</plist>
launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.rsl-innovation.mem-port.plist # start now + on every login
launchctl bootout gui/$(id -u)/com.rsl-innovation.mem-port # stop and unregister
tail -f ~/Library/Logs/mem-port.log ~/Library/Logs/mem-port.error.log # logs
To pick up a new version after npm install -g @rsl-innovation/mem-port, restart the running job in place — no need to unload/reload the plist:
launchctl kickstart -k gui/$(id -u)/com.rsl-innovation.mem-port
To stop it and start it again later, use bootout/bootstrap (above) rather than launchctl stop — this plist's KeepAlive is unconditionally true, so a plain stop gets immediately relaunched by launchd. bootout actually unregisters the job, and bootstrap registers and starts it again.
Linux (systemd --user)
# ~/.config/systemd/user/mem-port.service
[Unit]
Description=mem-port
[Service]
ExecStart=/usr/bin/node /path/to/lib/node_modules/@rsl-innovation/mem-port/bin/mem-port.js serve
Restart=on-failure
[Install]
WantedBy=default.target
systemctl --user enable --now mem-port
journalctl --user -u mem-port -f
Configuration
| Env var | Default | Purpose |
|---|---|---|
MEM_PORT_PORT |
8787 |
HTTP port |
MEM_PORT_DATA_DIR |
OS-appropriate app data dir | Where the SurrealDB store and cached embedding model live |
MEM_PORT_EMBEDDING_MODEL |
Xenova/all-MiniLM-L6-v2 |
Local embedding model id (reserved for future use) |
MEM_PORT_MODEL_CACHE_DIR |
<data-dir>/models |
Override the embedding model cache location |
All state lives under one data directory — the SurrealDB store (surrealkv://, persistent across restarts) and the cached local embedding model. Delete the data dir to fully reset.
Development
npm install
npm run dev # start the daemon with tsx, no build step
npm test # vitest: tenancy isolation + export/import round-trip
npm run typecheck
npm run build # tsup -> dist/, what npx @rsl-innovation/mem-port actually runs
scripts/smoke.sh is a plain-curl smoke test against a already-running daemon (no Node/Inspector dependency, usable in CI):
npm run dev &
./scripts/smoke.sh
Gotchas
- mem-port is a localhost server — it only works with clients running on the same machine. Web/cloud-hosted chat sessions (e.g. chatgpt.com or claude.ai in a browser tab) run server-side and have no route to
127.0.0.1on your computer, so they can't reach mem-port no matter how it's configured. To connect ChatGPT, Claude, or similar tools, install their desktop app and add mem-port there — the desktop app runs locally and can reach the daemon, whereas the same account's web session cannot. - Claude Code's CLI and VS Code extension both run locally already, so they work out of the box (see the connection instructions above) — this gotcha mainly matters for tools you might otherwise only use through a browser.
Known limitations (v1)
- Vector search is brute-force (no HNSW/DISKANN index yet) — fine at personal-memory-store scale, revisit if a library grows very large.
export_library's scope filtering supportsmemory_typesandsince; filtering byentity_idsisn't implemented yet.- No authentication — the daemon binds to
127.0.0.1only and trusts anything running locally on your machine. @huggingface/transformers' bundledonnxruntime-node/sharpcarry known transitive advisories (ZIP/image parsing libs) with no upstream fix yet. mem-port never feeds them untrusted input, butnpm auditwill flag them.
Install Mem Port in Claude Desktop, Claude Code & Cursor
unyly install mem-portInstalls into Claude Desktop, Claude Code, Cursor & VS Code — handles npx, uvx and build-from-source repos for you.
First time? Get the CLI: curl -fsSL https://unyly.org/install | sh
Or configure manually
Run in your terminal:
claude mcp add mem-port -- npx -y @rsl-innovation/mem-portStep-by-step: how to install Mem Port
FAQ
Is Mem Port MCP free?
Yes, Mem Port MCP is free — one-click install via Unyly at no cost.
Does Mem Port need an API key?
No, Mem Port runs without API keys or environment variables.
Is Mem Port hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Mem Port in Claude Desktop, Claude Code or Cursor?
Open Mem Port on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
by modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
by xuzexin-hzCompare Mem Port with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All ai MCPs
