Skip to content

MCP Bridge

The MCP Bridge connects AI platforms to AutoMem’s memory service. It exists in two forms that serve different integration scenarios:

  1. mcp-sse-server (in the automem repo) — A Node.js/Express service that exposes AutoMem’s HTTP API as an MCP server over Streamable HTTP or SSE transports, enabling cloud-hosted AI platforms (ChatGPT, Claude.ai, ElevenLabs) to access memory over the network.

  2. mcp-automem (separate npm package) — A TypeScript package that runs as a local stdio MCP server, spawned directly by AI platforms on the developer’s machine (Claude Desktop, Cursor, Claude Code, OpenAI Codex).

Both approaches implement the same six MCP tools and use the same AutoMemClient HTTP client to call the AutoMem API, but they differ in their transport mechanism, deployment model, and target use case.


graph TB
    subgraph "Cloud AI Platforms"
        ChatGPT["ChatGPT / Claude.ai<br/>ElevenLabs"]
    end

    subgraph "Local AI Platforms"
        LocalAI["Claude Desktop<br/>Cursor IDE / Claude Code<br/>OpenAI Codex"]
    end

    subgraph "MCP Bridge (mcp-sse-server)"
        Express["Express App<br/>:8080"]
        AutoMemClientSSE["AutoMemClient<br/>(HTTP)"]
        Sessions["Legacy SSE Session Map"]
    end

    subgraph "MCP Bridge (mcp-automem package)"
        StdioServer["stdio MCP Server<br/>spawned by platform"]
        AutoMemClientLocal["AutoMemClient<br/>(HTTP)"]
    end

    subgraph "AutoMem API"
        Flask["Flask App<br/>:8001"]
    end

    ChatGPT -->|"HTTPS MCP<br/>Streamable HTTP / SSE"| Express
    Express --> AutoMemClientSSE
    AutoMemClientSSE -->|"HTTP REST"| Flask

    LocalAI -->|"stdin/stdout<br/>MCP protocol"| StdioServer
    StdioServer --> AutoMemClientLocal
    AutoMemClientLocal -->|"HTTP REST"| Flask
ComponentFile LocationPurpose
Express appserver.jsHTTP server with endpoint routing
AutoMemClientserver.js:266-367HTTP client for AutoMem API
buildMcpServer()server.js:456-748MCP server factory with tool handlers
InMemoryEventStoreserver.js:224-263Dormant event-buffer helper; not wired into the current /mcp handler
Session managementserver.js:768-792Legacy SSE session tracking with TTL sweep

The mcp-automem npm package operates as a local MCP server using stdio transport. When invoked with no arguments, it launches the server; with arguments, it runs CLI commands.

graph LR
    START["npx @verygoodplugins/mcp-automem"]

    subgraph Detection["Mode Detection<br/>src/index.ts:30-31"]
        CHECK{"process.argv[2]<br/>exists?"}
    end

    subgraph Server_Mode["Server Mode"]
        STDIO_GUARD["installStdioErrorGuards()<br/>src/index.ts:102-112"]
        MCP_SERVER["new Server()<br/>src/mcp-surface.ts:1026"]
        STDIO_TRANSPORT["StdioServerTransport<br/>src/index.ts:448"]
        TOOL_HANDLER["CallToolRequestSchema<br/>handler<br/>src/mcp-surface.ts:1038"]
    end

    subgraph CLI_Mode["CLI Mode"]
        INSTALL["runInstallCommand()<br/>src/cli/install.ts"]
        SETUP["runSetup()<br/>src/cli/setup.ts"]
        CONFIG["runConfig()<br/>src/cli/setup.ts"]
        CURSOR["runCursorSetup()<br/>src/cli/cursor.ts"]
        CLAUDE_CODE["runClaudeCodeSetup()<br/>src/cli/claude-code.ts"]
        COPILOT["runCopilotSetup()<br/>src/cli/copilot.ts"]
        CODEX["runCodexSetup()<br/>src/cli/codex.ts"]
        OPENCLAW["runOpenClawSetup()<br/>src/cli/openclaw.ts"]
        HERMES["runHermesSetup()<br/>src/cli/hermes.ts"]
        GROK["runGrokSetup()<br/>src/cli/grok.ts"]
        MIGRATE["runMigrateCommand()<br/>src/cli/migrate.ts"]
        UNINSTALL["runUninstallCommand()<br/>src/cli/uninstall.ts"]
        QUEUE["runQueueCommand()<br/>src/cli/queue.ts"]
        RECALL["Direct recall via<br/>AutoMemClient"]
    end

    START --> CHECK
    CHECK -->|"No args"| STDIO_GUARD
    CHECK -->|"Command"| INSTALL

    STDIO_GUARD --> MCP_SERVER
    MCP_SERVER --> STDIO_TRANSPORT
    MCP_SERVER --> TOOL_HANDLER

    CHECK --> SETUP
    CHECK --> CONFIG
    CHECK --> CURSOR
    CHECK --> CLAUDE_CODE
    CHECK --> COPILOT
    CHECK --> CODEX
    CHECK --> OPENCLAW
    CHECK --> HERMES
    CHECK --> GROK
    CHECK --> MIGRATE
    CHECK --> UNINSTALL
    CHECK --> QUEUE
    CHECK --> RECALL

