dkdc-io-imessage
An iMessage MCP plugin. Lets an LLM CLI (Codex CLI, Claude Code, or any JSON-RPC-over-stdio MCP client) read and send iMessages on macOS.
Three tools:
reply(chat_id, text)— send an iMessage.list_messages(query, limit)— search recent messages.read_message(id)— fetch one message by GUID.
Fail-closed by default: an empty allowlist makes every tool call error out with a pointer back to the config file.
Install
That installs the dkdc-io-imessage binary on your $PATH.
macOS prerequisites
- Full Disk Access. The binary reads
~/Library/Messages/chat.db. Grant it to whatever you're launching the MCP server from (your terminal, Codex, Claude Code). System Settings -> Privacy & Security -> Full Disk Access. - Messages.app signed in. Sending goes through
osascript-> Messages, so the app has to be running and logged in to your Apple ID.
Allowlist
Edit ~/.config/dkdc-io/imessage/access.toml:
# Your own chat GUID. Lets an LLM `reply` with no chat_id to text you.
# Copy it from the URL bar in Messages after selecting your "note to self"
# chat, or look at `chat.guid` in chat.db.
[]
= "iMessage;-;+15551234567"
= ["+15551234567", "you@icloud.com"]
# Other handles the LLM can interact with via DMs.
= [
"friend@example.com",
]
Verify with:
Empty allowlist is intentional. Any tool call returns:
allowlist is empty. dkdc-io-imessage is fail-closed by default. Edit
~/.config/dkdc-io/imessage/access.toml to add `self.chat_id` and/or
`allow_from` handles, then retry.
Configure the client
Codex CLI
Add to ~/.codex/config.toml:
[]
= "dkdc-io-imessage"
= ["--stdio"]
Then start Codex and list tools:
# inside the REPL
> /mcp
You should see reply, list_messages, read_message under imessage.
Claude Code
Add to ~/.claude.json (or per-project .mcp.json):
Then start Claude Code. Run /mcp to confirm the imessage source is
connected.
Example prompts
After setup:
- "text myself 'build done'"
- "what did I text Friend today?"
- "read the last message from my note-to-self chat"
Config
| Env var | Purpose |
|---|---|
DKDC_IO_ACCESS_FILE |
Override the allowlist TOML path. |
DKDC_IO_STATE_DIR |
Override the config dir (default ~/.config/dkdc-io/imessage). |
DKDC_IO_CHAT_DB |
Override the chat.db path. Useful for tests. |
DKDC_IO_LOG |
Tracing filter (warn, info, debug, ...). |
Security posture
- Allowlist is the only access surface. Empty = fail closed.
replyrejects chat GUIDs that don't resolve through an allowlisted handle (orself.chat_id).read_message/list_messagesnever surface rows from non-allowlisted chats.- osascript is invoked with
text/chat_guidas argv items; the AppleScript body is a fixed string. There is no shell or string-concatenation path for user-controlled input. Seetests/injection.rsfor the anti-regression.
License
MIT OR Apache-2.0.