MCP 接続済みアプリの統合標準

MCP サーバーは、アプリの機能(MCP ツール)を Connected Apps Platform に接続するためのフレームワークを確立します。サービスの結果をより確実に選択、呼び出し、処理できるようにするには、MCP 構成が次の標準に厳密に準拠している必要があります。

指針

各関数について、関数の機能ではなく、ユーザーの意図とユースケースに焦点を当てます。説明は、ツールの目的と、対応できるユースケースをモデルに伝える主な方法です。

バージョニング

スケーラブルで堅牢な MCP デプロイをサポートするには、パスベースのバージョニング(/v1、/v2 など)を利用する構造化された URI アーキテクチャを採用します。これにより、下位互換性を維持し、新機能をゲートできます。これを https://gemini.mcp.company.com/mcp/v1 などのプロバイダ固有のサブドメインで補完することで、きめ細かいトラフィック管理が可能になり、さまざまな AI モデルの固有のコンテキストと処理動作に合わせてツール定義を最適化できます。

MCP プロトコル バージョンの互換性

Connected Apps Platform は、バージョン 2025-11-25 までの Model Context Protocol(MCP)仕様をサポートしています。新しい仕様リリースはまだサポートされていません。

  • デベロッパーの責任: デベロッパーは、initialize handshake 中、およびすべてのツールとスキーマ定義で、MCP サーバーが Connected Apps Platform(2025-11-25)でサポートされているプロトコル バージョンに厳密に準拠していることを確認する責任があります。
  • プラットフォームの下位互換性: Connected Apps Platform は、今後、新しい MCP 仕様バージョンを採用する予定です。クライアントは、以前にサポートされていたプロトコル バージョンとの下位互換性を維持するため、既存の本番環境の統合は中断されることなく機能し続けます。
  • アップグレードの管理: 新しくサポートされた MCP 仕様を採用する準備が整った場合や、スキーマの変更を導入する場合は、アクティブなトラフィック用に既存のエンドポイント(/mcp/v1)を維持しながら、新しいバージョンの URI パス(/mcp/v2 など)でこれらの更新を公開します。

MCP スキーマの変更は、アプリのバージョン間で許可されます。この機能を利用して MCP エンドポイントをバージョニングし、新機能の緩やかなロールアウトをサポートするか、下位互換性のある変更に厳密に依存することをおすすめします。

トランスポート プロトコルの仕様

Connected Apps Platform は、Streamable HTTP トランスポート Model Context Protocol 仕様のバージョン 2025-03-26 以降のみをサポートしています。2024 年 11 月 5 日の仕様に記載されている SSE トランスポートを使用した以前の HTTP はサポートしていません。

  • 単一の HTTP エンドポイント。Connected Console で提供される MCP エンドポイント(https://api.example.com/mcp など)は、該当する Google サービスが標準の HTTP POST を介してすべての JSON-RPC リクエスト(initialize、tools/list、tools/call)を送信する単一の URL です。
  • ストリーミング可能な HTTP 内の SSE ストリーミング。以前のマルチエンドポイント SSE トランスポートはサポートされていませんが、text/event-stream などのサーバー送信イベントは Streamable HTTP 内でサポートされています。該当する Google サービスからの送信リクエストには Accept: application/json, text/event-stream が含まれます。つまり、サーバーは標準の application/json ペイロードを返すか、HTTP POST レスポンス本文で Content-Type: text/event-stream を直接使用して増分レスポンスをストリーミングできます。
  • GET ストリームと 405 メソッドが許可されていません。クライアントは、サーバーからクライアントへの通知のために、エンドポイントでオプションの GET ストリームを試行できます。サーバーがステートレスまたはリクエスト / レスポンスのみの場合、HTTP 405 Method Not Allowed を返すことは明示的にサポートされており、該当する Google プロダクトのクライアント プロキシによって適切に処理されます。

サーバーの手順

Connected Apps Platform は、サーバーの指示を取り込むように最適化されており、他の方法では不可能なモデルの動作をある程度制御できます。

サーバーの手順に沿って操作します。

使用コンテキストを含む「モデルヒント」として扱う

モデルにヒントを提供する際は、次のガイドラインに沿ってください。

  • LLM がサーバーの全体的な目的と機能を理解できるように、手順を大まかな「ヒント」またはガイドとして記述します。
  • 機能を列挙したり、モデルがサーバーのツールやリソースをどのように使用すべきかを説明したりするのではなく、何ができるかを説明します。モデルが「何」を正しく理解していれば、ユーザー ジャーニーに基づいて「どのように」をかなり適切に判断できます。
  • このテキストは、モデルのシステム プロンプトに直接追加されると想定します。明確で、指示的で、トークン効率の高いものにします。

補完し、重複させない

このスペースは、すべてのツールに適用されるグローバル コンテキストに使用し、個々のツールの説明との重複を避けます。

サーバー指示の例

次の例は、サーバー指示を適切に記述するための推奨事項と禁止事項を示しています。

推奨 非推奨の方法

GitHub リポジトリの専門メンテナーとして答えて。このサーバーは、リポジトリ メタデータ、Issue Tracker、PR ワークフローへの詳細なアクセスを提供します。プロジェクトの健全性の維持、トリアージの自動化、コード標準の確保に使用します。特に指定がない限り、すべてのアクションは認証された組織のコンテキスト内で実行されると想定します。リポジトリを整理された状態に保つために、古いスレッドやリンクされていない PR の特定を優先します。

簡潔で、指示的で、モデルを補完する

  • 「どのように」ではなく「何を」(プロジェクトの健全性、トリアージ)を定義する
  • すべてのツールに適用される認証スコープについて言及している

このサーバーには GitHub 用のツールがあります。お客様から問題について問い合わせがあった場合は、list_issues ツールを使用する必要があります。create_pull_request を使用して PR を作成できます。これらのツールは、お客様がコードを管理できるように慎重に使用してください。ツールを呼び出す前に、必ずリポジトリ名を確認してください。ユーザーが要約を求めている場合は、まずツールを呼び出してから、出力を要約します。

  • ツール名を再リストしない、
  • モデルに「どのように」考えるかを指示しないでください。これは、ユーザー コンテキストを使用して適切な選択を行うモデルの組み込みの推論と競合する可能性があります。
  • サーバーのアクセスの性質や特定の制約については説明していません)。

