imessage-rich-search
Búsqueda de texto completo en iMessages de macOS — incluyendo los metadatos de vista previa de enlaces (títulos, resúmenes, nombres de sitios) que Messages.app indexa pero que la columna de texto
chat.dbsin procesar nunca expone.
👁 License: MIT
👁 Python 3.9+
👁 Platform: macOS
👁 No deps
👁 MCP
El problema que resuelve
Cuando pegas una URL en iMessage, macOS obtiene una vista previa enriquecida (título, resumen, nombre del sitio, imagen principal) y almacena esos metadatos en chat.db como un blob de NSKeyedArchiver en message.payload_data. La barra de búsqueda de Messages.app los lee. La columna text básica de chat.db no los contiene.
Por lo tanto, si un amigo te envió https://x.com/foo/status/123 y la tarjeta de vista previa decía "Obsidian + Claude Code es la pila de productividad más subestimada" — buscar "obsidian" en cualquier herramienta que solo lea text devuelve cero resultados. Messages.app los encuentra. Esta herramienta los encuentra. Ambas buscan en la misma superficie.
Related MCP server: iMessage MCP Server
Características
Busca en el cuerpo del mensaje y en los metadatos de vista previa de enlaces decodificados en una sola pasada
Filtrar por identificador (teléfono / correo electrónico)
Salida legible por humanos o en formato JSON
Solo lectura en
chat.db(usa el modo URI de SQLite)Cero dependencias en tiempo de ejecución para la CLI (solo biblioteca estándar de Python)
Servidor MCP opcional para que Claude Desktop / Claude.ai pueda llamarlo directamente
Resultados de más reciente a más antiguo, marcas de tiempo ISO 8601, flechas de dirección, rowid para referencia cruzada
Qué es — y qué no es
Es:
Una búsqueda forense / de archivo de solo lectura sobre tu
chat.dblocalUn complemento directo para herramientas MCP de iMessage que solo ven texto sin procesar
~200 líneas de Python de la biblioteca estándar
No es:
Un reemplazo de Messages.app (sin interfaz de usuario, sin envío/edición/eliminación)
Una forma de acceder a los mensajes de otra persona
Una herramienta de sincronización de iCloud / multidispositivo — busca solo lo que está localmente en este Mac
Un bypass para el Acceso total al disco — debes otorgarlo explícitamente
Un lector de OCR / imagen / audio / sticker / escritura a mano (solo texto + metadatos de enlace)
Una forma de recuperar mensajes eliminados más allá de lo que SQLite aún conserva
Requisitos
SO | macOS 11 Big Sur o posterior (probado hasta macOS 26) |
Arquitectura | Apple Silicon (arm64) o Intel (x86_64) |
Python | 3.9+ (el |
Disco | Despreciable (~50 KB instalado) |
Permisos | Acceso total al disco para la terminal/aplicación que ejecuta el script |
Los campos del esquema de chat.db en los que se basa (text, payload_data, balloon_bundle_id, handle.id) han sido estables desde macOS 10.13 High Sierra; es probable que esta herramienta funcione incluso en versiones anteriores a su límite reclamado oficialmente, aunque no está probado.
Instalación
Opción A — pipx (recomendado, se requiere Python del sistema para el servidor MCP)
pipx aísla la herramienta en su propio venv. Instala pipx primero si es necesario:
brew install pipx
pipx ensurepathLuego instala esta herramienta desde GitHub. Usa /usr/bin/python3 explícitamente — esto es importante para el servidor MCP porque macOS solo propaga el Acceso total al disco desde Claude.app a procesos secundarios firmados por Apple. El Python de Homebrew está firmado por terceros; el /usr/bin/python3 del sistema está firmado por Apple y se hereda limpiamente. Si no te interesa el servidor MCP (solo CLI), cualquier Python 3.9+ funciona.
pipx install --python /usr/bin/python3 "git+https://github.com/cannavis/imessage-rich-search"Esto instala tres comandos en tu PATH (bajo ~/.local/bin):
imessage-rich-search— la CLIimrs— un alias corto para la CLIimessage-rich-search-mcp— el servidor MCP
Opción B — pip en un venv
git clone https://github.com/cannavis/imessage-rich-search
cd imessage-rich-search
/usr/bin/python3 -m venv .venv && source .venv/bin/activate
pip install -e .Opción C — archivo único, sin instalación
El módulo CLI no tiene dependencias. Puedes descargarlo con curl y ejecutarlo:
curl -O https://raw.githubusercontent.com/cannavis/imessage-rich-search/main/src/imessage_rich_search/cli.py
python3 cli.py "obsidian"Otorgar Acceso total al disco (única vez, obligatorio)
chat.db está bloqueado por TCC de macOS. Sin FDA obtendrás unable to open database file.
Abre Ajustes del Sistema → Privacidad y seguridad → Acceso total al disco
Haz clic en + y añade la aplicación desde la que ejecutarás esto:
¿Ejecutas
imessage-rich-searchdirectamente en la shell? → añade Terminal (o iTerm, Warp, Ghostty, Alacritty, etc. — la terminal que realmente uses)¿Lo ejecutas desde Claude Desktop vía MCP? → añade Claude.app
¿Lo ejecutas desde un editor de scripts o IDE? → añade esa aplicación
Cierra y reinicia esa aplicación por completo (⌘Q, no solo cerrar la ventana) para que el permiso surta efecto
Verifica:
python3 -c "import sqlite3; sqlite3.connect('file:'+__import__('os').path.expanduser('~/Library/Messages/chat.db')+'?mode=ro', uri=True).execute('SELECT COUNT(*) FROM message').fetchone()"— debería imprimir un número, no un error
Uso
# Basic search across all conversations
imessage-rich-search "obsidian"
# Restrict to one contact
imessage-rich-search "obsidian" --contact "+14073993471"
# JSON for piping into jq, scripts, or another tool
imessage-rich-search "obsidian" --contact "+14073993471" --json | jq '.[].preview[0]'
# Limit results, point at a backup chat.db
imessage-rich-search "claude code" --limit 20 --db /path/to/chat.db
# Short alias
imrs "obsidian"
# Module form (no entry point needed)
python3 -m imessage_rich_search "obsidian"Salida
6 match(es) for 'obsidian':
[2026-04-08T22:56:23+00:00] -> +14073993471 (rowid=234953)
url: https://x.com/aiedge_/status/2041908011078447222?s=42
* preview: Claude Code + Obsidian Ultimate Guide (build an AI second brain)
...-> = enviado · <- = recibido · * = línea de vista previa que contiene tu consulta · rowid = clave de referencia cruzada en chat.db.
Uso como servidor MCP (Claude Desktop)
Permite que Claude Desktop llame a la búsqueda directamente durante las conversaciones.
Instala el paquete usando el Python del sistema (Opción A anterior con
--python /usr/bin/python3). Esto es obligatorio: el Acceso total al disco de macOS solo se propaga desde Claude.app a subprocesos firmados por Apple./usr/bin/python3está firmado por Apple; los Pythons instalados por Homebrew / pyenv / asdf no lo están, y serán denegados silenciosamente portccd.Encuentra la ruta absoluta del punto de entrada:
which imessage-rich-search-mcpEdita
~/Library/Application Support/Claude/claude_desktop_config.json:{ "mcpServers": { "imessage-rich-search": { "command": "/full/path/from/which/imessage-rich-search-mcp" } } }Confirma que Claude.app ya tiene Acceso total al disco (lo tiene por defecto una vez que lo otorgas una vez — verifica en Ajustes del Sistema → Privacidad y seguridad → Acceso total al disco)
Cierra y reinicia Claude Desktop por completo (⌘Q)
Claude ahora puede llamar a search_imessages_rich(query, contact?, limit?) como una herramienta.
Verificación de que la herencia TCC funciona
Si el servidor MCP devuelve "unable to open database file" dentro de Claude Desktop, la cadena de atribución de lanzamiento está rota. Revisa el registro del demonio TCC de macOS:
log show --predicate 'process == "tccd"' --last 5m | grep -iE "imessage-rich|chat\.db|SystemPolicyAllFiles"A una instalación que funciona se le muestra la solicitud como permitida. Una instalación rota muestra responsible_path= apuntando a un binario de Python no firmado por Apple, seguido de recording denied. Reinstala con pipx install --python /usr/bin/python3 ... para corregirlo.
Cómo funciona
chat.db (SQLite, read-only)
└─ message
├─ text ← raw text (what basic tools see)
├─ payload_data (BLOB) ← NSKeyedArchiver bplist of LPLinkMetadata
│ (title, summary, site, image refs)
└─ balloon_bundle_id ← e.g. com.apple.messages.URLBalloonProvider
For every row:
1. Read text + payload_data
2. plistlib.loads(payload_data) → walk $objects → collect strings
3. Lower-case haystack = text + "\n".join(preview_strings)
4. Match if query.lower() in haystackEl truco de "extraer cadenas de $objects" evita la necesidad de ccl_bplist, pyobjc o semántica completa de NSKeyedUnarchiver — para la búsqueda de texto completo no nos importa el grafo de objetos, solo las cadenas hoja.
Privacidad y seguridad
Solo lectura. Abre
chat.dbcon la bandera URI de SQLitemode=ro.Solo local. Sin llamadas de red. Nunca. (
grep -r 'urllib\|requests\|http' src/no devuelve nada.)Sin telemetría.
Ningún dato sale de tu Mac a menos que elijas compartir la salida.
La CLI no tiene dependencias en tiempo de ejecución — nada que pueda ser atacado a través de la cadena de suministro.
Consulta SECURITY.md para reportar vulnerabilidades.
Limitaciones
Solo coincidencia de subcadenas. Sin clasificación FTS5, sin regex, sin operadores booleanos. Añádelo si lo deseas (
PR welcome).Solo base de datos local. Si un mensaje vive solo en iCloud y no está sincronizado con el
chat.dbde este Mac, no aparecerá.Los metadatos de vista previa dependen de que Messages.app los haya obtenido. Si la tarjeta de enlace nunca se cargó (envío sin conexión, URL caducada), no hay
payload_datapara buscar.La extracción de cadenas es con pérdida por diseño. Extrae cada cadena del bplist; ocasionalmente puedes ver tipos MIME de imágenes, tuplas de dimensiones como
{0, 0}o URLs de imágenes de perfil en la lista de vista previa. No afectan los resultados de búsqueda pero aparecen en la salida sin procesar.El Acceso total al disco es un requisito estricto — no hay solución alternativa.
Solución de problemas
Síntoma | Solución |
| Acceso total al disco no otorgado a la aplicación en ejecución. Añade la aplicación, luego ⌘Q + reiniciar. |
Devuelve 0 coincidencias pero Messages.app las encuentra | Formato de |
| TCC denegó el Python generado. Reinstala con Python del sistema: |
| Reinstala con |
Claude Desktop no ve la herramienta | Verifica la sintaxis JSON en |
La búsqueda es lenta en bases de datos enormes | La implementación actual realiza un escaneo lineal + análisis bplist por fila. Para bases de datos de más de 100k mensajes, espera unos segundos. Un índice respaldado por tabla virtual FTS5 está en la hoja de ruta. |
Contribución
Consulta CONTRIBUTING.md. Problemas y PRs son bienvenidos.
Registro de cambios
Consulta CHANGELOG.md.
Licencia
MIT — consulta LICENSE.
Agradecimientos
El esquema
chat.dbde Apple, que ha sido notablemente estable a lo largo de una década de lanzamientos de macOSLas personas que realizaron ingeniería inversa de
payload_data/LPLinkMetadataa lo largo de los añosModel Context Protocol por la especificación MCP
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Tools
Appeared in Searches
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/cannavis/imessage-rich-search'
If you have feedback or need assistance with the MCP directory API, please join our Discord server
