Skip to main content
LongMem implements the Model Context Protocol (MCP) to expose memory tools to any MCP-compatible client. This enables the LLM to search past sessions on demand without auto-injection.

How it works

The MCP server (mcp/server.ts) runs as a stdio-based JSON-RPC service that provides four tools:
  1. mem_search — Full-text search across all projects
  2. mem_timeline — Chronological context around a specific observation
  3. mem_get — Retrieve full details by observation IDs
  4. mem_export — Export memory to JSON or Markdown

Protocol implementation

LongMem uses a minimal stdio MCP implementation:
interface MCPRequest {
  jsonrpc: "2.0";
  id: string | number;
  method: string;
  params?: Record<string, unknown>;
}

interface MCPResponse {
  jsonrpc: "2.0";
  id: string | number;
  result?: unknown;
  error?: { code: number; message: string };
}

function respond(id: string | number, result: unknown): void {
  const response: MCPResponse = { jsonrpc: "2.0", id, result };
  process.stdout.write(JSON.stringify(response) + "\n");
}
The server handles three MCP methods:
  • initialize — Handshake and capability negotiation
  • tools/list — Returns available tools
  • tools/call — Executes a tool with arguments

Tool schemas

Description: Search past coding session memory across ALL projects
{
  name: "mem_search",
  description: `Search past coding session memory across ALL projects. Returns a compact index of matching observations. Use this FIRST to find relevant context, then call mem_get for full details on specific items. Current project context: ${currentProject}`,
  inputSchema: {
    type: "object",
    properties: {
      query: { type: "string", description: "Search query — keywords or natural language" },
      project: { type: "string", description: "Filter by project name (optional — omit to search across all projects)" },
      limit: { type: "number", description: "Max results to return (default: 5, max: 20)" },
    },
    required: ["query"],
  },
}
Example usage:
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "mem_search",
    "arguments": {
      "query": "authentication bug",
      "project": "my-app",
      "limit": 10
    }
  }
}
Response format:
Found 3 memories (project: my-app):

[ID:42] 2024-03-01 | bash | src/auth/login.ts
  Fixed JWT token validation to check expiry correctly

[ID:108] 2024-03-02 | edit | src/middleware/auth.ts
  Added rate limiting to prevent brute force attacks

[ID:256] 2024-03-03 | grep | src/
  Located all authentication-related error handling

2. mem_timeline

Description: Get chronological context around a specific observation
{
  name: "mem_timeline",
  description: "Get chronological context around a specific observation — what happened before and after. Use an ID from mem_search results.",
  inputSchema: {
    type: "object",
    properties: {
      observation_id: { type: "number", description: "Observation ID from mem_search results" },
      before: { type: "number", description: "Observations to show before (default: 3, max: 10)" },
      after: { type: "number", description: "Observations to show after (default: 3, max: 10)" },
    },
    required: ["observation_id"],
  },
}
Example usage:
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "mem_timeline",
    "arguments": {
      "observation_id": 108,
      "before": 2,
      "after": 2
    }
  }
}
Response format:
**Before:**
  [42] 2024-03-01 | bash: Ran tests for authentication module
  [99] 2024-03-02 | read: Reviewed JWT token implementation

**Target [108]:** edit — Added rate limiting to auth middleware
Files: src/middleware/auth.ts

**After:**
  [123] 2024-03-02 | bash: Tested rate limiting with siege
  [145] 2024-03-02 | edit: Updated rate limit threshold to 100/min

3. mem_get

Description: Get full details of specific observations by ID
{
  name: "mem_get",
  description: "Get full details of specific observations by ID. Use after mem_search to retrieve complete information about relevant items. Only costs tokens for what you actually need.",
  inputSchema: {
    type: "object",
    properties: {
      ids: {
        type: "array",
        items: { type: "number" },
        description: "Observation IDs to retrieve (from mem_search, max: 20)",
      },
    },
    required: ["ids"],
  },
}
Example usage:
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "mem_get",
    "arguments": {
      "ids": [42, 108, 256]
    }
  }
}
Response format:
**[42] bash** — 2024-03-01 10:30
Summary: Fixed JWT token validation to check expiry correctly
Files: src/auth/login.ts
Concepts: authentication, JWT, token-validation
Input: {"command": "npm test auth"}
Output: ✓ All 15 tests passed
  ✓ Token validation
  ✓ Expiry check
  ✓ Refresh token flow

---