ツールのガイドライン

次のガイドラインでは、アプリ内のさまざまな関数やツール用の MCP サーバー構成を作成するためのベスト プラクティスについて説明します。

ツールの命名規則

ツールの命名に関する次のガイドラインに従ってください。

わかりやすく、人が読める形式の名前を使用する

曖昧な名前ではなく、明確で直感的な意味を持つ、人が読める名前を使用します。たとえば、get_user_information は userInfo よりもわかりやすいです。

適切な大文字と小文字のスタイルを使用する

ツール関数の名前とアプリトリガーには、次の大文字と小文字のルールを適用します。

  • ツールの関数名の大文字と小文字。MCP スキーマで定義されているツール関数名(get_user_information や publishDraft など)には、snake_case または camelCase を使用します。
  • アプリトリガー ハンドルのケーシング。アプリのトリガーとメンション(@MyTwoWordApp など)では、大文字と小文字が区別されません。プラットフォームは、ユーザー入力を小文字(@mytwowordapp)、PascalCase(@MyTwoWordApp)、camelCase(@myTwoWordApp)に正規化します。
  • 表示名の形式。UI 要素に明確に表示されるように、PascalCase または標準のスペースを使用して公式のアプリタイトルを登録します。
  • 入力ミスの処理。大文字と小文字のバリエーションは自動的に処理されますが、文字の入力ミス(@mytwowrodapp など)は、直接的な文字列の一致ではなく、フォールバック インテントの認識に依存します。デベロッパーは、ドキュメントでハンドルの正確なスペルを推奨する必要があります。

明示的な動詞 + 名詞の命名を使用する

verb_noun の名前は具体的に指定し、曖昧さを避けます。たとえば、handle_content よりも publish_draft の方が適切です。

ツールの粒度

ツールの粒度については、次のガイドラインに従ってください。

ツールをアトミック エンドポイントとして扱う

ツールは、内部ツール条件や、それぞれの必須パラメータを持つ複数の機能を持たない、アトミック エンドポイントとして扱います。きめ細かなツールを使用すると、モデルはステップを論理的に連結できるため、ハルシネーションが軽減されます。

フラットなスキーマを使用する

深くネストされたオブジェクトや、入力の検証に複雑な oneOf / anyOf スキーマ ロジックが必要な場合、ツールが広範すぎる可能性があります。

事前集計とペイロードのガードレールを遵守する

小規模なスコープ付きペイロードの場合、プロトコルでデータの事前集計が厳密に適用されるわけではありませんが、実際には、大規模なレコードセット、縦断的な履歴、マルチソース データセットを扱う場合、バックエンドの事前集計が強く求められます。Connected Apps Platform は、コンテキスト ウィンドウの上限、実行レイテンシ、モデルの推論ステップに関するガードレールを適用します。これらのガードレールを遵守するには、次のガイドラインに従ってください。

  • バックエンドでフィルタリングと要約を行う。該当する Google サービスにレスポンスを返す前に、MCP サーバーで大規模なデータ ストリームをフィルタ、事前集計、要約します。
  • 未加工のダンプを避ける。未加工のデータベース行や、インデックスのない完全なログをツールの戻りペイロードにダンプしないでください。

内部ツールとメタツールを省略する

