For the complete documentation index, see llms.txt. This page is also available as Markdown.

セルフホスト MCP Server の接続仕様

自社システムを MCP Server として公開し、MaiAgent の Agent から呼び出すための仕様です。対応するトランスポートと URL 要件、認証(固定ヘッダー、連絡先の認証情報、OAuth 動的登録)、許可するツール、タイムアウトと再試行、モデルへのエラー返却、MCP Apps のインタラクティブカードについて説明します。

このページは「自社システムを MCP Server として公開し、MaiAgent の Agent から呼び出したい」エンジニア向けです。MaiAgent がサーバーに接続する方法、送信するヘッダー、OAuth の処理、ツール一覧の取得とツール呼び出し時のタイムアウト、再試行、エラー処理について説明します。

1 回の呼び出しの流れ

MaiAgent は MCP Client です。Agent は呼び出すツールと引数を決定するだけで、実際の接続はプラットフォームが行います。

トランスポートと URL 要件

項目
仕様

対応するトランスポート

Streamable HTTP と SSE に対応します。stdio には対応しません(プラットフォーム上で npx や node などのローカルコマンドを起動しません)。

トランスポートの判定

URL から自動判定します。パスの末尾が /sse、パスに /sse/ が含まれる、またはクエリ文字列に transport=sse が含まれる場合は SSE を使用し、それ以外はすべて Streamable HTTP を使用します。

URL スキーム

https:// が必須です。接続先がプラットフォームで許可された内部ネットワーク(デプロイ設定の内部 CIDR 許可リスト)に解決される場合のみ、http:// を許可します。

ネットワーク上の配置

ドメインの名前解決が必要です。プライベートアドレスやループバックなどの内部アドレスに解決される場合は拒否します(内部 CIDR 許可リストに含まれるアドレスは除きます)。リンクローカルアドレス(169.254.x.x など)は常に拒否し、許可リストでも許可できません。SaaS 環境では、サーバーにパブリックインターネットからアクセスできる必要があります。

TLS

デフォルトで厳格な証明書検証を行います。Subject Key Identifier のない古いルート証明書が証明書チェーンに含まれ、接続できない場合、検証を緩和するオプションは MaiAgent がシステム管理側でツールごと、またはドメインごとに有効にする必要があります。MaiAgent にお問い合わせください。

