Direct API vs MCP Tools
The AutoMem system is accessible through two interfaces: the HTTP API (direct REST calls to the AutoMem server) and the MCP tools (JSON-RPC calls through the mcp-automem bridge). Both interfaces reach the same backend but differ in transport, parameter style, and what they expose to callers.
For the HTTP API reference, see Memory Operations, Recall Operations, and related pages. For MCP setup, see MCP Integration.
Architecture Overview
Section titled “Architecture Overview”graph LR
subgraph mcp["MCP JSON-RPC Tools"]
StoreMemory["store_memory"]
RecallMemory["recall_memory"]
AssociateMemories["associate_memories"]
UpdateMemory["update_memory"]
DeleteMemory["delete_memory"]
CheckHealth["check_database_health"]
end
subgraph client["AutoMemClient Methods"]
StoreMethod["storeMemory(args)"]
RecallMethod["recallMemory(args)"]
AssociateMethod["associateMemories(args)"]
UpdateMethod["updateMemory(args)"]
DeleteMethod["deleteMemory(args)"]
HealthMethod["checkHealth()"]
end
subgraph api["AutoMem HTTP API"]
PostMemory["POST /memory"]
GetRecall["GET /recall"]
PostAssociate["POST /associate"]
PatchMemory["PATCH /memory/:id"]
DeleteMemoryEndpoint["DELETE /memory/:id"]
GetHealth["GET /health"]
end
StoreMemory --> StoreMethod
RecallMemory --> RecallMethod
AssociateMemories --> AssociateMethod
UpdateMemory --> UpdateMethod
DeleteMemory --> DeleteMethod
CheckHealth --> HealthMethod
StoreMethod -->|"JSON body"| PostMemory
RecallMethod -->|"Query params"| GetRecall
AssociateMethod -->|"JSON body"| PostAssociate
UpdateMethod -->|"JSON body"| PatchMemory
DeleteMethod -->|"URL param"| DeleteMemoryEndpoint
HealthMethod -->|"No params"| GetHealth
The MCP bridge (mcp-automem) operates as a thin translation layer. Each MCP tool call is mapped to an AutoMemClient method, which in turn makes an HTTP request to the AutoMem server. The bridge keeps no storage or ranking logic of its own — it handles parameter mapping, argument validation, the client-side supersede flow, and response formatting.
MCP Server Architecture
Section titled “MCP Server Architecture”Dual Operational Mode
Section titled “Dual Operational Mode”The mcp-automem package (src/index.ts) serves two purposes from a single entry point:
- Server Mode: When launched without arguments, it becomes an MCP server communicating over stdio
- CLI Mode: When launched with commands (
setup,cursor,recall, etc.), it executes utility functions and exits
Mode detection occurs immediately at startup:
// src/index.ts lines 30-31const command = (process.argv[2] || '').toLowerCase();const isServerMode = command.length === 0;In server mode the entry point goes on to rebind the console and start the stdio server. In CLI mode it runs the matching command handler and exits; an unrecognized command prints an error and exits with code 1 (src/index.ts lines 407-411).
This allows a single npm package to serve as both an interactive MCP server for AI platforms and a command-line toolkit for configuration management.
Stdio Transport
Section titled “Stdio Transport”In server mode, all MCP communication occurs over stdin/stdout using the StdioServerTransport from @modelcontextprotocol/sdk. console.log, console.info, console.debug, and console.warn are rebound to console.error, which writes to stderr, to keep logging off the JSON-RPC channel:
// src/index.ts lines 78-84 (server mode only)if (isServerMode) { const logToStderr = (...args: unknown[]) => console.error(...args); console.log = logToStderr; console.info = logToStderr; console.debug = logToStderr; console.warn = logToStderr;}Process Lifecycle
Section titled “Process Lifecycle”| Stage | Lines | Description |
|---|---|---|
| Entry | 1–28 | Shebang, imports, isInteractiveTerminal() helper |
| Mode Detection | 30–84 | Determine server vs CLI mode, decide whether to silence the dotenv banner, and redirect logging in server mode |
| Startup Helpers | 86–125 | Load .env, set the optional process title, define installStdioErrorGuards(), read the package version |
| CLI Routing | 127–411 | Print help, execute CLI commands and exit, reject unknown commands |
| Configuration | 413–433 | Resolve the API URL and key, create AutoMemClient |
| Server Setup | 435–439 | Build the server with createAutoMemMcpServer() (tools and handlers live in src/mcp-surface.ts) |
| Main Loop | 441–496 | main(): install stdio guards, create StdioServerTransport, register shutdown triggers, connect |
Error Resilience
Section titled “Error Resilience”The server guards against two classes of failures:
Broken pipe errors — When the AI platform terminates the connection unexpectedly:
// src/index.ts lines 102-112function installStdioErrorGuards() { const handler = (error: unknown) => { const err = error as { code?: string } | undefined; if (err?.code === 'EPIPE' || err?.code === 'ECONNRESET') { process.exit(0); } };
process.stdout.on('error', handler); process.stderr.on('error', handler);}Tool execution errors — All tool handlers are wrapped in try-catch (src/mcp-surface.ts lines 1041-1320), returning MCP error responses rather than crashing the server.
The Six MCP Tools
Section titled “The Six MCP Tools”graph TB
subgraph tools["MCP Tools (createAutoMemMcpServer)"]
direction TB
T1["store_memory<br/>One of: content (single)<br/>or memories[] (batch)<br/>Optional: tags, importance,<br/>embedding, metadata, timestamps,<br/>supersede fields"]
T2["recall_memory<br/>Modes: memory_id (fetch),<br/>tags + exhaustive (enumerate),<br/>or ranked retrieval<br/>Optional: query, queries,<br/>embedding, limit, sort,<br/>time filters, tags,<br/>expand options, context hints"]
T3["associate_memories<br/>Pair: memory1_id, memory2_id,<br/>type, strength<br/>or associations[] (batch)"]
T4["update_memory<br/>Required: memory_id<br/>Optional: content, tags,<br/>importance, metadata, timestamps"]
T5["delete_memory<br/>One of: memory_id or tags"]
T6["check_database_health<br/>No parameters"]
end
subgraph schemas["Input Schemas"]
S1["type: object<br/>properties: {content, memories[],<br/>tags[], importance, embedding[], ...}<br/>no top-level required"]
S2["type: object<br/>properties: {memory_id, exhaustive,<br/>query, queries[], embedding[],<br/>limit, offset, sort, format,<br/>expand_relations, expand_entities,<br/>context, language, ...}<br/>no top-level required"]
S3["type: object<br/>properties: {memory1_id,<br/>memory2_id, type, strength,<br/>associations[], edge props}<br/>no top-level required"]
S4["type: object<br/>properties: {memory_id,<br/>content, tags[], importance, ...}<br/>required: ['memory_id']"]
S5["type: object<br/>properties: {memory_id, tags[]}<br/>no top-level required"]
S6["type: object<br/>properties: {}"]
end
T1 --- S1
T2 --- S2
T3 --- S3
T4 --- S4
T5 --- S5
T6 --- S6
Tool Summary
Section titled “Tool Summary”| Tool Name | HTTP Equivalent | Read-Only | Destructive | Idempotent |
|---|---|---|---|---|
store_memory | POST /memory (batch mode: POST /memory/batch) | No | No | No |
recall_memory | GET /recall (ID fetch: GET /memory/:id; tag enumeration: GET /memory/by-tag) | Yes | No | Yes |
associate_memories | POST /associate (pair and batch modes) | No | No | Yes |
update_memory | PATCH /memory/:id | No | No | Yes |
delete_memory | DELETE /memory/:id (bulk by tag: DELETE /memory/by-tag) | No | Yes | No |
check_database_health | GET /health | Yes | No | Yes |
MCP Tool Annotations
Section titled “MCP Tool Annotations”MCP tool annotations provide semantic hints to AI platforms about tool behavior:
| Annotation | Type | Meaning | Applied To |
|---|---|---|---|
readOnlyHint | boolean | Tool only reads data | recall_memory, check_database_health |
destructiveHint | boolean | Tool may perform destructive updates (only meaningful when readOnlyHint is false) | delete_memory only |
idempotentHint | boolean | Repeated calls with the same arguments have no additional effect on the environment (only meaningful when readOnlyHint is false) | All except store_memory and delete_memory |
openWorldHint | boolean | Tool may interact with an open world of external entities, such as web search (a memory tool’s domain is closed) | false for all tools |
Side-by-Side Tool Reference
Section titled “Side-by-Side Tool Reference”store_memory vs POST /memory
Section titled “store_memory vs POST /memory”MCP Tool Input Schema:
store_memory is mode-multiplexed: pass top-level content for a single memory (add supersedes_memory_id to replace an existing one), or memories: [...] for a batch. The input schema has no top-level required array, but the MCP client throws if you send neither content nor memories.
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
content | string | Single mode (XOR memories) | Runtime: ≤2000 chars | Memory content to store |
memories | array[object] | Batch mode (XOR content) | 1–500 items; each item requires non-empty content | Memories to store in one request. Per-item fields: tags, importance, timestamp, type, confidence, metadata |
tags | array[string] | No | — | Categorization tags |
importance | number | No | 0–1 | Significance score |
embedding | array[number] | No | Single mode only | Optional pre-computed vector |
metadata | object | No | — | Structured additional data |
timestamp | string | No | ISO format | Creation timestamp |
type | string | No | enum: Decision, Pattern, Preference, Style, Habit, Insight, Context | Memory type classification |
confidence | number | No | 0–1 | Classification confidence (defaults to 0.9 when type is set) |
t_valid, t_invalid | string | No | ISO 8601, single mode only | Validity window |
updated_at, last_accessed | string | No | ISO 8601, single mode only | Explicit timestamps |
supersedes_memory_id | string | No | Single mode only | Existing memory this one replaces or corrects |
supersede_relation | string | No | INVALIDATED_BY (default) | EVOLVED_INTO | Relation created from the old memory to the new one |
supersede_reason | string | No | — | Reason stored on the old memory’s metadata |
In batch mode, put tags, importance, and the other per-item fields inside each memories entry. The client rejects any top-level single-mode field sent alongside memories, and it rejects per-item id, embedding, t_valid, and t_invalid.
MCP Tool Output:
Only message is a required output field. The rest depend on which mode ran.
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | Confirmation message |
memory_id | string | No | Single and supersede modes: ID of the stored memory |
memory_ids | array[string] | No | Batch mode: IDs of the stored memories |
stored | integer | No | Batch mode: number of memories stored |
qdrant, enrichment | string | No | Batch mode: indexing and enrichment status reported by the server |
query_time_ms | number | No | Batch mode: server-reported execution time |
superseded_memory_id | string | No | Supersede mode: ID of the memory marked invalid |
association_created | boolean | No | Supersede mode: whether the old → new association was created |
HTTP API equivalent:
curl -X POST https://your-automem-instance/memory \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "content": "User prefers TypeScript for new projects", "tags": ["preference", "language:typescript"], "importance": 0.85 }'Content Size Governance (single mode; the MCP layer adds two-tier validation):
| Limit | Value | Behavior |
|---|---|---|
| Target | 150–300 chars | Optimal embedding quality |
| Soft limit | 500 chars | Warning; backend may auto-summarize |
| Hard limit | 2000 chars | MCP layer rejects before sending to API |
In batch mode the client only checks that each item’s content is non-empty. The AutoMem service enforces its own content limits.
recall_memory vs GET /recall
Section titled “recall_memory vs GET /recall”MCP Tool Input Schema:
recall_memory picks one of three modes from the arguments you pass: memory_id fetches a single record, tags with exhaustive: true enumerates a tag exactly, and anything else is ranked hybrid retrieval. The input schema has no top-level required array.
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
memory_id | string | No | — | ID-fetch mode: returns that one memory. No other parameter is sent to the server, but format still shapes the response. An ID that does not exist returns count: 0 with empty results |
exhaustive | boolean | No | Requires non-empty tags; rejects tag_match: "prefix", tag_mode: "all", and ranked-only options such as query or sort | Tag-enumeration mode: paginated exact-match listing, not ranked retrieval |
query | string | No | — | Semantic search query |
queries | array[string] | No | — | Multiple queries for broader recall |
embedding | array[number] | No | — | Optional embedding vector for direct similarity search |
limit | integer | No | 1–200 (schema default 5) | Max results to return. Ranked mode defaults to 5; enumeration without limit uses the server default of 20. Enumeration mode honors up to 200; in ranked mode the server enforces its own cap (default 100 via RECALL_MAX_LIMIT) |
offset | integer | No | ≥ 0 | Pagination offset (enumeration mode only; rejected with a validation error in ranked mode — raise limit instead) |
tags | array[string] | No | — | Filter by tags |
tag_mode | string | No | "any" | "all" | Tag matching mode |
tag_match | string | No | "exact" | "prefix" | Tag matching strategy |
time_query | string | No | — | Natural language time filter |
start | string | No | ISO timestamp | Time range start |
end | string | No | ISO timestamp | Time range end |
expand_entities | boolean | No | — | Enable multi-hop entity expansion |
expand_relations | boolean | No | — | Follow graph relationships |
expansion_limit | integer | No | 1–500, default 25 | Max expanded results |
relation_limit | integer | No | 1–200, default 5 | Relations per seed memory |
expand_min_importance | number | No | 0–1 | Filter expanded results by importance |
expand_min_strength | number | No | 0–1 | Min relation strength to traverse |
expand_respect_tags | boolean | No | — | Restrict graph expansion to the active tag scope |
context | string | No | — | Context label for boosting |
language | string | No | — | Programming language hint |
MCP Tool Output:
| Field | Type | Required | Description |
|---|---|---|---|
count | integer | Yes | Number of memories returned |
results | array[object] | Yes | Array of memory objects with scores |
dedup_removed | integer | No | Duplicates removed in multi-query mode |
mode | string | No | Mode that produced the result: "ranked", "enumeration", or "id_fetch" |
has_more | boolean | No | Enumeration mode: whether more pages exist past offset + limit |
limit, offset | integer | No | Enumeration mode: page size and offset used for this response |
Response shaping and backend-owned recall:
The MCP bridge forwards recall arguments to the AutoMem backend and then formats the response for MCP clients. Hybrid scoring, tag filtering, deduplication, entity expansion, and priority_ids guarantees all live in AutoMem itself, so HTTP and MCP produce the same recall behavior when you pass the same arguments.
MCP response budgeting (v0.15+; content previews since v0.16): Budgeted formats (text, items, detailed) trim each memory to stay under MCP client tool-response caps (~25k tokens in Claude Code). Content longer than 400 characters is cut to a 400-character preview and flagged with content_truncated and content_chars (the full length). A server-generated summary is kept as an additional field; it only stands in for the preview in the text channel when content is empty. In detailed, relations collapse to compact stubs (max 3 per memory) and metadata collapses to its key list; text and items structured results leave both out. The default token budget is 18,000 estimated tokens (override with AUTOMEM_RECALL_TOKEN_BUDGET). format: "json" keeps raw per-field passthrough but the global budget still applies. ID fetches via memory_id are never truncated — use that mode to retrieve a full record.
HTTP API equivalent:
curl "https://your-automem-instance/recall?query=typescript+preferences&tags=preference&limit=10" \ -H "Authorization: Bearer YOUR_API_TOKEN"associate_memories vs POST /associate
Section titled “associate_memories vs POST /associate”MCP Tool Input Schema:
Like store_memory, this tool has a single-pair mode and a batch mode. The input schema has no top-level required array, so the pair-mode fields below are required by the MCP client at runtime rather than by the schema.
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
memory1_id | string | Pair mode | — | Source memory UUID |
memory2_id | string | Pair mode | — | Target memory UUID |
type | string | Pair mode | enum: 11 authorable types | Relationship type |
strength | number | Pair mode | 0–1 | Relationship strength. The MCP client throws if it is missing; the HTTP API defaults to 0.5 when you omit it |
associations | array[object] | Batch mode | 1–500 items; each item requires memory1_id, memory2_id, type, and strength | Batch of associations. Do not combine with the pair-mode fields |
context, reason, pattern_type, confidence, resolution, observations, timestamp, transformation, role | — | No | Each applies to specific relationship types | Relation-specific properties. Accepted at the top level in pair mode and inside each batch item |
Relationship type enum values (11 authorable):
RELATES_TO— General relationshipLEADS_TO— Causal relationshipOCCURRED_BEFORE— Temporal orderingPREFERS_OVER— Chosen alternativeEXEMPLIFIES— Concrete example of a patternCONTRADICTS— Conflicts withREINFORCES— Strengthens validityINVALIDATED_BY— Superseded byEVOLVED_INTO— Updated versionDERIVED_FROM— Implementation of a decisionPART_OF— Component of a larger effort
System-generated relations may still appear in recall results, but they are not valid inputs to associate_memories: SIMILAR_TO, PRECEDED_BY, and DISCOVERED. The tool description also lists EXPLAINS, SHARES_THEME, and PARALLEL_CONTEXT as non-inputs; the server normalizes those three legacy names to DISCOVERED with a matching kind when it returns relations.
MCP Tool Output:
| Field | Type | Required | Description |
|---|---|---|---|
success | boolean | Yes | Whether every requested association was created; false for partial batch results |
message | string | Yes | Confirmation message (batch mode: the service summary) |
created_count, failed_count | integer | No | Batch mode: number of associations created and failed |
succeeded, failed | array[object] | No | Batch mode: per-association records |
summary | string | No | Batch mode: service summary |
HTTP API equivalent:
curl -X POST https://your-automem-instance/associate \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "memory1_id": "a1b2c3d4-...", "memory2_id": "b2c3d4e5-...", "type": "INVALIDATED_BY", "strength": 0.95 }'Batch mode sends {"associations": [...]} to the same POST /associate endpoint.
update_memory vs PATCH /memory/:id
Section titled “update_memory vs PATCH /memory/:id”MCP Tool Input Schema:
| Parameter | Type | Required | Constraints | Description |
|---|---|---|---|---|
memory_id | string | Yes | — | ID of memory to update |
content | string | No | — | New content (replaces existing) |
tags | array[string] | No | — | New tags (replaces existing) |
importance | number | No | 0–1 | New importance score |
metadata | object | No | — | Metadata (replaces existing) |
timestamp | string | No | ISO format | Override creation timestamp |
t_valid, t_invalid | string | No | ISO 8601 | Validity window: when the memory becomes valid, and when it expires or was superseded |
updated_at | string | No | ISO format | Explicit update timestamp |
last_accessed | string | No | ISO format | Last access timestamp |
type | string | No | enum: Decision, Pattern, Preference, Style, Habit, Insight, Context | Memory type classification |
confidence | number | No | 0–1 | Confidence score |
MCP Tool Output:
| Field | Type | Required | Description |
|---|---|---|---|
memory_id | string | Yes | ID of updated memory |
message | string | Yes | Confirmation message |
HTTP API equivalent:
curl -X PATCH https://your-automem-instance/memory/a1b2c3d4-... \ -H "Authorization: Bearer YOUR_API_TOKEN" \ -H "Content-Type: application/json" \ -d '{"importance": 0.95, "tags": ["preference", "language:typescript", "reviewed"]}'delete_memory vs DELETE /memory/:id
Section titled “delete_memory vs DELETE /memory/:id”MCP Tool Input Schema:
| Parameter | Type | Required | Description |
|---|---|---|---|
memory_id | string | No | ID of memory to delete (XOR with tags) |
tags | array[string] | No | Bulk-delete all memories matching any tag (XOR with memory_id) |
Exactly one of memory_id or tags must be provided.
MCP Tool Output:
Only message is a required output field. memory_id is absent in bulk-by-tag mode.
| Field | Type | Required | Description |
|---|---|---|---|
message | string | Yes | Confirmation message |
memory_id | string | No | Single-delete mode: ID of the deleted memory |
deleted_count | integer | No | Bulk-by-tag mode: number of memories deleted |
tags | array[string] | No | Bulk-by-tag mode: tags used for the bulk delete |
HTTP API equivalent:
curl -X DELETE https://your-automem-instance/memory/a1b2c3d4-... \ -H "Authorization: Bearer YOUR_API_TOKEN"Bulk-by-tag mode calls DELETE /memory/by-tag?tags=... instead.
check_database_health vs GET /health
Section titled “check_database_health vs GET /health”MCP Tool Input Schema: Empty object — no parameters required.
MCP Tool Output:
| Field | Type | Required | Description |
|---|---|---|---|
status | string | Yes | "healthy", "degraded" (the service is reachable but a backend or sync check needs attention), or "error" |
backend | string | Yes | Backend type (always "automem") |
statistics | object | No | Database statistics (memory counts, etc.) |
error | string | No | Error message if status is "error" |
Difference from GET /health: check_database_health calls GET /health and repackages the response rather than trimming it. The service fields (falkordb, qdrant, graph, memory_count, vector_count, sync_status, vector_dimensions, enrichment with its queue counters, and timestamp) move under statistics, and backend is added. Any status other than healthy or degraded becomes error, and a failed request returns status: "error" with the error message and an empty statistics object. The text block is a summary that leaves out the enrichment queue counters and vector dimensions. Call /health directly for monitoring dashboards that poll without an MCP client.
HTTP API equivalent:
curl https://your-automem-instance/healthResponse Formatting
Section titled “Response Formatting”MCP tool handlers return dual-representation responses conforming to the MCP protocol:
contentarray — Human-readable text (type:"text") for display in chat interfacesstructuredContentobject — Machine-readable data matching the tool’soutputSchema
Example from store_memory in single mode (abridged from src/mcp-surface.ts lines 1112-1161):
let responseText = `Memory stored successfully!\n\nMemory ID: ${result.memory_id}`;// ...supersede, message, auto-summarize, and size-warning lines are appended when present
const output = { memory_id: result.memory_id, message: result.message, // ...supersede, auto-summarize (summarized, original_length, summarized_length), // and size-warning fields when present};
return { content: [{ type: 'text', text: responseText }], structuredContent: output,};This dual format ensures:
- AI platforms can parse structured data programmatically via
structuredContent - Users viewing responses in chat see clean, formatted text via
content - Tools remain compatible with both chat interfaces and API clients
When to Use Each Interface
Section titled “When to Use Each Interface”| Scenario | Use HTTP API | Use MCP Tools |
|---|---|---|
| AI agent integration (Claude, Cursor, etc.) | — | Preferred — native JSON-RPC |
| Custom application or script | Preferred — direct control | — |
| Bulk operations (migration, reprocessing) | Preferred — no overhead | — |
| Content size validation before storage | — | Built-in two-tier limits (single mode) |
| Structured tool output for chat clients | Manual formatting | Built-in content + structuredContent |
| Admin operations (reembed, reprocess) | Preferred — admin endpoints | Not available |
| Health monitoring dashboards | Preferred — full response | Same fields under statistics; the text block is a summary |
| Process supervision (stable process title) | — | Supported via the AUTOMEM_PROCESS_TAG (or MCP_PROCESS_TAG) env var |
Tool Registration and Discovery
Section titled “Tool Registration and Discovery”The mcp-automem server registers tools via the MCP SDK’s schema-based routing. Tool definitions and request handlers live in src/mcp-surface.ts; src/index.ts only builds the server from them through createAutoMemMcpServer().
ListToolsRequestSchema handler (src/mcp-surface.ts line 1034): Returns the complete tools array when AI platforms query available tools via MCP introspection, so platforms can discover what tools are available.
CallToolRequestSchema handler (src/mcp-surface.ts lines 1038-1321): Executes tool logic based on the name parameter using a switch-based dispatcher, then delegates to the corresponding AutoMemClient method.
The tools array (src/mcp-surface.ts lines 85-1007) contains six static tool definitions with extensive inline documentation in the description field. This documentation is directly visible to AI platforms via MCP introspection, informing the model when and how to invoke each tool.