サーバーの tools/list レスポンスで、モデル向けの機能のみを公開します。

  • ヘルパー ツールをフィルタする: モデルから呼び出されることを想定していない内部ツール、管理ツール、メタツール(サーバー ヘルスチェック、内部セットアップ ルーティン、デベロッパー ユーティリティ ヘルパーなど)は除外します。
  • コンテキスト ウィンドウの効率: 不要なツールを除外することで、MCP スキーマを簡潔に保ち、コンテキスト ウィンドウのトークン消費量を削減し、モデルのツール ルーティングの混乱を防ぐことができます。数十個のツールを公開している MCP サーバーや、深くネストされた「メガツール」スキーマを公開している MCP サーバーは、審査中に修正が必要なものとしてフラグが付けられます。

ツールの粒度に関する推奨事項と禁止事項

次の例は、ツールの命名と粒度の使用に関する推奨事項と禁止事項を示しています。

推奨 非推奨の方法

明確な名前とパラメータを持つ、きめ細かいツール

各ツールの入力スキーマは厳格です。LLM がユーザーを作成する場合は、メールアドレスを指定する必要があります。削除する場合は、ID を指定する必要があります。推測は不要です。

...
@mcp.tool()
def create_user(email: str, role: str = "viewer") -> str:
    """Register a new user. Returns the new User ID."""
    # Logic is purely creation
    return "user_123"

@mcp.tool()
def delete_user(user_id: str) -> str:
    """Permanently remove a user by their ID."""
    # Logic is purely deletion
    return f"User {user_id} deleted"

@mcp.tool()
def update_user_role(user_id: str, new_role: str) -> str:
    """Change an existing user's permission level."""
    return f"User {user_id} is now {new_role}"

    ...

ツール名: manage_user

説明: 「このツールを使用して、ユーザーの作成、更新、削除、取得を行います。」

