Referencia de Tools
Resumen
Sección titulada «Resumen»mcp-memory expone 19 tools vía el protocolo MCP. Las primeras 8 son 100% compatibles con la API de MCP Memory de Anthropic — úsalo como reemplazo drop-in. Las 11 restantes extienden la funcionalidad con búsqueda semántica, recuperación híbrida, gestión de entidades y operaciones de mantenimiento.
Resumen de Compatibilidad
Sección titulada «Resumen de Compatibilidad»| Tool | Descripción | Anthropic | Nueva |
|---|---|---|---|
create_entities | Crea o actualiza entidades (fusiona observaciones) | ✅ | |
create_relations | Crea relaciones tipadas entre entidades | ✅ | |
add_observations | Añade observaciones a una entidad existente | ✅ | |
delete_entities | Elimina entidades (cascada a observaciones + relaciones) | ✅ | |
delete_observations | Elimina observaciones específicas de una entidad | ✅ | |
delete_relations | Elimina relaciones específicas | ✅ | |
search_nodes | Búsqueda por substring (nombre, tipo, contenido de observaciones) | ✅ | |
open_nodes | Recupera entidades por nombre exacto | ✅ | |
search_semantic | Búsqueda semántica vía embeddings vectoriales + re-ranking límbico | 🆕 | |
migrate | Importa desde formato JSONL de Anthropic (idempotente) | 🆕 | |
analyze_entity_split | Analiza una entidad para determinar si necesita splitting (umbrales: Sesion=15, Proyecto=25, otras=20) | 🆕 | |
propose_entity_split | Analiza y propone un split si la entidad lo necesita | 🆕 | |
execute_entity_split | Ejecuta un split aprobado (crea nuevas entidades, mueve observaciones) | 🆕 | |
find_split_candidates | Encuentra todas las entidades candidatas para splitting | 🆕 | |
find_duplicate_observations | Encuentra observaciones semánticamente duplicadas dentro de una entidad (coseno + containment) | 🆕 | |
consolidation_report | Genera un reporte de consolidación de solo lectura (candidatas a split, obs marcadas, entidades estancadas) | 🆕 | |
end_relation | Expira una relación activa estableciendo active=0 y ended_at=now | 🆕 | |
add_reflection | Añade una reflexión narrativa a una entidad, sesión, relación o global | 🆕 | |
search_reflections | Busca reflexiones vía búsqueda híbrida semántica (KNN) y texto (FTS5) con RRF | 🆕 |
1. create_entities
Sección titulada «1. create_entities»Crea o actualiza entidades en el knowledge graph. Si una entidad ya existe, las observaciones se fusionan — los datos existentes nunca se sobrescriben.
Signature: create_entities(entities: list[dict[str, Any]]) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
entities | list[dict] | Sí | Lista de entidades a crear o actualizar |
Cada diccionario de entidad se valida contra el modelo Pydantic EntityInput:
| Campo | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
name | str | Sí | — | Nombre de la entidad (mínimo 1 carácter). Actúa como identificador único. |
entityType | str | No | "Generic" | Categoría de la entidad (ej: "Project", "Task", "Component"). |
observations | list[str] | No | [] | Observaciones a adjuntar a la entidad. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "entities": [ { "name": "CachorroSpace", "entityType": "Project", "observations": [ "Stack: Astro 6.x + Starlight 0.38.x", "Deployed on Vercel at cachorro.space" ] } ]}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "entities": [ { "name": "CachorroSpace", "entityType": "Project", "observations": [ "Stack: Astro 6.x + Starlight 0.38.x", "Deployed on Vercel at cachorro.space" ] } ]}Respuesta de Error
Sección titulada «Respuesta de Error»{ "error": "1 validation error for EntityInput\nname\n Field required [type=missing, input_value={'entityType': 'Project'}, input_type=dict]"}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Implementa upsert vía
INSERT … ON CONFLICT(name) DO UPDATE. Si la entidad ya existe, actualizaentity_typeyupdated_atsin eliminar las observaciones previas. - Las observaciones se fusionan: las nuevas se añaden y los duplicados exactos se descartan silenciosamente.
- Genera un embedding con el snapshot completo de la entidad (nombre + tipo + todas las observaciones). Si el motor de embeddings no está disponible, la operación se completa sin error.
- Se pueden crear múltiples entidades en una sola llamada pasando varios diccionarios en el array
entities.
2. create_relations
Sección titulada «2. create_relations»Crea relaciones entre entidades. Ambas entidades — origen y destino — deben existir en el knowledge graph antes de crear una relación.
Signature: create_relations(relations: list[dict[str, Any]]) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
relations | list[dict] | Sí | Lista de relaciones a crear |
Cada diccionario de relación se valida contra el modelo Pydantic RelationInput:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
from | str | Sí | Nombre de la entidad origen. Debe existir en el grafo. |
to | str | Sí | Nombre de la entidad destino. Debe existir en el grafo. |
relationType | str | Sí | Tipo de relación (ej: "contains", "depends_on", "uses"). |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "relations": [ { "from": "CachorroSpace", "to": "Astro", "relationType": "uses" } ]}Ejemplo de Respuesta (éxito)
Sección titulada «Ejemplo de Respuesta (éxito)»{ "relations": [ { "from": "CachorroSpace", "to": "Astro", "relationType": "uses" } ]}Respuesta de Error (entidad no encontrada)
Sección titulada «Respuesta de Error (entidad no encontrada)»{ "relations": [ { "error": "Entity not found: NonExistentEntity" } ], "errors": [ "Entity not found: NonExistentEntity" ]}Respuesta de Error (relación duplicada)
Sección titulada «Respuesta de Error (relación duplicada)»{ "relations": [ { "from": "CachorroSpace", "to": "Astro", "relationType": "uses", "error": "Relation already exists" } ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Ambas entidades (
fromyto) deben existir antes de crear la relación. Si falta alguna, la relación no se crea y se retorna un error. - La tabla
relationstiene una restricciónUNIQUE(from_entity, to_entity, relation_type). Si la relación ya existe, el diccionario se retorna con una clave"error". - No modifica embeddings — las relaciones son metadatos estructurales y no participan en la búsqueda semántica.
3. add_observations
Sección titulada «3. add_observations»Añade observaciones a una entidad existente. La entidad debe existir previamente — usa create_entities para crear nuevas entidades.
Signature: add_observations(name: str, observations: list[str]) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
name | str | Sí | Nombre exacto de la entidad. Debe existir. |
observations | list[str] | Sí | Observaciones a añadir. Los duplicados exactos se descartan. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "name": "CachorroSpace", "observations": [ "ECharts 6.x chosen for visualizations", "Accent color: teal (#2dd4bf)" ]}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "entity": { "name": "CachorroSpace", "entityType": "Project", "observations": [ "Stack: Astro 6.x + Starlight 0.38.x", "Deployed on Vercel at cachorro.space", "ECharts 6.x chosen for visualizations", "Accent color: teal (#2dd4bf)" ] }}Respuesta de Error (entidad no encontrada)
Sección titulada «Respuesta de Error (entidad no encontrada)»{ "error": "Entity not found: NonExistentEntity"}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- La entidad debe existir. Esta tool nunca crea entidades nuevas.
- Los duplicados exactos de observaciones se descartan silenciosamente — no se genera error por duplicados.
- Regenera el embedding con el snapshot actualizado de la entidad (todas las observaciones existentes + las nuevas).
- Usa esta tool cuando quieras añadir datos a una entidad sin reespecificar su tipo u observaciones existentes.
4. delete_entities
Sección titulada «4. delete_entities»Elimina entidades y todas sus observaciones y relaciones asociadas.
Signature: delete_entities(entityNames: list[str]) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
entityNames | list[str] | Sí | Nombres de entidades a eliminar. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "entityNames": ["Old Project", "Deprecated Component"]}Ejemplo de Respuesta (éxito)
Sección titulada «Ejemplo de Respuesta (éxito)»{ "deleted": ["Old Project", "Deprecated Component"]}Respuesta de Error (parcial)
Sección titulada «Respuesta de Error (parcial)»{ "deleted": ["Old Project"], "errors": ["Entity not found: Already Deleted Entity"]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Eliminación en cascada: eliminar una entidad remueve automáticamente todas sus observaciones y relaciones vía
ON DELETE CASCADEen SQLite. - Crítico — embeddings: la tabla virtual
vec0de sqlite-vec no soporta CASCADE. El código elimina manualmente los embeddings antes de eliminar entidades: (1) busca los rowids de la entidad, (2) elimina deentity_embeddingsporrowid, (3) elimina deentities. Todo dentro de una transacción implícita de SQLite. - Puede fallar intermitentemente con
"cannot start a transaction"bajo alta concurrencia en modo WAL. Reintentar normalmente lo resuelve. - Las entidades que no existen se reportan en el array
errorspero no impiden otras eliminaciones válidas.
5. delete_observations
Sección titulada «5. delete_observations»Elimina observaciones específicas de una entidad. La entidad se preserva — solo se remueven las observaciones coincidentes.
Signature: delete_observations(name: str, observations: list[str]) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
name | str | Sí | Nombre exacto de la entidad. Debe existir. |
observations | list[str] | Sí | Observaciones a eliminar (coincidencia de contenido exacto). |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "name": "CachorroSpace", "observations": [ "Accent color: teal (#2dd4bf)" ]}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "entity": { "name": "CachorroSpace", "entityType": "Project", "observations": [ "Stack: Astro 6.x + Starlight 0.38.x", "Deployed on Vercel at cachorro.space", "ECharts 6.x chosen for visualizations" ] }}Respuesta de Error (entidad no encontrada)
Sección titulada «Respuesta de Error (entidad no encontrada)»{ "error": "Entity not found: NonExistentEntity"}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- La eliminación es por coincidencia de contenido exacto. No hay patrones, wildcards ni coincidencia por substring.
- Si una observación no existe para esa entidad, no ocurre nada — no se genera error por observaciones no encontradas.
- Regenera el embedding con las observaciones restantes después de la eliminación.
- Útil para remover observaciones obsoletas o incorrectas sin recrear la entidad completa.
6. delete_relations
Sección titulada «6. delete_relations»Elimina relaciones entre entidades. Requiere el triple completo para identificar la relación.
Signature: delete_relations(relations: list[dict[str, Any]]) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
relations | list[dict] | Sí | Relaciones a eliminar (mismo formato que create_relations) |
Cada diccionario de relación:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
from | str | Sí | Nombre de la entidad origen |
to | str | Sí | Nombre de la entidad destino |
relationType | str | Sí | Tipo de relación |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "relations": [ { "from": "CachorroSpace", "to": "Astro", "relationType": "uses" } ]}Ejemplo de Respuesta (éxito)
Sección titulada «Ejemplo de Respuesta (éxito)»{ "deleted": [ { "from": "CachorroSpace", "to": "Astro", "relationType": "uses" } ]}Respuesta de Error
Sección titulada «Respuesta de Error»{ "deleted": [], "errors": [ "Relation not found: A -> B (contains)" ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Requiere el triple completo (
from+to+relationType) para identificar la relación. Las coincidencias parciales no funcionan. - Si alguna entidad no existe:
"Entity not found: X or Y". - Si la relación no existe:
"Relation not found: X -> Y (relationType)". - No modifica embeddings — las relaciones no forman parte del índice semántico.
7. search_nodes
Sección titulada «7. search_nodes»Busca entidades por nombre, tipo de entidad o contenido de observaciones usando coincidencia de substring. Es una búsqueda ligera que no requiere el modelo de embeddings.
Signature: search_nodes(query: str) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
query | str | Sí | Término de búsqueda. Se aplica como patrón LIKE en múltiples campos. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "query": "astro" }Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "entities": [ { "name": "CachorroSpace", "entityType": "Project", "observations": [ "Stack: Astro 6.x + Starlight 0.38.x", "Deployed on Vercel at cachorro.space" ] }, { "name": "CachorroInk", "entityType": "Project", "observations": [ "Blog built with Astro 5.x" ] } ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Usa LIKE con el patrón
%query%aplicado simultáneamente en tres campos:name,entity_typeycontentde observaciones. - Usa
SELECT DISTINCTpara evitar retornar la misma entidad múltiples veces cuando coincide en varios campos. - No requiere el modelo de embeddings ONNX — funciona de inmediato sin configuración adicional.
- La búsqueda es sensible a mayúsculas por defecto (comportamiento estándar de
LIKEen SQLite). Para búsqueda insensible a mayúsculas, usa la búsqueda semántica. - Para consultas dirigidas en grafos grandes, prefiere
search_nodeso la búsqueda semántica sobreopen_nodes.
8. open_nodes
Sección titulada «8. open_nodes»Recupera entidades específicas por nombre exacto. Retorna los datos completos de la entidad con todas sus observaciones.
Signature: open_nodes(names: list[str]) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
names | list[str] | Sí | Nombres de entidades a recuperar. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "names": ["CachorroSpace", "Astro"] }Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "entities": [ { "name": "CachorroSpace", "entityType": "Project", "observations": [ "Stack: Astro 6.x + Starlight 0.38.x", "Deployed on Vercel at cachorro.space" ] } ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Búsqueda por nombre exacto (
WHERE name = ?). Sin patrones, wildcards ni coincidencia LIKE. - Si un nombre no coincide con ninguna entidad, se omite silenciosamente de los resultados — no se genera error. En el ejemplo anterior, si
"Astro"no existe, solo se retorna"CachorroSpace". - No incluye relaciones en la respuesta. Para obtener relaciones, usa
search_nodescon una consulta relevante a relaciones osearch_semantic. - Ideal para consultas rápidas cuando se conoce el nombre exacto de la entidad.
9. search_semantic
Sección titulada «9. search_semantic»Búsqueda semántica usando embeddings vectoriales con búsqueda híbrida de texto completo opcional. Combina resultados semánticos (KNN) y de texto (FTS5) vía Reciprocal Rank Fusion, y luego aplica re-ranking límbico basado en patrones de acceso y co-ocurrencia.
Requiere el modelo de embeddings — ejecuta download_model.py primero. Consulta Búsqueda Semántica para los detalles completos del pipeline y Búsqueda Híbrida para el mecanismo de fusión RRF.
Signature: search_semantic(query: str, limit: int = 10) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
query | str | Sí | — | Texto de consulta. Se codifica como embedding y se compara contra los vectores almacenados. |
limit | int | No | 10 | Número máximo de resultados a retornar. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "query": "web framework for documentation sites", "limit": 5}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "results": [ { "name": "CachorroSpace", "entityType": "Project", "observations": [ "Stack: Astro 6.x + Starlight 0.38.x", "Documentation site for open-source repos" ], "limbic_score": 0.6742, "scoring": { "importance": 0.8512, "temporal_factor": 0.9923, "cooc_boost": 1.2341 }, "distance": 0.1234, "rrf_score": 0.018542 }, { "name": "CachorroInk", "entityType": "Project", "observations": [ "Blog built with Astro 5.x" ], "limbic_score": 0.4521, "scoring": { "importance": 0.6234, "temporal_factor": 0.8756, "cooc_boost": 0.5123 }, "distance": 0.3591, "rrf_score": 0.012341 } ]}Respuesta de Error (modelo no disponible)
Sección titulada «Respuesta de Error (modelo no disponible)»{ "error": "Embedding model not available. Run 'python scripts/download_model.py' to download the model first."}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Requiere que el modelo de embeddings ONNX esté descargado. Si no está disponible, retorna un error descriptivo. Todas las demás tools funcionan sin él.
- Usa búsqueda híbrida: KNN (distancia coseno de sqlite-vec) se ejecuta en paralelo con FTS5 (texto completo BM25). Los resultados se fusionan vía Reciprocal Rank Fusion (k=60).
- Si FTS5 no retorna resultados o no está disponible, recurre al modo semántico puro (solo KNN + re-ranking límbico).
- Cada resultado incluye:
limbic_score— score de ranking final (consulta Sistema Límbico)scoring— desglose de importancia, decay temporal y boost de co-ocurrenciadistance— distancia coseno desde el vector de consultarrf_score— score de Reciprocal Rank Fusion (solo presente en modo híbrido; ausente en modo semántico puro)
- Tracking post-respuesta: después de retornar resultados, el motor registra eventos de acceso y co-ocurrencias para las entidades top-K. Esto mejora los rankings futuros. Es best-effort — no afecta la respuesta actual.
- Menor distancia = mayor similitud. Fórmula:
d = 1 - cos(A, B), rango[0, 2]. - El texto de la entidad se codifica usando una estrategia de selección Head+Tail+Diversity con un presupuesto de 480 tokens (no es concatenación simple). Consulta Búsqueda Semántica para más detalles.
10. migrate
Sección titulada «10. migrate»Importa datos desde el formato JSONL de Anthropic MCP Memory a SQLite. Idempotente — ejecutarlo múltiples veces no duplica datos. Consulta Migración para una guía paso a paso.
Signature: migrate(source_path: str = "") → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
source_path | str | Sí | "" | Ruta al archivo JSONL fuente de Anthropic. Debe existir. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "source_path": "~/.config/opencode/mcp-memory.jsonl"}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "entities_imported": 32, "relations_imported": 37, "errors": 0, "skipped": 2}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Idempotente: las entidades se insertan o actualizan (upsert), las relaciones se crean solo si no existen ya, y las observaciones duplicadas se descartan. Seguro para ejecutar repetidamente.
- Las relaciones se importan solo si ambas entidades ya existen en el grafo al momento de procesar la línea. Esto significa que el archivo JSONL debería listar entidades antes que sus relaciones.
- Generación de embeddings en batch: si el motor de embeddings está disponible, se generan embeddings para todas las entidades importadas al final del proceso de migración.
- El contador
skippedincluye líneas que no se pudieron procesar (JSON malformado, campos requeridos faltantes, etc.). - También disponible como script independiente — consulta Primeros Pasos para la invocación por CLI.
11. analyze_entity_split
Sección titulada «11. analyze_entity_split»Signature: analyze_entity_split(entity_name: str) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
entity_name | str | Sí | Nombre de la entidad a analizar |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "entity_name": "Proyecto cachorrites"}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "analysis": { "entity_name": "Proyecto cachorrites", "entity_type": "Proyecto", "observation_count": 28, "threshold": 25, "needs_split": true, "topics": { "Arquitectura": ["Stack: FastMCP + SQLite", "MCP Memory v2"], "Implementacion": ["97 tests passing", "Query routing implementado"], "Despliegue": ["Deploy: Vercel", "URL: cachorro.space"] }, "split_score": 1.12 }}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Analiza si una entidad excede su umbral específico por tipo (Sesion=15, Proyecto=25, otras=20)
- Usa TF-IDF para agrupar observaciones en tópicos
needs_split: truecuandosplit_score > 1.0Yobservation_count > threshold- NO modifica la entidad — solo analiza
12. propose_entity_split
Sección titulada «12. propose_entity_split»Signature: propose_entity_split_tool(entity_name: str) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
entity_name | str | Sí | Nombre de la entidad a analizar y dividir |
Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "proposal": { "original_entity": { "name": "Proyecto cachorrites", "entity_type": "Proyecto" }, "suggested_splits": [ { "name": "Proyecto cachorrites - Arquitectura", "entity_type": "Proyecto", "observations": ["Stack: FastMCP + SQLite", "MCP Memory v2"] }, { "name": "Proyecto cachorrites - Implementacion", "entity_type": "Proyecto", "observations": ["97 tests passing", "Query routing implementado"] } ], "relations_to_create": [ {"from": "Proyecto cachorrites", "to": "Proyecto cachorrites - Arquitectura", "type": "contiene"}, {"from": "Proyecto cachorrites - Arquitectura", "to": "Proyecto cachorrites", "type": "parte_de"}, {"from": "Proyecto cachorrites", "to": "Proyecto cachorrites - Implementacion", "type": "contiene"}, {"from": "Proyecto cachorrites - Implementacion", "to": "Proyecto cachorrites", "type": "parte_de"} ], "analysis": { "observation_count": 28, "threshold": 25, "split_score": 1.12, "num_topics": 3 } }}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Retorna
proposal: nullsi la entidad no necesita splitting - Crea relaciones
contiene(parent→child) yparte_de(child→parent) - Usa TF-IDF con stop words en español para extraer tópicos
- Los nombres de entidades preservan acentos, entityType no tiene acentos
13. execute_entity_split
Sección titulada «13. execute_entity_split»Signature: execute_entity_split_tool(entity_name: str, approved_splits: list[dict[str, Any]], parent_entity_name: str | None = None) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
entity_name | str | Sí | Nombre de la entidad original a dividir |
approved_splits | list[dict] | Sí | Lista de definiciones de splits aprobadas |
parent_entity_name | str | No | Nombre opcional del parent explícito |
Cada approved_split debe tener:
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
name | str | Sí | Nombre para la nueva sub-entidad |
entity_type | str | Sí | Tipo de entidad (típicamente igual al original) |
observations | list[str] | Sí | Observaciones a mover a esta sub-entidad |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "entity_name": "Proyecto cachorrites", "approved_splits": [ { "name": "Proyecto cachorrites - Arquitectura", "entity_type": "Proyecto", "observations": ["Stack: FastMCP + SQLite", "MCP Memory v2"] } ]}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "result": { "new_entities": ["Proyecto cachorrites - Arquitectura"], "moved_observations": 2, "relations_created": 2, "original_observations_remaining": 26 }}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Crea nuevas entidades a partir de los splits aprobados
- Mueve las observaciones especificadas de la entidad original a las nuevas
- Establece relaciones
contiene/parte_de - Usa transacción atómica (todo o nada)
- Regenera embeddings para las nuevas entidades
14. find_split_candidates
Sección titulada «14. find_split_candidates»Signature: find_split_candidates() → dict[str, Any]
Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "candidates": [ { "entity_name": "Proyecto cachorrites", "entity_type": "Proyecto", "observation_count": 28, "threshold": 25, "needs_split": true, "topics": {...}, "split_score": 1.12 }, { "entity_name": "Sesión 2026-03-31", "entity_type": "Sesion", "observation_count": 18, "threshold": 15, "needs_split": true, "topics": {...}, "split_score": 1.2 } ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Escanea TODAS las entidades en el knowledge graph
- Retorna lista vacía si no encuentra candidatas
- NO modifica ninguna entidad — solo analiza
15. find_duplicate_observations
Sección titulada «15. find_duplicate_observations»Encuentra observaciones que pueden estar semánticamente duplicadas dentro de una entidad. Retorna pares de observaciones con scores de similitud y tipo de match.
Requiere el modelo de embeddings — ejecuta download_model.py primero.
Signature: find_duplicate_observations(entity_name: str, threshold: float = 0.85, containment_threshold: float = 0.7) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
entity_name | str | Sí | — | Nombre de la entidad a revisar |
threshold | float | No | 0.85 | Similitud coseno mínima para considerar dos observaciones como duplicadas |
containment_threshold | float | No | 0.7 | Score de containment mínimo para pares de texto asimétricos (ratio de longitud >= 2.0) |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "entity_name": "Mi Proyecto", "threshold": 0.85}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "entity_name": "Mi Proyecto", "total_observations": 12, "duplicate_pairs": [ { "obs_text_a": "Desplegado en Vercel con dominio personalizado", "obs_text_b": "Deployment: Vercel, dominio personalizado configurado", "similarity_score": 0.91, "match_type": "cosine" }, { "obs_text_a": "Stack: FastMCP + SQLite + ONNX Runtime para embeddings", "obs_text_b": "FastMCP", "similarity_score": 0.73, "match_type": "containment" } ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Usa similitud combinada: similitud coseno >=
thresholdOR score de containment >=containment_thresholdcuando un texto es 2x+ más largo que el otro (longitud asimétrica). - Clustering Union-Find agrupa observaciones en clusters de duplicados — cada par aparece una sola vez.
- El campo
match_typeindica qué métrica de similitud disparó el match:"cosine"para similitud coseno estándar,"containment"para pares de texto asimétricos. - Solo lectura — no se realizan modificaciones al knowledge graph. Revisa los resultados y usa
delete_observationspara consolidar manualmente. - Requiere el modelo de embeddings. Retorna un error si el modelo no está disponible.
- Consulta Mantenimiento & Operaciones para el workflow completo de deduplicación.
16. consolidation_report
Sección titulada «16. consolidation_report»Genera un reporte de consolidación de solo lectura que analiza la salud del knowledge graph en cuatro dimensiones: candidatas a split, observaciones marcadas, entidades estancadas y entidades grandes.
Signature: consolidation_report(stale_days: float = 90.0) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
stale_days | float | No | 90.0 | Días de inactividad para considerar una entidad como estancada |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "stale_days": 90}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "summary": { "total_entities": 47, "total_observations": 312, "split_candidates_count": 3, "flagged_observations_count": 8, "stale_entities_count": 12, "large_entities_count": 5 }, "split_candidates": [ { "entity_name": "Sesión 2026-03-31", "entity_type": "Sesion", "observation_count": 18, "threshold": 15, "split_score": 1.2 } ], "flagged_observations": [ { "entity_name": "Mi Proyecto", "observation_text": "Desplegado en Vercel", "similarity_flag": 1 } ], "stale_entities": [ { "entity_name": "Experimento Antiguo", "entity_type": "Generic", "last_accessed_days_ago": 145, "access_count": 2, "observation_count": 3 } ], "large_entities": [ { "entity_name": "Proyecto cachorritos", "entity_type": "Proyecto", "observation_count": 35 } ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Solo lectura — genera un reporte sin modificar datos. sofia revisa el reporte y decide qué acciones tomar.
- Verifica 4 áreas:
- Candidatas a split: entidades que exceden umbrales de observaciones por tipo (Sesion=15, Proyecto=25, otras=20) con diversidad temática suficiente
- Observaciones marcadas: observaciones con
similarity_flag=1(posibles duplicados semánticos detectados poradd_observations) - Entidades estancadas: entidades no accedidas en
stale_daysdías con bajo count de acceso - Entidades grandes: entidades que exceden umbrales de tamaño y pueden necesitar split
- No requiere el modelo de embeddings para la mayoría de verificaciones (solo el análisis de candidatas a split usa TF-IDF, que está integrado).
- Consulta Mantenimiento & Operaciones para el workflow completo de consolidación.
17. end_relation
Sección titulada «17. end_relation»Expira una relación activa estableciendo active=0 y ended_at=now. Para pares inversos (contiene/parte_de), también expira la relación inversa.
Signature: end_relation(relation_id: int) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
relation_id | int | Sí | El ID de la relación a expirar |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "relation_id": 42}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "result": "Relation 42 expired successfully"}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Establece
active=0yended_at=nowen la relación especificada - Para pares
contiene/parte_de, ambas direcciones se expiran automáticamente - La relación no se elimina — permanece en la base de datos con
active=0como referencia histórica - Si la relación ya está expirada (active=0), la operación es un no-op
- Usa esta tool en lugar de
delete_relationscuando quieras preservar el hecho histórico de que existió una relación
18. add_reflection
Sección titulada «18. add_reflection»Añade una reflexión narrativa para dar contexto y significado a un recuerdo. Las reflexiones son prosa libre adjunta a entidades, sesiones, relaciones o de forma global, con metadatos de autor y mood.
Signature: add_reflection(target_type: str, content: str, author: str = "sofia", mood: str | None = None, target_id: int | None = None) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
target_type | str | Sí | — | Qué objetivo tiene esta reflexión — 'entity', 'session', 'relation' o 'global' |
content | str | Sí | — | El texto de la reflexión (prosa libre, sin prefijos) |
author | str | No | "sofia" | Quién la escribió — 'nolan' o 'sofia' |
mood | str o null | No | null | Mood opcional — 'frustracion', 'satisfaccion', 'curiosidad', 'duda', 'insight' |
target_id | int o null | No | null | ID de la entidad/relación objetivo. Requerido para tipos entity y relation. null para session y global. |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "target_type": "entity", "target_id": 15, "content": "Esta entidad representa la decisión arquitectónica central que dio forma a todo el proyecto.", "author": "nolan", "mood": "insight"}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "result": { "id": 5, "target_type": "entity", "target_id": 15, "author": "nolan", "content": "Esta entidad representa la decisión arquitectónica central que dio forma a todo el proyecto.", "mood": "insight", "created_at": "2026-04-14 22:47:23" }}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Las reflexiones se almacenan en una tabla
reflectionsseparada — independiente de las observaciones - Cada reflexión se indexa con FTS5 paralelo (
reflection_fts) y embeddings vectoriales (reflection_embeddings) para búsqueda híbrida target_type='entity'o'relation'requiere untarget_idválido.target_type='session'o'global'usatarget_id=null- El campo
contentes prosa libre — no requiere formato estructurado - El campo
moodes opcional y usa términos en español (consistente con las convenciones del proyecto) - Los embeddings de reflexiones usan el mismo modelo ONNX que las entidades, almacenados en una tabla
vec0separada
19. search_reflections
Sección titulada «19. search_reflections»Busca reflexiones por similitud semántica y filtros opcionales. Combina resultados semánticos (KNN) y de texto (FTS5) vía Reciprocal Rank Fusion — el mismo pipeline híbrido usado para la búsqueda de entidades.
Signature: search_reflections(query: str, author: str | None = None, mood: str | None = None, target_type: str | None = None, limit: int = 10) → dict[str, Any]
Parámetros
Sección titulada «Parámetros»| Parámetro | Tipo | Requerido | Default | Descripción |
|---|---|---|---|---|
query | str | Sí | — | Texto de búsqueda |
author | str o null | No | null | Filtrar por autor ('nolan' o 'sofia') |
mood | str o null | No | null | Filtrar por mood |
target_type | str o null | No | null | Filtrar por tipo de objetivo ('entity', 'session', 'relation', 'global') |
limit | int | No | 10 | Máximo de resultados (default 10) |
Ejemplo de Petición
Sección titulada «Ejemplo de Petición»{ "query": "decisiones de arquitectura que formaron el proyecto", "author": "nolan", "limit": 5}Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "results": [ { "id": 5, "target_type": "entity", "target_id": 15, "author": "nolan", "content": "Esta entidad representa la decisión arquitectónica central que dio forma a todo el proyecto.", "mood": "insight", "created_at": "2026-04-14 22:47:23", "score": 0.8456 } ]}Notas de Comportamiento
Sección titulada «Notas de Comportamiento»- Usa el mismo pipeline híbrido RRF que la búsqueda de entidades: KNN (semántico) + FTS5 (texto) fusionados vía Reciprocal Rank Fusion
- Busca solo en el índice de reflexiones — no busca observaciones de entidades
- Todos los filtros (
author,mood,target_type) son opcionales — combínalos para consultas dirigidas - Requiere el modelo de embeddings (igual que
search_semantic) - Retorna un campo
scoreque representa la similitud semántica combinada con RRF
Comportamiento de Embeddings por Operación
Sección titulada «Comportamiento de Embeddings por Operación»Toda operación de escritura que cambia el contenido de una entidad dispara una actualización del embedding. La siguiente tabla resume cómo interactúa cada tool con el sistema de embeddings:
| Operación | Acción sobre Embedding | Detalle |
|---|---|---|
create_entities | ✅ Genera/Actualiza | Snapshot completo: nombre + tipo + todas las observaciones |
add_observations | ✅ Regenera | Regenera con todas las observaciones (antiguas + nuevas) |
delete_observations | ✅ Regenera | Regenera sin las observaciones eliminadas |
delete_entities | 🗑️ Elimina | Eliminación manual antes de CASCADE (limitación de vec0) |
create_relations | ❌ Ninguna | Las relaciones no participan en la búsqueda semántica |
delete_relations | ❌ Ninguna | Ídem |
search_nodes | ❌ Ninguna | Búsqueda basada en LIKE, no requiere embeddings |
open_nodes | ❌ Ninguna | Búsqueda directa por nombre exacto |
search_semantic | 📖 Solo lectura | Codifica la consulta, busca por distancia coseno, re-ranke con Limbic Scoring. Registra accesos + co-ocurrencias post-respuesta. |
migrate | ✅ Batch | Genera embeddings para todas las entidades importadas al final de la migración |
analyze_entity_split | ❌ Ninguna | Solo análisis, no modifica |
propose_entity_split | ❌ Ninguna | Retorna propuesta, no modifica |
execute_entity_split | ✅ Regenera | Crea nuevas entidades con embeddings frescos |
find_split_candidates | ❌ Ninguna | Escanea sin modificar |
find_duplicate_observations | 📖 Solo lectura | Codifica observaciones, calcula similitud coseno + containment por pares. Requiere modelo de embeddings. |
consolidation_report | ❌ Ninguna | Solo análisis, no modifica |
end_relation | ❌ Ninguna | Solo actualiza metadatos de la relación |
add_reflection | ✅ Genera | Embedding almacenado en tabla vec0 paralela reflection_embeddings |
search_reflections | 📖 Solo lectura | Codifica la consulta, busca embeddings de reflexiones vía KNN + FTS5 RRF |