Server Mode (no arguments): Launches an MCP server using stdio transport. AI platforms (Claude Desktop, Cursor, etc.) spawn this process as an MCP server. Console output is redirected to stderr to avoid corrupting the stdio protocol stream.

CLI Mode (with arguments): Provides interactive commands for setup, configuration, platform installation, and memory operations.

graph LR
    subgraph Platform_Config["Platform Configuration"]
        CD_JSON["claude_desktop_config.json<br/>~/.config/Claude/"]
        CURSOR_MCP["mcp.json<br/>~/.cursor/"]
        CODEX_TOML["config.toml<br/>~/.codex/"]
        COPILOT_JSON["MCP configuration<br/>GitHub repo settings"]
    end

    subgraph Rule_Files["Memory-First Rules"]
        CURSOR_MDC["automem.mdc<br/>.cursor/rules/"]
        CLAUDE_MD["CLAUDE.md<br/>~/.claude/"]
        AGENTS_MD["AGENTS.md<br/>project root"]
    end

    subgraph MCP_Server["MCP Server Process"]
        NPX["npx -y<br/>@verygoodplugins/mcp-automem"]
        SERVER_PROC["Server Mode<br/>stdio transport"]
    end

    CD_JSON -->|"Launch command"| NPX
    CURSOR_MCP -->|"Launch command"| NPX
    CODEX_TOML -->|"Launch command"| NPX
    COPILOT_JSON -->|"Launch command"| NPX

    NPX --> SERVER_PROC

    CURSOR_MDC -.->|"Guides behavior"| SERVER_PROC
    CLAUDE_MD -.->|"Guides behavior"| SERVER_PROC
    AGENTS_MD -.->|"Guides behavior"| SERVER_PROC

The mcp-sse-server bridge supports two MCP transport protocols with different characteristics and lifecycle models.

Implementation Details:

  • Request handling: server.js:1050-1101 — Handles all /mcp methods through a fresh server/transport per request
  • Session header: server.js:1056-1065 — Logs and ignores any incoming Mcp-Session-Id
  • Transport setup: server.js:1073-1085 — Creates StreamableHTTPServerTransport with sessionIdGenerator: undefined
  • Session persistence: Not implemented in the current handler; no streamable session map, event store, or TTL cleanup is used

Implementation Details:

FeatureStreamable HTTPSSE (Deprecated)
Protocol version2025-03-262024-11-05
InitializationSingle endpoint (POST /mcp)Separate endpoints (GET /mcp/sse, POST /mcp/messages)
Session IDNone; Mcp-Session-Id is ignoredQuery param in POST URL
ResumabilityNot implemented in current handlerNone
Event bufferingNot wired in current handlerNone
Connection styleRequest-scoped, fresh transport per requestLong-lived SSE stream
HeartbeatNot needed (stateless requests)20-second ping interval

Both bridge implementations translate between MCP JSON-RPC tool calls and AutoMem’s REST API.

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
sequenceDiagram
    participant Handler as "Tool Handler"
    participant Client as "AutoMemClient"
    participant Request as "_request(method, path, body)"
    participant API as "Flask API :8001"

    Handler->>Client: client.storeMemory({content, tags, ...})
    Client->>Client: Build request body with all fields
    Client->>Request: _request('POST', 'memory', body)
    Request->>Request: Construct URL:<br/>endpoint + '/' + path
    Request->>Request: Add headers:<br/>Content-Type: application/json<br/>Authorization: Bearer ${apiKey}
    Request->>API: fetch(url, {method, headers, body})
    API-->>Request: HTTP response
    Request->>Request: await res.json()
    alt Response OK
        Request-->>Client: Parsed JSON data
        Client-->>Handler: {memory_id, message}
    else Response Error
        Request->>Request: throw Error(data.message || data.detail)
        Request-->>Handler: Error thrown
    end

Key AutoMemClient Methods (mcp-sse-server):

