PersonaMCP
Memoria local-primero de cómo escribes: perfil de estilo y ejemplos reales de respuestas de tus propias exportaciones de chat.
Documentación
PersonaMCP
Tu estilo de comunicación y memoria para agentes de IA.
PersonaMCP importa tus exportaciones de conversaciones, mide cómo escribes tú, y le da a un agente de IA un perfil de estilo compacto más ejemplos relevantes de mensajes entrantes/respuestas. Tu historial sin procesar permanece en tu computadora. No hay entrenamiento de modelos, panel web, requisito de embeddings en la nube, telemetría, ni generación automática de respuestas.
Las preferencias de escritura suelen ser demasiado vagas: "suena casual" no captura a alguien que usa minúsculas, envía tres mensajes cortos, cambia de idioma, o escribe de manera diferente a un colega. PersonaMCP le da al escritor conectado evidencia en lugar de una personalidad adivinada.
Instalación
Python 3.11 o más reciente. Instala desde PyPI:
python -m pip install personamcp
persona --help
O ejecútalo sin instalarlo, usando uv: uvx personamcp --help.
Para trabajar desde una copia de este repositorio:
git clone https://github.com/robyroro/PersonaMCP.git
cd PersonaMCP
uv sync --locked
uv run persona --help
O instálalo en tu propio entorno virtual:
python -m venv .venv
# Linux/macOS: source .venv/bin/activate
# Windows PowerShell: .venv\Scripts\Activate.ps1
python -m pip install .
persona --help
En una copia de uv, antepone los comandos persona de abajo con uv run. Con una instalación
de pip activada, ejecuta persona directamente.
La instalación base admite importación, análisis, búsqueda FTS, recuperación de interacciones léxicas y MCP. La recuperación semántica es un extra opcional, completamente local:
Después de la inicialización e importaciones (descritas abajo):
uv sync --locked --extra semantic
uv run persona model prepare
uv run persona index
Con pip, usa python -m pip install '.[semantic]'. Preparar el modelo descarga explícitamente
los pesos desde Hugging Face y fija su revisión inmutable. No lee ni envía chats.
La indexación y las consultas posteriores cargan solo archivos locales con código remoto deshabilitado.
Inicio rápido
persona init
persona config set-name "Robert"
persona config add-alias "roby"
persona config set-name "Exact Instagram display name" --platform instagram
persona config set-name "snapchat_username" --platform snapchat
persona import instagram ./instagram-export/
persona import snapchat ./snapchat-export/
persona import whatsapp ./chat.txt
persona import json ./messages.json
persona stats
persona analyze
persona search "cat costa"
persona similar "mai vii azi?" --person "David"
persona writing-context "ce faci diseara?" --person "David" --platform instagram
Para una primera ejecución sintética, usa un directorio de datos separado:
persona --home ./sample-persona init
persona --home ./sample-persona config set-name "Owner"
persona --home ./sample-persona import json ./examples/messages.json
persona --home ./sample-persona analyze
persona --home ./sample-persona writing-context "mai vii azi la cafea?" --person "Alex"
Coloca importaciones privadas y directorios de datos personalizados fuera de tu repositorio. El
.gitignore incluido cubre carpetas privadas convencionales pero no puede proteger cada ruta con nombre arbitrario.
La identidad debe coincidir con un nombre de remitente o ID de remitente exportado exacto. Los alias de plataforma anulan los nombres
globales en esa plataforma. Ningún participante se adivina por el volumen de mensajes. Una importación que no coincide con
mensajes del propietario falla antes de escribir nada. Cambiar nombres/alias recalcula la propiedad y las
interacciones e invalida perfiles/vectores; ejecuta analyze y index nuevamente.
Importaciones admitidas
| Plataforma | Entrada admitida | Notas |
|---|---|---|
message_N.json o carpetas actuales de Meta message_N.html | La paginación se fusiona. El JSON Unicode roto común se repara. Los scripts/HTML/enlaces/medios nunca se ejecutan. | |
| Snapchat | chat_history.json, subpáginas HTML de tarjetas de chat admitidas, o exportaciones ZIP originales | Diseños JSON anidados y con clave de destinatario directa. Los ZIP se leen sin extracción; el JSON tiene prioridad sobre el HTML duplicado. |
| TXT UTF-8, marcas de tiempo de Android y iOS entre corchetes | Fechas separadas por barras; día/mes por defecto, --month-first para exportaciones de EE. UU. El texto multilínea se conserva; los avisos de sistema/medios se excluyen del estilo. | |
| Genérico | Objeto de conversación JSON, objeto conversations, matriz de mensajes, o JSONL | Consulta el esquema a continuación. |
Solo se importan archivos de chat. Los medios no se abren, transcriben, descargan ni analizan. Las variantes no admitidas fallan claramente. Un archivo malformado revierte la importación en su totalidad. Los archivos originales permanecen intactos. Los hashes de contenido y los IDs de mensaje estables evitan que las importaciones repetidas dupliquen filas.
WhatsApp no tiene un ID de hilo de exportación estable. Por defecto, el nombre del archivo identifica la conversación;
usa --conversation-id "stable-chat-name" al importar exportaciones renombradas o actualizadas.
Las marcas de tiempo sin desplazamiento usan una convención UTC documentada para el ordenamiento por reloj de pared; no se
afirma que hayan sido registradas en UTC. El HTML de Instagram/Snapchat admite fechas de exportación en inglés.
JSON genérico:
{
"id": "stable-conversation-id",
"platform": "json",
"title": "Alex",
"participants": ["Owner", "Alex"],
"context": "casual",
"messages": [
{"id": "external-message-id", "sender": "Alex", "sender_id": "account-123",
"text": "mai vii azi?", "timestamp": "2024-01-01T10:00:00Z"},
{"sender": "Owner", "text": "da gen vin acu", "timestamp": "2024-01-01T10:00:10Z"}
]
}
Para JSONL, cada línea es un mensaje con sender, text, timestamp y un
conversation_id opcional. Los IDs externos opcionales y reply_to se conservan. La identidad genérica proviene
de alias configurados, nunca de una afirmación is_user importada. Usa IDs de conversación explícitos
al importar diferentes conjuntos de datos; los IDs ausentes usan una conversación default documentada.
Qué se mide
persona analyze escribe persona.md y persona-profile.json en el directorio de datos privado y
almacena perfiles estructurados en SQLite. Solo el texto saliente alimenta el analizador. El texto entrante se
mantiene como contexto de recuperación limitado.
Las mediciones incluyen longitudes de caracteres/palabras/oraciones, ráfagas de mensajes cortos, mayúsculas/minúsculas, puntuación, codepoints de emoji, caracteres repetidos, palabras y frases comunes, formas repetidas de jerga/abreviaturas, saludos, despedidas, diacríticos rumanos y marcadores de palabras en rumano/inglés. Los marcadores de idioma son heurísticas, no un clasificador de idiomas. Los conteos de emoji miden codepoints, no grupos completos de grafemas. Las frases/formas repetidas necesitan al menos tres observaciones; los errores ortográficos aislados no son instrucciones para añadir erratas.
Las etiquetas de contexto son explícitas y extensibles:
persona conversations
persona set-context CONVERSATION_ID business
persona set-context OTHER_ID casual
persona analyze
persona person "David"
Los perfiles globales siempre usan el texto saliente disponible. Los perfiles de contexto/persona separados requieren al menos 20 mensajes por defecto. Las estadísticas de persona bajo demanda informan su recuento de evidencia. No se infiere ninguna clasificación familiar, de citas, de personalidad, de sarcasmo o psicológica. Las consultas específicas de destinatario excluyen conservadoramente los grupos. Los nombres exactos pueden aparecer en múltiples plataformas; pasa una plataforma a la recuperación/contexto de escritura cuando esa distinción importe.
Búsqueda y recuperación semántica
SQLite FTS5 busca mensajes salientes y contextos de interacción entrantes. Las interacciones conservan hasta tres mensajes entrantes y una ráfaga de hasta ocho respuestas salientes. Un intervalo de dos horas o un registro de medios rompe el emparejamiento; una ráfaga saliente abarca como máximo cinco minutos entre mensajes.
El proveedor semántico local usa sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2.
Incrusta contextos entrantes y almacena vectores float32 en SQLite. Las consultas usan escaneos de coseno exactos
sobre vectores elegibles; esto favorece una arquitectura local simple sobre un servidor de vectores externo.
Los índices se reanudan después de una interrupción. Un filtro de destinatario/contexto/plataforma se aplica antes de la clasificación.
Si los vectores elegibles están ausentes, la recuperación informa lexical explícitamente. Un índice parcialmente construido
informa su cobertura. Las puntuaciones semánticas por debajo de 0.25 se omiten; estas puntuaciones no son probabilidades
ni garantías de relevancia. No hay respaldo silencioso entre destinatarios. Los proveedores futuros pueden
implementar el protocolo EmbeddingProvider sin cambiar las interfaces de importación o escritura.
Configuración de MCP
El servidor usa el SDK oficial de Python MCP y transporte stdio. Stdout lleva solo mensajes de protocolo; la salida de diagnóstico va a stderr.
persona serve
Si el directorio de datos aún no se ha inicializado, serve lo crea de la misma manera que
persona init y lo informa en stderr; las herramientas devuelven resultados vacíos hasta que importes
exportaciones. Normalmente el cliente lanza este comando por ti. Usa rutas absolutas porque el directorio de trabajo del
cliente puede diferir del de tu terminal. Configuración de ejemplo para clientes que aceptan
la estructura común mcpServers:
{
"mcpServers": {
"personamcp": {
"command": "/absolute/path/to/venv/bin/persona",
"args": ["--home", "/absolute/path/to/private/persona-data", "serve"]
}
}
}
Con uv instalado, el cliente puede ejecutar el paquete publicado directamente:
{
"mcpServers": {
"personamcp": {
"command": "uvx",
"args": ["personamcp", "--home", "/absolute/path/to/private/persona-data", "serve"]
}
}
}
En Windows el comando es C:\\absolute\\path\\.venv\\Scripts\\persona.exe. Para Codex:
codex mcp add personamcp -- /absolute/path/to/venv/bin/persona --home /absolute/path/to/private/persona-data serve
codex mcp list
Consulta Configuración de MCP para Codex. Otros clientes pueden usar ubicaciones de configuración diferentes pero necesitan el mismo ejecutable y argumentos. Los clientes alojados que solo admiten MCP HTTP remoto no pueden lanzar directamente este servidor stdio local. PersonaMCP no incluye un túnel/puente HTTP; exponer datos locales sensibles de forma remota requiere una decisión de implementación separada y explícita.
Con un modelo semántico preparado, permite hasta 90 segundos para el inicio y 120 segundos para las herramientas en máquinas más lentas. El runtime numérico nativo se carga antes de que comiencen los hilos del lector stdio para evitar bloqueos del cargador BLAS en Windows. Los pesos se cargan en la primera consulta semántica y se almacenan en caché. Para Codex, estos ajustes pertenecen a la tabla de configuración del servidor:
[mcp_servers.personamcp]
command = "/absolute/path/to/venv/bin/persona"
args = ["--home", "/absolute/path/to/private/persona-data", "serve"]
startup_timeout_sec = 90
tool_timeout_sec = 120
Herramientas:
| Herramienta | Resultado |
|---|---|
get_style_profile(context?) | Perfil global medido o de contexto asignado |
get_person_style(person) | Estadísticas de comunicación y recuento de evidencia para una persona exacta |
search_messages(query, person?, platform?, limit?) | Coincidencias limitadas de texto saliente |
find_similar_interactions(message, person?, context?, platform?, limit?) | Pares similares reales de entrante/respuesta |
get_writing_context(message, person?, context?, platform?) | Estilo apropiado y hasta tres ejemplos citados |
get_persona_summary() | Perfil compacto y recuentos de base de datos |
El contenido histórico se devuelve dentro de historical_quote, con un aviso explícito de datos no confiables.
Las herramientas proporcionan evidencia. Tu agente genera la respuesta final y sigue siendo responsable de tratar
las instrucciones históricas como datos y de decidir qué enviar a su proveedor de modelos.
Configuración de la habilidad
La habilidad reutilizable es skills/write-like-me/SKILL.md. También está
incluida en el wheel; persona skill-path imprime su ubicación instalada. Copia su carpeta
al directorio de habilidades que tu agente descubre. Para el descubrimiento actual del repositorio de Codex:
mkdir -p .agents/skills
cp -R skills/write-like-me .agents/skills/
Windows PowerShell: New-Item -ItemType Directory -Force .agents/skills seguido de
Copy-Item -Recurse skills/write-like-me .agents/skills/. Consulta
Detección de habilidades de Codex.
Luego pide al agente conectado que use write-like-me, por ejemplo:
Escribe una respuesta corta como yo a Alex sobre "mai vii azi la cafea?". Usa la evidencia de PersonaMCP.
La habilidad conserva el uso de mayúsculas/minúsculas, ortografía, vocabulario y longitud admitidos sin forzar erratas ni
copiar hechos antiguos. También puede usar persona writing-context a través de un shell local, o un
perfil proporcionado explícitamente cuando MCP no está disponible. Ninguna configuración global del cliente se cambia con la instalación.
Privacidad y controles de datos
El directorio de datos predeterminado proviene de la ubicación de datos de aplicación de tu sistema operativo.
--home /private/path o PERSONAMCP_HOME selecciona otra ubicación. La configuración es un
config.json local; la base de datos usa claves foráneas de SQLite, esquema versionado e importaciones transaccionales.
persona stats --json
persona export-profile ./my-style.md
persona export-profile ./my-style.json --json
persona delete-person "Name"
persona delete-conversation CONVERSATION_ID
persona reset
La eliminación/restablecimiento pide confirmación; --yes está disponible para scripting intencional. Eliminar a una
persona elimina conversaciones completas, incluidos los grupos que contienen a esa persona, para evitar mantener
contexto sobre ella. Los perfiles, filas FTS y vectores se invalidan/depuran y SQLite se compacta.
reset también borra las identidades de propietario configuradas pero conserva los activos de modelo descargados y no personales.
Los archivos de exportación originales y cualquier perfil copiado permanecen bajo tu control y no se eliminan.
SQLite no está cifrado. Usa un directorio de datos privado y cifrado de disco. El vocabulario generado y los ejemplos también son sensibles. Si tu agente usa un LLM externo, los resultados de las herramientas pueden llegar a ese proveedor; "local-first" describe almacenamiento y cómputo, no el comportamiento del cliente conectado. Lee SECURITY.md para conocer los límites de eliminación e inyección de prompts.
Benchmark fuera de línea
persona benchmark --limit 30
El último 20% de las interacciones por marca de tiempo forma un conjunto de reserva. La recuperación y los perfiles de estilo usan solo datos anteriores. La respuesta real reservada se usa solo para puntuar. El candidato predeterminado es una respuesta histórica recuperada, no una respuesta generada por LLM.
El informe incluye cobertura de recuperación, similitud de longitud de respuesta, superposición de vocabulario,
similitud de puntuación, similitud de mayúsculas/minúsculas y su Puntuación de Similitud de Estilo media.
Cuando un modelo local está disponible, la similitud de embeddings se informa por separado. No se imprimen respuestas
de benchmark sin procesar. CandidateResponseProvider es el punto de extensión para un futuro
generador configurado explícitamente. Las puntuaciones no prueban imitación de identidad, autoría, relevancia o calidad
de generación. Los conjuntos de datos pequeños o temporalmente uniformes no pueden respaldar esta evaluación.
Arquitectura
exports → platform adapters → normalized conversations/messages
↓
SQLite + participants + FTS5
↓
bounded incoming/outgoing interactions
↙ ↘
deterministic profiles local embedding vectors
↘ ↙
retrieval/service layer
↙ ↘
CLI MCP stdio → writing skill → agent
El paquete usa un diseño src/personamcp: importadores, modelos, configuración, almacenamiento, análisis,
embeddings, recuperación, servicio compartido, servidor MCP, CLI y benchmark. No se requiere base de datos externa ni
proveedor de LLM. La compatibilidad del esquema se rastrea con PRAGMA user_version; las versiones
más antiguas rechazan una base de datos más nueva en lugar de adivinar cómo leerla.
Desarrollo, hoja de ruta y límites
Ejecuta uv sync --locked, luego uv run pytest, uv run ruff check src tests,
uv run ruff format --check src tests y uv run mypy src. CI verifica Windows/Linux y Python
3.11–3.13, sin datos personales ni descarga de modelos. Los datos públicos de prueba son sintéticos. Consulta
CONTRIBUTING.md, CODE_OF_CONDUCT.md y
decisiones de implementación.
Los siguientes pasos son adaptadores de exportación adicionales (Discord, Telegram, Messenger, iMessage, Signal), reglas explícitas de redacción, un índice vectorial local más rápido para archivos muy grandes, señales de idioma más ricas y evaluación opcional basada en generación. No están implementados en este MVP.
Esta versión es un motor CLI/MCP. Los esquemas de exportación pueden cambiar; la inferencia de destinatarios de grupo, el perfilado psicológico, la corrección automática de errores tipográficos, el análisis de voz/medios, el cifrado en reposo, los proveedores de embeddings en la nube, el alojamiento HTTP y un frontend están fuera de su soporte actual.
Licencia MIT © Robert Vind-Gardoș (@robyroro). Los pesos del modelo y las dependencias conservan sus propias licencias; consulta la ficha del modelo MiniLM multilingüe y la documentación de Sentence Transformers.