MCPO の Oってなに?
MCP OpenAPI の内部動作を徹底解説
この記事では MCP OpenAPI(OpenAPI 仕様を MCP サーバとして公開する仕組み)について、詳細に解説します。Claude や ChatGPT、Cursor などのエージェント環境と連携する際に、どのように OpenAPI が MCP の Tools/Resources に変換され、実際に API 呼び出しが行われるのか、内部実装寄りに掘り下げます。
MCP とは何か
MCP(Model Context Protocol)は、LLM が外部システムと安全に対話するためのプロトコルです。主な特徴は以下の通りです:
-
JSON-RPC ベース:LLM クライアントと MCP サーバが双方向に JSON メッセージで通信。
-
Tools(操作)と Resources(情報):サーバが公開する機能は大きく 2 種類に分かれる。
- Tools: 呼び出し可能な操作(例:ユーザー情報取得、ファイル書き込み)
- Resources: 参照可能な静的・動的データ(例:仕様書、ヘルプテキスト)
-
接続方法:標準入出力(stdio)や WebSocket で接続可能。
MCP OpenAPI は、この枠組みに「OpenAPI 仕様で定義された REST API」を載せるためのアダプタです。つまり 任意の OpenAPI 対応 API を LLM にそのまま Tools として認識させることが可能になります。
MCP OpenAPI の役割
通常、OpenAPI は人間やプログラムが「どのエンドポイントがあり、どの引数やレスポンスを持つか」を知るための仕様書です。しかし、そのままでは LLM にとって次の課題があります:
- スキーマの複雑さ:数百のパラメータや複雑なネストを含むことが多い。
- 戻り値の過剰さ:必要以上のデータを返し、トークン消費が大きい。
-
操作の粒度が LLM に適さない:例えば
createUserとupdateUserが曖昧。
MCP OpenAPI は、この OpenAPI をパースして MCP の Tool として適切な形にマッピングします。これにより LLM は、あたかも「関数を呼ぶように」API を利用できるのです。
内部動作フロー
1. 起動と OpenAPI 読み込み
MCP OpenAPI サーバは起動時に指定された OpenAPI ドキュメント(YAML または JSON)を読み込みます。
-
openapi: 3.xのバージョンを確認 - JSON Schema 準拠でバリデーション
-
paths,components,servers,securityなどを解析
2. Operation → Tool マッピング
各エンドポイント(paths.{path}.{method})ごとに MCP Tool を生成します。
-
名前付け
-
operationIdがあればそれを利用 - 無ければ
get_/users/{id}のようにメソッド+パスから自動生成
-
-
説明文
-
summaryとdescriptionを統合
-
-
入力スキーマ
-
parameters(path/query/header/cookie)を抽出 -
requestBody(特にapplication/json)を統合 - JSON Schema に変換して MCP の
input_schemaに設定
-
-
出力のヒント
-
responses.200.contentのスキーマを解析 - LLM に「JSON で返る」と伝えられるように整備
-
3. Resources の生成(オプション)
サーバは resources として以下を公開することもあります:
-
openapi_spec(仕様書全体) -
endpoints_index(操作一覧) - 各種サンプルレスポンス
これにより LLM が「この API にはどんな機能があるか?」を introspection 可能になります。
4. MCP クライアントとの接続
クライアント(例:Claude Desktop, ChatGPT MCP, Cursor IDE)は次のシーケンスで接続します:
-
initialize→ サーバ情報を交換 -
list_tools→ 利用可能な操作を取得 -
list_resources→ 利用可能なリソースを取得 - 必要に応じて
read_resource→ 仕様やサンプルを参照
5. Tool 実行
クライアントが Tool を呼び出すと次の流れになります:
-
引数の受け取りとバリデーション
- JSON Schema に基づき必須項目の確認
- 型変換(string→date, enum 値のチェックなど)
-
HTTP リクエスト構築
- メソッド(GET, POST, ...)
- URL(
servers[0].url+ path + query) - ヘッダ(認証や Content-Type)
- ボディ(必要なら JSON にシリアライズ)
-
送信と応答処理
- HTTP クライアントで API 呼び出し
- タイムアウト、リトライ、レート制御
- レスポンスの JSON 化
-
MCP 形式に変換して返却
- 成功時:
tool_resultとして JSON を返す - 失敗時:
errorフィールドにエラーメッセージ
- 成功時:
具体例
OpenAPI 定義(抜粋)
paths:
/users/{id}:
get:
operationId: getUser
parameters:
- name: id
in: path
required: true
schema: { type: string }
- name: fields
in: query
schema: { type: string }
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/User"
MCP Tool に変換
{
"name": "getUser",
"description": "Get user by ID",
"input_schema": {
"type": "object",
"properties": {
"id": { "type": "string" },
"fields": { "type": "string" }
},
"required": ["id"]
}
}
クライアントはこれを「getUser(id, fields)」のような関数として利用可能になります。
セキュリティとリスク
MCP OpenAPI サーバは「外部 API への代理呼び出し器」となるため、以下のリスクがあります:
- 認証情報の漏洩:API Key や Bearer Token を適切にマスクする必要
- 悪意あるサーバ:npm に混入した悪意ある MCP サーバが実在
- 過剰権限:scope が広いトークンを使うと、LLM が不用意に高権限操作を実行する危険
推奨対策
- 最小権限の API キーを利用
- 出所が明確な MCP サーバのみ導入
- ログに機微情報を残さない
- 外部 MCP サーバはゼロトラスト前提で設計
実運用上の工夫
- 引数のデフォルト化:LLM が曖昧な入力を出す場合、既定値で補う
- レスポンスの要約:巨大な JSON をそのまま返すのではなく、要約を追加
-
ページング対応:
nextPageTokenなどを LLM が扱いやすい形で返却 -
エラーの正規化:OpenAPI の多様なエラー形式を
{code, message, details}に揃える
まとめ
MCP OpenAPI は以下の流れで動作しています:
- OpenAPI 仕様を読み込み
- 各エンドポイントを MCP Tool として生成
- Resources として仕様やサンプルを提供
- クライアントが Tool を呼び出すと HTTP リクエストを代理実行
- レスポンスを MCP 形式に整えて返す
これにより LLM は「API を直接叩く」ことなく、抽象化された関数群として外部システムを操作できます。
今後の展望としては、
- GraphQL, gRPC, SOAP など OpenAPI 以外の仕様からの自動変換
- レスポンスの自動要約・正規化
- LLM に適したエンドポイントの自動推奨
などが進むと考えられます。
MCP OpenAPI は「LLM に外部 API を安全に開放する」ための強力な武器であり、エージェント開発者にとって必須の技術になりつつあります。
Discussion