MethodHTTP MethodEndpoint PatternRequest Body
storeMemory()POST/memoryAll Memory fields
recallMemory()GET/recall?{params}URLSearchParams encoding
associateMemories()POST/associateTwo IDs + type/strength, or an associations array (1-500 entries) for batch
updateMemory()PATCH/memory/{id}Partial updates
deleteMemory()DELETE/memory/{id}ID in URL
checkHealth()GET/healthNo body

Batch associations: associateMemories() sends { associations } as the request body when associations is an array, and otherwise sends the single memory1_id/memory2_id/type/strength pair. The associate_memories tool schema requires either that single pair or associations, with 1-500 entries per batch, and each entry needs memory1_id, memory2_id, type, and strength.

Error Handling: server.js:129-221 wraps fetch failures and non-OK responses into Error objects.


Both bridge implementations support multiple authentication methods for flexibility across different client platforms.

graph TB
    subgraph client["Client Request"]
        ReqHeaders["Request Headers:<br/>- Authorization: Bearer TOKEN<br/>- X-API-Key: TOKEN<br/>- X-API-Token: TOKEN"]
        ReqQuery["Query Parameters:<br/>?api_key=TOKEN<br/>?apiKey=TOKEN<br/>?api_token=TOKEN"]
    end

    subgraph bridge["MCP Bridge"]
        GetAuthToken["getAuthToken(req)<br/>Extraction priority:<br/>1. Bearer Authorization<br/>2. X-API-Key/X-API-Token<br/>3. Query params"]
        Validate["Token validation"]
        ConfigToken["process.env.AUTOMEM_API_TOKEN"]
    end

    subgraph forwarding["Request Forwarding"]
        AddHeader["Add Authorization:<br/>Bearer ${apiKey}<br/>to AutoMem request"]
        AutoMemAPI["AutoMem API<br/>require_api_token middleware"]
    end

    ReqHeaders --> GetAuthToken
    ReqQuery --> GetAuthToken
    GetAuthToken --> Validate
    ConfigToken --> Validate

    Validate -->|"Valid"| AddHeader
    Validate -->|"Missing/Invalid"| Reject["401 Unauthorized"]

    AddHeader --> AutoMemAPI
    AutoMemAPI -->|"Valid token"| Success["Process request"]
    AutoMemAPI -->|"Invalid token"| ApiReject["403 Forbidden"]

Token Extraction Priority (mcp-sse-server):

  1. Authorization: Bearer header (preferred)
  2. X-API-Key or X-API-Token header
  3. Query parameters: api_key, apiKey, or api_token

Environment Fallback: If client doesn’t provide token, uses process.env.AUTOMEM_API_TOKEN from server.js (Streamable HTTP and SSE endpoints).

mcp-automem environment variable priority:

  1. AUTOMEM_API_KEY (primary, current)
  2. AUTOMEM_API_TOKEN (deprecated alias, still read)
  3. CLAUDE_PLUGIN_OPTION_API_KEY (or the lowercase-suffix spelling CLAUDE_PLUGIN_OPTION_api_key)
  4. CLAUDE_PLUGIN_OPTION_API_TOKEN (or CLAUDE_PLUGIN_OPTION_api_token)

The first non-blank value wins. readAutoMemApiKeyFromEnv() in src/env.ts implements this priority chain. Entries 3 and 4 carry the Claude Code plugin’s userConfig answers, which Claude Code exports to plugin subprocesses as CLAUDE_PLUGIN_OPTION_* variables; both key spellings are accepted because the exported casing is not pinned.


Both bridge implementations expose six MCP tools with JSON schemas for validation.

store_memory — server.js:469-492

ParameterTypeRequiredConstraintsDescription
contentstringYes—Memory text content
tagsstring[]No—Classification tags
importancenumberNo0.0-1.0Relevance score
embeddingnumber[]No—Pre-computed vector
metadataobjectNo—Custom key-value pairs
timestampstringNoISO 8601Creation time
typestringNo—Memory classification
confidencenumberNo0.0-1.0Classification confidence

recall_memory — server.js:493-540

Advanced recall parameters:

  • expand_relations (boolean): Enable graph traversal
  • expand_entities (boolean): Multi-hop via entities
  • auto_decompose (boolean): Generate sub-queries
  • expansion_limit (integer 1-500): Max expanded results
  • relation_limit (integer 1-200): Relations per seed
  • expand_min_importance (number 0-1): Filter threshold
  • expand_min_strength (number 0-1): Relation strength threshold

Context hints:

  • context (string): e.g., “coding-style”, “architecture”
  • language (string): e.g., “python”, “typescript”
  • active_path (string): Current file path
  • context_tags (string[]): Priority tags
  • context_types (string[]): Priority memory types
  • priority_ids (string[]): Specific IDs to boost

