How to Add Persistent Memory to Any AI Agent (So It Remembers Yesterday)

Solve the 'I don't remember yesterday' problem in AI workflows. Add persistent memory to any AI agent using MCP protocol. Includes setup guide, memory patterns, and agent handoff examples.

Ashley Innocent

Ashley Innocent

19 March 2026

How to Add Persistent Memory to Any AI Agent (So It Remembers Yesterday)

TL;DR

Add persistent memory to AI agents in 4 steps: (1) Set up an MCP memory server with remember, recall, search, and rollback tools, (2) Add memory instructions to agent prompts, (3) Configure ~/.claude/settings.json for Claude Code or .cursor/mcp.json for Cursor, (4) Use memory patterns for decision logging, agent handoffs, and session checkpoints. Agents retain context across sessions—no more copy-pasting previous conversations.

Solve the “I don’t remember yesterday” problem. Add persistent memory to AI agents using MCP protocol, and they’ll recall decisions, deliverables, and context from previous sessions.

You know the drill:

Day 1: "Build the user authentication system"
Agent: [Builds JWT auth, creates users table, implements refresh tokens]

Day 2: "Continue from yesterday"
Agent: "I don't have context from previous sessions. Can you paste what we did?"

You copy-paste the previous conversation. The agent reads 2000 lines of context. You both waste 15 minutes getting back up to speed.

Persistent memory fixes this. With MCP (Model Context Protocol) memory, agents store decisions automatically and recall them when needed. No copy-paste. No re-explanation.

In this tutorial, you’ll set up MCP memory for AI agents. You’ll learn how to store decisions from Backend Architect sessions, recall context when switching to Database Optimizer, and hand off deliverables to Frontend Developer—all without losing context. The same memory patterns work whether you’re building APIs with Apidog integration or managing multi-day development sprints.

button

What Is MCP Memory?

MCP memory lets AI agents store and retrieve information across sessions. Think of it as a shared notebook that agents can write to and read from.

Four tools power MCP memory:

Tool Purpose Example
remember Store information with tags Save “users table with UUID, bcrypt”
recall Search by keyword or tag Find “auth decisions”
rollback Restore to previous state Undo bad schema changes
search Find across sessions “What did Backend Architect decide?”
┌─────────────────┐         ┌──────────────────┐         ┌─────────────┐
│  AI Agent       │         │  MCP Memory      │         │  Storage    │
│  (Claude Code)  │◄───────►│  Server          │◄───────►│  (SQLite)   │
└─────────────────┘   JSON  └──────────────────┘  I/O    └─────────────┘

Step 1: Set Up an MCP Memory Server

You need an MCP server that exposes memory tools. Several open-source implementations exist.

Option A: Use a hosted memory server

npm install -g @example/mcp-memory-server

Option B: Run a simple local server

Create memory-server.js:

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import fs from "fs/promises";
import path from "path";

const MEMORY_FILE = path.join(process.env.HOME, ".mcp-memory", "memories.json");

const server = new McpServer({
  name: "memory",
  version: "1.0.0"
});

// Ensure memory file exists
async function initMemory() {
  await fs.mkdir(path.dirname(MEMORY_FILE), { recursive: true });
  try {
    await fs.access(MEMORY_FILE);
  } catch {
    await fs.writeFile(MEMORY_FILE, JSON.stringify([]));
  }
}

// Tool: remember
server.tool(
  "remember",
  {
    content: z.string().describe("Information to store"),
    tags: z.array(z.string()).describe("Tags for retrieval (e.g., ['backend', 'auth'])"),
    agent: z.string().optional().describe("Agent name for tagging")
  },
  async ({ content, tags, agent }) => {
    await initMemory();
    const memories = JSON.parse(await fs.readFile(MEMORY_FILE, "utf-8"));
    const memory = {
      id: Date.now().toString(),
      content,
      tags,
      agent,
      timestamp: new Date().toISOString()
    };
    memories.push(memory);
    await fs.writeFile(MEMORY_FILE, JSON.stringify(memories, null, 2));
    return { content: [{ type: "text", text: `Stored memory with tags: ${tags.join(", ")}` }] };
  }
);

// Tool: recall
server.tool(
  "recall",
  {
    query: z.string().describe("Search query or tag to find"),
    agent: z.string().optional().describe("Filter by agent name")
  },
  async ({ query, agent }) => {
    await initMemory();
    const memories = JSON.parse(await fs.readFile(MEMORY_FILE, "utf-8"));
    const results = memories.filter(m => {
      const matchesQuery = m.content.toLowerCase().includes(query.toLowerCase()) ||
                          m.tags.some(t => t.toLowerCase().includes(query.toLowerCase()));
      const matchesAgent = !agent || m.agent === agent;
      return matchesQuery && matchesAgent;
    });
    return {
      content: [{
        type: "text",
        text: results.length === 0
          ? "No memories found"
          : results.map(m => `[${m.timestamp}] ${m.content}`).join("\n\n")
      }]
    };
  }
);

