DEV Community

Cover image for Cómo Añadir Memoria Persistente a Agentes de IA para Recordar el Pasado
Roobia
Roobia

Posted on • Originally published at apidog.com

Cómo Añadir Memoria Persistente a Agentes de IA para Recordar el Pasado

En resumen

Añade memoria persistente a tus agentes de IA en 4 pasos prácticos: 1) Configura un servidor de memoria MCP con las herramientas remember, recall, search y rollback. 2) Añade instrucciones de memoria directamente en los prompts del agente. 3) Configura ~/.claude/settings.json para Claude Code o .cursor/mcp.json para Cursor. 4) Usa patrones de memoria para registrar decisiones, traspasos entre agentes y checkpoints de sesión. Así, los agentes conservarán contexto entre sesiones, evitando el copiar/pegar de conversaciones anteriores.

Prueba Apidog hoy

Resuelve el problema de "no recuerdo lo de ayer". Con memoria persistente mediante el protocolo MCP, tus agentes recordarán decisiones, entregables y contexto de sesiones previas.

Ya conoces el problema:

Día 1: "Construir el sistema de autenticación de usuarios"
Agente: [Construye la autenticación JWT, crea la tabla de usuarios, implementa tokens de actualización]

Día 2: "Continuar desde ayer"
Agente: "No tengo contexto de sesiones anteriores. ¿Puedes pegar lo que hicimos?"
Enter fullscreen mode Exit fullscreen mode

Copias y pegas la conversación anterior. El agente procesa 2000 líneas de contexto. Ambos perdéis 15 minutos poniéndoos al día.

La memoria MCP soluciona esto. Los agentes almacenan decisiones automáticamente y las recuperan cuando es necesario. Sin copiar y pegar, sin repetir explicaciones.

En este tutorial implementarás memoria MCP para agentes de IA. Aprenderás a almacenar decisiones de sesiones de Backend Architect, traspasar entregables a Frontend Developer y mantener el contexto entre agentes. Los patrones funcionan tanto si construyes APIs con integración Apidog como si gestionas sprints de varios días.

¿Qué es la memoria MCP?

La memoria MCP permite a los agentes de IA almacenar y recuperar información entre sesiones, como un cuaderno compartido.

Las 4 herramientas clave son:

Herramienta Propósito Ejemplo
remember Almacenar información con etiquetas Guardar "tabla de usuarios con UUID, bcrypt"
recall Buscar por palabra clave o etiqueta Encontrar "decisiones de auth"
rollback Restaurar a un estado anterior Deshacer cambios de esquema erróneos
search Buscar entre sesiones "¿Qué decidió el arquitecto de backend?"
┌─────────────────┐         ┌──────────────────┐         ┌─────────────┐
│  Agente de IA   │         │  Memoria MCP     │         │  Almacenam. │
│  (Claude Code)  │◄───────►│  Servidor        │◄───────►│  (SQLite)   │
└─────────────────┘   JSON  └──────────────────┘  E/S    └─────────────┘
Enter fullscreen mode Exit fullscreen mode

Paso 1: Configura un servidor de memoria MCP

Necesitas un servidor MCP que exponga herramientas de memoria. Puedes elegir entre:

Opción A: Usar un servidor alojado

npm install -g @example/mcp-memory-server
Enter fullscreen mode Exit fullscreen mode

Opción B: Ejecutar un servidor local

Crea 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"
});

// Asegura que el archivo de memoria existe
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([]));
  }
}

// Herramienta: remember
server.tool(
  "remember",
  {
    content: z.string().describe("Información a almacenar"),
    tags: z.array(z.string()).describe("Etiquetas para búsqueda (ej: ['backend', 'auth'])"),
    agent: z.string().optional().describe("Nombre del agente")
  },
  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: `Memoria almacenada con etiquetas: ${tags.join(", ")}` }] };
  }
);