Output Formats (server.js:684-714):

  • text (default): Single-block text with all results
  • items: One MCP content item per memory
  • detailed: Items with timestamps, relations, scores
  • json: Raw API response as JSON string

formatRecallAsItems() Function:

server.js:372-452 transforms AutoMem API responses into MCP content items.

Compact (text and items): text is the default single-block response and items returns the same compact representation as one MCP content item per memory. When a memory provides timestamp (the normal recall shape) or created_at (the ID-fetch fallback), compact output adds a standalone Created: line after ID:. That date tells a reader whether relative language in the recalled memory still refers to the current moment. (server.js:381-398)

Detailed (detailed): Detailed output keeps the existing Timestamp: label and uses the same timestamp then created_at fallback, alongside metadata, scores, and relation details. (server.js:401-451)

Raw (json): json bypasses result formatting and returns the raw upstream API response unchanged as a JSON string. (server.js:684-687)

Relation Summarization: server.js:438-449 — Shows up to 5 relations with type, strength, and source ID.


The mcp-sse-server bridge maintains stateful sessions for the legacy SSE transport only. The Streamable HTTP endpoint is request-scoped at AutoMem v0.16.2: it ignores incoming session IDs and creates a fresh MCP server/transport per request.

Session Creation:

Streamable HTTP — server.js:1050-1101 (fresh request-scoped transport; no stored session)

SSE — server.js:1104-1135

Session Cleanup:

TransportCleanup StrategyTTLImplementation
Streamable HTTPResponse close closes the per-request transportRequest lifetimeserver.js:1080-1082
SSEConnection close plus stale-session sweepUntil disconnect; 1 hour idle sweepserver.js:768-792, server.js:1123-1126

Purpose: Provide event buffering primitives for resumable streams. At AutoMem v0.16.2, the class is present but not instantiated by the current Streamable HTTP or SSE handlers.

server.js:224-263 InMemoryEventStore class:

MethodParametersReturnDescription
storeEvent()streamId, messageeventIdStore event with auto-generated ID, limit 1000 per stream
replayEventsAfter()streamId, lastEventIdmessage[]Return all events after specified ID
removeStream()streamIdvoidDelete all events for stream
stopCleanup()—voidStop TTL sweep timer

Event ID Format: server.js:244-245 — ${streamId}-${Date.now()}-${randomUUID().slice(0, 8)}

TTL Sweep: server.js:225-236 — Runs every 5 minutes by default and removes streams idle > 1 hour when the helper is instantiated.


Route: GET /health — server.js:869-885

Purpose: Railway health checks, monitoring systems, and client capability detection.


The MCP Bridge deploys as a separate service alongside the AutoMem API service.

Required Environment Variables:

VariableExamplePurpose
PORT8080Express listener port (Railway requires)
AUTOMEM_API_URLhttp://memory-service.railway.internal:8001Internal AutoMem API endpoint
AUTOMEM_API_TOKEN${shared.AUTOMEM_API_TOKEN}Shared secret for API authentication

Railway Template Setup: docs/RAILWAY_DEPLOYMENT.md — One-click deployment includes mcp-sse-server by default.

Manual Setup: Add service with root directory mcp-sse-server, auto-detects Dockerfile.

Internal Networking: Uses *.railway.internal domains for service-to-service communication (IPv6).

Port Configuration:

  • MCP Bridge: External :443 (HTTPS) → Internal :8080 (HTTP)
  • AutoMem API: Internal :8001 (HTTP only, no public domain by default)
  • FalkorDB: Internal :6379 (Redis protocol, no public access)

Resource Sizing:

ComponentCPUMemoryMonthly Cost
mcp-sse-server0.25 vCPU256 MB~$2-3
memory-service0.5 vCPU512 MB~$5
FalkorDB1 vCPU1 GB~$10

Token Exposure:

  • Query parameter auth (?api_token=) may appear in logs
  • Prefer header-based auth (Authorization: Bearer) when platform supports it
  • Railway internal logs capture all request URLs

Network Isolation:

  • MCP bridge has public domain (required for cloud AI platforms)
  • AutoMem API should remain internal (*.railway.internal)
  • FalkorDB never exposed publicly

Token Rotation:

  • Update AUTOMEM_API_TOKEN in both mcp-sse-server and memory-service simultaneously
  • Use Railway shared variables (${shared.AUTOMEM_API_TOKEN}) to maintain consistency

ScenarioRecommended Approach
Claude Desktop, Cursor, Claude Code, Codexmcp-automem npm package (local stdio)
ChatGPT, Claude.ai, ElevenLabs, any cloud AImcp-sse-server (Railway deployment)
Self-hosted local AI with network accessEither approach depending on platform support

For platform-specific integration guides, see Platform Integrations.