Waggle-mcp
¿Por qué waggle-mcp?
La mayoría de los LLM olvidan todo cuando termina la conversación.waggle-mcp soluciona esto dándole a tu IA un grafo de conocimiento persistente que puede leer y escribir a través de cualquier cliente compatible con MCP.
La ventaja clave de Waggle es la eficiencia de tokens con contexto estructurado:
Sin waggle-mcp | Con waggle-mcp |
Contexto incluido en un prompt de 200k tokens | ~4 veces menos tokens — subgrafo compacto, solo se recuperan los nodos relevantes |
"¿Qué decidimos sobre el esquema de la BD?" → ❌ Perdido al terminar la sesión | ✅ Recuerda el nodo de decisión, cuándo se tomó y qué contradice |
Memoria de lista de viñetas plana | Aristas tipadas: |
Una sesión, un agente | Multi-inquilino, multisesión, multiagente |
Nota sobre la recuperación: Waggle sacrifica algo de cobertura de recuperación bruta a cambio de un costo de tokens drásticamente menor y un contexto relacional más rico. Consulta la sección de benchmarks para ver números honestos.
Inicio rápido — 30 segundos
pip install waggle-mcp
waggle-mcp initEl asistente init detecta tu cliente MCP, escribe su archivo de configuración y crea el directorio de la base de datos; no se requiere edición de JSON. Compatible con Claude Desktop, Cursor, Codex y un fallback de JSON genérico.
Después de la inicialización, reinicia tu cliente MCP y tu IA tendrá memoria persistente.
Sin servicio en la nube. Sin clave API. La búsqueda semántica se ejecuta completamente de forma local.
Véalo en acción
Aquí hay un antes y después concreto para un desarrollador que usa la IA a diario:
Sesión 1 — 10 de abril
User: Let's use PostgreSQL. MySQL replication has been painful.
Agent: [calls observe_conversation()]
→ stores decision node: "Chose PostgreSQL over MySQL"
→ stores reason node: "MySQL replication painful"
→ links them with a depends_on edgeSesión 2 — 12 de abril (ventana de contexto nueva, sin historial)
User: What did we decide about the database?
Agent: [calls query_graph("database decision")]
→ retrieves the decision node + linked reason from April 10
"You decided on PostgreSQL on April 10. The reason recorded was
that MySQL replication had been painful."Sesión 3 — 14 de abril
User: Actually, let's reconsider — the team is more familiar with MySQL.
Agent: [calls store_node() + store_edge(new_node → old_node, "contradicts")]
→ conflict is flagged automatically; both positions are preserved in the graphEl agente nunca necesitó instrucciones explícitas para recordar o recuperar; llamó a las herramientas correctas basándose en la conversación y el grafo le proporcionó el contexto adecuado.
Cómo funciona
La memoria no solo se almacena, sino que fluye a través de un ciclo de vida:
You talk to your AI
│
▼
observe_conversation() ← AI drops the turn in; facts extracted via structured LLM (regex fallback)
│
▼
Graph nodes are created ← "Chose PostgreSQL" becomes a decision node
Edges are inferred ← linked to the "database" entity node
│
▼
Future conversation starts
│
▼
query_graph("DB schema") ← semantic search finds the node from 3 sessions ago
│
▼
AI answers with full context ← "You decided on PostgreSQL on Apr 10, here's why…"Cada nodo lleva incrustaciones (embeddings) semánticas calculadas localmente usando all-MiniLM-L6-v2, un modelo rápido y ligero que se ejecuta completamente en el dispositivo sin necesidad de clave API ni llamadas de red. Esto significa que la búsqueda semántica funciona sin conexión, no cuesta nada por consulta y mantiene tus datos privados.
La herramienta mágica: observe_conversation
Esta es la herramienta que más usarás. No tienes que almacenar hechos manualmente; solo dile al agente que observe cada turno de la conversación y él se encarga del resto.
observe_conversation(user_message, assistant_response)Internamente, hace lo siguiente:
Extrae hechos atómicos de ambos lados de la conversación
Elimina duplicados frente a nodos existentes usando similitud semántica
Crea aristas tipadas entre conceptos relacionados
Marca contradicciones con las creencias almacenadas existentes
No se necesitan instrucciones. No hay esquema que definir. Solo observa.
Internamente, cada llamada ejecuta una pasada de extracción de LLM validada por Pydantic (con un fallback de regex) para extraer hechos estructurados de diálogos desordenados.
Ejemplo: "Usemos PostgreSQL porque la replicación de MySQL es demasiado dolorosa."
{
"facts": [
{
"label": "PostgreSQL for generic events",
"content": "Chose PostgreSQL over MySQL because MySQL replication is too painful.",
"node_type": "decision",
"confidence": 0.95,
"tags": ["llm-extracted", "confidence:0.95"]
}
]
}Cualquier extracción con confidence < 0.5 o un esquema no válido se descarta silenciosamente para evitar ruido por alucinaciones.
Modelo de memoria
Tipos de nodos — qué se almacena:
Tipo | Ejemplo |
| "La API usa tokens JWT" |
| "El usuario prefiere el modo oscuro" |
| "Elegimos PostgreSQL sobre MySQL" |
| "Proyecto: waggle-mcp" |
| "Limitación de tasa" |
| "¿Deberíamos añadir GraphQL?" |
| "TODO: añadir pruebas de integración" |
Tipos de aristas — cómo se conectan los nodos:
relates_to · contradicts · depends_on · part_of · updates · derived_from · similar_to
Herramientas MCP
Tu IA llama a estas herramientas directamente; no necesitas usarlas manualmente.
Herramienta | Qué hace |
| Introduce un turno de conversación: los hechos se extraen, almacenan y vinculan |
| Búsqueda semántica y temporal en todo el grafo |
| Guarda manualmente un hecho, preferencia, decisión o nota |
| Vincula dos nodos con una relación tipada |
| Recorre las aristas desde un nodo específico |
| Actualiza el contenido o las etiquetas de un nodo existente |
| Elimina un nodo y todas sus aristas |
| Divide contenido largo en nodos atómicos automáticamente |
| Mira qué cambió en las últimas N horas |
| Genera un resumen compacto para una nueva conversación |
| Detecta clústeres de temas mediante detección de comunidades |
| Recuento de nodos/aristas y nodos más conectados |
| Visualización interactiva en el navegador |
| Copia de seguridad JSON portátil |
| Restaura desde una copia de seguridad JSON |
Rendimiento y Benchmarking
Todos los números a continuación son reproducibles a partir de los fixtures incluidos en benchmarks/fixtures/ usando el arnés en scripts/benchmark_extraction.py. Los artefactos de salida guardados viven en tests/artifacts/.
Un comando produce todas las tablas a continuación (línea base de regex de extracción, recuperación, deduplicación y la prueba piloto de eficiencia de tokens comparativa):
PYTHONPATH=src .venv/bin/python scripts/benchmark_extraction.py \
--extraction-backend regex \
--systems waggle rag_naive \
--output tests/artifacts/benchmark_current.jsonLa fila de extracción de LLM (75%) requiere una ejecución separada con una instancia local de Ollama; no está incluida en benchmark_current.json:
# Requires Ollama running locally with qwen2.5:7b pulled
PYTHONPATH=src .venv/bin/python scripts/benchmark_extraction.py \
--extraction-backend llm --ollama-model qwen2.5:7b --ollama-timeout-seconds 30Precisión de extracción
Corpus: 12 pares de diálogo que cubren recuperación simple, interrupciones, reversiones, declaraciones vagas y señales contradictorias (benchmarks/fixtures/extraction_cases.json).
Backend | Casos | Precisión |
Regex (fallback) | 12 | 33% |
LLM ( | 12 | 75% |
Precisión de recuperación
Corpus: 18 nodos, 18 consultas: 6 fáciles (parafraseo directo) y 12 difíciles (adversarias: generalización semántica, desambiguación temporal, traducción de dominio indirecta, encuadre de privacidad). Fuente: benchmarks/fixtures/retrieval_cases.json.
Dificultad | Consultas | Hit@k |
Fácil | 6 | 6/6 = 100% |
Difícil (adversaria) | 12 | 9/12 = 75% |
General | 18 | 15/18 = 83% |
Eficiencia de tokens vs. RAG de vectores fragmentados ingenuo
La tabla de precisión de recuperación anterior mide la calidad de búsqueda independiente de Waggle. La comparación a continuación utiliza un corpus multisesión separado diseñado para probar la eficiencia de tokens frente a una línea base de vectores fragmentados.
Corpus: 24 escenarios multisesión, 66 consultas de recuperación en 7 familias de tareas (benchmarks/fixtures/comparative_eval.json).
Familia de tareas | Consultas | Waggle Hit@k | RAG Hit@k |
| 18 | 18/18 = 100% | 100% |
| 19 | 17/19 = 89% | 100% |
| 11 | 10/11 = 91% | 100% |
| 8 | 8/8 = 100% | 100% |
| 4 (n pequeño) | 4/4 = 100% | 100% |
| 4 (n pequeño) | 2/4 = 50% | 100% |
| 2 (n pequeño) | 1/2 = 50% | 100% |
General | 66 | 60/66 = 91% | 100% |
Sistema | Tokens medios | Tokens medianos | Tokens p95 | Hit@k | Soporte exacto |
Waggle | 36.9 | 37.0 | 42.0 | 91% | 74% |
RAG de vectores fragmentados ingenuo | 152.8 | 155.0 | 162.8 | 100% | 100% |
Waggle utiliza ~4 veces menos tokens por recuperación que la línea base fragmentada ingenua en este corpus.
La brecha entre el Hit@k de Waggle (91%) y el soporte exacto (74%) indica que la recuperación por grafo encuentra el tema correcto pero a veces devuelve detalles de apoyo insuficientes, más visiblemente en consultas de cross_scenario_synthesis (8/8 hit, 1/8 exacto). Mejorar el ensamblaje de contexto, específicamente la profundidad de recorrido de aristas y la expansión de subgrafos de múltiples saltos, es un siguiente paso rastreado.
La compensación es honesta: la línea base fragmentada logra un 100% de Hit@k en este corpus porque en top_k=5 cada hecho es recuperable desde su propio fragmento de sesión. La ventaja de eficiencia de tokens es real y reproducible; la afirmación de superioridad de recuperación requiere un corpus donde la cobertura de fragmentos no pueda compensar la falta de contexto relacional. El endurecimiento del corpus está en curso.
Cuando la extracción falla
Usuario: "Sí, hagamos esa cosa de la que hablamos."
El LLM asigna baja confianza (confidence < 0.5) a entradas ambiguas; Waggle descarta la extracción silenciosamente en lugar de almacenar una suposición. La tubería no recurre silenciosamente a regex en caso de tiempo de espera; los fallos del backend aparecen como errores explícitos que se registran.
Corpus: 22 pares de nodos: 11 duplicados verdaderos (sinónimo, parafraseo, equivalencia de dominio) y 11 falsos amigos (misma categoría tecnológica, tecnología diferente). Fuente: benchmarks/fixtures/dedup_cases.json.
La tubería ejecuta cinco capas:
Capa 0 — Bloqueo estricto de clave de entidad — si ambos nodos nombran tecnologías diferentes en la misma categoría (ej.
postgresqlvsmysql), la fusión se bloquea incondicionalmente.Capa 0b — Guardia de conflicto numérico — misma entidad pero números críticos diferentes (ej.
jwt15 min vs 1 hr) → bloquear. Protege contra la fusión de hechos distintos que comparten una tecnología pero difieren en un valor clave.Capa 1 — Coincidencia de cadena exacta — igualdad de contenido o etiqueta normalizada.
Capa 2 — Contención de subcadena — una oración es un subconjunto estricto de la otra.
Capa 3 — Similitud semántica — coseno mediante
all-MiniLM-L6-v2:Ruta agresiva de misma entidad: si ambos hacen referencia al mismo token de entidad, fusionar con coseno ≥ 0.60 (atrapa duplicados verdaderos de parafraseo como "se eligió fastapi" / "elegimos fastapi porque es asíncrono")
Umbral consciente del tipo:
decision/preference→ 0.82;fact→ 0.92;entity→ 0.97Ruta potenciada por Jaccard: superposición de palabras ≥ 0.35 Y coseno ≥ (umbral de tipo − 0.05)
Fallback global conservador
Mejor medido: 18/22 = 82% en el umbral 0.82. fp=0 en todos los umbrales — no hay fusiones de falsos amigos en ningún umbral probado.
Los 4 falsos negativos restantes son pares de parafraseo puro sin ancla de entidad reconocible ("el usuario prefiere el modo oscuro" / "el usuario quiere una interfaz de modo oscuro", "asíncrono no negociable" / "concurrente sin bloqueo"). Estos requieren un ajuste fino de similitud semántica o un clasificador de parafraseo aprendido para cerrarse.
Barrido completo de umbrales y metodología detallada: tests/artifacts/README.md.
Artefactos completos, metodología y comparación rag_tuned:
tests/artifacts/README.md
Hoja de
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/Abhigyan-Shekhar/Waggle-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server