camfortin

imessage-mcp

Community camfortin
Updated

Local MCP server for macOS iMessage — read chat.db and send via Messages.app, with on-the-fly contact name resolution

imessage-mcp

A local MCP server that exposes your Mac's iMessage data to Claude Desktop / Claude Code.Two surfaces:

  1. SEND via AppleScript → Messages.app
  2. READ via direct, read-only SQLite access to ~/Library/Messages/chat.db

Everything is local. No API keys, no network calls.

Install

# 1. Clone / copy into ~/mcp-servers/imessage-mcp
cd ~/mcp-servers/imessage-mcp

# 2. Create a Python 3.11+ venv and install deps
python3.12 -m venv .venv
.venv/bin/pip install -e .

Permissions (required)

Full Disk Access — so we can read chat.db

System Settings → Privacy & Security → Full Disk Access → toggle ON for:

  • your terminal app (e.g. Terminal, iTerm2, Ghostty), AND
  • Claude.app (if using Claude Desktop)

Automation — so we can control Messages.app

System Settings → Privacy & Security → Automation → expand your terminal / Claude.appand toggle Messages to ON.

Messages.app must be running and signed into iMessage.

If a permission step is missing, the server errors with the exact settings path to open.

Claude Desktop config

Merge into ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "imessage": {
      "command": "/Users/YOUR_USERNAME/mcp-servers/imessage-mcp/.venv/bin/python",
      "args": ["-m", "imessage_mcp.server"]
    }
  }
}

(The absolute path to the venv's python is the safest — it avoids PATHambiguity. Replace YOUR_USERNAME.)

Tools

Tool Purpose
send_imessage(recipient, body, service?) Send via Messages.app. recipient is a phone, Apple ID email, or existing buddy name.
list_recent_chats(limit=20) Newest-first chats with last-message preview and unread count.
get_chat_messages(chat_id?, handle?, limit=50, since?) Messages for a chat; provide chat_id or handle.
search_imessages(query, since?, until?, from_contact?, limit=25) Case-insensitive LIKE across message bodies.
get_my_info() Self-handles + DB metadata.

Dates are ISO8601 in and out. Internally, Apple stores message.date asnanoseconds since 2001-01-01 UTC; the server converts both ways.

Safety invariants

  • chat.db is opened with sqlite3.connect("file:...chat.db?mode=ro", uri=True).Any write attempt raises sqlite3.OperationalError: attempt to write a readonly database.
  • send_imessage passes recipient / body / service as separate osascript argventries — no shell interpolation, no injection.
  • Attachments return metadata only (filename, mime_type, total_bytes). Blobs arenever read.

Limitations

  • Scheduled / delayed sends are not supported.
  • Rich / reply-threaded messages may have their text stored in attributedBody(NSKeyedArchive). We best-effort extract the embedded NSString; messages withmore exotic payloads (images, taps, Apple Pay) will show empty body butcorrect metadata.
  • Delivery confirmation: send_imessage reports success from osascript's exitcode. To verify the message actually went through, call search_imessages orget_chat_messages a few seconds later.
  • This is macOS-only and will not work on sandboxed App Store apps.

Local development

.venv/bin/pytest -q

MCP Server · Populars

MCP Server · New