The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Mac Messages MCP listing page.
Use Claude, Codex, Cursor, VS Code, or any local MCP client to search, read, and send messages through the macOS Messages app.
Mac Messages MCP runs locally on your Mac. It opens the Messages and Contacts databases read-only, returns only the data a client asks for, and uses Messages.app automation only when the client explicitly calls the send tool.
[!IMPORTANT] This server is macOS-only. Reading messages requires Full Disk Access. Sending requires a Mac signed into Messages plus permission for the launching app to automate Messages.
uvConfirm that the launcher is available:
Python 3.10 or newer is required. uvx can provision a compatible Python and
installs Mac Messages MCP in an isolated environment, so you do not need to
create a virtual environment first.
Open System Settings → Privacy & Security → Full Disk Access and enable the app that will launch the MCP server:
Quit and reopen the app after changing Full Disk Access. On the first contact lookup or send, macOS may separately ask for access to Contacts or permission to control Messages. Allow those prompts.
Also make sure Messages.app is open, signed in, and already able to send a normal message.
The server command is the same everywhere:
Choose your client below.
Open Claude → Settings → Developer → Edit Config, then add:
Preserve any other servers already in claude_desktop_config.json, save the
file, and restart Claude Desktop.
Claude Desktop also supports installable .mcpb extensions. See
Build the Claude Desktop extension if you
want to package this repository as one.
Add it once at user scope so it is available in every project:
Verify it:
Inside Claude Code, run /mcp to inspect the connection and tools.
Codex clients on the same Mac share MCP configuration. Add the server with:
Then verify it:
You can also add it directly to ~/.codex/config.toml:
Restart the desktop app or IDE extension after changing the configuration. In
Codex CLI, use /mcp to view the active server.
Or open Cursor Settings → Tools & MCP → New MCP Server and use:
Restart the server from Cursor's MCP settings after saving.
Open the Command Palette and run MCP: Add Server. Choose Command
(stdio), enter uvx as the command, add mac-messages-mcp as the argument,
and install it globally.
Or add it from a terminal:
The equivalent user or workspace mcp.json entry is:
[!NOTE] VS Code uses a top-level
serversobject. Claude Desktop and Cursor usemcpServers.
Use this generic server definition:
If a GUI client reports that uvx cannot be found, run which uvx in Terminal
and replace "uvx" with the returned absolute path. Homebrew commonly installs
it at /opt/homebrew/bin/uvx on Apple silicon and /usr/local/bin/uvx on Intel
Macs.
Ask your client to call tool_check_db_access, then tool_check_addressbook.
Once both succeed, try prompts such as:
The first uvx launch can take longer while it downloads and caches Python
dependencies.
Phone numbers written in national format (06 39 98 00 01, (415) 555-1234)
have to be expanded to E.164 before they can be matched against the Messages
database, and that expansion needs to know which country they belong to. The
server reads your Mac's own region setting for this, so on a correctly
configured Mac there is nothing to do.
Set MAC_MESSAGES_REGION to an ISO 3166-1 alpha-2 code when your
numbers belong to a different region than your Mac is configured for — a French
SIM on a Mac set to en_US, say:
For Claude Code:
The region is resolved once at startup, so restart the server after changing
it. Resolution order: MAC_MESSAGES_REGION, then the macOS AppleLocale
preference, then LC_ALL / LC_CTYPE / LANG, then US. Numbers already
written in E.164 (+33639980001) are never reinterpreted and need none of
this.
| Tool | Purpose | Side effect |
|---|---|---|
tool_get_recent_messages | Read recent messages, optionally filtered by contact or group chat ID | Read-only |
tool_fuzzy_search_messages | Search message bodies by approximate text match; defaults to 30 days, or use hours=0 for all history | Read-only |
tool_find_contact | Fuzzy-match a name in Contacts and return phone numbers | Read-only |
tool_get_chats | List named group chats and their identifiers | Read-only |
tool_search_attachments | Find attachment metadata by date, contact, MIME type, and limit | Read-only |
tool_get_attachment | Fetch one attachment by ID, inline when supported or as a local path | Read-only |
tool_check_imessage_availability | Check likely iMessage availability for a phone number or email | Read-only |
tool_check_db_access | Diagnose access to ~/Library/Messages/chat.db | Read-only |
tool_check_contacts | Return a contact count and a small sample | Read-only |
tool_check_addressbook | Diagnose Contacts/AddressBook database access | Read-only |
tool_send_message | Send one direct or group message through Messages.app | Sends a real message |
The server also exposes two MCP resources:
messages://recent/{hours}messages://contact/{contact}/{hours}For direct messages, E.164 phone numbers are the most reliable format:
Numbers written in national format work too. They are expanded to E.164 using
the region your Mac is configured for, so (415) 555-1234 becomes
+14155551234 on a US Mac and 06 39 98 00 01 becomes +33639980001 on a
French one. Set MAC_MESSAGES_REGION to an ISO 3166-1 alpha-2 code
(MAC_MESSAGES_REGION=GB) when your numbers belong to a different region than
your Mac does. Numbers already in E.164 are never reinterpreted.
The server also accepts email addresses, contact names, and contact:N
selections returned after an ambiguous contact search.
For a group conversation, call tool_get_chats, pass its chat ID to
tool_send_message, and set group_chat=true. Use the same ID as chat_id in
tool_get_recent_messages to read that conversation.
Attachment access is deliberately split into three steps:
[attachments: #42 image/jpeg (invitation.jpg)].tool_search_attachments searches metadata without loading file contents.tool_get_attachment fetches one selected attachment.Images up to 5 MB are returned inline by default. HEIC images are converted to
PNG. Larger images, PDFs, video, and audio are returned as local filesystem
paths so the MCP client can decide whether to open them. Stickers, link-preview
payloads, and .pluginPayloadAttachment containers are filtered out.
query_only.<untrusted-mcp-output> block.
That is not an anti-injection guarantee: third-party iMessage/SMS content
can still attempt prompt injection. The server makes that content
non-structural and labeled; the client must not treat it as authorization,
confirmation, or tool instructions.tool_send_message, escapes AppleScript inputs, and
uses a bounded execution timeout. This server does not perform human
confirmation; the MCP client must gate sends.See SECURITY.md to report a vulnerability privately.
uvx or spawn uvx ENOENTThe GUI app cannot see your shell's Homebrew path. Run:
Use that full path as the MCP command, then restart the client.
Operation not permitted, unable to open database file, or no messagesGrant Full Disk Access to the app that launches the server, not just to
Messages.app. Completely quit and reopen the launcher afterward, then call
tool_check_db_access again.
For Claude Code or Codex CLI, the launcher is normally your terminal. For a desktop or IDE integration, it is normally Claude Desktop, Cursor, VS Code, or the ChatGPT desktop app itself.
Allow the launching app to access Contacts if macOS prompts. Confirm Full Disk
Access, restart the app, and call tool_check_addressbook followed by
tool_check_contacts.
If contacts are listed but their numbers carry the wrong country code, the
server is expanding your national-format numbers against the wrong region. Set
MAC_MESSAGES_REGION to the right ISO 3166-1 alpha-2 code and restart the
server.
+14155551234 for a direct recipient.tool_check_imessage_availability to inspect the likely route.Messages may retain database metadata after macOS has offloaded the file. Open
the conversation in Messages.app and download the attachment, then retry
tool_get_attachment.
That is normal for an MCP stdio server: it waits for protocol input from a client. Use your client's MCP status view, or launch the MCP Inspector:
MCP clients can launch the package directly with uvx; a permanent installation
is optional.
Upgrade or remove it with:
The MCP server is the primary interface, but the package also exports its core read/send functions:
These calls use the same macOS permissions and can send real messages.
Tests mock AppleScript and use temporary database fixtures; they must never read a contributor's real Messages or Contacts data. See CONTRIBUTING.md for the contribution checklist and VERSIONING.md for releases.
The repository includes an MCPB manifest.json and a build script that can
bundle an architecture-specific uv binary:
For an Intel build:
Install the generated .mcpb from Claude Desktop → Settings → Extensions →
Advanced settings → Install Extension…. A bundled extension still needs
network access on first launch to download Python and the package dependencies.
Use --no-bundle to package against the system uv, or run
uv run python scripts/build_mcpb.py --help for every option.
The included Dockerfile is for package and catalog validation. A Linux container cannot access macOS TCC permissions or automate Messages.app, so Docker is not a supported way to read or send messages on the host Mac.
MIT © Carter Lasalle
Issues and focused pull requests are welcome. Do not include real message contents, contacts, phone numbers, database files, or attachments in bug reports or fixtures.
Changelog · Contributing · Security · PyPI