// Herramienta: recall
server.tool(
  "recall",
  {
    query: z.string().describe("Consulta o etiqueta"),
    agent: z.string().optional().describe("Filtrar por agente")
  },
  async ({ query, agent }) => {
    await initMemory();
    const memories = JSON.parse(await fs.readFile(MEMORY_FILE, "utf-8"));
    const results = memories.filter(m =>
      (m.content.toLowerCase().includes(query.toLowerCase()) ||
      m.tags.some(t => t.toLowerCase().includes(query.toLowerCase()))) &&
      (!agent || m.agent === agent)
    );
    return {
      content: [{
        type: "text",
        text: results.length === 0
          ? "No se encontraron memorias"
          : results.map(m => `[${m.timestamp}] ${m.content}`).join("\n\n")
      }]
    };
  }
);

// Herramienta: search
server.tool(
  "search",
  {
    tags: z.array(z.string()).describe("Etiquetas para buscar"),
    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")
      }]
    };
  }
);

// Herramienta: rollback
server.tool(
  "rollback",
  {
    agent: z.string().describe("Nombre del agente"),
    timestamp: z.string().describe("Restaurar hasta este 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: `Restaurado ${agent} a ${timestamp}`
      }]
    };
  }
);

const transport = new StdioServerTransport();
await server.connect(transport);
Enter fullscreen mode Exit fullscreen mode

Ejecuta el servidor:

node memory-server.js
Enter fullscreen mode Exit fullscreen mode

Paso 2: Añade instrucciones de memoria a cualquier agente

No necesitas modificar archivos del agente. Añade instrucciones directamente en tu prompt:

Tienes acceso a las herramientas de memoria MCP: remember, recall, search, rollback.

Sigue estos protocolos de memoria:

**Cuando inicies una sesión:**
1. Recordar contexto: recall(query="ecommerce-api", agent="Backend Architect")
2. Revisar los elementos pendientes de la última sesión

**Cuando completes el trabajo:**
1. Recordar entregables con etiquetas:
   - remember(content="Creada tabla de usuarios con clave primaria UUID, hashing de contraseña bcrypt, autenticación JWT con tokens de actualización", tags=["ecommerce-api", "database", "auth"], agent="Backend Architect")
2. Incluir decisiones tomadas y elementos pendientes

**Al traspasar a otro agente:**
1. Dejar contexto para el agente receptor:
   - remember(content="Endpoints de API: /auth/login, /auth/register, /products, /orders. Flujo de autenticación: token de acceso JWT (15min) + token de actualización (7 días). Problema conocido: la limitación de velocidad aún no está implementada", tags=["ecommerce-api", "handoff"], agent="Backend Architect", for="Frontend Developer")

**Cuando algo falle:**
1. Buscar el último estado bueno conocido
2. Usar rollback para restaurar
Enter fullscreen mode Exit fullscreen mode

Ejemplo en acción:

Tú: "Activa el modo Arquitecto de Backend. Diseña el sistema de usuarios para nuestra API de comercio electrónico."

[El agente diseña el sistema, crea el esquema, implementa la autenticación]

Agente: "Sistema de usuarios completado. Almacenando memoria..."
→ Llama a: remember("tabla de usuarios con UUID, bcrypt, JWT + tokens de actualización", tags: ["ecommerce-api", "auth", "database"])

[La sesión termina]

[Al día siguiente]

Tú: "Continuar desde ayer"

Agente: "Recuperando contexto..."
→ Llama a: recall(query="ecommerce-api")
→ Devuelve: "tabla de usuarios con UUID, bcrypt, JWT + tokens de actualización"

Agente: "Ayer diseñé la tabla de usuarios con claves primarias UUID, implementé el hashing de contraseñas bcrypt y configuré la autenticación JWT con tokens de actualización. Siguiente paso: esquema de catálogo de productos. Listo para continuar."
Enter fullscreen mode Exit fullscreen mode

Paso 3: Configura para Claude Code

Agrega el servidor de memoria en tu configuración MCP.

Edita ~/.claude/settings.json:

