- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
memory_forget akzeptiert wie memory_get/pending/consolidate einen
server-autorisierten Unterprojekt-Scope, sodass Pending-Einträge aus dem
Root-Scope heraus verworfen werden können. Autorisierung mit
for_mutation=True: nur eigener Scope und Scopes darunter. read_scopes
werden dafür nun auch bei memory_forget mit project berechnet.
Fix: Das Label des eigenen Scopes (".") wurde bei Mutationen fälschlich
als read-only abgelehnt; betraf auch memory_consolidate.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
||
| .forgejo/workflows | ||
| deploy/k8s | ||
| docs | ||
| evals | ||
| hooks | ||
| mongomind | ||
| tests | ||
| .dockerignore | ||
| .gitignore | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| COMMERCIAL-LICENSE.de.md | ||
| COMMERCIAL-LICENSE.es.md | ||
| COMMERCIAL-LICENSE.md | ||
| CONTRIBUTING.de.md | ||
| CONTRIBUTING.es.md | ||
| CONTRIBUTING.md | ||
| Dockerfile | ||
| LICENSE | ||
| pyproject.toml | ||
| README.de.md | ||
| README.es.md | ||
| README.md | ||
| SECURITY.de.md | ||
| SECURITY.es.md | ||
| SECURITY.md | ||
MongoMind
MongoMind is a resource-efficient, project-based memory system for coding agents. It provides the same MCP toolkit locally via stdio and remotely via Streamable HTTP. Active knowledge is curated; automatically captured session events are initially placed in a pending layer.
The runtime requires Python 3.10 or newer, pymongo, and PyJWT[crypto]. It does not launch an LLM,
an embedding model, a graph runtime, or a background worker. Compression, redaction,
ranking, and rollups are mechanical and limited.
Operating Modes
| Mode | Transport and Project Binding | Authentication | Use Case |
|---|---|---|---|
| Local Standard | Dedicated stdio process per MCP client; project from Git top-level/cwd or MONGOMIND_PROJECT_ID |
Local process boundary and MongoDB access | Recommended for single-machine operation |
| Remote | POST /mcp/<slug>; slug is mapped to a fixed project ID via a server-side ACL |
OAuth/OIDC, external discovery/JWKS, exact resource audience and scopes | HTTPS/multi-machine operation |
Remote identity comes exclusively from the verified token and the server-side
project registry. The old headers X-MongoMind-Project and X-MongoMind-Client are invalid
and will be rejected. The HTTP transport will not even start without a complete OAuth 2.1
configuration (MONGOMIND_OAUTH_ISSUER).
Installation
git clone <REPOSITORY-URL> mongomind-mcp
cd mongomind-mcp
python3 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -e .
This makes mongomind-mcp, mongomind-http, mongomind-admin,
mongomind-hook-start, and mongomind-hook-capture available in .venv/bin/.
MongoDB User
The runtime user requires read and write permissions on the database
mongomind in the target system, but no user management permissions. init and migrate additionally require
index/schema permissions; for this purpose, a separate administration account should only be used during the
maintenance window.
Example in mongosh as an existing MongoDB administrator. The runtime role is intentionally not allowed to
create indexes or physically delete records; init also creates counters and locks
before the first runtime startup:
use mongomind
db.createRole({
role: "mongomindRuntime",
privileges: [
{
resource: {db: "mongomind", collection: "observations"},
actions: ["find", "insert", "update"]
},
{
resource: {db: "mongomind", collection: "counters"},
actions: ["find", "insert", "update"]
},
{
resource: {db: "mongomind", collection: "locks"},
actions: ["find", "insert", "update", "remove"]
}
],
roles: []
})
db.createUser({
user: "mongomind-runtime",
pwd: "LONG-RANDOM-RUNTIME-PASSWORD",
roles: [{role: "mongomindRuntime", db: "mongomind"}]
})
db.createUser({
user: "mongomind-admin",
pwd: "DIFFERENT-LONG-RANDOM-ADMIN-PASSWORD",
roles: [
{role: "readWrite", db: "mongomind"},
{role: "dbAdmin", db: "mongomind"}
]
})
install -d -m 700 ~/.env
install -m 600 /dev/null ~/.env/.mongomind_env
Contents of ~/.env/.mongomind_env:
MONGODB_MONGOMIND_URI="mongodb://mongomind-runtime:PASSWORD@localhost:27017/mongomind?authSource=mongomind"
MONGODB_MONGOMIND_ADMIN_URI="mongodb://mongomind-admin:ADMIN-PASSWORD@localhost:27017/mongomind?authSource=mongomind"
mongomind/store.py automatically reads this file and rejects insecure file permissions,
symlinks, foreign owners, or sizes exceeding 64 KiB. Runtime paths use only
MONGODB_MONGOMIND_URI; admin database commands prefer
MONGODB_MONGOMIND_ADMIN_URI and only fall back to the runtime URI if it is missing. URIs and
passwords do not belong in the repo or in hook files.
Initialize and Migrate the Database
New, empty database:
.venv/bin/mongomind-admin init
.venv/bin/mongomind-admin check
Before migrating existing data, follow this sequence: dry run → secure backup → migration → check. The runtime itself does not perform any migration or index changes.
Before the write migration run, terminate all MongoMind HTTP/MCP processes and pause the
hooks. Do not restart the runtime until migrate and the subsequent check are healthy; during
normalization, uniqueness indexes are checked and rebuilt.
.venv/bin/mongomind-admin migrate --dry-run
set -a
. ~/.env/.mongomind_env
set +a
umask 077
backup_dir="$(mktemp -d "$HOME/mongomind-backup.XXXXXX")"
backup_uri="${MONGODB_MONGOMIND_ADMIN_URI:-$MONGODB_MONGOMIND_URI}"
mongodump --uri="$backup_uri" \
--archive="$backup_dir/mongomind.archive.gz" --gzip
unset backup_uri
chmod 700 "$backup_dir"
chmod 600 "$backup_dir/mongomind.archive.gz"
.venv/bin/mongomind-admin migrate
.venv/bin/mongomind-admin check
For these four commands, MONGODB_MONGOMIND_ADMIN_URI should point to the separate
administration account; the running runtime retains its restricted URI.
migrate --dry-run does not write. check pings the database, checks migration invariants, and compares each
named index exactly, including key order, unique and
partialFilterExpression. If there is drift, the check is invalid; running init/migrate
restores the canonical definitions.
Local stdio operation
Claude Code:
claude mcp add mongomind --scope user \
--env MONGOMIND_CLIENT=claude -- "$PWD/.venv/bin/mongomind-mcp"
Codex:
codex mcp add mongomind \
--env MONGOMIND_CLIENT=codex -- "$PWD/.venv/bin/mongomind-mcp"
Other MCP clients run the same stdio command. MONGOMIND_PROJECT_ID can intentionally merge multiple worktrees
under a stable, local project ID. MONGOMIND_READONLY=1
denies write tools and also prevents reinforcement.
Remote Operation with OAuth/OIDC
MongoMind is a resource server, not an identity provider. The external provider must
provide OIDC discovery, JWKS, asymmetrically signed JWT access tokens, and the required scopes.
For the slug mixxx, the resource and the expected single aud are exactly:
https://memory.example/mcp/mixxx
Multiple audiences or a different spelling will be rejected. The project and principal are
bound on the server side from <slug>, sub, and client_id.
Project Registry v1
/etc/mongomind/projects.json:
{
"version": 1,
"projects": {
"mixxx": {
"project_id": "repo:mixxx",
"allowed_principals": [
{"sub": "user-123", "client_id": "codex-client"},
{"sub": "hooks-mixxx", "client_id": "mongomind-hooks"}
],
"read_children": ["mixxx-worktree"]
},
"mixxx-worktree": {
"project_id": "repo:mixxx/worktree",
"allowed_principals": []
}
}
}
sudo chown mongomind:mongomind /etc/mongomind/projects.json
sudo chmod 600 /etc/mongomind/projects.json
The file must be regular, symlink-free, owned by the server process, and have the exact mode
0600. Slugs, project IDs, principals, count, and file size are limited; unknown
fields and duplicate JSON keys are rejected using fail-closed. read_children is optional and
also grants the project read access to transitive subprojects; the
relationships must point to registered slugs and must not contain cycles. Reading
children is an explicit registry permission, not a filesystem search. The optional
include_global: false hides the curated global entries for that slug (see docs/configuration.md).
Start the server
Behind a TLS-terminating reverse proxy:
MONGOMIND_PUBLIC_BASE_URL=https://memory.example \
MONGOMIND_OAUTH_ISSUER=https://id.example/realms/agents \
MONGOMIND_PROJECTS_FILE=/etc/mongomind/projects.json \
MONGOMIND_HTTP_HOST=0.0.0.0 MONGOMIND_HTTP_PORT=8642 \
MONGOMIND_HTTP_BEHIND_PROXY=1 \
.venv/bin/mongomind-http
Alternatively, MongoMind terminates TLS itself if MONGOMIND_TLS_CERT and
MONGOMIND_TLS_KEY are set together. The proxy must set request and header limits at least
as strictly, enforce connection timeouts, and must not make the unencrypted backend port
publicly accessible.
Public, project-specific protected resource metadata:
GET https://memory.example/.well-known/oauth-protected-resource/mcp/mixxx
The metadata refers to the configured issuer and resource. Discovery and JWKS are loaded only via HTTPS, without redirects, with size limits, and with caching.
Scopes
| Scope | Permission |
|---|---|
mongomind:read |
Index, Search, Detail Retrieval, Pending, and Statistics |
mongomind:write |
Save, Forget, Consolidate, and Rollup; also allows Reinforcement with memory_get |
mongomind:transfer |
Server-side file export and import |
mongomind:hooks:read |
POST /hooks/<slug>/start |
mongomind:hooks:write |
POST /hooks/<slug>/events |
mongomind:global:write |
Additional gate for memory_save(scope="global"); MONGOMIND_ALLOW_GLOBAL_WRITE=1 must also apply on the server side; always refused for registry slugs with include_global: false |
Remote Clients
Codex registers the resource and then initiates interactive provider authorization:
codex mcp add mongomind-mixxx \
--url https://memory.example/mcp/mixxx \
--oauth-client-id codex-client \
--oauth-resource https://memory.example/mcp/mixxx
codex mcp login mongomind-mixxx \
--scopes mongomind:read,mongomind:write,mongomind:transfer
Claude Code:
claude mcp add --transport http --scope user \
--client-id claude-client mongomind-mixxx \
https://memory.example/mcp/mixxx
The OAuth provider must register these client IDs, allow redirect URIs as specified by the respective client, and issue JWTs with the exact resource audience. User authorization takes place at the provider; MongoMind does not accept passwords, authorization codes, or static remote headers.
Hooks
Templates are available at hooks/hooks.json (Claude Code) and
hooks/codex.json (Codex). Using the admin tools, you can generate templates for the
current installation and then review them in read-only mode:
.venv/bin/mongomind-admin hooks render --client claude --transport local \
> /tmp/mongomind-claude-hooks.json
.venv/bin/mongomind-admin hooks check --file /tmp/mongomind-claude-hooks.json
The output is intentionally not automatically merged into an existing client configuration;
copy the field hooks from it into the respective client configuration. The committed files
are examples for this checkout, while hooks render uses the interpreter and remote environment
of the current installation.
Local Hooks
Without MONGOMIND_HOOK_URL, the hook processes access MongoDB directly. SessionStart reads
the active index; UserPromptSubmit, PostToolUse, Stop, and SessionEnd update one
pending entry per project, client, and session. The templates must point to the scripts or the
installed entry points of the virtual environment being used.
When the pending threshold is reached, SessionStart returns, in addition to the model context,
a visible systemMessage for Claude Code and Codex with the instruction to check memory_pending
and consolidate relevant entries. Active curated entries from nested
subprojects appear in the index; pending sessions remain limited to the specific project.
A git push is an exception to the otherwise strict “Pending” recording (see
memory.md, section “Exception: git push”): PostToolUse immediately
creates an additional active auto-captured/git-push note and returns—synchronously to the same still
open session—a curation prompt, rather than waiting until the next SessionStart to
remind the user. If curation does not occur, the auto-note remains active as a safety net.
This is not currently a foolproof guarantee with Codex: The Codex template still uses
exec_command|functions.exec_command, while Codex Unified Exec is matched under Bash according to the current
Hook documentation.
On the local Codex CLI (0.147.0), PostToolUse errors with invalid JSON and
exit code 1 were also observed. A terminal push outside of Codex is not captured by this hook.
The open issue is documented in the
Codex Review.
Remote Hooks
Remote hooks use OAuth client_credentials; user tokens are not reused.
install -d -m 700 ~/.config/mongomind
install -m 600 /dev/null ~/.config/mongomind/hook-client.secret
printf '%s\n' 'PROVIDER-CLIENT-SECRET' > ~/.config/mongomind/hook-client.secret
chmod 600 ~/.config/mongomind/hook-client.secret
export MONGOMIND_HOOK_URL=https://memory.example/hooks/mixxx
export MONGOMIND_OAUTH_RESOURCE=https://memory.example/mcp/mixxx
export MONGOMIND_OAUTH_CLIENT_ID=mongomind-hooks
export MONGOMIND_OAUTH_CLIENT_SECRET_FILE=$HOME/.config/mongomind/hook-client.secret
export MONGOMIND_OAUTH_TOKEN_CACHE_FILE=$HOME/.config/mongomind/hook-token.json
export MONGOMIND_OAUTH_SCOPES='mongomind:hooks:read mongomind:hooks:write'
.venv/bin/mongomind-admin hooks render --client codex --transport remote \
> /tmp/mongomind-codex-remote-hooks.json
.venv/bin/mongomind-admin hooks check --file /tmp/mongomind-codex-remote-hooks.json
The hook and resource URLs must have the same HTTPS origin and slug. The client determines the
token endpoint via Protected-Resource and Authorization-Server metadata, does not follow any redirects,
and stores the token atomically in a file with 0600. The secret and cache must be separate
files. The secret itself is never written to rendered hook commands.
Hook inputs are limited to 1 MiB. Only a normalized and redacted payload containing
the event, a stable SHA-256-event_id, session/turn ID, limited prompt/assistant text,
tool name, and at most 20 modified paths. Raw tool_input, cwd, and secrets
do not leave the client. Repeated event_ids are idempotent. Hook entry points are intentionally
fail-open: In the event of configuration, OAuth, network, or database errors, they write {} and
terminate with status 0 so that the coding agent can continue working. stderr with status 0
ends up only in the debug log of the respective host CLI—it does not appear in the transcript and is
invisible to both the user and the model. For the one error where this is relevant—MongoDB is
unreachable—session_start.py therefore specifically sets a systemMessage instead of relying on stderr
(see docs/configuration.md).
All hook variables, limits, and CA/timeout settings are listed in
docs/configuration.md.
Cross-Device Sync
memory_import always recalculates the target scope from the calling context—locally, this is
the device-dependent Git top-level path; remotely, it is the device-independent slug project_id. To ensure
that the same repo ends up on multiple devices within the same mongomind-web project,
mongomind-sync push bundles the export, scp, and the import to the correct /mcp/<slug> endpoint:
.venv/bin/mongomind-sync push --dry-run # export locally only
MONGOMIND_SYNC_BASE_URL=https://memory.example \
.venv/bin/mongomind-sync push # export -> scp -> import
The target slug is resolved from .mongomind.json in the repo or ~/.mongomind/project-map.json (key:
normalized git remote get-url origin); it is never guessed. Details, all options, and the
OAuth variables used can be found in
docs/configuration.md.
MCP Tools
| Tool | Behavior |
|---|---|
memory_save |
Save redacted, compressed, deduplicated active knowledge |
memory_index |
Prioritized and type-diversified index of the current project and its child projects |
memory_search |
Full-text search within the read scope, with automatic synonym expansion, filters, and hybrid ranking |
memory_get |
Content and provenance for up to 10 IDs; child-project results are shown, while reinforcement remains scoped to the exact project. Optional project targets an already server-authorized child project explicitly, including its pending entries |
memory_pending |
Check automatically recorded pending sessions. Optional project targets an already server-authorized child project instead of the current one |
memory_consolidate |
Transfer pending sources atomically to an active memory. Optional project curates an already server-authorized child project; the result then records which scope it was curated from |
memory_forget |
Archive exact project IDs |
memory_stats |
Active, pending, archive, and expiration counters |
memory_rollup |
Consolidate a limited batch of old pending sessions |
memory_export |
Export data as a file to the server process’s file system |
memory_import |
Import a file from the server process’s file system |
memory_index, memory_search, and memory_get mark hits with Projekt=. Locally,
this is a path relative to the selected workspace root; remotely, it is the registry slug. This origin is
read-only; saving, forgetting, and consolidating remain specific to the exact project.
Remote import/export does not transfer files via MCP. The paths are always located on the server side under
~/.mongomind/exports/; therefore, a remote client does not receive a direct download or
upload. This is listed as an open UX enhancement in the Roadmap.
The distinction between MongoMind as a project-specific memory layer and a direct,
generic MongoDB MCP is documented in
docs/mongomind-vs-mongodb-mcp.md.
Security Boundaries
- MCP request and entire response: maximum of 1 MiB each; tool text maximum of 768 KiB; JSON depth 64; no duplicate keys, non-finite numbers, or JSON-RPC batches.
- HTTP: Request line 8 KiB, total headers 32 KiB and 50 fields, MCP body 1 MiB, hook body 64 KiB, 16 concurrent connections (configurable from 1 to 128), queue 32, request timeout 5 s.
- HTTP rates: globally 1200 requests/minute and per peer/principal 240/minute; MCP tools additionally 120 calls/minute and 30 write calls/minute per rate key.
memory_get: maximum of 10 IDs; general ID lists 100; title 300 characters; content 64 KiB; 20 tags; search query 500 characters.- Export: maximum of 500 records and 40 MiB, fixed export folder with
0700/0600and path traversal protection. Import undergoes the same field validation, redaction, compression, and deduplication asmemory_save. - Secrets and
<private>blocks are redacted before storage or hook transmission. However, memories remain untrusted data and must be verified against the repository.
Administration and Diagnostics
.venv/bin/mongomind-admin auth check --offline
.venv/bin/mongomind-admin auth check
.venv/bin/mongomind-admin interop render --help
.venv/bin/mongomind-admin hooks render --help
.venv/bin/mongomind-admin hooks check --help
The offline auth check verifies the configuration and registry without provider access; the online check
additionally loads the OIDC discovery and validates the issuer as well as jwks_uri. The JWKS itself is
loaded to a limited extent during the first token check. The complete variable reference is available at
docs/configuration.md, the staging interoperability verification at
docs/interop.md, the architecture at docs/architecture.md
and the memory model in docs/memory.md, the roadmap in
docs/roadmap.md, and the security review in
docs/feedback-codex.md.
Tests
.venv/bin/python -m unittest discover -s tests -v
E2E exclusively against a disposable database:
MONGOMIND_TEST_URI=mongodb://127.0.0.1:27717/mongomind_test \
.venv/bin/python -m unittest tests.test_store_e2e -v
Compression benchmark:
.venv/bin/python -m evals.bench
License
MongoMind is free for personal, educational, scientific, charitable, and other non-commercial purposes. Commercial use requires a separate agreement.