// Tool: search
server.tool(
  "search",
  {
    tags: z.array(z.string()).describe("Tags to search for"),
    limit: z.number().optional().default(10)
  },
  async ({ tags, limit }) => {
    await initMemory();
    const memories = JSON.parse(await fs.readFile(MEMORY_FILE, "utf-8"));
    const results = memories
      .filter(m => tags.some(t => m.tags.includes(t)))
      .slice(0, limit);
    return {
      content: [{
        type: "text",
        text: results.map(m => `[${m.agent || "unknown"}] ${m.content}`).join("\n\n")
      }]
    };
  }
);

// Tool: rollback
server.tool(
  "rollback",
  {
    agent: z.string().describe("Agent name to rollback"),
    timestamp: z.string().describe("Rollback to this timestamp")
  },
  async ({ agent, timestamp }) => {
    await initMemory();
    const memories = JSON.parse(await fs.readFile(MEMORY_FILE, "utf-8"));
    const rolledBack = memories.filter(m =>
      m.agent !== agent || new Date(m.timestamp) <= new Date(timestamp)
    );
    await fs.writeFile(MEMORY_FILE, JSON.stringify(rolledBack, null, 2));
    return {
      content: [{
        type: "text",
        text: `Rolled back ${agent} to ${timestamp}`
      }]
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);

Run the server:

node memory-server.js

Step 2: Add Memory Instructions to Any Agent

You don’t need to modify agent files. Add memory instructions in your prompt:

You have access to MCP memory tools: remember, recall, search, rollback.

Follow these memory protocols:

**When you start a session:**
1. Recall context: recall(query="ecommerce-api", agent="Backend Architect")
2. Review pending items from last session

**When you complete work:**
1. Remember deliverables with tags:
   - remember(content="Created users table with UUID primary key, bcrypt password hashing, JWT auth with refresh tokens", tags=["ecommerce-api", "database", "auth"], agent="Backend Architect")
2. Include decisions made and pending items

**When handing off to another agent:**
1. Leave context for the receiving agent:
   - remember(content="API endpoints: /auth/login, /auth/register, /products, /orders. Auth flow: JWT access token (15min) + refresh token (7 days). Known issue: rate limiting not yet implemented", tags=["ecommerce-api", "handoff"], agent="Backend Architect", for="Frontend Developer")

**When something fails:**
1. Search for last known-good state
2. Use rollback to restore

Example in action:

You: "Activate Backend Architect mode. Design the user system for our e-commerce API."

[Agent designs the system, creates schema, implements auth]

Agent: "User system complete. Storing memory..."
→ Calls: remember("users table with UUID, bcrypt, JWT + refresh tokens", tags: ["ecommerce-api", "auth", "database"])

[Session ends]

[Next day]

You: "Continue from yesterday"

Agent: "Recalling context..."
→ Calls: recall(query="ecommerce-api")
→ Returns: "users table with UUID, bcrypt, JWT + refresh tokens"

Agent: "Yesterday I designed the users table with UUID primary keys, implemented bcrypt password hashing, and set up JWT authentication with refresh tokens. Next step: product catalog schema. Ready to continue."

Step 3: Configure for Claude Code

Add the memory server to your MCP configuration:

Edit ~/.claude/settings.json:

{
  "mcpServers": {
    "memory": {
      "command": "node",
      "args": ["/absolute/path/to/memory-server.js"],
      "env": {
        "HOME": "/Users/your-username"
      }
    }
  }
}

Restart Claude Code. The memory tools should now be available.

Test it:

Use the remember tool to store: "Test memory for ecommerce project"
Tags: ["test", "ecommerce-api"]
Use the recall tool to find memories about "test"

Step 4: Configure for Cursor

Create .cursor/mcp.json in your project:

{
  "mcpServers": {
    "memory": {
      "command": "node",
      "args": ["/absolute/path/to/memory-server.js"]
    }
  }
}

Test it:

@memory remember "Starting ecommerce API project with PostgreSQL"
Tags: ["ecommerce-api", "setup"]
@memory recall query="ecommerce"

Memory Patterns for Real Workflows

Pattern 1: Decision Logging

Every time you make a technical decision, log it:

remember({
  content: "Chose PostgreSQL over MySQL for: (1) JSONB support for flexible product attributes, (2) better full-text search, (3) UUID native support",
  tags: ["ecommerce-api", "database", "decision"],
  agent: "Backend Architect"
})

Later, when someone asks “Why PostgreSQL?”:

recall(query="PostgreSQL MySQL decision")

Pattern 2: Agent Handoffs

When switching agents, leave a handoff note:

remember({
  content: "Backend complete. Endpoints: POST /auth/login, POST /auth/register, GET /products, POST /orders. Auth: JWT 15min access + 7 day refresh. Pending: rate limiting, email verification. Frontend needs: login form, product list, cart, checkout.",
  tags: ["ecommerce-api", "handoff", "backend-complete"],
  agent: "Backend Architect",
  for: "Frontend Developer"
})

Frontend Developer starts with:

recall(query="handoff", agent="Backend Architect")

Pattern 3: Session Checkpoints

At the end of each work session:

remember({
  content: "Session complete. Done: users table, auth endpoints, product schema. Next session: order system, payment webhook. Blockers: waiting for Stripe API keys.",
  tags: ["ecommerce-api", "checkpoint", "session-1"],
  agent: "Backend Architect"
})

Resume next session:

recall(query="checkpoint session-1")

Pattern 4: Bug Tracking

When you find a bug:

remember({
  content: "BUG: Refresh token not expiring after logout. Token stored in memory, not persisted. Fix: move to Redis with TTL.",
  tags: ["ecommerce-api", "bug", "auth"],
  agent: "Code Reviewer",
  severity: "high"
})

Search for bugs later:

search(tags=["bug", "ecommerce-api"])

Troubleshooting

Memory not persisting:

Too many results on recall:

Memory file growing large:

What You Built

Component Purpose
MCP Memory Server Stores/retrieves information across sessions
remember tool Log decisions, deliverables, handoffs
recall tool Find context from previous sessions
search tool Query by tags across all memories
rollback tool Restore to previous state when needed
Memory patterns Decision logging, handoffs, checkpoints, bug tracking

Next Steps

Extend the memory server:

Build team memory:

Integrate with tools:

Troubleshooting Common Issues

Memory not persisting between sessions:

Recall returns empty results:

Memory file growing too large:

Server fails to start:

Multiple agents overwriting each other’s memories:

Memory Server Security Considerations

API Key Storage:If your memory server stores sensitive data (API keys, passwords), implement encryption:

import crypto from 'crypto';

const ENCRYPTION_KEY = process.env.MEMORY_ENCRYPTION_KEY;
const ALGORITHM = 'aes-256-gcm';

function encrypt(text) {
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv(ALGORITHM, Buffer.from(ENCRYPTION_KEY), iv);
  const encrypted = cipher.update(text, 'utf8', 'hex');
  return {
    encryptedData: encrypted + cipher.final('hex'),
    iv: iv.toString('hex'),
    authTag: cipher.getAuthTag().toString('hex')
  };
}

function decrypt(encrypted) {
  const decipher = crypto.createDecipheriv(
    ALGORITHM,
    Buffer.from(ENCRYPTION_KEY),
    Buffer.from(encrypted.iv, 'hex')
  );
  decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex'));
  return decipher.update(encrypted.encryptedData, 'hex', 'utf8') + decipher.final('utf8');
}

Access Control:For team memory servers, add authentication:

Your AI agents now have persistent memory. They remember yesterday. They recall decisions. They hand off context without copy-paste.

No more “I don’t have context from previous sessions.” No more re-explaining. No more wasted time.

That’s the power of MCP memory: give your agents a shared notebook, and watch them become actually useful across multi-day projects.

button

FAQ

What is MCP memory?MCP memory is a protocol implementation that lets AI agents store and retrieve information across sessions. Think of it as a shared notebook agents can write to and read from, persisting context beyond single conversations.

How do I set up persistent memory for Claude Code?Install an MCP memory server, then add it to ~/.claude/settings.json with the server command and path. Restart Claude Code and the memory tools (remember, recall, search, rollback) become available.

Which AI agents support MCP memory?Any agent running on MCP-compatible clients (Claude Code, Cursor, Windsurf) can use memory tools. You don’t need to modify agent files—just add memory instructions to your prompts.

What are the best memory patterns for agent handoffs?Use remember with tags like ["handoff", "project-name"] to leave context for the next agent. Include completed work, pending items, and known issues. The receiving agent calls recall(query="handoff") to retrieve it.

How much memory can MCP servers store?Depends on implementation. The reference server uses a JSON file that grows indefinitely. Production servers should add expiration policies, auto-archiving, or database backends for large-scale use.

Can teams share a central memory server?Yes. Run the memory server on a shared machine or cloud instance, configure all team members’ clients to connect to it, and tag memories by project and developer for organized retrieval.

What if memory recall returns too many results?Add more specific tags when storing memories. Filter by agent name in your recall queries. Use exact phrases in quotes. Consider implementing semantic search with embeddings for smarter retrieval.

Explore more

How MiroFish Creates Digital Parallel Worlds ?

How MiroFish Creates Digital Parallel Worlds ?

Learn how MiroFish builds multi-agent simulation systems that create digital parallel worlds for social media prediction. Complete technical breakdown of swarm intelligence architecture.

19 March 2026

How to generate 100+ agent configurations using LLMs with batch processing

How to generate 100+ agent configurations using LLMs with batch processing

Learn how to generate 100+ agent configurations using LLMs with batch processing, JSON repair strategies, and rule-based fallbacks. Complete technical guide.

19 March 2026

How to Set Up 5 AI Agents to Build a Complete API (From Spec to Test)

How to Set Up 5 AI Agents to Build a Complete API (From Spec to Test)

Build a complete API using 5 specialized AI agents in sequence. Backend Architect designs the system, Database Optimizer reviews schema, Frontend Developer builds the client, Code Reviewer checks security, and Reality Checker validates before ship.

19 March 2026

Practice API Design-first in Apidog

Discover an easier way to build and use APIs