# Connect iMessage to MCP Clients and AI Agents

Canonical: https://figment.so/imessage-mcp

Giving an AI agent access to iMessage means solving two problems at once: getting authorized, scoped access to the user's messages, and exposing that access through a protocol the agent understands. Figment handles the first part — a user-approved OAuth grant that your app exchanges for an access token, not the user's Apple password. Your local MCP adapter handles the second part, translating tool calls into authenticated REST requests against Figment's API.

## What the adapter enables

The adapter wraps four iMessage operations:

- **List conversations** — paginated chat list; each chat returns a `guid` used as `chatGuid` in subsequent calls
- **Message history** — paginated messages per conversation; check `hasMore` and `historyComplete` before assuming full coverage
- **Search** — scans messages available on the connected Mac; pagination is bounded by documented limits; not a guaranteed complete index
- **Send** — posts to an existing conversation included in the user's send grant; requires a stable idempotency key

When Messages in iCloud is enabled, SMS, MMS, and RCS threads sync alongside iMessage. The iPhone must be on, connected to a network, and signed in to the same Apple Account for new traffic to reach the Mac (see [Apple: carrier forwarding setup](https://support.apple.com/en-us/102545)). Previously synced carrier-message history can remain on the Mac when the iPhone goes offline — but phone availability directly affects any new messages that have not yet synced. `historyComplete: false` does not prove complete iCloud history.

## Connection lifecycle

Each Apple service reports its own state independently of the account sign-in. The iMessage connector can reach any of these states: `connecting`, `needs_approval`, `syncing`, `ready`, `offline`, `reconnect_required`, `revoked`.

Your adapter should validate the grant at startup and handle API errors at call time. Non-ready or revoked connectors return non-2xx responses rather than a diagnostic state object — treat those as errors and surface setup guidance to the user. Direct users to [/apple-connect/account](/apple-connect/account) for connection status and resolution. A `ready` state does not guarantee complete message history or delivery.

## Adapter tool design

The table below is a **custom adapter design** — these are suggested tool names for your MCP server, not Figment product tools. There are exactly two iMessage scopes: `messages:read` covers listing, history, and search; `messages:send` is a separate grant for outbound sends.

| Adapter tool | Scope | REST endpoint |
|---|---|---|
| `list_chats` | `messages:read` | `GET https://figment.so/api/apple-connect/v1/connections/{id}/chats` |
| `list_messages` | `messages:read` | `GET https://figment.so/api/apple-connect/v1/connections/{id}/messages?chatGuid=ENCODED_CHAT_GUID` |
| `search_messages` | `messages:read` | `GET https://figment.so/api/apple-connect/v1/connections/{id}/messages/search?chatGuid=ENCODED_CHAT_GUID&query=ENCODED_QUERY` |
| `send_message` | `messages:send` | `POST https://figment.so/api/apple-connect/v1/connections/{id}/messages/send` |

Request only the scopes your agent needs. A conversation returned by `list_chats` is not automatically authorized for sends — the user's `messages:send` grant must explicitly include that existing conversation. A selected-conversation read grant requires `chatGuid` for both history and search; encode all query parameter values with a URL builder and do not paste raw strings directly into GET URLs.

## Credentials and local adapter architecture

Register your app at [/apple-connect/developers](/apple-connect/developers). Figment is the token issuer — this is not an Apple-issued credential and is not related to Sign in with Apple. Access tokens are opaque strings that normally expire after 900 seconds; store and rotate refresh tokens separately per grant; refresh calls must be serialized per grant and replacement refresh tokens saved. Token refresh is application work in your adapter.

There is no published Figment MCP server package or remote MCP URL. You build and run a local process — typically a Node script or similar — that reads credentials from a protected environment or secret store at startup. Never place a live token value in a shared or version-controlled config file. Your adapter is responsible for loading credentials from its own protected environment or secret store — do not rely on a host application to expand environment-variable references or retrieve secret values from an OS keychain automatically. For general host configuration, see [local server setup](https://modelcontextprotocol.io/docs/develop/connect-local-servers).

## Sending messages safely

`submitted` means the bridge accepted the request — not that the message was delivered. Generate and persist one stable idempotency key per intended action before the first request, bound to the exact payload. Reuse it only for that same action and body — a body hash alone can wrongly merge two separately intended identical messages.

Receipt states: `submitted`, `delivered`, `read`, `failed`, `unknown`, `simulated` (sandbox). A `failed` receipt does not automatically retry — repeating the request with the same key returns the same recorded result. If `state` is `unknown`, poll only; never resend under a new key. Receipt envelope: `{data:{idempotencyKey,state,guid?,delivery?,retrySend?},mode,replayed}`. Sandbox responses carry `mode:"sandbox"` and `state:"simulated"`.

## Pricing

The developer pays **$29 per month per active live Apple connection**. Sandbox is free — synthetic conversations, no real message delivery, no charge. Access starts after setup. Manage grants at [/apple-connect/account](/apple-connect/account).

---

**[Connect Apple Account](/apple-connect/developers)** to register your app and start building.
