MemoCat MCP Server — Self-Hosted AI Agent Memory and Vector RAG
MemoCat is a self-hosted MCP memory server for Claude Desktop, Cursor,
ChatGPT integrations, and autonomous AI agents. It gives MCP clients private,
persistent, semantically searchable long-term memory. memocat-mcp is a
Model Context Protocol server for
Montycat, combining AI agent memory, semantic
search, vector RAG, and NoSQL storage in one self-hosted service.
Memories are embedded on-device and recalled by meaning, metadata, timestamp, or exact key. No cloud vector database, external embedding API, or per-query bill.
Features
- Self-hosted long-term memory for MCP-compatible AI agents.
- Semantic vector search with metadata and time-range filtering for RAG.
- Persistent memory, in-memory working spaces, bulk writes, updates, and deletion.
- Real-time memory-change subscriptions without database polling.
- Multi-agent scopes, shared memory, delegated-owner governance, and policy explanations.
- Keyspace lifecycle, semantic-model controls, snapshots, and revocation-safe watch buffers.
- One-command
uvx memocat-mcpentry point with native/Docker engine bootstrap.
Why
LLM agents forget context between runs. MemoCat stores each fact in Montycat, embeds and indexes it automatically, and retrieves relevant memories through 22 agent-readable MCP tools. It is both a retrieval layer for RAG and a durable memory layer for autonomous agents.
Quick start
uvx memocat-mcp
MemoCat reuses a configured Montycat Semantic engine or attempts the supported native/Docker bootstrap path. For an existing engine:
export MONTYCAT_URI="montycat://memory-agent:password@localhost:21210/memories"
uvx memocat-mcp
Tools
| Tool | What it does |
|---|---|
memocat_semantic_search |
Recall by meaning (vector kNN), with text or a supplied query vector. |
memocat_remember |
Store a fact/record; embedded automatically or indexed with a supplied vector. |
memocat_remember_bulk |
Store many memories at once. |
memocat_recall |
Fetch by exact key or by field filter. |
memocat_list_memories |
Browse / list stored memories (optionally most-recent first). |
memocat_update |
Revise a memory in place — memory is mutable. |
memocat_forget |
Delete a stored record. |
memocat_list_keyspaces |
Discover available memory namespaces. |
memocat_create_keyspace |
Provision a new memory namespace. |
memocat_remove_keyspace |
Permanently remove an authorized memory namespace with safe watch cleanup. |
memocat_enable_semantic |
Enable semantic search and backfill one authorized keyspace. |
memocat_enable_external_vectors |
Enroll one keyspace for caller-supplied vectors and a named embedding space. |
memocat_semantic_status |
Inspect semantic configuration and backfill state. |
memocat_reembed_semantic |
Replace an enrolled text embedding model and backfill the keyspace. |
memocat_disable_semantic |
Disable semantic search for one authorized keyspace. |
memocat_start_snapshots |
Start scheduled snapshots for one authorized in-memory keyspace. |
memocat_stop_snapshots |
Stop scheduled snapshots for one authorized in-memory keyspace. |
memocat_clean_snapshots |
Delete snapshot files for one authorized in-memory keyspace. |
memocat_policy_view |
View the configured owner's effective governance policy and constraints. |
memocat_policy_explain |
Explain whether a proposed governed action is allowed and why. |
memocat_policy_history |
View governance history visible to the configured owner. |
memocat_await_memory_change |
Wait for memory to change — returns the moment another agent or session writes. Live subscription, not polling. |
Real-time memory watch
Other memory servers can only be polled: ask again, and again, in case something changed. Montycat has native live subscriptions, so this one pushes.
agent B: memocat_await_memory_change(scope="shared", timeout_sec=60)
⏳ sleeps — no polling, no wasted tokens
agent A: memocat_remember({"text": "the deploy key rotated"}, scope="shared")
agent B: ← returns in milliseconds with the key, the value, and the event
Two agents, one shared scope, one notices what the other just learned. Pass the
returned next_seq back as since_seq to resume exactly where you left off —
changes that happen between calls are buffered, not lost.
Memory namespaces are also exposed as MCP resources
(memocat://memory/<keyspace>) with resources.subscribe support, so clients
that implement resource subscriptions get notifications/resources/updated
pushed to them as well. Both surfaces share one engine subscription.
Subscriptions open on demand and close when idle
(MONTYCAT_WATCH_IDLE_TIMEOUT), so users who never watch pay nothing.
Requirements
-
Python 3.10+ through
uv/uvx. -
Access to a Montycat Semantic engine.
uvx memocat-mcpfirst reuses an existing engine, then attempts the supported native/platform installation path, and finally falls back to Docker. Semantic search is enabled by default in the Semantic edition.To start the engine manually with Docker, pick the tag for your CPU—the tag carries the architecture:
Apple Silicon (M1/M2/M3/M4) — use
arm64-semantic:docker run -d --name montycat -p 21210:21210 -p 21211:21211 \ -e MONTYCAT_SUPEROWNER="admin" -e MONTYCAT_PASSWORD="change-me" \ -v montycat_data:/var/lib/.montycat \ montygovernance/montycat:arm64-semantic
Intel / AMD (x86_64) — use
semantic:docker run -d --name montycat -p 21210:21210 -p 21211:21211 \ -e MONTYCAT_SUPEROWNER="admin" -e MONTYCAT_PASSWORD="change-me" \ -v montycat_data:/var/lib/.montycat \ montygovernance/montycat:semantic
On Apple Silicon the plain
semantictag is the amd64 image and runs under emulation, where the embedding runtime's warm-up crashes. Usearm64-semantic— a native build, not a workaround. Unsure which you have?uname -mprintsarm64on Apple Silicon andx86_64on Intel.Port
21211is the subscription server and is required formemocat_await_memory_change(real-time watch); without it the other tools still work.
Docker Compose deployment
Use Compose when you want a reproducible local deployment with a persistent Semantic engine and an MCP container on the same private Docker network. Docker is optional when you already manage a reachable Montycat server.
Create a .env file beside compose.yaml:
MONTYCAT_USERNAME=admin
MONTYCAT_PASSWORD=replace-with-a-strong-password
MONTYCAT_STORE=memories
# Apple Silicon: arm64-semantic. Intel/AMD64: semantic.
MONTYCAT_IMAGE_TAG=semantic
Start the engine and build the MCP image:
docker compose up -d montycat
docker compose build mcp
The image installs the released montycat>=1.2.2,<2 Python client declared in
the package metadata.
The engine data is stored in the named montycat_data volume. Ports 21210
and 21211 are published for debugging and external clients; the MCP container
uses the private montycat:21210 network address. Credentials are passed as
separate environment variables, so passwords with URL-special characters need
no URL encoding. Port 21211 carries live subscription traffic for
memocat_await_memory_change.
MCP uses stdio, so do not run it as a web service. Configure a desktop MCP client to invoke the Compose service on demand:
{
"mcpServers": {
"memocat": {
"command": "docker",
"args": [
"compose",
"-f", "/absolute/path/to/montycat_mcp/compose.yaml",
"run", "--rm", "-T", "mcp"
]
}
}
}
For Apple Silicon set MONTYCAT_IMAGE_TAG=arm64-semantic in .env; the plain
semantic image is AMD64. Stop the stack with docker compose down; include
-v only when you intentionally want to erase persisted memories.
Engine auto-start
MemoCat first reuses an engine already reachable through MONTYCAT_URI or the
host/port settings. If none is running, it looks for an installed
montycat_bin and then attempts the official platform route:
| Platform | Route | If it cannot complete |
|---|---|---|
| macOS Apple Silicon | Discover and download the latest verified montycat-semantic_<version>_arm64.pkg, open Installer, and wait for installation (may prompt for admin approval) |
Docker |
| macOS Intel | No Semantic package currently published | Docker |
| Windows x86_64 | Download verified .msi and invoke Windows Installer (may prompt for UAC) |
Docker |
| Linux AMD64 | Run the official one-command APT setup for montycat-semantic (may prompt for sudo) |
Docker |
| Other platforms | — | Docker |
MemoCat asks the shared Montycat release catalog for the current Semantic
artifact for macOS or Windows. Artifact URLs are treated as opaque, and the
package's adjacent .sha256 is required and verified before Installer opens;
verified packages are cached by filename. If catalog discovery is unavailable,
automatic native installation falls through to Docker instead of silently
installing an older package.
Override the URL with MEMOCAT_INSTALLER_URL, pin a release with
MEMOCAT_ENGINE_VERSION, or adjust the Installer completion budget with
MEMOCAT_INSTALLER_TIMEOUT. On Linux, set
MEMOCAT_APT_INSTALL_COMMAND to use an organization-managed mirror or package
command. ARM64 Linux goes directly to Docker because the official APT repository
is AMD64-only. Set MEMOCAT_AUTOSTART=off to disable all installation/start
attempts.
Use with Claude Desktop / Cursor
Add to your MCP client config (e.g. claude_desktop_config.json):
{
"mcpServers": {
"memocat": {
"command": "uvx",
"args": ["memocat-mcp"],
"env": {
"MONTYCAT_URI": "montycat://memory-agent:agent-password@localhost:21210/mystore"
}
}
}
}
Use a delegated Montycat owner such as memory-agent for the MCP process.
Grant that owner only the keyspace read/write and provisioning capabilities its
agent needs. Keep the superowner credential in a separate bootstrap or
governance-administration workflow.
The read-only memocat_policy_view, memocat_policy_explain, and
memocat_policy_history tools expose policy information for the authenticated
owner. They do not accept an owner override and cannot grant, revoke, deny, or
otherwise mutate policy. When automatic keyspace provisioning fails, MemoCat
also requests a read-only policy explanation and appends it to the original
engine error when available.
memocat_remove_keyspace is destructive and remains engine-authorized. A
delegated owner may remove a keyspace through creator authority or an explicit
remove-keyspace grant unless policy contains an overriding denial. MemoCat
closes active watches and releases resource subscriptions before requesting
removal.
Semantic management is always keyspace-scoped. The MCP server does not expose
database-wide semantic controls; Montycat checks manage-semantic, creator
authority, denials, and model allow-lists for every enable or disable request.
Snapshot tools are likewise keyspace-scoped and work only with in-memory
keyspaces. MemoCat does not expose the global snapshot-rate setting. A
Snapshot rate is not set response means scheduling has not been configured
on the engine; it is distinct from a governance denial.
Active watches use short authorization leases because the current engine checks read authority when a subscription opens but does not terminate that connection after a later revocation. MemoCat revalidates against the engine's filtered structure view, closes the subscription on access loss, removes MCP resource ownership, wakes pending callers with an error, and permanently purges buffered changes so they cannot be replayed after access is restored.
Configuration
| Variable | Default | Purpose |
|---|---|---|
MONTYCAT_URI |
— | montycat://user:pass@host:port/store (preferred; overrides the parts below) |
MONTYCAT_HOST |
127.0.0.1 |
Engine host |
MONTYCAT_PORT |
21210 |
Engine port |
MONTYCAT_USERNAME / MONTYCAT_PASSWORD |
— | Credentials |
MONTYCAT_STORE |
— | Store name |
MONTYCAT_TLS |
false |
Connect over TLS |
MONTYCAT_DEFAULT_KEYSPACE |
memory |
Keyspace used when a tool omits scope/keyspace |
MONTYCAT_PERSISTENT |
true |
Storage type for newly created keyspaces (durable vs in-memory). Existing keyspaces are auto-detected — the server binds the correct type regardless of this setting. |
MONTYCAT_SCOPE |
— | Default owner/scope, applied when a tool omits scope |
MONTYCAT_SCOPE_PREFIX |
mem_ |
Prefix for per-owner keyspaces (mem_<scope>) |
MONTYCAT_SHARED_KEYSPACE |
mem_shared |
The common/shared keyspace name |
MONTYCAT_AUTO_PROVISION |
true |
Auto-create a scope's keyspace on first use. Requires provision-keyspace authority for the configured owner and requested storage/model constraints. |
MONTYCAT_AUTO_TIMESTAMP |
true |
Stamp each memory with an indexed _created_at, enabling time-range recall (since/until). Costs a server-side timestamp parse per write — turn off if memories are never recalled by time. |
MONTYCAT_SUBSCRIPTION_PORT |
main + 1 | Engine subscription server port (21211 by default; enabled by default) |
MONTYCAT_WATCH_BUFFER |
500 |
Changes retained per watched keyspace, so changes between calls aren't lost |
MONTYCAT_WATCH_IDLE_TIMEOUT |
300 |
Seconds before an unused subscription is closed |
MONTYCAT_WATCH_AUTH_LEASE_SEC |
5 |
Seconds between read-authority checks for active watches. Access loss closes the subscription and purges buffered changes. |
MONTYCAT_WATCH_AUTH_TIMEOUT_SEC |
10 |
Maximum seconds allowed for one watch authorization check. A failed check closes the watch safely. |
memocat_create_keyspace works with delegated-owner credentials when policy
grants provision-keyspace for the requested store, storage type, and semantic
model. memocat_forget deletes one record and requires write authority for its
keyspace. The engine makes every final authorization decision.
Memory scoping (multi-tenant)
Pass scope (an owner/user id) to any memory tool to isolate that owner's
memory. Because Montycat's semantic search runs per keyspace, each scope gets its
own keyspace mem_<scope> — so semantic recall for one owner never sees another
owner's memories:
remember(value={"fact": "..."}, scope="alice") # -> keyspace mem_alice
semantic_search(query="...", scope="alice") # searches only mem_alice
remember(value={"fact": "..."}, scope="shared") # -> the shared keyspace
- Per-owner private memory —
scope="<owner>"→mem_<owner>, auto-created on first use when the configured owner has provisioning authority. - Shared/common memory —
scope="shared"→ theMONTYCAT_SHARED_KEYSPACE. - Group memory — use a group id as the scope (e.g.
scope="team_eng"). - Single-tenant — set
MONTYCAT_SCOPEonce and omitscopeper call.
This maps onto Montycat's keyspace governance. In production, run one server instance per agent or service with delegated-owner credentials and grant only the provisioning and data authority it needs.
Isolation note: scope is routing convenience, not authenticated identity.
With one server instance sharing one connection, scopes provide logical
keyspace organization. For credential-enforced isolation, run one server
instance per owner with that owner's delegated credentials; the engine then
denies cross-owner access. Reserve superowner credentials for bootstrap and
governance administration.
Links
- Montycat: https://montygovernance.com
- Docs: https://montygovernance.com/docs
- Engine on Docker Hub: https://hub.docker.com/r/montygovernance/montycat
- Python client (PyPI): https://pypi.org/project/montycat/
License
MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file memocat_mcp-0.4.0.tar.gz.
File metadata
- Download URL: memocat_mcp-0.4.0.tar.gz
- Upload date:
- Size: 59.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0dbce97338ee350f3d9c7684cd2fc9cfe3f2aa77b59e30b1a2d362db92d8965
|
|
| MD5 |
10d45961345f9917e1a53ca64870f243
|
|
| BLAKE2b-256 |
904072ee0a0db20c34a04975625ad03f0b3d595cd503efcf5d072cea76d8be49
|
File details
Details for the file memocat_mcp-0.4.0-py3-none-any.whl.
File metadata
- Download URL: memocat_mcp-0.4.0-py3-none-any.whl
- Upload date:
- Size: 38.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a37af68c1b5352729a871f903034d3d89df23e8f98fc9577456389056eece8f1
|
|
| MD5 |
2ea9422aa5f8454ed3ebe9ffd888c7b0
|
|
| BLAKE2b-256 |
a770f5ffb0c2a6664cc2b925c38a804212d231f5502a2c67ec0ec195b167dda9
|