...
@mcp.tool()
def manage_user(
    action: Literal["create", "update", "delete", "get"],
    user_id: Optional[str] = None,
    email: Optional[str] = None,
    role: Optional[str] = "viewer"
) -> str:
    """
    Use this to manage users.
    WARNING: logic is hidden inside Python, not visible in the schema.
    """
    if action == "create":
        if not email: return "Error: Email required for creation" # Runtime error, not schema error
        return f"Created user {email}"
    elif action == "delete":
        if not user_id: return "Error: User ID required"
        return f"Deleted {user_id}"
    
    return "Action completed"
    """
    ...

安全のためにツール アノテーションを宣言する

ツール定義内にプロトコル アノテーションを構成して、実行動作を伝達し、該当する Google サービス全体で組み込みの安全ゲートをトリガーします。

  • ランタイム確認ゲート: 該当する Google プロダクトは、annotations.destructiveHint: true と annotations.openWorldHint: true をキーフラグとして使用して、ランタイム ユーザー確認プロンプトをトリガーします。状態変更、書き込み、破壊的なアクションに destructiveHint: true を宣言し、オープンワールド環境や外部環境とやり取りするツールに openWorldHint: true を設定します。これにより、サーフェスは実行前にユーザーに確認を求めるようになります。
  • 読み取り専用クエリヒント: バックエンドの状態を変更せずにデータを取得するだけのクエリツールに readOnlyHint: true を設定します。
  • 明示的なアノテーションのデフォルト: Model Context Protocol の仕様に従い、readOnlyHint を省略すると、クライアントは安全のためにデフォルトで readOnlyHint: false と destructiveHint: true を想定します。すべてのツールでアノテーションを明示的に宣言することで、予測可能なモデル ルーティングと適切な実行安全性が確保されます。

ツールの説明

説明は、ツールが現在の問題を解決できるかどうかをモデルが判断するための唯一のコンテキストです。説明を記述する際は、次のガイドラインに従ってください。

コメントではなく指示を書く

ツールの説明は、コードのコメント(多くの場合、受動的)ではなく、指示として記述します。LLM は指示に適切に応答します。

「方法」を説明する

適切な説明を記述することで、「ツールがある」という状態と「このツールを会話に組み込む方法がわかる」という状態のギャップを埋めることができます。

「理由」を説明する

このツールを類似のツールと区別します(例: 「内部ユーザーにはこれを使用し、外部ユーザーには customer_update を使用する」)。

引数の取得元をモデルに指示します(例: 「order_search ツールから」)。

形式を指定する

単位(メートルとフィート)と形式(ISO 日付、セマンティック バージョン)を指定します。

モデルの裁量を避ける

モデルに「最善の判断」を使用するように指示したり、オプションのガイドなしのアクションを提案したりしないでください。

ツールの説明の例

次の例は、ツールの説明の作成に関する推奨事項と禁止事項を示しています。

推奨 非推奨の方法

信頼できる情報源

「ユーザーのメールアドレスを更新します。search_users ツールから返された UUID「id」を厳密に使用する必要があります。ユーザー ID を推測しないでください。」

(1 つのツールの出力をこのツールの入力に明示的にリンクします。)

「ユーザーのメールアドレスを更新します。」

(モデルは 12345 などの ID を推測する可能性があります)。

形式と制約

「会議の予定を作成して。「date」は ISO 8601 形式(YYYY-MM-DD)にする必要があります。ユーザーが「明日」や別の相対的な表現を使用した場合は、現在のコンテキストに基づいて日付を計算します。」

「指定された日付に会議をスケジュールします。」

(人間には正しく見える(例: 「明日」)が、スキーマ検証に失敗する(「2025-10-12」が必要))

出力の期待値

「サーバーログを取得します。未加工テキストの最後の 50 行を返します。分析を行う場合は、トークン制限を回避するために、より短い期間をリクエストしてください。」

「サーバーログを取得する」

(モデルが要約を期待してツールを呼び出し、5 MB の未加工の JSON ダンプを取得すると、ユーザー エクスペリエンスが低下する可能性があります)。

@mcp.tool()
def update_campaign_status(campaign_id: str, status: str) -> str:
    """
    Promotes or pauses an advertising campaign.
    
    CRITICAL USAGE RULES:
    1. 'campaign_id': Must be the 32-character UUID retrieved from 'list_campaigns'.
    2. 'status': Must be exactly one of: ['active', 'paused', 'archived'].
    
    Returns: A confirmation string with the new status and timestamp.
    """
    # Logic...

    ...

この説明は、ミニマニュアルとして機能します。ソース(ID の取得元)、制約(有効な列挙型)、アクションを処理します。

@mcp.tool()
def update_campaign_status(id: str, status: str) -> str:
    """
    Updates the campaign status in the database.
    """
    # Logic...

この場合、すべての処理は変数名に依存します。「status」の有効な値について、モデルが推測することになります。

ツールのパラメータ

ツール自体に加えて、パラメータを明確に記述します。

明示的な型

強力で具体的な型(string、integer、boolean、array)を使用します。

固定値セットに列挙型を使用する

パラメータが固定値のセット(daylight、cool、warm など)のみを受け入れる場合は、enum 配列にリストします。これにより、精度が大幅に向上します。

必須パラメータを明確に指定する

関数の動作に必須のパラメータを明確に定義します。

セマンティック スキーマ マッチングを適用する

アプリを統合する際、ツールのパラメータと開発対象の業種とのセマンティック スキーマ マッチングが必要になる場合があります。オンボーディング プロセス中に、想定される業種スキーマ(JSON スキーマ)が届きます。

ツール パラメータの例

次の例は、ツール パラメータの処理に関する推奨事項と非推奨事項を示しています。

推奨 非推奨の方法

引数の形式と単位

radius: 「半径(メートル単位)。0 より大きい浮動小数点数にする必要があります。」

(ユニットのハルシネーションを防止)

radius: 「円の半径。」

ID の形式とコンテキスト

user_id: 「データベース UUID(例: 550e8400-e29b...)。ここではメールアドレスを使用しないでください。」

注: ベスト プラクティスとして、すべての数値 ID フィールドは文字列値として扱う必要があります。特に、ID が 10 桁以上になる可能性がある場合、内部システムによって切り捨てられ(32 ビット コンテナに強制的に格納され)、このバージョンが今後のツール呼び出しでモデルによって使用されるリスクがあります。

(型エラーを防止)

user_id: "ユーザーの ID。"

戻り値の期待値

「レコードを更新し、新しいタイムスタンプを含む更新された JSON オブジェクトを返します。」

(変更を確認するために「update」の直後に「get」ツールを呼び出す必要がないことをモデルに伝えます)。

「レコードを更新します。」


@mcp.tool()
def search_logs(query: str, limit: int = 10) -> str:
    """
    Searches server error logs using Lucene syntax (e.g. 'level:ERROR AND service:auth').
    
    Args:
        query: A Lucene-formatted search string.
        limit: Max results to return. capped at 50.
    
    Returns:
        A formatted string of log entries with timestamps.
    """
    ...
  
@mcp.tool()
def search_logs(query: str, limit: int = 10) -> str:
    """Searches the logs."""
    ...

LLM は、「query」がサポートする構文(SQL?正規表現書式なしテキスト?) 最大「上限」が何であるかは認識されません。

レスポンスとエラー処理

レスポンスは次のプロンプトであるという基本原則に従って、ツールはデータ ペイロードを返すことで、基盤となる実行の結果を報告します。このペイロードは、LLM のコンテキスト ウィンドウに直接貼り付けられます。結果の成功または失敗によって、次の処理が決まります。

  • 成功した場合: モデルは、次のステップを決定するために、何が起こったかを知るための戻り値を必要とします。
  • 失敗した場合: モデルは失敗した理由と修正方法を把握する必要があります。クラッシュ(500 エラー)が発生すると会話が停止します。わかりやすいエラー メッセージが表示されると、モデルは自己修正できます。

ツールの基盤となるロジックが成功したか失敗したかにかかわらず、モデルが簡単に解析できるように、戻り値のペイロードをフォーマットする必要があります。レスポンス ペイロードをパッケージ化する際は、次のベスト プラクティスに従ってください。

JSON を使用する

構造化データを TextContent 形式にする(一時的な制約)。structuredContent は Connected Apps Platform でまだサポートされていないため、データを手動でシリアル化します。単純なリストを返す場合でも、json.dumps() します。

レスポンスに URL を含める

返される URL は比較的短く、パラメータが多くないものにする必要があります。トークン数を節約し、ハルシネーションのリスクを軽減するために、URL 短縮サービスを使用することをおすすめします。

自己記述型のハルシネーション防止ペイロード

未加工のコードや内部 ID は、常に人間が読める表示名、明示的な測定単位、基準範囲とペアにします。圧縮された辞書キーや、モデルにコンテキストの推測を強制するマッピングされていない数値コードは返さないでください。

堅牢なエラー処理を実装する

モデルが何が問題だったかを理解してユーザーに通知できるように、明確で意味のあるエラー メッセージを返します。MCP のエラー処理を確認する。

try/except を使用する

ツールのロジックを try/except ブロックでラップし、文字列化されたエラーを返します。

対処可能なエラーを返す

エラー メッセージで次のステップを提案します(例: 「まずツール X をお試しください」)。

操作の確認

副作用ツール(作成 / 更新 / 削除)に空の文字列を返さないでください。

レスポンスとエラー処理の例

次の例は、レスポンスとエラー処理に関する推奨事項と禁止事項を示しています。

推奨 非推奨の方法

明示的なシリアル化


...
import json

@mcp.tool()
def query_metrics(metric_id: str) -> str:
    result = {"id": metric_id, "value": 42, "unit": "ms"}
    # GOOD: Returns '{"id": "cpu", "value": 42}' -> Valid JSON
    return json.dumps(result, indent=2)

...
@mcp.tool()
def query_metrics(metric_id: str) -> str:
    result = {"id": metric_id, "value": 42, "unit": "ms"}
    # BAD: Returns "{'id': 'cpu', 'value': 42}" -> Invalid JSON
    return str(result)

キャッチして通知


...
@mcp.tool()
def get_user_details(user_id: str) -> str:
    try:
        user = db.get_user(user_id)
        if not user:
             # GOOD: Informative error returned as content
            return f"Error: User with ID '{user_id}' not found. Please verify the ID using 'search_users'."
        return json.dumps(user)
    except Exception as e:
        return f"Error: Database connection failed ({str(e)}). Please try again later."

(ツールは技術的には「成功」し(文字列を返します)、文字列にはエラーの詳細が含まれます。モデルはこれを読み取り、「その ID は存在しない」と認識して、ユーザーに正しい ID を尋ねることができます。


...
@mcp.tool()
def get_user_details(user_id: str) -> str:
    # BAD: Unhandled exception if ID not found
    user = db.get_user(user_id)
    return json.dumps(user)

(get_user が失敗すると、サーバーは 500 をスローします。LLM は一般的な実行エラーを受け取りますが、その理由はわかりません(ID が間違っていたのか、データベースがダウンしている?権限が拒否されましたか?)。まったく同じ不正な入力が再試行される可能性があります。

空のレスポンス

...
@mcp.tool()
def post_story(story_content: str) -> str:
    service_name = "story_service"
    api_client.post("/stories", json={"content": story_content})
    # GOOD: Explicit confirmation of state change.
    return f"Service '{service_name}' successfully posted content. Status is now 'posted'."

...
@mcp.tool()
def post_story(storyContent: str):
    subprocess.post(["postsrv", "story", storyContent])
    # BAD: Returns null/empty string. Model is confused.

LLM は空のレスポンスに混乱することがよくあります。「ツールが失敗した」というハルシネーションが発生したり、呼び出しが繰り返されたりする可能性があります。

自己記述型のハルシネーション防止ペイロード

未加工のコードや内部 ID は、常に人間が読める表示名、明示的な測定単位、通常の基準範囲とペアにします。

{"lab_code": "2345-7", "display_name": "Glucose [Mass/volume] in Blood", "value": 105, "unit": "mg/dL", "reference_range": "70-99 mg/dL"}

(これにより、モデルは単位や参照しきい値を推測することなく、値の意味を正確に把握できます)。

未加工の ID、カスタム圧縮、マッピングされていないコード

ラベルのない未加工の内部 ID、カスタム辞書の略語、数値コードを返す。

{"code": "2345-7", "v": 105}

(モデルは 105 が何を指しているのかを推測せざるを得なくなり、ハルシネーションによる単位の生成、コンテキストの欠落、不正確な説明につながります)。

MCP のエラー処理

エラーを適切に処理することが重要です。

  • 回復可能なエラー(無効なユーザー ID やオプション パラメータの欠落など)の場合は、ツールのレスポンスにエラーの詳細を説明する通常のテキスト文字列を返します。これにより、モデルはフィードバックを検査し、何がうまくいかなかったかを理解して、自己修正したり、ユーザーに説明を求めたりできます。
  • ターミナル エラー(レート制限、認証エラー、権限エラー、バックエンド サーバーの停止など)の場合は、適切なエラーコードを含む McpError を発生させ、プラットフォームがエラーを体系的に処理できるようにします。

エラー レスポンスの本文の例(JSON)

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32302,
    "message": "User permission denied for the requested operation.",
    "data": null
  },
  "id": 1
}

Message には、MCP の ErrorData フィールドの JSON ダンプが含まれています。正しい code とモデルに表示される message を返すことで、Connected Apps Platform はエラー メッセージを読み取り、わかりやすい自然言語の説明をユーザーに返すことができます。たとえば、「申し訳ございませんが、その ID の会場が見つかりませんでした。名前をご確認いただけますか?」

MCP を使用すると、クライアントは JSON-RPC 2.0 仕様を使用して MCP サーバーに接続できます。JSON-RPC には、無効なリクエスト、解析エラーなど、一般的に発生するエラーに対して送信される事前定義されたエラーがあります。このガイドでは、MCP サーバーがカスタムエラーを返送する方法について説明します。

ステータス
コード
メッセージ 使用方法
明示的に
返す必要があるか?
ユーザー / お客様のエラー
-32300 USER_RATE_LIMITED ユーザーが使用量上限に達しました。 ○
-32301 MISSING_REQUIRED_INFORMATION 入力リクエストに必要な情報がすべて含まれていない ○
-32302 USER_PERMISSION_DENIED お客様がツールの使用を許可しなかった。たとえば、ユーザーが企業アカウント、年齢制限、言語 / 地域などを持っている、またはツールの企業サブスクリプションを持っていないことが必要です。 ○
アプリケーション エラー / ビジネス ロジックエラー
-32400 RUNTIME_ERROR サーバーコードの実行でエラーが発生しました ○
-32401 NULL_POINTER_EXCEPTION null ポインタ / オブジェクトを実行しようとする ○
-32402 OUT_OF_MEMORY サーバーコードでオブジェクトに割り当てるメモリが不足している ○
インフラストラクチャ エラー
-32500 DEADLINE_EXCEEDED リクエストに許容時間を超える時間がかかっています。サーバーの過負荷、ネットワークの問題など、さまざまな原因で発生する可能性があります。 ○
-32501 RESOURCE_EXHAUSTED サーバーのメモリ不足、ディスク容量、スレッド、CPU 時間など。 ○
-32502 SERVICE_UNAVAILABLE 依存サービス(別のマイクロサービス、データベース、キャッシュなど)が利用できない ○
JSON-RPC エラー(これらのエラーは MCP トランスポートの一部です)
-32700 PARSE_ERROR サーバーがリクエストを解析できませんでした いいえ
-32600 INVALID_REQUEST クライアント リクエストの形式が正しくありません いいえ
-32601 METHOD_NOT_FOUND 無効な MCP ツール名 いいえ
-32602 INVALID_PARAMS リクエスト パラメータが無効です。パラメータが不足しているか、パラメータのタイプが一致していません いいえ
-32603 INTERNAL_ERROR デフォルトのレスポンス いいえ

次の例は、公式の Python SDK(mcp)を使用してサーバーで MCP エラーを発生させる方法を示しています。ErrorData ペイロードを含む McpError を発生させます。SDK は、エラー ステータスが入力された必要な JSON-RPC エラー形式に自動的にシリアル化します。

from mcp import types
from mcp.shared.exceptions import McpError

@mcp.tool()
def foo_tool() -> list[types.TextContent]:
  """Always returns an error."""
  raise McpError(
    types.ErrorData(
        code=-32302, # USER_PERMISSION_DENIED
        message="Message to show to the model."
    ),
  )

ツールの概要

該当する Google プロダクトは、MCP サーバーにシグナルを渡すための Tool Context API をサポートしています。この API は、機密情報を必要とする有効なユースケースで使用されます。たとえば、ローカライズが必要なツールのロケールなど、コアツール定義の一部ではないメタデータです。Tool Context API は、Connected Console を介してのみ公開されます。

Connected Console でアプリに current_user_location_fine などのシグナルを登録すると、該当する Google サービスは、リクエストされたデータを提供する _meta エントリを追加して MCP tools/call リクエストを拡張します。サポートされているシグナルのセットは次のとおりです。

  • current_user_location_fine(Gemini のみ、許可された業種向け)
  • user_locale
  • current_user_location_coarse
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "find-restaurant",
    "arguments": {"query": "restaurants near me"},
    "_meta": {
      "current_user_location_fine": {
        "latitude_degrees": 37.7749,
        "longitude_degrees": -122.4194,
        "accuracy_meters": 112.4221
      },
      "user_locale": {
        "language_code": "en",
        "region_code": "US"
      }
    }
  }
}

このデータを詳しく見てみましょう。

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("remote_mcp")

@mcp.tool()
async def find_restaurants(query: str, ctx: Context) -> str:
   # Access context directly from _meta
   request_context = ctx.request_context
   meta_dict = ctx.request_context.meta.model_dump() if ctx.request_context.meta else {}

   location_context = meta_dict.get("current_user_location_fine", {})
   lat = location_context.get("latitude_degrees")
   lng = location_context.get("longitude_degrees")
   if lat and lng:
       return f"Finding '{query}' near ({lat}, {lng})"
   return f"Finding '{query}' (no location provided)"

UX のレンダリング

MCP アプリ

該当する Google サービスは、選択したユーザー ジャーニーの MCP アプリ統合をサポートしており、カスタム ユーザー インターフェースを構築できます。一般的な統合手順については、仕様に沿って対応してください。

該当する Google サービスでの MCP アプリの統合には、次の注意事項があります。

登録時のリソースの取り込み

該当する Google サービスは、ツールリストやツールの説明と同様に、ツールの取り込み時に UI リソースを取得します。つまり、リソースの更新(JavaScript の変更など)は自動的に取得されず、ツールの再取り込みが必要になります。

1 つの UI リソースのサイズは 15 MB 以下にする必要があります。また、サーバー全体の UI リソースの合計サイズは 100 MB 以下にする必要があります。

UI リソースは、サポートされている MIME タイプ(text/html、text/javascript、text/css、text/html;profile=mcp-app)のいずれかを使用する必要があります。標準以外の MIME タイプやプラットフォーム固有の MIME タイプは、プレビューに push するときに検証に失敗します。

CSP ガイドライン

該当する Google サービスは、CSP [1]、[2] を含む公式の MCP アプリ仕様に準拠しており、CSP ディレクティブに違反するリクエストをブロックします。

該当する Google サービスでは、blob: と data: を使用する場合、これらを CSP に追加する必要があります。これらはデフォルトでは追加されません。CSP に追加するかどうかはデベロッパーが選択できます。

script-src は例外

許可されるディレクティブは、unsafe-inline(デフォルトで追加)、wasm-unsafe-eval、data:(resource_domains に含まれている場合)のみです。iframe が外部スクリプトを読み込んでいる場合は、JS を HTML にバンドルするか、サブリソース整合性(SRI)ハッシュを使用することで解決できます。

  • オプション 1: JS を HTML にインライン化 / バンドルする(最も簡単)

    • バンドル JS コード:

      • UI リソースに対して返される HTML ペイロードの <script> タグ内に、component-init.js の内容を直接インライン化します。

        <script>
        // Paste component-init.js content directly here
        </script>
        
    • リモート <script src> タグを削除する

      • HTML ドキュメントから <script src="https://api.mycompany.com/..."> 参照を削除します。
    • 再取り込み / 更新ツール

  • オプション 2: サブリソース整合性(SRI)ハッシュを使用する:

    スクリプトを https://api.company.com/... で外部ホストする必要がある場合は、この方法を使用します。

    • スクリプトの SHA-256 ハッシュを計算する
      • component-init.js の base64 SHA-256 ハッシュを生成します。
    • resourceDomains にハッシュを追加します(integrity 属性と一致するように sha256- 接頭辞を含める必要があります)。
    • HTML <script> タグを更新する
      • HTML ウィジェットのスクリプトタグに integrity 属性と crossorigin 属性を追加する
    • CDN / サーバーで CORS ヘッダーを確認する
      • api.company.com が Access-Control-Allow-Origin: * で component-init.js を提供する(または scf.usercontent.goog を許可する)ようにして、ブラウザが SRI 検証のためにレスポンス本文を読み取れるようにします。
    • 再取り込み / 更新ツール

MCP ツールの説明に関するセキュリティ ガイドライン

説明は、モデルがツールの機能を理解するための唯一のコンテキストであるため、意図しない動作を防ぐために、正確かつ安全に記述する必要があります。ツールの説明を作成する際は、次のガイドラインに沿ってください。

  • 機能を説明するが、動作を指示しない。説明では、モデルに後続のアクションを実行するよう指示するのではなく、ツールが行うことを正確に説明する必要があります。
  • 範囲と要件を定義する。ツールの主な目的、使用する特定の状況(いつ)、必要なすべての入力(パラメータ / 引数)を明確に記述します。
  • 真実性を確保する。説明は、ツールの基盤となるコードを正確に表している必要があります。書き込みオペレーションまたは削除オペレーションを実行するツールを読み取り専用として宣言しないでください。

セキュリティ リスクとその回避方法

リスク領域 推奨 この方法は絶対に避けてください

プロンプト インジェクション

客観的で宣言的な表現を使用して、ツールの目的と機能を明確に記述します。

モデルの動作をオーバーライドしたり、システムフローを変更したりするには、命令型のコマンドを使用します(例: 「...と言わなければならない」、「ランニング後は、必ず...」)。MUST や CRITICAL などの命令形の用語は、構造化されたパラメータ制約や使用ルールを定義する場合にのみ使用できます。

ツールの説明テキストには、標準の書式なしテキストを使用します。

人目を引く書式(大文字の過度な使用や、VERY IMPORTANT:、**CRITICAL** などのタグ)を使用する。

ツールの機能と想定される動作のみに焦点を当てます。

ロールプレイングの指示や、以前の指示を無視するコマンドを含める。

ツールのシャドーイングとハイジャック

説明は具体的で、ツールの実際の関連機能に限定されていることを確認します。

ツールの説明を過度に広範または曖昧にしたり、1 つのツールが多くの関連性のない機能を実行すると主張したりする。

一意で、わかりやすく、適切なツール名を選択します。

信頼できるツールの名前を少し変えた名前や、一般的な名前(do_everything_tool、assistant_tool など)を使用する。

説明の中で、他のアプリや外部プラットフォーム ツールの名前を挙げないでください。

他のツールを明示的に参照したり、他のツールを使用するタイミングや方法について新しいルールを作成したりする。

モデルのプランナーがユーザーのコンテキストに基づいて最も適切なツールを選択できるようにします。

反競争的な表現や、類似のツールよりも自社のツールを優先するようモデルに指示する SEO プロンプトを含める。

トリガーの操作

説明が、一般的な会話履歴のフレーズを参照したり、反応したりしていない。

一般的な無害なユーザー フレーズ(「ありがとう」、「要約すると」など)に基づいて有害なアクションをトリガーする条件付きロジックを作成する。

パラメータの不正使用

ツールの機能に必要なパラメータのみを定義し、入力データに固有の名前(file_id、search_term など)を使用します。

エージェントの内部状態を反映する名前(system_prompt、conversation_history、full_context など)で関数パラメータを定義します。

データの引き出し

プライバシー バイ デザイン - 不透明な識別子とホスト管理の認証。

未加工の個人を特定できる情報(PII)ではなく、機密性の低い ID を使用します。すべてのデータ処理は、承認された安全な境界内で行う必要があり、外部に送信されるものとして公開説明で言及されていない必要があります。ツールの実行は、OAuth ハンドシェイクを介してサイレントに権限を継承します。

機密情報は、該当する Google サービスに送信する前にサニタイズする必要があります。

ユーザー、個人データ、ビジネスデータ、エンティティから、個人情報(PII)、保護対象保健情報(PHI)、その他の個人情報や機密情報を、該当する Google サービスの利用規約に違反する形でリクエストすること。

ユーザーデータ(クエリ、位置情報、コンテキスト)を、承認されていない第三者の URL、ロギング サービス、外部システムに送信することに言及したり、送信を要求したりすること。

機能と命名に関するベスト プラクティス

ツールの説明を保護するだけでなく、モデルが混乱することなくツールを確実に選択して実行できるようにする必要があります。機能と命名に関する次のベスト プラクティスに従ってください。

  • パラメータの精度。説明内のすべてのパラメータ名と型が、ツールの実際の実装と完全に一致していることを確認します。
  • 適切な命名。ツールの名前は、その機能に関する強力で明確なヒントにする必要があります。「execute」などの一般的な名前は避けてください。また、名前はより広範なツール エコシステムと整合している必要があります。

付録: インフラストラクチャとネットワークの許可リスト

ホスティング インフラストラクチャ、API Gateway、ファイアウォールで、送信元 IP アドレスによる受信接続が制限されている場合は、次の Google アウトバウンド CIDR ブロックを許可リストに登録します。

  • 108.177.64.0/20
  • 142.250.88.0/22
  • 172.217.80.0/20
  • 192.178.20.0/22
  • 192.179.0.0/20
  • 74.125.232.0/24
  • 136.121.40.0/21

該当する Google プロダクトが MCP の初期化、ツールの検出、リクエストの実行のためにリモート MCP サーバーにアクセスできるように、環境でこれらの IP 範囲からのトラフィックを HTTPS ポート 443 で許可していることを確認してください。