**[108] edit** — 2024-03-02 14:15
Summary: Added rate limiting to auth middleware
Files: src/middleware/auth.ts
Concepts: security, rate-limiting, brute-force-protection
Input: {"filePath": "/src/middleware/auth.ts", "oldString": "..."}
Output: Edited src/middleware/auth.ts (32 lines changed)

4. mem_export

Description: Export memory to JSON or Markdown
{
  name: "mem_export",
  description: "Export memory to JSON or Markdown for backup, sharing, or analysis. Returns the exported data or a summary.",
  inputSchema: {
    type: "object",
    properties: {
      project: { type: "string", description: "Filter by project name (optional — omit for all projects)" },
      days: { type: "number", description: "Only include last N days (default: all, max: 365)" },
      format: { type: "string", enum: ["json", "markdown"], description: "Export format (default: json)" },
      include_raw: { type: "boolean", description: "Include raw tool_input/tool_output (default: false)" },
    },
  },
}
Example usage:
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "mem_export",
    "arguments": {
      "project": "my-app",
      "days": 30,
      "format": "markdown"
    }
  }
}
Response format (JSON):
**LongMem Export**
Exported: 2024-03-04T10:30:00Z
Sessions: 12
Observations: 345
User observations: 8
Concepts: 67
Response format (Markdown):
# LongMem Export — my-app (last 30 days)

Exported: 2024-03-04T10:30:00Z

## Sessions (12)

### Session 1 — 2024-03-01
- Duration: 2h 15m
- Observations: 28
- Files touched: src/auth/*, src/middleware/*

...

## Observations (345)

### [42] bash — 2024-03-01 10:30
**Summary:** Fixed JWT token validation
**Files:** src/auth/login.ts
**Concepts:** authentication, JWT

...

Tool limits

The MCP server enforces these limits:
const MCP_LIMITS = {
  searchLimit: 20,           // Max search results
  timelineBeforeAfter: 10,   // Max timeline context items
  getIds: 20,                // Max observation IDs per request
  exportDays: 365,           // Max days for export
};

Configuration

OpenCode

Add the MCP server to your OpenCode config:
{
  "mcpServers": {
    "longmem": {
      "command": "~/.longmem/bin/longmem-mcp",
      "args": [],
      "env": {}
    }
  }
}

Claude Code CLI

Add the MCP server to your Claude CLI config:
{
  "mcpServers": {
    "longmem": {
      "command": "~/.longmem/bin/longmem-mcp",
      "args": [],
      "env": {}
    }
  }
}

Cursor

Add the MCP server to Cursor’s MCP settings:
{
  "mcp": {
    "servers": {
      "longmem": {
        "command": "/Users/you/.longmem/bin/longmem-mcp"
      }
    }
  }
}

Cline (VSCode extension)

Add to your Cline settings:
{
  "cline.mcpServers": {
    "longmem": {
      "command": "/home/you/.longmem/bin/longmem-mcp"
    }
  }
}

Auto-start behavior

The MCP server automatically starts the LongMem daemon if it’s not running:
async function callTool(name: string, args: Record<string, unknown>): Promise<string> {
  const daemonUp = await ensureDaemonRunning();

  if (!daemonUp) {
    return `Memory daemon is not running. Start it with: bun ${MEMORY_DIR}/daemon.js`;
  }

  // ... execute tool
}

Verification

Test the MCP server manually:
echo '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | ~/.longmem/bin/longmem-mcp
You should see:
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "tools": [
      {"name": "mem_search", "description": "..."},
      {"name": "mem_timeline", "description": "..."},
      {"name": "mem_get", "description": "..."},
      {"name": "mem_export", "description": "..."}
    ]
  }
}

Troubleshooting

MCP server not responding

Check if the server is running:
ps aux | grep longmem-mcp

Tool calls timing out

Increase timeout in client config:
{
  "mcpServers": {
    "longmem": {
      "command": "~/.longmem/bin/longmem-mcp",
      "timeout": 30000
    }
  }
}

Daemon not starting

Verify daemon binary exists:
ls -la ~/.longmem/bin/longmemd
Start daemon manually:
~/.longmem/bin/longmemd

Debug MCP communication

Enable MCP debug logging (varies by client): OpenCode:
export OPENCODE_MCP_DEBUG=1
opencode
Claude Code CLI:
export CLAUDE_MCP_DEBUG=1
claude-code
Check logs at ~/.longmem/logs/mcp-debug.log

Build docs developers (and LLMs) love