imessage-rich-search
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.
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
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
Available Tools
1 toolsearch_imessages_richA
Full-text search across macOS iMessages including link preview metadata (title, summary, site name) that Apple stores in payload_data — content the basic chat.db text column does not expose. Returns newest-first matches where the query (case-insensitive substring) appears in either the message body OR the rich link preview.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Substring to search for (case-insensitive). | |
| contact | No | Optional handle filter, e.g. '+14073993471' or 'name@example.com'. | |
| limit | No | Max matches to return (default 50). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, description carries full burden. Discloses search over message body and rich link preview, case-insensitive substring matching, and newest-first sorting. Could add more on returns (empty results, pagination) but covers key behavioral traits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose, no superfluous words. Each sentence adds value: first defines scope, second details ordering and search targets.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema, so description should cover return structure. It mentions 'newest-first matches' but does not describe fields (e.g., message text, sender, timestamp, preview metadata). Agent may need to infer or handle uncertainly. Lacks completeness for a search tool without output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions cover 100% of parameters, but description adds operational context: query searches both body and preview, contact is an optional handle filter, and limit default/max. Adds meaning beyond schema fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it performs full-text search across macOS iMessages, including link preview metadata beyond basic chat.db. Specifies scope, search scope (body or preview), and result ordering (newest-first). Distinguishes from potential siblings by highlighting the rich link preview capability.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides context that this tool searches rich link preview metadata not exposed by basic chat.db, implying its niche. However, it does not explicitly state when not to use it or mention alternatives. Still clear enough for an agent to infer appropriate scenarios.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.2.0- First observed
search_imessages_rich
TDQS
Scored across 1 tool
Only one tool exists, so there is no possibility of confusion or ambiguity between tools.
With a single tool, naming consistency is perfect; the name 'search_imessages_rich' is descriptive and follows a clear verb_noun pattern.
A single tool feels thin for a server named 'imessage-rich-search', as it likely covers only a narrow part of iMessage interaction. While the tool is focused, users may expect additional functionality like retrieving messages or managing conversations.
The tool thoroughly performs the described search across both message text and rich link previews, but lacks complementary operations such as fetching individual messages or performing more advanced queries, which are minor gaps.
Maintenance
Related MCP Connectors
MCP connector for iMessage & Contacts via a local Mac agent + Vercel relay
Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.
Explore your Messages SQLite database to browse tables and inspect schemas with ease. Run flexible…
Mac & Windows: let ChatGPT, Claude & Cursor use your email, calendar, iMessage, Teams, files.
Related MCP Servers
- AlicenseAqualityCmaintenanceA local MCP server that enables reading iMessage conversations and sending new messages through Claude Desktop. It provides secure, read-only access to your Mac's iMessage database and AppleScript-based message sending capabilities.6MIT
- FlicenseAqualityDmaintenanceA read-only MCP server that exposes your iMessage data to Claude Code and Claude Desktop, with automatic contact name resolution.3-
- AlicenseNot gradedqualityAmaintenanceRead, search, and send iMessages locally from your terminal or through MCP clients like Claude, Cursor, and VS Code.MIT
- AlicenseNot gradedqualityCmaintenancemacOS-only MCP server that exposes iMessage history to Claude and exports per-chat conversations into an Obsidian vault.2MIT