claude mcp add --transport http mnemomatic https://your-server-hostname/mcp \
-H "Authorization: Bearer your-secret-key-here"Replace your-server-hostname with the hostname or IP you used when generating the TLS certificate. The client device must have the mkcert CA trusted (see TLS Setup).
Point any MCP-compatible client to https://your-server-hostname/mcp using the Streamable HTTP transport. Include the Authorization: Bearer <key> header with every request.
Authentication is optional and uses the Bearer token scheme. Requests that fail authentication are rejected before any MCP processing.
Set MNEMOMATIC_API_KEY to enable token validation:
# docker-compose.yml
services:
mnemomatic:
environment:
- MNEMOMATIC_API_KEY=your-secret-key-hereWhen authentication is enabled, all requests must include the Authorization header:
Authorization: Bearer <your-secret-key-here>
If MNEMOMATIC_API_KEY is not set or is empty, the server runs without authentication. This is suitable for local development and trusted networks. The server logs a warning at startup:
WARNING mnemomatic: Authentication disabled — server is running without API key validation
For LAN deployments with TLS, the API key is required — it is the only per-request credential. On TLS alone, any device on your network that trusts the CA could connect without it.
For production deployments:
-
Use a strong, random key — At least 32 characters. Example:
openssl rand -base64 32 # Zn8p7xQvJ9kL2mN3bC4dE5fG6hI7jK8lMnOpQrStUvW= -
Never commit keys to version control — Use environment variables, secrets managers (e.g., Docker Secrets, Kubernetes Secrets), or
.envfiles (excluded from git). -
Use HTTPS in production — Deploy behind a reverse proxy (nginx, Caddy, or similar) with TLS encryption. Authentication headers are transmitted in the
Authorizationheader, which should be encrypted in transit. -
Rotate keys periodically — If a key is compromised or exposed:
- Update
MNEMOMATIC_API_KEY - Restart the server:
docker compose down && docker compose up -d - Update all clients with the new key
- Update
-
Log authentication events — Mnem-O-matic logs all authentication attempts (both successful and failed) at WARNING and DEBUG levels. Monitor these logs for suspicious activity.
| Status | Error | Reason |
|---|---|---|
| 401 | Missing Authorization header | No Authorization header sent with request |
| 401 | Invalid Authorization header format | Header format is not Bearer <token> |
| 401 | Malformed Authorization header | Token is missing or header is incomplete |
| 401 | Invalid Authorization header (empty token) | Token is present but empty |
| 403 | Invalid API key | Token was sent but does not match MNEMOMATIC_API_KEY |
All error responses include a details field explaining the exact issue.
"Missing Authorization header"
- Ensure you're sending the
Authorizationheader with every request - Verify the format:
Bearer <key>(note the space afterBearer)
"Invalid API key"
- Check that the key in your request matches
MNEMOMATIC_API_KEYexactly - Keys are case-sensitive
- Verify there's no leading/trailing whitespace
"Invalid Authorization header format"
- Ensure the header starts with
Bearer(case-insensitive) - The format must be:
Authorization: Bearer <token> - Common mistake: using
TokenorBasicinstead ofBearer
Server starts with "Authentication disabled"
MNEMOMATIC_API_KEYis not set or is empty- Set it in
docker-compose.ymlor pass it via-eflag:docker compose up -e MNEMOMATIC_API_KEY=your-key
Once connected, your LLM has access to these tools:
| Tool | Description |
|---|---|
store_document |
Save a document (code, spec, config) |
store_knowledge |
Save a fact, decision, or observation |
store_note |
Save a quick thought, idea, or transcript |
update_document |
Modify an existing document |
update_knowledge |
Modify an existing knowledge entry |
update_note |
Modify an existing note |
delete_document |
Remove a document |
delete_knowledge |
Remove a knowledge entry |
delete_note |
Remove a note |
tag |
Add or remove tags on any entry |
search |
Search across all stored data |
Mnem-O-matic validates all inputs to prevent silent failures:
| Constraint | Limit | Impact |
|---|---|---|
| Namespace length | ≤ 100 chars | Used for grouping related entries |
| Content length | ≤ 100,000 chars | Documents, notes, facts |
| Title length | ≤ 500 chars | Document/note titles, knowledge subjects |
| Search query | Non-empty, ≤ 10,000 chars | Empty queries rejected; very long queries capped |
| Search results | ≤ 100 results | Limited to prevent memory exhaustion; use smaller limits for faster results |
| Tags per entry | ≤ 100 tags | Too many tags degrade performance |
| Tag length | ≤ 50 chars each | Keep tags short and descriptive |
| Metadata keys | ≤ 50 keys | Avoid excessive metadata |
| Metadata value | ≤ 10,000 chars | Keep values reasonably sized |
| Confidence (knowledge) | 0.0 to 1.0 | Must be a valid probability |
| Embedding dimension | Must match embedder | Mismatch causes search errors; server warns at startup |
If validation fails, tools return an error with details — fix the input and retry.
Store tools use upsert semantics — if an entry with the same namespace and title (for documents) or namespace and subject (for knowledge) already exists, it is updated in place rather than creating a duplicate.
This matters because LLMs don't track what's already stored. Without deduplication, restarting a session and re-storing the same facts would create duplicate rows. With upsert, the second call updates the existing entry and the response includes "created": false so the caller knows it was an update. Notes deduplicate on namespace + title.
# First call — creates a new entry
store_knowledge(namespace="webapp", subject="auth method", fact="Uses JWT with RS256")
→ {"id": "abc-123", "created": true}
# Second call — same namespace + subject, updates in place
store_knowledge(namespace="webapp", subject="auth method", fact="Migrated to session cookies")
→ {"id": "abc-123", "created": false}
The search tool supports three modes:
- fulltext — keyword and phrase matching via SQLite FTS5
- semantic — meaning-based search via vector embeddings
- hybrid (default) — combines both, ranked by a blended score
After connecting Claude Code, you can interact naturally:
"Store a knowledge entry in the 'webapp' namespace: the API uses JWT with RS256 signing for authentication"
"Search for anything related to authentication"
"Store this deployment config as a document in the 'infra' namespace"
"What do you know about the database setup?"
MCP resources provide read-only access to browse stored data:
| Resource URI | Description |
|---|---|
mnemomatic://namespaces |
List all namespaces |
mnemomatic://documents/{namespace} |
List documents in a namespace |
mnemomatic://knowledge/{namespace} |
List knowledge in a namespace |
mnemomatic://notes/{namespace} |
List notes in a namespace |
mnemomatic://document/{id} |
Get a specific document |
mnemomatic://knowledge-entry/{id} |
Get a specific knowledge entry |
mnemomatic://note/{id} |
Get a specific note |