Skip to main content
Glama
0xdeadd
by 0xdeadd
README.md
# imessage-mcp

A local MCP (Model Context Protocol) server that lets Claude Code read your
macOS Messages history directly, so you stop copy-pasting text threads into
chat by hand.

It reads `~/Library/Messages/chat.db` and your local Contacts database
directly with Python's stdlib `sqlite3`. There are no native dependencies and
nothing leaves your Mac: every tool is a local, read-only SQL query plus a
small typedstream decoder for the message bodies that Messages stores as
binary blobs.

## What it gives Claude

- `list_chats(query, limit)`: recent chats, with names resolved from Contacts.
- `read_thread(chat, since, limit)`: a thread in order, with sender names,
  attachment paths, and tapback reactions folded into the message they landed
  on.
- `search(text, chat, since, limit)`: full text search over decoded message
  bodies.
- `whats_new(mark_seen)`: everything new across every chat since the last
  call, using a small cursor file at `~/.imessage-mcp/cursor.json`.
- `send(chat, text)`: sends a message through Messages.app. Disabled unless
  you explicitly turn it on, see "Sending" below.

## Requirements

- macOS with Messages.app signed in and syncing.
- Full Disk Access granted to whatever process runs this server (your
  terminal, or Claude Code itself, depending on how you launch it). Without
  it, `~/Library/Messages/chat.db` will fail to open even in read-only mode.
  Grant it under System Settings, Privacy and Security, Full Disk Access.
- Python 3.12 or newer, managed with `uv`.

## Install

```
cd /Users/clint/Projects/imessage-mcp
uv sync
```

## Register with Claude Code

```
claude mcp add --scope user imessage -- uv run --directory /Users/clint/Projects/imessage-mcp python -m imessage_mcp.server
```

That registers the server once, for every project, over stdio.

## Sending is off by default

`send(chat, text)` only works when the server process has the environment
variable `IMESSAGE_SEND=1` set. Without it, the tool returns a plain message
saying sending is disabled, and does nothing else.

When enabled, sending goes through `osascript` and Messages.app:
- a one on one chat sends with `send text to buddy handle of (service 1
  whose service type is iMessage)`.
- a group chat sends with `send text to chat id "<guid>"`.

The first send will prompt macOS for Automation permission for whatever
process is driving Messages.app. Treat this as a real send: nothing here
double checks with you before the message goes out, so only turn
`IMESSAGE_SEND` on in a session where you are prepared to review the exact
text before asking the tool to send it.

## Privacy

Everything runs locally. The server opens `chat.db` and your Contacts
database read only (`sqlite3` URI `mode=ro`), decodes text and attachment
paths in process, and returns plain text to Claude. Nothing is uploaded
anywhere, and no network calls happen anywhere in this codebase.

## Tests

```
uv run pytest
```

The tests read your live `chat.db` and Contacts database and skip themselves
cleanly if either is unreadable (for example, no Full Disk Access, or run on
a machine with no Messages history).

## Layout

- `imessage_mcp/typedstream.py`: decodes the `attributedBody` blob that
  Messages uses instead of plain `text` for most rows.
- `imessage_mcp/db.py`: all the read only SQL against `chat.db` and Contacts.
- `imessage_mcp/server.py`: the FastMCP server and tool definitions.
- `tests/`: pytest tests against the live database.

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct action: listing chats, reading a thread, searching messages, incremental polling, and sending. Even though read_thread and search both return messages, their purposes are clearly separated and easy to tell apart.

Naming Consistency4/5

list_chats and read_thread follow a verb_noun pattern, while search and send are bare verbs and whats_new is a phrase. All names use lower_snake_case and are readable, but the naming is not fully uniform.

Tool Count5/5

Five tools is a well-scoped set for an iMessage bridge. It covers the main interactions without unnecessary redundancy or surface-area bloat.

Completeness5/5

The tool set covers the core messaging workflow: enumerate chats, read conversations, search content, poll for new messages, and send replies. There are no obvious dead ends or missing operations for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues