Apple Messages について
iMessage、SMS、RCS の会話を検索・閲覧し、アーカイブされた本文もデコードする macOS 向け MCP サーバーです。利用にはフルディスクアクセスが必要で、送信は初期状態で無効です。
主な機能
- 01メッセージの検索・一覧・閲覧
- 02アーカイブ本文のデコード
- 03日付・チャット・連絡先別の集計
- 04Contacts によるハンドルの名前解決
- 05オプションのワンタイムコード抽出
- 06明示的な有効化後のメッセージ送信
活用シーン
- 01過去の会話から内容を検索
- 02連絡先や期間ごとの件数を集計
- 03最近届いた認証コードを検索
- 04書き込みを有効化して確認後に送信
MCP 対応
診断、チャットとメッセージの取得、集計ツールを MCP クライアントに公開します。コード抽出とメッセージ送信は、それぞれ個別の設定で有効化します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @mgcrea/mcp-apple-messagesAPPLE_MESSAGES_ALLOW_WRITESRegister the mutating tools. Off by default, and the gate decides whether the write tools exist at all rather than merely refusing — an agent with writes off cannot see them.APPLE_MESSAGES_ALLOW_CODESRegister apple_messages_find_codes, which reads one-time codes out of recent messages. Its own gate rather than allowWrites: it is a read, and the one read most worth an explicit decision.APPLE_MESSAGES_ALLOW_FILE_SENDLet apple_messages_send_message attach a local file. Off by default even with writes on, because a path argument is a way to send anything the server can read.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
@mgcrea/mcp-apple-messages
macOS 上の Apple Messages(iMessage、SMS、RCS)向け Model Context Protocol サーバーです。
非公式です。 Apple とは無関係です。お使いの Mac にすでに保存されているメッセージを読み取ります。
もう一つの経路がないインターフェース
このファミリーの他のサーバーには、アクセス方法が2通りあり、より速い方を選びます。このサーバーには1つしかなく、それも推測ではなく実測に基づいています。Messages のスクリプティングディクショナリ経由の読み取りはすべて失敗します。 NSRunningApplication では実行中と報告されているにもかかわらず、Application isn't running と応答します。これは、スクリプトで起動されることを拒む、ウィンドウのないバックグラウンドプロセスとして動作しているためです。
そのため、フルディスクアクセスは必須であり、追加機能ではありません。 これがないと、このサーバーは何もできません。機能を制限して動作するモードもありません。
Apple Events は、動詞が1つだけという条件で引き続き利用します。ディクショナリ内で動作するコマンドは send だけです。そのため、ここは Apple Events が書き込み専用の経路となる唯一のインターフェースであり、書き込みゲートが権限の境界も兼ねます。APPLE_MESSAGES_ALLOW_WRITES がオフの場合、Apple Event は一切送信されず、オートメーションの許可も要求されません。読み取りが存在しないため、ゲートをすり抜ける読み取りもありません。
32件に1件のメッセージは SQL では見えない
chat.db はメッセージ本文を2か所に保持しており、最初に参照するであろう方は_不完全_です。実際の97,416件のメッセージを保存したデータベースで測定した結果は次のとおりです。
| メッセージ数 | 97,416 |
通常の text カラムがあるもの | 94,043 |
attributedBody BLOB があるもの | 97,094 |
| BLOB のみ — テキストなし | 3,051(3.1%) |
BLOB は NSArchiver の_型付きストリーム_であり、SQL で内部を読み取ることはできません。text を選択するサーバーでは、32件に1件のメッセージが、気づくためのエラーもなく、ひそかに取得されません。
また、この割合は過去の平均値です。 このサーバーを使ってライブデータベースを測定したところ、2016年から2025年までは約99%が通常の text でしたが、その後は変化しました。2026年3月以降、すべてのメッセージがBLOBのみです。 Apple は2月下旬から3月下旬の間にこのカラムを廃止したようです。つまり、デコーダーは特殊なケースに対処するものではなく、最近のデータを読む唯一の方法です。デコーダーのないサーバーでは、会話が2月に途切れたと報告されてしまいます。
このパッケージはそれをデコードします。macOS 26 にも NSArchiver が残っており、これらのBLOBを書き込んだのもこれなので、既知の文字列をアーカイブすれば、推測に頼る必要のないテスト用データを作れます。こうして正解を確定したうえで、ラベル付きの94,043行に対して text を照合基準としてデータベース全体で検証しました。
一致率100.000%。97,094件中97,094件のBLOBをデコードし、失敗はありませんでした。 1,000件あたり約2ミリ秒です。
decodeAttributedBody() はパッケージのルートからエクスポートされています。
名前はContactsから取得します
chat.db には相手が +15551234567 のような形式でしか記録されないため、このサーバーはそれを名前に変換するために @mgcrea/mcp-apple-contacts に依存します。相手ごとに、電話番号と名前の両方に加えて、resolution の状態が含まれます。
unknown は通常の状態であり、エラーではありません。 実際のアドレス帳を対象に測定したところ、過去1年のメッセージでは97.6%の相手を解決できましたが、最も頻繁にやり取りする25人では約84%でした。つまり、よく話す相手の約6人に1人には連絡先カードがありません。未解決のハンドルを失敗として扱うコードは、実際の受信箱では何度も誤動作します。
Contacts の権限が許可されていない場合、名前の解決はスキップされ、ハンドルはそのまま返されます。これは機能の低下として diagnostics で報告され、例外は発生しません。
検索は Contacts パッケージのデフォルト設定で実行されます。APPLE_CONTACTS_* 設定が適用されるのは Contacts サーバーであり、このサーバーではありません。ここで設定しても何も変わらず、Messages が読み取る設定スイッチは APPLE_MESSAGES_RESOLVE_CONTACTS だけです。
ツール
読み取り:diagnostics、list_chats、list_messages、search_messages、get_message、
count_messages。
count_messagesは集計用の経路です。送信・受信の内訳を含む合計と、groupByによる日、月、チャット、ハンドル、方向ごとの件数を返します。すべての一致項目をSQLで集計するため、「誰と最も頻繁にメッセージをやり取りしているか」を調べるのに必要なのは小さな結果ひとつだけで、会話の一覧を手作業で数える必要はありません。また、handleでグループ化すると、1人が複数のチャットに参加していてもまとめて集計できます。list_chatsのチャットごとの合計では、これらを合算できません。意図的にメタデータのみを扱います。2026年以降のメッセージ本文はSQLで読み取れないアーカイブ済みのblobに保存されているため、ここでテキストを絞り込むと、正しそうな数値が返る一方で、ストアの後半部分がひそかに抜け落ちます。
オプトイン読み取り:APPLE_MESSAGES_ALLOW_CODESで有効にするfind_codes。[設定](#configuration)を参照してください。デフォルトでは無効で、書き込みゲートの対象ではありません。
書き込み:send_messageのみです。利用できるコマンドはこれですべてです。sdefには3つのコマンド、send、login、logoutが記載されていますが、ほかの2つを使うと、ユーザーが所有するすべてのデバイスでiMessageからサインアウトしてしまいます。公開できる編集、削除、既読への変更、リアクションの動詞はありません。そのため、このサーバーが表示できるものは、何ひとつ変更できません。
sendの直接パラメーターはfileまたはtext型で、どちらも上限の異なる2つの経路で送信されます。attachmentIdは、このMacのMessagesストアにすでにあるファイルを転送します。save_attachmentが受け取るものと同じguidを使い、同じ「~/Library/Messages内でなければ拒否する」という境界を適用するため、任意のパスには到達せず、ALLOW_WRITES以外のフラグも必要ありません。filePathは任意のローカルファイルを指定します。これは、テキスト形式と異なり、モデルが何を言えるかによって影響範囲を制限できない、情報流出の手段です。このパラメーターが存在するのはAPPLE_MESSAGES_ALLOW_FILE_SENDが有効な場合だけで、デフォルトでは無効です。意図的にディレクトリの制約は設けていません。その理由については、境界の服を着たスピードバンプを設けても意味がないことを説明するdocs/messages.mdを参照してください。
1回の呼び出しで送信できるのは1つだけなので、キャプション付きの写真は2回の呼び出しになります。
送信と、送信内容の報告方法
生のハンドルより、list_chatsから取得したchatRefを優先してください。Messagesはスクリプトに対して参加者の列挙を拒否するため、既存の会話だけが確実に指定できる宛先です。ただし、chatにはIDがあり、ストアにはすべての会話のguidが保存されています。読み取り経路で宛先を選び、書き込み経路ではIDで指定します。これなら、どちらの経路も自分にできないことをする必要がありません。
その後、Apple Eventsは何も返しません。送信したメッセージの識別子も返しません。そのため、クライアントは送信前にタイムスタンプを取得し、chat.dbをポーリングして送信済みの行を探します。
reconciliation | 意味 |
|---|---|
matched | 行が見つかりました。結果には実際のメッセージ参照が含まれます |
pending | Messagesは送信を受け付けましたが、まだ行を書き込んでいません |
unavailable | 検索対象となる既存のチャットがありません |
pendingは失敗ではありません。再試行しないでください。メッセージは送信済みで、再試行すると二重に送信されます。
**実際に動作するMessagesに対して送信を実行したことは、まだ一度もありません。**この経路は辞書とストアをもとに実装されており、意図的に偽のosascriptを使ってテストされています。これによって未検証のまま残る点をdocs/messages.mdに正確に記載しています。安全に確認する方法は、自分自身のハンドルにメッセージを送ることです。
設定
| 変数 | デフォルト | |
|---|---|---|
APPLE_MESSAGES_RESOLVE_CONTACTS | on | 連絡先から名前を検索します。 |
APPLE_MESSAGES_INDEX_MODE | auto | auto | ro | immutable | off。 |
APPLE_MESSAGES_STORE | auto | ストアのパスを明示的に指定します。 |
APPLE_MESSAGES_DEFAULT_RANGE_DAYS | 30 | 開始日時のみ指定した場合の期間です。 |
APPLE_MESSAGES_MAX_RESULTS | 50 | デフォルトのページサイズです。 |
APPLE_MESSAGES_ALLOW_WRITES | off | send_message を登録するかどうかです。 |
APPLE_MESSAGES_ALLOW_CODES | off | find_codes を登録するかどうかです。 |
APPLE_MESSAGES_ALLOW_WATCHES | off | watch と unwatch を登録します。 |
APPLE_MESSAGES_ALLOW_EVENTS | off | 実験的な messages.received イベント(ドラフト版 MCP Events 拡張、2026-07-28 のみ)を提供します。 |
APPLE_MESSAGES_ALLOW_FILE_SEND | off | send_message に filePath を追加します。 |
APPLE_MESSAGES_SEND_RECONCILE_MS | 5000 | 送信済みの行を待つ時間です。 |
APPLE_MESSAGES_ALLOW_CODES は、最近受信したメッセージからワンタイム 2FA コードを抽出する find_codes を制御します。これは読み取り機能であり、意図的に ALLOW_WRITES には含めていません。書き込み用のゲートを通じて読み取りを利用できるようにすると、メッセージを送信する権限を付与しなければ、その機能を利用できないことになるためです。
この機能は、組み合わせる情報を考慮してゲートで制限しています。このサーバーは会話履歴をすでに保持しており、@mgcrea/mcp-apple-mail は受信トレイを保持しています。つまり、両者を合わせるとパスワードの_リセット_経路にアクセスできます。リアルタイムの認証コードを加えると、それぞれ単独では妥当だった要素からアカウント乗っ取りの手段が完成するため、デフォルトでは無効であり、2 つのゲートは相互に独立しています。
コードは \d{4,8} の正規表現ではなく、シグナルに基づいて照合されます。また、各結果には confidence と、検出方法を示す matched が含まれます。high 未満の結果は、使用前にメッセージ本文で確認してください。@mgcrea/mcp-apple-core の src/codes.ts を参照してください。このヒューリスティックは、@mgcrea/mcp-apple-safari が 2 つ目の呼び出し元になった際に、そこへ移動しました。また、Passwords アプリ自体にアクセスできない理由と、その代わりにこれが提供されている理由については、リポジトリの docs/passwords.md を参照してください。
注意が必要な点
- 日付は JavaScript の数値に収まりません。 すべての日付列は 2001 年からのナノ秒単位で、18 桁あり、
Number.MAX_SAFE_INTEGERを超えます。そのため、node:sqliteは切り捨てるのではなく、例外をスローします。その例外をtry/catchで握りつぶすと、「この列は空です」とまったく同じ結果になります。実際、ある調査では、97,414 件のメッセージにわたる 7 列すべてについて「日付はありません」と報告されました。ここでは、整数が JavaScript に渡らないよう、すべてのクエリで SQL 内で割り算を行います。 - Tapback はメッセージテーブルの行です。 実測したストアには 2,788 件あり、フィルターしないリーダーでは、誰かが入力したかのように
Liked "see you at 8"と表示されます。Tapback はデフォルトで会話から除外され、対象のメッセージ上に報告されます。 - 検索対象には、blob のみのメッセージも含まれます。 列に対する
LIKEの検索(97,416 行を 16 ms)に加え、SQL から見えない 3,051 行をデコードする処理(約 6 ms)も行います。完全性を確保するコストは、ほとんどかからないことがわかりました。3%を黙って検索対象から外すような検索では、そうはいきません。 - 参照値は rowid ではなく GUID です。 SQLite は削除された行の ID を再利用し、Messages は頻繁に削除を行います。そのため、あるターンで渡された rowid が、2 ターン後には別のメッセージを指していることがあります。もっともらしく見えますが、誤りで、しかも気づきにくい問題です。
- 送信を取り消すことはできず、ここではそれができるかのように装うこともありません。 この辞書には送信取り消しも、下書きも、プレビューもありません。
sendはメッセージを送信します。このツールはALLOW_WRITESによって制限され、confirm: trueが必須です。また、これらすべてを説明文に記載しています。ツールを呼び出すモデルが、文面と宛先の間にある最後の歯止めだからです。
ライセンス
MIT。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。