App Intents vs MCP:ルーティングの問題
App IntentsとMCPという2つのプロトコルは、いずれも外部のエージェントがアプリのドメインを操作することを可能にします。しかし、両者が1つに統合されることはありません。問題は、どちらをどこに配置するか、そしてなぜ各プロトコルがそれぞれの呼び出し元にとって正しい答えなのか、ということです。
AppleはApp Intentsをリリースし、Apple IntelligenceがサードパーティアプリをそのUIに触れることなく操作するための、型付き宣言的なインターフェースを提供しました。1 AnthropicはModel Context Protocolをリリースし、あらゆるLLMがそのUIに触れることなく任意のツールを操作するための、型付きでサーバー仲介型のインターフェースを提供しました。2 形は似ています。呼び出し元は異なります。両者を1つのインターフェースとして扱うと、どちらも満たさないアーキテクチャが生まれてしまいます。
このクラスターの先行する2本の記事では、それぞれのプロトコルを単独で扱いました。App IntentsはApp Intents Are Apple’s New API to Your Appで、MCPはTwo Agent Ecosystems, One Shopping Listで取り上げています。本記事のテーマはルーティングの問題です。どの機能にAppIntentを割り当て、どれにMCPツールを割り当て、どれに両方を割り当て、何をアプリ内部だけに留めるべきなのでしょうか。
TL;DR
- App IntentsはApple Intelligence、Siri、ショートカット、そしてシステムの提案スタックへの唯一の経路です。システムはインストール時およびアプリのアップデートを通じてこれらを利用可能にし、App Shortcutsのドネーションとインデックス化によってSpotlightやSiriの提案に表示します。
- MCPツールはApple以外のすべてのLLM(Claude、ChatGPT、Gemini、ローカルモデル)への経路となります。トランスポートはstdioまたはStreamable HTTPで、
.mcpbはローカルstdioサーバーをパッケージ化することが一般的なフォーマットです。ホストはセッション開始時にツールを読み込みます。 - 両プロトコルとも、型付きスキーマ、
entity → action → resultの構造、そしてパラメータの解決という点で共通しています。一方で、アイデンティティ、永続性、レイテンシー、レンダリングの場という点で異なります。 - ルーティングのルール:ユーザーがSiriに尋ねたりSpotlightから呼び出したりしそうな機能ならApp Intents。開発者がClaude Codeセッションや外部エージェントの実行に組み込みそうな機能ならMCP。ほとんどのアプリは同じドメインに対して両方を必要とします。
2つのプロトコル、同じ形
両プロトコルは、外部の呼び出し元とアプリのドメインとの間の操作契約を定義します。この契約には3つの構成要素があります。スキーマ(呼び出し元が要求できる内容)、リゾルバ(スキーマが指定するエンティティをアプリがどのように見つけるか)、そしてアクション(何が実行され、何が返ってくるか)です。
App IntentsはこれをSwiftで表現します。プロトコルの表面はAppIntent、AppEntity、AppEnumであり、@Parameterマクロがスキーマを駆動し、func perform()が結果を返します。3 スキーマはコンパイル時に生成され、インストール時にアプリにバンドルされます。Apple Intelligence、Siri、ショートカット、Spotlightはすべて同じスキーマを読み込み、型付きリクエストを同じperform()エントリポイントを通じてルーティングします。
MCPはこれをJSON-RPCを介してstdioまたはStreamable HTTPで表現します。プロトコルの表面はtools/listとtools/callメソッドで、各ツールは名前、説明、inputSchemaを宣言します(2025-06-18仕様では構造化された戻り値のためのオプションのoutputSchemaが追加されました)。4 MCPホスト(Claude Desktop、Claude Code、Cursor、ChatGPTデスクトップアプリ)はセッション開始時にツールを発見し、JSONペイロードを使って名前で呼び出します。ホストはモデルを実行し、サーバーはツールを実行します。
形は同じです。スキーマ、リゾルバ、アクション。違いは、各部分を誰がどこで実行するか、そして信頼境界がどこに位置するかです。App Intentsはアプリプロセス内で、ユーザーのデバイス上で、アプリの権限の下で、システムが呼び出しのルーティングを仲介しながら実行されます。MCPサーバーは開発者が選んだ場所(ローカルstdio、ホストされたHTTP、組み込みバンドル)で実行され、ホストのLLMが無制限のツール群を超えて呼び出しのルーティングを仲介します。
2つのプロトコルが食い違うところ
表面的な形を超えて、ルーティングにおいて重要となる4つの運用上の違いがあります。
アイデンティティと永続性。 App IntentsはAppEntity型で会話します。これはシステムが保存し、表示し、後で再解決できる型です。今日Hey Siri、Waterに250mlを記録で保存した水分摂取記録は、再起動を超えて存続し、ユーザーのiCloudデバイス間で同期され、後で他のintentから参照できます(昨日の水分摂取記録を見せて)。システムはこれらすべての呼び出しにわたってエンティティIDを追跡します。3 MCP自体はライフサイクル管理を備えたステートフルなプロトコルであり、Streamable HTTPは接続の継続性のためのセッションIDをサポートしますが、永続的なドメインアイデンティティはサーバー所有の関心事です。ホストモデルがセッションをまたいで頼れる、AppEntity識別子に相当するプロトコルレベルの仕組みは存在しません。MCPは永続的な参照データのためにresourcesをサポートしますが、アイデンティティは第一級のプロトコル契約というよりも、サーバー側の責任のままです。4
レイテンシーとバッテリー。 App Intentのperform()本体は、デバイス上のアプリまたはアプリ拡張のコンテキストで実行されます。ネットワークの利用は、アプリ自身のコードか、その周囲のApple Intelligence/Siri層から発生するもので、intent契約自体からは発生しません。型付きでオンデバイスのアクションが型付きの結果を返すため、一般的なケースでは高速です。MCPツールは、ローカルのものであっても、別プロセス境界を持つstdio JSON-RPCのフレーミングを経由しますし、リモートのMCPツールはHTTPラウンドトリップを伴います。レイテンシーの予算が異なります。250mlを記録というApp IntentはSiriのターン取りウィンドウ内に完了できます。リモートMCPツールはClaude Codeセッションのボトルネックになる可能性があります。
レンダリングの場。 App Intentsが返す結果は、Apple Intelligenceがシステムのインターフェースにレンダリングします。ロック画面のバナー、Siriの応答、ショートカットの出力、Spotlightの結果などです。アプリは結果がどのように提示されるかをコントロールしません。MCPツールはコンテンツブロック(テキスト、画像、音声、埋め込みリソース、または構造化コンテンツ)を返し、ホストモデルがそれを読んで、どのように表示するかを決定します。Claude Codeセッションは結果を開発者に引用したり、要約したり、後続の呼び出しに渡したりします。レンダリングの判断はモデル層に存在します。
発見可能性。 Apple IntelligenceはApp Intentsをインストール時から利用可能にし、App Shortcutsのドネーションとインデックス化により、ユーザーの行動に基づいてintentをSpotlight検索やSiriの提案に表示します。アプリのアップデートと動的エンティティが時間とともに表面を調整します。ユーザーがツール名を入力することはありません。MCPホストはセッション開始時にツールを読み込みます。ユーザー(またはシステムプロンプト)がモデルが見ることのできるツールを決めます。MCP側では発見は明示的な設定で、App Intents側では暗黙的なシステム推論です。
2つのプロトコルは、アイデンティティ、レイテンシー、レンダリング、発見の4つの特性で食い違います。これらはすべて1つの根本的な違いに由来します。App Intentsはユーザーが設定していないシステムレベルのエージェントに仕えます。MCPは開発者が設定したセッションレベルのエージェントに仕えます。呼び出し元が異なれば、義務も異なるのです。
ルーティングのルール
両プロトコルを備えたアプリの機能マップは次のようになります。
┌──────────────────────────────────────────┐
│ App's domain capabilities │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ CRUD │ │ Queries │ │ Actions │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└────┬────────────┬────────────┬────────────┘
│ │ │
┌──────────┴──────┐ │ ┌────────┴──────────┐
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌────────────┐ ┌─────────────────────┐ ┌──────────────┐
│ App Intents │ │ Both (AppIntent + │ │ MCP tools │
│ only │ │ MCP tool wrapper) │ │ only │
└────────────┘ └─────────────────────┘ └──────────────┘
│ │ │
Siri / Spotlight Cross-protocol Claude Code,
Shortcuts capabilities external agents,
Apple Intelligence where both callers LLM tooling,
proactive surfaces should reach the dev workflows
same domain
ルーティングのルールは、順番に並んだ3つの質問です。
ユーザーがSiriに尋ねたり、ショートカットから呼び出したりするような機能か? その答えがイエスなら、その機能にはApp Intentが必要です。250mlの水を記録、瞑想を始める、リストにバナナを追加、昨日の体重は何キロだったかはintentです。なぜなら、ユーザーはこれらを声に出すかもしれないし、Spotlightに入力するかもしれないし、ショートカットでチェーンするかもしれないからです。これらの機能ではApp Intentは必須であり、Apple Intelligenceの一級エージェント層に到達する手段は他にないのです。
外部エージェントが駆動できるべき機能か? その答えがイエスなら、その機能にはMCPツールが必要です。Claude Codeセッションから買い物リストにアイテムを追加、Get Bananasの状態をCursorエージェントのコンテキストに読み込む、リモートツール使用のLLMからワークフローをトリガーはMCPツールです。なぜなら、呼び出し元はApple Intelligenceではなく、開発者が組み込んだ任意のLLMだからです。MCPツールはApp Intentが呼び出すのと同じドメイン層のSwift関数をラップできますが、プロトコルの表面は開発者が選んだトランスポート上のJSON-RPCです。
この機能は単一セッションを超えて、システムが認識する安定したアイデンティティを持つ必要があるか? その答えがイエスなら、App Intentの経路が自然な選択です。なぜなら、システムがAppEntityのアイデンティティ、クエリのサポート、永続化のセマンティクスを無料で提供してくれるからです。ノーなら、MCPツールはコンテンツブロックを返し、永続的なアイデンティティはサーバーの裁量に任せ、エンティティモデリングのコストを省くことができます。
ほとんどの非自明なアプリ機能は両方の列に入ります。Waterの水分記録機能にはAppIntent(Siriが口述筆記できるように)とMCPツール(Claude Codeセッションがエクスポートされたログから埋め戻せるように)があります。2つのルートはSwift関数を共有しますが、その関数はどちらの呼び出し元から起動されたかを知りません。5
コードでの形は、1つのドメインメソッドと、それを両方とも呼び出す2つのアダプタラッパーになります。
// Domain layer (Swift, no protocol assumptions)
func logWater(amount: Measurement<UnitVolume>, at: Date, caller: Caller) throws -> WaterEntry {
try guards.requireWritePermission(caller)
let entry = WaterEntry(amount: amount, timestamp: at)
try store.insert(entry)
return entry
}
// Adapter 1: App Intent (Apple Intelligence / Siri / Shortcuts)
struct LogWaterIntent: AppIntent {
static var title: LocalizedStringResource = "Log Water"
@Parameter(title: "Amount") var amount: Measurement<UnitVolume>
func perform() async throws -> some IntentResult & ReturnsValue<WaterEntry> {
let entry = try domain.logWater(amount: amount, at: .now, caller: .siri)
return .result(value: entry)
}
}
// Adapter 2: MCP tool (Claude Desktop / Code / external agent)
// Tool name "log_water" with inputSchema {amount_ml: number}
// Handler:
let entry = try domain.logWater(
amount: .init(value: ml, unit: .milliliters),
at: .now,
caller: .mcp(host: hostName)
)
return .text("Logged \(entry.amount) at \(entry.timestamp)")
2つのアダプタは、呼び出し元が異なるため、見た目も異なります。しかし、それらが呼び出す関数は同じなのです。
アプリ内に留めるべきもの
小さいながらも重要な一部の機能は、アプリの内部にとどめるべきです。これらをいずれかのプロトコルにルーティングするのは間違いです。
UI状態に関する機能。 「3番目のタブを開く」「最下部までスクロール」「この行をハイライト」はドメイン操作ではありません。これらはインタラクションのプリミティブです。App IntentsはOpensIntentとショートカットを通じてある程度サポートしますが、ジャンルの適合性は低いです。ユーザーが求めているのは通常、ナビゲーションではなく結果です。MCPのUIナビゲーションのサポートはさらに不向きです。モデルは画面を駆動しているのではなく、ツールを駆動しているのです。
人の身体がループに必要となる機能。 写真撮影、生体認証、機微なPIIの入力、ユーザーが画面を見てタップすることを求めるすべてのフロー。AppleのCameraCaptureIntentはカメラフロー用に存在しますが、その設計意図はフォアグラウンドのキャプチャアクティビティを起動することであり、エージェントにバックグラウンドのカメラアクセスを許可することではありません。両プロトコルに対する正直なルール:カメラ、生体認証、機微な入力フローは、サイレントなintentやツール呼び出しではなく、明示的なユーザー確認を伴うフォアグラウンドUIとして実行されるべきです。これらの機能はアプリのUIの背後に留め、エージェントには画面へユーザーをルーティングさせ、画面を通り抜けて処理させないようにしましょう。
長時間実行されるバックグラウンド作業。 App Intentsは進捗状況を表示するためのProgressReportingIntentを備え、MCPは進捗通知とタスクのプリミティブを備えますが、いずれのプロトコルのレンダリング層も、コンシューマーフローでの持続的な進捗表示を想定して作られていません。MCPセッションのホストモデルは通常、複数分のツールが完了するずっと前に、推論チェーンをタイムアウトさせます。コンシューマー向けの長時間実行作業については、その操作をアプリ自身のUIを通じて公開し、プロトコルにはリクエストはキューに入りましたとだけ返させて、ステータス画面へのリンクを提示してください。
他のユーザーのデータに触れるあらゆるもの。 両プロトコルにおける信頼境界は、呼び出し元のエージェントです。Apple IntelligenceはユーザーのiCloudアカウントの下で実行されます。MCPは開発者が組み込んだ任意の認証情報の下で実行されます。ユーザーをまたぐ操作(共有、複数アカウントへのアクセス、管理者操作)は、いずれのプロトコルでも安全ではありません。なぜなら、呼び出し側のアイデンティティが間違ったアイデンティティだからです。
自分なら違うやり方で作るもの
上述したルーティングルールを踏まえると、Swiftアプリのドメイン層は、私が今サービスの境界でAPIを設計するのと同じように設計するでしょう。ドメインメソッドは型付きの入力を受け取り、型付きの出力を返し、プロトコルに関する前提を組み込みません。App Intentsは@Parameterスキーマとperform()の接着剤でドメインメソッドを薄くラップします。MCPツールはJSONスキーマとstdioフレーミングで同じドメインメソッドを薄くラップします。両プロトコルは薄いアダプタであり、本質的な作業はドメインにあるのです。
ここから2つの帰結が導かれます。
呼び出し元のアイデンティティはプロトコルの関心事ではなく、ドメインの関心事です。 App Intentの本体は、システムが解決したパラメータを受け取り、ユーザーがシステムのintent呼び出しフローを通過したコンテキストで実行されます。MCPツールの本体は、ホストが用意した認証情報を受け取ります。両者は明示的なcaller引数としてドメインメソッドに渡されます。ドメインメソッドが認可、確認プロンプト、その他のドメイン不変条件を強制します。どちらのプロトコルも、呼び出し元がユーザーであるかのように振る舞うことは許されません。
両アダプタは同じ機能セットを表に出します。 どの機能をどの呼び出し元に公開するかという決定は、散在するプロトコルコードではなく、2つのマニフェストに集約されます。新しい機能を追加するには、1つのドメインメソッド、2つのアダプタラッパー、2つのマニフェストエントリを追加するだけです。機能の削除も対称的です。上記のマトリックスが実際のファイルになるのです。
今後数年間のAppleプラットフォームのフロンティアは、1つのプロトコルを選ぶことではありません。フロンティアは、両者を同じドメイン層で構成される直交契約として扱うことです。Apple Intelligenceエージェントはユーザーに対して1つの義務セットを持ちます(オンデバイスで実行され、Siriで会話し、システムを通じてレンダリングする)。外部のLLMエージェントは開発者に対して別の義務セットを持ちます(任意の場所で実行され、JSON-RPCで会話し、開発者が選んだ任意のモデルを通じてレンダリングする)。両者ともアプリへの型付きインターフェースに値します。どちらも唯一のインターフェースに値するわけではありません。
両方を作るべきでないとき
この議論には反対方向の側面もあります。一部のアプリは、片方のプロトコルだけが必要で、もう一方は不要です。
開発者向けの表面を持たない、純粋なコンシューマーユーティリティ。 懐中電灯。鳥の鳴き声識別アプリ。AR測定テープ。ユーザーがSiri経由で呼び出したいかもしれません(App Intentsは有用です)が、開発者がLLMワークフローに組み込むことはありません(MCPは装飾的なものになるでしょう)。
エンドユーザー向けの表面を持たない、純粋な開発者ツール。 コードフォーマッター用MCPサーバー。リポジトリ検索ツール。パッケージバージョン検査ツール。ユーザーはClaude Codeセッションの開発者であり、SiriやApple Intelligenceに役割はありません。
いずれのエージェントクラスにもうまく仕えないアプリ。 高度にインタラクティブなゲーム、リアルタイムマルチプレイヤーアプリ、価値がアプリ内・画面上にあるアプリ。両プロトコルとも適合性が悪く、正しい答えは素晴らしいアプリを作ってエージェント契約を持たないことです。
判断はデフォルトで片方または両方ではありません。判断はこのアプリは何のためのものか、そして他に誰がそのドメインを操作したいと思うかです。答えはどちらでもない、片方、両方のいずれにもなり得ます。ドメイン層がうまく設計されていれば、片方を作るコストは小さいです。そのドメイン層の上に両方を作るコストも小さいです。ユースケースが要求しているのに片方を作らないコストは、そのエージェント表面からその機能が完全に欠落することです。
このパターンがiOS 26+のAppleスタックにとって何を意味するか
2つのポイントがあります。
-
App IntentsとMCPを、競合するプロトコルではなく、同じドメイン上の直交契約として扱いましょう。 Apple Intelligence、Siri、ショートカット、Spotlightは、システムレベルの義務を持つ1つの呼び出し元クラスです。Claude、Cursor、ChatGPTなどは、セッションレベルの義務を持つ第2の呼び出し元クラスです。両者とも型付きアクセスに値します。それらの下にあるドメイン層は変化しません。
-
ルーティングのルールは誰が呼び出すかであって、何が実行されるかではありません。 App IntentとMCPツールは同じSwift関数を呼び出すことができます。両者は、呼び出し元が背負う義務、戻ってくるレンダリング、期待する永続性において異なります。関数を正しく作り、プロトコル層を薄く保ちましょう。
Apple Ecosystemクラスター全体:Apple Intelligenceのための型付きApp Intents、クロスLLMエージェントのためのMCP servers、ロック画面ステートマシンのためのLive Activities、ビジュアル層のためのLiquid Glass patterns、そしてクロスデバイスの到達範囲のためのmulti-platform shipping。ハブはApple Ecosystem Seriesにあります。AIエージェントを伴うiOSのより広いコンテキストについては、iOS Agent Development guideをご覧ください。
FAQ
同じ機能に対して、App IntentとMCPツールのどちらを作るべきですか?
その機能をApple Intelligence、Siri、ショートカット、Spotlightに到達させたいなら、App Intentを作りましょう。その機能を外部のLLM(Claude、ChatGPT、Claude CodeやCursor内のエージェント)に到達させたいなら、MCPツールを作りましょう。両方の呼び出し元クラスに仕えるべきドメイン機能については、共有のSwiftドメインメソッドの上に薄いアダプタとして両方を作りましょう。
App IntentsとMCPサーバーは互いに競合しますか?
いいえ。App IntentsはApple独自のエージェントスタックへの経路で、MCPはそれ以外のすべてのLLMへの経路です。Apple IntelligenceはMCPツールを呼び出さず、外部のLLMエージェントはApp Intentsを直接呼び出すことはできません(システムを介します)。2つのプロトコルは、信頼モデル、レイテンシー予算、レンダリング表面が異なる呼び出し元クラスにそれぞれ仕えるのです。
1つのアプリが両方のプロトコルを通じて自身のドメインを公開できますか?
はい。完全なエージェントの到達範囲を望む非自明なアプリのほとんどは、そうすべきです。Get Bananas(MCP server postで取り上げ)とWater(App Intents postで取り上げ)が初期の例です。パターンは、下にドメイン層を置き、その上にApp IntentアダプタとMCPツールアダプタを配置するというものです。両方のアダプタが同じSwift関数を呼び出します。
Apple IntelligenceがトラッキングしてMCPがトラッキングしない状態は何ですか?
Apple Intelligenceは、呼び出し、セッション、再起動を超えてAppEntityのアイデンティティを追跡します。エンティティモデルは、ユーザーがintent間で連鎖させることのできる、システム永続的な参照を提供します。MCP自体はライフサイクル管理とStreamable HTTPでのセッションIDを備えたステートフルなプロトコルですが、永続的なドメインアイデンティティは第一級のプロトコル契約というよりサーバー側の責任です。ホストモデルはプロトコル表面からAppEntity相当の識別子を得ることはできません。MCPのresourcesコンセプトは永続的な参照データをサポートしますが、同じサーバー所有層で動作します。
いずれのプロトコルでも公開すべきでない機能はありますか?
はい。UI状態に関する機能(このタブを開く、ここまでスクロール)、人の身体がループに必要となる機能(カメラ撮影、生体認証、機微な入力)、長時間実行されるバックグラウンド作業、複数のユーザーのデータをまたぐ操作はすべてアプリのUIの背後に留めるべきです。両プロトコルともこれらに対するプリミティブが弱く、ユーザー間で安全に動作させるために必要な信頼シグナルをいずれも備えていません。
References
-
Apple Developer, “App Intents framework”. Apple Intelligence、Siri、ショートカット、Spotlightがルーティングできるintent、エンティティ、パラメータ、クエリを宣言するための表面。 ↩
-
Anthropic, “Model Context Protocol”. LLMホスト全体での型付きツール公開のためのオープンプロトコル。トランスポートはstdioまたはStreamable HTTPで、
.mcpbはローカルstdioサーバーをパッケージ化することが一般的なフォーマット。仕様はtools/list、tools/call、resources、プロンプトをカバー。 ↩ -
Apple Developer, “Creating your first app intent” and “AppEntity”.
AppIntentプロトコル、@Parameterマクロ、func perform()エントリポイント、永続的アイデンティティのためのAppEntity。 ↩↩ -
Anthropic, “MCP Specification: Tools (2025-06-18)”, “MCP Architecture”, and “Transports (2025-06-18)”.
tools/listとtools/callのためのJSON-RPCメソッド定義、inputSchemaとオプションのoutputSchema、ホストの責任、ライフサイクル管理、stdio / Streamable HTTPトランスポート。 ↩↩ -
著者の分析:App Intents Are Apple’s New API to Your AppおよびTwo Agent Ecosystems, One Shopping List。デュアルアダプタパターン(1つのSwiftドメインメソッド、2つのプロトコルラッパー)は、両記事でWaterとGet Bananasそれぞれの実装レベルで説明されています。 ↩