{
  "mcpServers": {
    "memory": {
      "command": "node",
      "args": ["/absolute/path/to/memory-server.js"],
      "env": {
        "HOME": "/Users/tu-nombre-de-usuario"
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Reinicia Claude Code. Las herramientas de memoria estarán disponibles.

Prueba:

Usa la herramienta remember para almacenar: "Memoria de prueba para el proyecto de comercio electrónico"
Tags: ["test", "ecommerce-api"]
Enter fullscreen mode Exit fullscreen mode
Usa la herramienta recall para encontrar memorias sobre "test"
Enter fullscreen mode Exit fullscreen mode

Paso 4: Configura para Cursor

Crea .cursor/mcp.json en tu proyecto:

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

Prueba:

@memory remember "Iniciando proyecto de API de comercio electrónico con PostgreSQL"
Tags: ["ecommerce-api", "setup"]
Enter fullscreen mode Exit fullscreen mode
@memory recall query="ecommerce"
Enter fullscreen mode Exit fullscreen mode

Patrones de memoria para flujos de trabajo reales

Patrón 1: Registro de decisiones

Registra cada decisión técnica:

remember({
  content: "Se eligió PostgreSQL sobre MySQL por: (1) soporte JSONB para atributos de producto flexibles, (2) mejor búsqueda de texto completo, (3) soporte nativo de UUID",
  tags: ["ecommerce-api", "database", "decision"],
  agent: "Backend Architect"
})
Enter fullscreen mode Exit fullscreen mode

Cuando alguien pregunte "¿Por qué PostgreSQL?":

recall(query="PostgreSQL MySQL decision")
Enter fullscreen mode Exit fullscreen mode

Patrón 2: Traspasos entre agentes

Al cambiar de agente, deja nota de traspaso:

remember({
  content: "Backend completado. Endpoints: POST /auth/login, POST /auth/register, GET /products, POST /orders. Auth: acceso JWT 15min + actualización 7 días. Pendiente: limitación de velocidad, verificación de email. Necesidades de Frontend: formulario de login, lista de productos, carrito, checkout.",
  tags: ["ecommerce-api", "handoff", "backend-complete"],
  agent: "Backend Architect",
  for: "Frontend Developer"
})
Enter fullscreen mode Exit fullscreen mode

Frontend Developer inicia con:

recall(query="handoff", agent="Backend Architect")
Enter fullscreen mode Exit fullscreen mode

Patrón 3: Puntos de control de sesión

Al final de cada sesión:

remember({
  content: "Sesión completada. Hecho: tabla de usuarios, endpoints de autenticación, esquema de producto. Siguiente sesión: sistema de pedidos, webhook de pago. Bloqueantes: esperando claves API de Stripe.",
  tags: ["ecommerce-api", "checkpoint", "session-1"],
  agent: "Backend Architect"
})
Enter fullscreen mode Exit fullscreen mode

Reanuda la siguiente sesión:

recall(query="checkpoint session-1")
Enter fullscreen mode Exit fullscreen mode

Patrón 4: Seguimiento de errores

Cuando detectes un bug:

remember({
  content: "BUG: El token de actualización no expira después del logout. Token almacenado en memoria, no persistido. Solución: mover a Redis con TTL.",
  tags: ["ecommerce-api", "bug", "auth"],
  agent: "Code Reviewer",
  severity: "high"
})
Enter fullscreen mode Exit fullscreen mode

Buscar errores:

search(tags=["bug", "ecommerce-api"])
Enter fullscreen mode Exit fullscreen mode

Resolución de problemas

La memoria no persiste:

  • Verifica la ruta del archivo de memoria (~/.mcp-memory/memories.json)
  • Asegúrate de que el servidor MCP esté ejecutándose
  • Confirma la configuración MCP en Claude Code/Cursor

Demasiados resultados:

  • Usa etiquetas más específicas
  • Filtra por nombre de agente
  • Usa frases exactas entre comillas

El archivo de memoria crece demasiado:

  • Archiva memorias antiguas
  • Usa rollback para limpiar proyectos completados
  • Añade expiración a tu esquema de memoria

Lo que construiste

Componente Propósito
Servidor de memoria MCP Almacena/recupera información entre sesiones
Herramienta remember Registra decisiones, entregables, traspasos
Herramienta recall Encuentra contexto de sesiones anteriores
Herramienta search Consulta por etiquetas en todas las memorias
Herramienta rollback Restaura a un estado anterior
Patrones de memoria Registro de decisiones, traspasos, checkpoints, bugs

Próximos pasos

Extiende el servidor de memoria:

  • Añade búsqueda semántica con embeddings
  • Implementa expiración automática de memorias (>30 días)
  • Añade resumen de memoria para sesiones largas

Construye memoria de equipo:

  • Comparte un servidor central en tu equipo
  • Etiqueta memorias por proyecto y desarrollador
  • Crea flujos de onboarding para nuevos miembros

Integra con herramientas:

  • Registra automáticamente los commits de git como memorias
  • Sincroniza con Jira, Linear, etc.
  • Exporta memorias a la documentación

Resolución de problemas comunes

La memoria no persiste entre sesiones:

  • Asegúrate de que el servidor MCP esté corriendo antes de iniciar Claude Code
  • Verifica la existencia del archivo: ls -la ~/.mcp-memory/memories.json
  • Revisa permisos: chmod 644 ~/.mcp-memory/memories.json
  • Confirma la ruta en ~/.claude/settings.json

La recuperación devuelve resultados vacíos:

  • Verifica que la consulta coincida con etiquetas almacenadas (sensible a mayúsculas/minúsculas)
  • Intenta términos más amplios o usa search con etiquetas específicas
  • Comprueba el contenido real del archivo: cat ~/.mcp-memory/memories.json
  • Asegúrate que el filtro de agente coincida si lo usas

El archivo crece demasiado:

  • Implementa archivo automático para memorias >30 días
  • Añade herramienta prune para eliminar por rango de fechas
  • Divide memorias por proyecto o fecha
  • Considera backend SQLite para uso intensivo

El servidor no se inicia:

  • Verifica versión de Node.js: node --version (recomendado 18+)
  • Instala dependencias: npm install @modelcontextprotocol/sdk zod
  • Busca errores de sintaxis
  • Ejecuta directamente: node memory-server.js

Múltiples agentes sobrescriben memorias:

  • Incluye siempre el campo agent en remember
  • Usa etiquetas únicas por proyecto
  • Filtra recuperación por agente
  • Considera archivos separados por proyecto

Consideraciones de seguridad del servidor de memoria

Almacenamiento de claves API: Si gestionas datos sensibles, implementa cifrado:

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');
}
Enter fullscreen mode Exit fullscreen mode

Control de acceso: Para servidores de equipo:

  • Exige clave API en las herramientas de memoria
  • Implementa namespaces por usuario
  • Registra todas las operaciones (auditoría)
  • Limita la tasa de solicitudes por usuario

Tus agentes de IA ahora tienen memoria persistente. Recuerdan lo de ayer, recuperan decisiones y traspasan contexto sin copiar y pegar.

Ese es el poder de la memoria MCP: dale a tus agentes un cuaderno compartido y observa cómo escalan en proyectos de varios días.

Preguntas frecuentes

¿Qué es la memoria MCP?

Es una implementación de protocolo que permite a los agentes de IA almacenar y recuperar información entre sesiones. Funciona como un cuaderno compartido y persistente.

¿Cómo configuro la memoria persistente para Claude Code?

Instala un servidor de memoria MCP y agrégalo a ~/.claude/settings.json con el comando y ruta del servidor. Reinicia Claude Code y tendrás las herramientas de memoria disponibles.

¿Qué agentes de IA son compatibles?

Cualquier agente en clientes MCP (Claude Code, Cursor, Windsurf). No necesitas modificar código, solo añade instrucciones a tus prompts.

¿Patrones recomendados para traspasos entre agentes?

Usa remember con etiquetas como ["handoff", "nombre-del-proyecto"]. Incluye trabajo completado, pendientes y problemas conocidos. El siguiente agente recupera contexto con recall(query="handoff").

¿Cuánta memoria pueden almacenar los servidores MCP?

Depende de la implementación. El ejemplo usa un archivo JSON que crece indefinidamente. En producción, añade políticas de expiración, autoarchivo o backend de base de datos.

¿Pueden los equipos compartir un servidor central?

Sí, ejecuta el servidor en una máquina compartida o en la nube y configura los clientes de todos para conectarse a él. Etiqueta memorias por proyecto y desarrollador.

¿Qué hago si obtengo demasiados resultados en la recuperación?

Utiliza etiquetas más específicas al almacenar memorias, filtra por agente y usa frases exactas. Considera búsqueda semántica para resultados más inteligentes.

Top comments (0)