Streamable HTTP を使用し、MCP エンドポイントを専用のパス(例:https://mcp.example.com/mcp)に配置することを推奨します。サーバーが SSE のみを提供する場合は、URL の末尾を /sse にすると、プラットフォームが SSE で接続します。

ツール作成時の接続検証

管理画面または API で MCP ツールを作成・更新するとき、プラットフォームはまずサーバーに実際に接続して tools/list を 1 回実行します。

  • 接続できない、またはツール一覧を取得できない場合、作成は失敗します。エラーメッセージには接続エラーの詳細が含まれます。

  • リクエストで mcpAllowedTools を指定しない、または空配列 [] を渡すと、プラットフォームは その時点 の tools/list が返すすべてのツール名を許可リストとして保存します。その後サーバーに追加したツールは 自動では有効になりません。ツール設定で一覧を再取得し、選択する必要があります。

  • 接続検証では、rawMcpHeader のうち {{変数}} を含まない ヘッダーのみを送信します(この時点では変数を代入する対話がありません)。サーバーが各リクエストに動的ヘッダーを要求する場合は、固定ヘッダーだけでも tools/list が応答できるようにしてください。

  • URL が OAuth に設定された MCP Registry に対応する場合(OAuth 2.0 を参照)、作成・更新時の検証を省略し、許可リストを空のままにします。認可完了後にツール一覧を取得します。

認証方式

プラットフォームは HTTP ヘッダーを使ってサーバーに識別情報を送信します。送信するヘッダーは、ツールの 認可対象(API フィールド authSubject)によって決まります。

authSubject

管理画面の名称

使用するユーザーの識別情報

適用するヘッダー(後のヘッダーが同名の前のヘッダーを上書きします)

shared(デフォルト)

組織共通

組織全体で 1 組の認可を共有します

ツール単位の OAuth トークン → rawMcpHeader → 該当する連絡先の MCP 認証情報

contact

連絡先ごとの個別認可

対話中の連絡先本人です

rawMcpHeader → 該当する連絡先の MCP 認証情報 → 該当する連絡先の OAuth トークン

contact モードでは、匿名の連絡先(sourceId がない連絡先)との対話で、このツールを Agent に 一切提供しません。

固定ヘッダー(API Key)

最も簡単な方法は、ツールの rawMcpHeader に JSON オブジェクトを設定することです。接続のたびに送信します。

  • rawMcpHeader は書き込み専用フィールドです。ツールを取得すると、マスク済みの rawMcpHeaderMasked のみが返されます。

  • 値では次の {{変数}} を使用でき、現在の対話に応じて代入します:contact_id、source_id、contact_name、conversation_id、inbox_id、organization_id、agent_slug、agent_version。

連絡先単位の MCP 認証情報

Agent が エンドユーザー本人の権限 でサーバーを呼び出せるようにするには、ユーザーのトークンを該当する連絡先の MCP 認証情報に書き込みます。

  • 各連絡先は、MCP ツールごとに最大 1 件の認証情報を持つことができ、その内容は headers のセットです。

  • 対話中、プラットフォームは「現在の対話の連絡先+このツール」で認証情報を検索し、headers を そのまま リクエストヘッダーにマージします。同名の場合は rawMcpHeader を上書きします。認証情報のヘッダーには {{変数}} を 代入しません。

  • 書き込み方法:

    • Web Chat の埋め込み時に setup-contact-credentials を呼び出し、mcpCredentials に toolId と headers を含めます(toolId は MCP タイプのツールである必要があり、それ以外は 400 を返します)。

    • バックエンドから連絡先 API の mcp-credentials エンドポイントを呼び出し、追加、更新、削除します。

両方の方法の全パラメータ、トークン更新、ログアウト時の失効処理は、連絡先の識別情報の同期とトークン更新 を参照してください。管理画面での手動設定は、ユーザーマニュアルの 連絡先の MCP 認証情報の設定 を参照してください。

対話識別ヘッダー

対話コンテキストがある場合、プラットフォームは各リクエストに X-Conversation-Id: <対話 ID> を追加します。状態を保持するサーバーは、モデルにセッショントークンを渡させることなく、対話単位で作業状態を保存できます。認証ヘッダーが同名の場合は、認証ヘッダーを優先します。

OAuth 2.0

MCP Server が OAuth で保護されている場合、プラットフォームは MCP 認可仕様に従い、次の処理を自動で行います。

1

保護対象リソースの探索

プラットフォームはまず、トークンなしで MCP URL に GET を送信します。401 と WWW-Authenticate: Bearer resource_metadata="..." が返された場合、その URL を読み取ります(https が必須で、ホストは MCP URL と同じである必要があります)。それ以外の場合は、RFC 9728 のデフォルトの場所を試します。最初に https://{host}/.well-known/oauth-protected-resource{MCP パス}、次に https://{host}/.well-known/oauth-protected-resource を試します。

そこから resource(トークンの audience)と authorization_servers(最初のエントリを使用し、https が必須です)を取得します。探索結果は 5 分間キャッシュします。

2

認可サーバーのメタデータの取得

RFC 8414 に従って /.well-known/oauth-authorization-server を読み取ります。認可サーバーの URL にパスが含まれる場合、「ホストとパスの間に well-known を挿入」「パスの後ろに well-known を追加」「ホストのルート」の 3 か所を順に試します。

3

Client の動的登録(RFC 7591)

メタデータに registration_endpoint がある場合、プラットフォームは次を送信します。

registration_endpoint がない場合、MCP Registry に oauthClientId を事前設定する必要があります(機密クライアントでは oauthClientSecret も設定します)。設定がないと認可は失敗します。

4

認可コード+PKCE

認可リクエストには response_type=code、state、code_challenge(S256)、resource を含めます。scope は、MCP Registry に設定された scope → 保護対象リソースのメタデータの scopes_supported → 認可サーバーのメタデータの scopes_supported の順で選択します。state の有効期間は 10 分です。

トークン交換では grant_type=authorization_code とともに code_verifier と resource を送信し、client secret がある場合のみそれも含めます。

5

トークンの自動更新

トークンの有効期限まで 60 秒以内になると、プラットフォームは grant_type=refresh_token で更新します。応答に新しい refresh_token がない場合は、古いものを引き続き使用します。

Callback URL:認可サーバーが動的登録に対応せず、redirect URI の事前登録が必要な場合は、以下の 2 つを両方登録してください。登録がないと、対応する処理が /authorize で失敗します。

処理
Callback URL

メンバー(組織共通)の認可

MaiAgent 管理画面のドメイン + /oauth/mcp/callback

連絡先ごとの個別認可

https://api.maiagent.ai/api/mcp/oauth/contacts/callback/(SaaS。プライベートデプロイでは、その環境の API ドメインを使用します)

MCP Registry:自社ホスト型サーバーで固定の oauthClientId、認可サーバー URL、または resourceIdentifier を指定する必要がある場合、コネクタ管理権限を持つメンバーが組織専用の MCP Registry(/api/v1/mcp/private-registry/)を作成できます。authType は oauth、service_account(ヘッダーでキーを送信)、none から選択できます。プラットフォームは「MCP URL が Registry の remoteMcpUrl で始まるか」で、ツールに対応する Registry を判定します。空欄のフィールドのみ、自動探索の結果を使用します。

許可するツール(mcpAllowedTools)

mcpAllowedTools はサーバーのツール名の配列で、Agent に提供するツールを決定します。実行時、保存された値は認可対象に応じて次のように解釈します。

値

shared

contact

null

サーバーのすべてのツールを許可します

サーバーのすべてのツールを許可します

[](空配列)

ツールを一切許可しません

サーバーのすべてのツールを許可します

["search_orders", ...]

指定されたツールのみ許可します

指定されたツールのみ許可します

contact モードで空配列をすべて許可と扱うのは、管理者が連絡先のトークンを持たず、事前にツール一覧を取得できないためです。OAuth を使用する shared モードでは、管理者が認可を完了してツール一覧を取得した後に、一覧に内容が入ります。

ツール一覧をモデルに渡す仕組み

  • 取得のタイミング:Agent のツールを構成するたびに、サーバーへ接続して tools/list を実行し、許可リストで絞り込みます。

  • 名前:ツールに name が設定されている場合、モデルに見える名前は {name}__{自社のツール名} です。英数字とアンダースコア以外の文字はアンダースコアに置き換え、先頭が英字でない場合は t_ を付けます。64 文字を超える場合は切り詰め、6 文字のハッシュサフィックスを付けます。

  • 説明:モデルに見える説明は、tools/list で返した description です。用途と使用するタイミングを明確に記述してください。

  • パラメータ:inputSchema をモデルのパラメータ定義に変換します。プラットフォームはよくある 2 つの形式を自動処理します。配列形式のプロパティ値を anyOf に変換し、ローカルの $ref をインライン展開します(再帰参照は任意の値を受け入れる形式に変更します)。それでもスキーマを変換できない場合は そのツールだけを省略 し、ほかのツールは通常どおり提供します。

  • 取得失敗:接続不能、タイムアウト、認証失敗の場合、この MCP ツールは今回の応答でモデルに ツールを一切提供しません。対話自体は中断しません。

ツール呼び出し:タイムアウト、再試行、エラー

セッションとタイムアウト

  • tools/call ごとに 新しい MCP セッションを開始 します(initialize の後に呼び出します)。呼び出し間でセッションを再利用しません。複数の呼び出しにまたがって状態を保持する場合は、X-Conversation-Id または独自の認証済み識別情報を使用してください。

  • MCP セッションの読み取りタイムアウトは 30 秒です。

一時的なエラーの自動再試行

接続タイムアウト、接続の中断やリセット、サーバーが応答する前の切断、途中で閉じられたセッション、および接続終了を示す MCP エラーコードまたは 408 の場合、プラットフォームは最大 3 回再試行します。間隔は 1、2、4 秒(上限 8 秒)です。サーバーが返すエラー結果やアプリケーション層のエラーは 再試行しません。

再送しても安全なツールのみ再試行します。判定順序は次のとおりです。

  1. ツールの annotations に readOnlyHint: true または idempotentHint: true がある場合 → 再試行します。

  2. いずれかが明示的に false の場合 → 再試行しません。

  3. どちらも宣言されていない場合、ツール名の最初の単語が get、list、read、fetch、search、find、check、query、describe、show、view、browse、lookup のいずれかかを確認します(camelCase と - は先に単語に分割します)。

tools/list で各ツールの readOnlyHint/idempotentHint を明示することを推奨します。副作用があるツール(注文やフォーム送信)は false にし、切断後の再送を防いでください。

モデルに返す内容

状況
モデルに見える内容

呼び出し成功

CallToolResult から変換したテキスト(content、structuredContent、isError フィールドを含みます)。isError: true を返した場合も、モデルはこの内容を受け取ります。

呼び出し中の例外(再試行後も失敗、または一時的でないエラー)

MCP ツール実行エラー\n MCP Tool Execution Error: <エラー内容>

結果が長すぎる場合

上限はモデルのコンテキストウィンドウ × ツール出力比率(デフォルト 0.8)で、トークン数から推定します。超過時は先頭と末尾を半分ずつ残して中間を省略し、先頭に結果が不完全であることを示す通知を付けます。

呼び出しごとにツール実行ログ(ツール、実際の MCP ツール名、入力引数、出力またはエラー、所要時間、再試行回数)を記録します。デバッグ方法は API ツールエンジニアリングガイドのログとデバッグ と同じです。

課金区分

成功した呼び出しごとに MCP ツール使用量を 1 回として計上し、ツール名から読み取り系または書き込み系に分類します。名前の最初の単語が上記の読み取りプレフィックスに一致する場合は読み取り系、それ以外で名前に書き込みキーワードが含まれる場合は書き込み系、残りはすべて読み取り系です。組織のクレジットが不足している場合、その呼び出しはサーバーに送信しません。

MCP Apps(インタラクティブカード)

MaiAgent は MCP Apps 拡張(SEP-1865)に対応しています。ツールはデータに加えて HTML インターフェースを添付でき、対話に操作可能なカードが表示されます。たとえばグラフ、フォーム、検索結果一覧などです。ユーザーから見た動作と制限は、ユーザーマニュアルの MCP インタラクティブカード(MCP Apps) を参照してください。すぐに試す場合は、最小の実行可能なサンプル に進んでください。

サーバー側:UI リソースの返し方

  1. UI リソースを関連付ける:tools/list のツール定義、または tools/call の結果の _meta に ui.resourceUri を含めます。値は ui:// で始まる必要があります。例:{"_meta": {"ui": {"resourceUri": "ui://orders/list"}}}。両方にある場合は呼び出し結果を優先します。フラット形式の _meta["ui/resourceUri"](@modelcontextprotocol/ext-apps の registerAppTool が生成する形式)も受け付けます。ツール定義の _meta は、ツール一覧を構成するたびに読み取ります。

  2. リソースの内容を提供する:ツール呼び出しの成功後、プラットフォームは同じ MCP セッションでこの URI に resources/read を送信し、最初のコンテンツの text をカードの HTML として使用します。mimeType は text/html;profile=mcp-app を推奨します。

  3. データを返す:カードが受け取るのは今回のツール結果、つまり content の最初のテキストと structuredContent(オブジェクト)です。カードのデータソースには structuredContent を使用してください。プラットフォームはツールの入力引数をカードに渡しません(ui/notifications/tool-input の arguments は空オブジェクトです)。

次の場合、カードは表示されないか、テキスト表示に切り替わります。

状況
結果

ツール結果が isError: true

カードを生成しません

ui:// リソースが関連付けられていない

カードを生成せず、対話には通常どおりツール結果を表示します

resources/read が失敗、または内容がない

カードには代わりに content の最初のテキストを表示します

カードの HTML は生成時にメッセージとともに保存します。その後サーバー上の UI を更新しても、過去のメッセージですでに生成されたカードは変わりません。新しい UI は、古いバージョンが生成したデータも処理できるようにしてください。

フロントエンド:カードの表示方法

  • 表示位置:Agent の応答完了後、その応答の下にカードを表示します。同じ応答内では、同じソースかつ同じ UI リソースのカードは最新の 1 枚のみ表示します。

  • サンドボックス:カードは sandbox="allow-scripts" の iframe で実行します(allow-same-origin はありません)。ホストページの Cookie やストレージを読み取れず、自身で新しいウィンドウを開くこともできません。

  • コンテンツセキュリティポリシー(CSP):デフォルトではインラインの script と style のみ許可します。画像、メディア、フォントは data:/blob: のみ許可し、connect-src は 'none'(外部へのリクエストは禁止)です。フォームの送信もできません。JS、CSS、画像は 1 つの HTML にまとめてください。

  • 追加で許可するオリジン:外部リソースの読み込みが必要な場合、組織専用の MCP Registry(/api/v1/mcp/private-registry/)の cspAllowedOrigins にオリジンを指定します。https:// で始まり、パスやワイルドカードを含まない origin のみ許可します。例:https://viewer.example.com。MCP ツールの作成・更新時に、URL が Registry の remoteMcpUrl で始まるツールを、その Registry に対応付けます。

  • サイズと表示モード:カードのデフォルトの高さは 220px で、カードが ui/notifications/size-changed で報告する height に応じて調整します(上限 2000px)。メッセージストリーム内の最大高さは min(62vh, 620px) で、超過時はカード内でスクロールします。カードは全画面(fullscreen)への切り替えを要求できます。プラットフォームは右上に終了ボタンを追加し、Esc でも元に戻れます。折りたたみ後は、カードが最後に報告した高さを維持します。pip の要求は通常(inline)モードで表示します。

  • ストリーミング中は非表示:Agent の応答ストリーミング終了後にカードをマウントします。同じ応答が複数回更新される場合、プラットフォームは ui/notifications/tool-result で新しい結果をその場で渡し、iframe を再作成しません。

カードとホストのハンドシェイク

カードとプラットフォームは、MCP Apps の JSON-RPC を window.parent.postMessage でやり取りします(ホスト側は @modelcontextprotocol/ext-apps 1.2 の AppBridge を使用し、プロトコルバージョンは 2026-01-26 です)。順序は次のとおりです。

  1. カードが ui/initialize(appInfo、appCapabilities、protocolVersion)を送信します。プラットフォームは hostInfo、hostCapabilities(serverTools、message.text、openLinks)、hostContext(displayMode、availableDisplayModes: ["inline", "fullscreen"]、theme: { primaryColor, mode })を返します。

  2. カードが ui/notifications/initialized を送信します。

  3. プラットフォームは ui/notifications/tool-input(arguments は空)と ui/notifications/tool-result(完全な CallToolResult)を順に送信します。その後、表示モードやテーマが変わると ui/notifications/host-context-changed を送信し、カードをアンマウントする前に ui/resource-teardown リクエストを送信します。

プラットフォームはさらに、カード HTML の <head> に window.__MCP_INITIAL_RENDER_DATA__(同じツール結果)を注入し、ハンドシェイク完了前でも描画できるようにします。正式なデータは引き続き tool-result 通知を基準にしてください。

カードから呼び出せるホスト機能

メソッド
プラットフォームの処理

tools/call

プラットフォームが代理で呼び出します。カードは自社サーバーや MaiAgent バックエンドへ直接接続できません。このカードを生成した同じ MCP ソースのツールで、この対話で有効かつ許可リストに含まれるツールのみ呼び出せます。認証ヘッダーは Agent の呼び出しと同じです。1 回のタイムアウトは 30 秒で、カードに返す結果は content の最初のテキスト、structuredContent、isError のみです。失敗時はカードの外側に「この操作を完了できませんでした。しばらくしてからもう一度お試しください。」と表示します。

ui/message

content はコンテンツブロックの 配列 が必要です。プラットフォームはテキストブロックを抽出し、ユーザーメッセージとして対話に送信します。先にカードを inline に折りたたみ、その後 Agent が回答します

ui/open-link

プラットフォームが新しいタブを開きます。https:、http:、tel:、mailto: のみ許可し、URL 内のユーザー名とパスワードは削除します。許可されない、またはブラウザーにブロックされた場合は { "isError": true } を返します

ui/request-display-mode

inline と fullscreen を切り替え、実際に適用したモードを返します

ui/notifications/size-changed

height に応じてカードの高さを調整します(全画面時は無視します)

ui/download-file、ui/update-model-context、resources/read

未対応です。プラットフォームは -32601 Method not found を返します

適用範囲

  • カードは Web Chat と MaiGPT の対話に表示します。LINE、Messenger などのほかのメッセージングプラットフォームには、Agent のテキスト応答のみを送信します。

  • Agent に追加した MCP ツール(Agent モード)と、メンバーが MaiGPT で使用を認可したコネクタの両方に対応します。MaiAgent 側で追加のスイッチは不要です。

  • オンプレミス環境の Web Chat でカードを表示するかは、デプロイ設定によって決まります。MaiAgent の担当者にお問い合わせください。

最小の実行可能なサンプル

Node.js(18 以上)の MCP Server です。注文状況を調べるツール(ダミーデータを返します)が ui://orders/status カードに関連付けられ、カードから再照会や AI への質問ができます。3 つのファイルを同じフォルダーに配置します。

1

プロジェクトの作成

2

server.mjs:ツールと UI リソース

3

card.html:単一ファイルのカード

パッケージを読み込まず、postMessage で直接 JSON-RPC を使用します。ハンドシェイク、tool-result の受信、高さの通知、tools/call による再取得、ui/message による AI への質問を行います。JS と CSS は同じファイル内に記述します(サンドボックスの CSP は外部リソースの読み込みを許可しません)。

4

起動と検証

別のターミナルを開き、プラットフォームと同じ順序で 3 つのリクエストを送信します(ステートレスモードではセッションヘッダーは不要です):

3 つとも正しい応答が返れば、プラットフォーム側でカードを表示できます。

MaiAgent に接続する手順

  1. Server にインターネットから https:// でアクセスできるようにします(ローカルテストでは、cloudflared tunnel --url http://localhost:8787 や ngrok http 8787 などのツールで一時的な URL を取得できます)。MCP エンドポイントは https://<你的網域>/mcp です。

  2. ユーザーマニュアルの MCP ツールの作成 に従って管理画面で MCP ツールを追加し、URL に前の手順のエンドポイントを入力します。この例ではヘッダーは不要です。「許可されたツール」の一覧を再取得すると、get_order_status が表示されます。

  3. 回答モードが Agent モードの Agent にツールを設定し、Web Chat または MaiGPT で「注文 A1001 は今どこにありますか?」と質問します。Agent の回答が完了すると、回答の下にカードが表示されます。再取得 をクリックすると tools/call、この注文について AI に質問 をクリックすると ui/message が実行されます。ユーザー側の動作については MCP インタラクティブカード(MCP Apps) を参照してください。

よくあるエラー

現象
原因

Agent がツールを呼び出してもカードが表示されません

tools/list のツール定義と tools/call の結果のどちらにも _meta.ui.resourceUri がありません(または値が ui:// で始まっていません)。ツールが isError: true を返しているか、LINE などカードを表示しないチャネルを使用している場合もあります

カードの位置にプレーンテキストだけが表示されます

resources/read が失敗するか空の内容を返すと、プラットフォームは content の最初のテキストブロックを代わりに表示します。上記の 3 番目の curl で確認してください

カードが「読み込み中…」のままです

カードのハンドシェイクが完了していません(ui/initialize の params に appInfo/appCapabilities/protocolVersion がないか、ui/notifications/initialized を送信していません)。この場合、プラットフォームは tool-result を送信しません。カードの HTML が読み込む外部 JS が CSP にブロックされている可能性もあります

カードが空白です

HTML が依存する外部 CSS/JS/画像がサンドボックスの CSP にブロックされています。同じ HTML ファイルにまとめるか、Registry で cspAllowedOrigins を設定してください

カードに「この操作は完了しませんでした。しばらくしてからもう一度お試しください。」と表示されます

カードの tools/call がプラットフォームに拒否されたか、失敗しています。ツール名がその MCP ツールの許可リストにない、ツールが Agent から削除された、認可が失効した、Server がエラーを返した、または 30 秒を超えて応答しなかった可能性があります

カードの「AI に質問」が反応しません

ui/message の content が配列ではないか、type: "text" のブロックがありません

公開前のチェックリスト

最終更新

役に立ちましたか?