AI Agent · MCP

なぜAI AgentはJSONなしでは動けないのか:Tool Calling・Function Calling・MCPデータフロー

AI Agent が Tool Calling と MCP で JSON に依存する理由

Function Calling / Tool Calling / MCP JSON-RPC — 4往復 / スキーマ方言 / 可観測性と隔離

Cursor、Claude Code、あるいは任意の Agent フレームワークのデバッグログを開くと、ほぼすべてのペイロードが JSON です。ツールカタログは JSON Schema、モデルの tool_calls は JSON、MCP Server のフレームは JSON-RPC 2.0。これは偶然ではありません — Agent は予測不能な自然言語と実行可能なプログラムインターフェースを橋渡ししなければならず、JSON は双方が確実にパースできる共通の交換フォーマットだからです。

本記事では Function Calling → Tool Calling → MCP をたどり、ツール呼び出し1回分の4往復 JSON をマッピングします。クラウド Mac 上の MCP Server をデプロイ中の方や、GitHub Agent まとめ からフレームワークを選んでいる方にとって、このフローを理解することは API ドキュメントの暗記よりデバッグに効きます。

Agent はほぼどこでも JSON を話す

LLM はトークン列を出力しますが、Shell、データベース、HTTP API は構造化された引数を必要とします。初期のやり方は「この JSON 形式で返して」とプロンプトに書くことでした — モデルは末尾カンマを付けたり、引用符を落としたり、Markdown フェンスで囲んだりして、パーサーが頻繁に失敗していました。

2023年以降、主要 API は構造化アクションをプロトコルに組み込みました:モデルはもはや任意の JSON テキストを自由に出力しない。サーバーが出力形状を制約し、Host が実行します。パイプラインは次のようになります:

  • 宣言 — JSON Schema でツールを定義;
  • 決定 — 制約された文法の中でツール名とパラメータを選ぶ;
  • 実行 — ローカルコードまたは MCP Server 経由で呼び出す;
  • 書き戻し — 結果を JSON メッセージとしてコンテキストに戻す。

設計原則:Agent の可観測性 = すべての JSON ステップをログ・再生・差分比較できること。構造化された中間表現がなければ、自動化は監査不可能です。

Function Calling:自然言語から構造化アクションへ

OpenAPI 時代の function オブジェクト

OpenAI は Chat Completions に functions / tools を追加しました。リクエストにツール定義を添付すると、モデルは正規表現で抜き出すテキストの代わりに function_call または tool_calls を返します。

典型的なリクエスト断片

json
{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "東京の天気は?"}],
  "tools": [{
    "type": "function",
    "function": {
      "name": "get_weather",
      "description": "都市別の現在の天気",
      "parameters": {
        "type": "object",
        "properties": { "city": { "type": "string" } },
        "required": ["city"]
      }
    }
  }]
}

プロンプト内の手書き JSON テンプレートはプロトコル制約に置き換えられ、Host は arguments をスキーマで検証してから実関数を呼び出します。Function Calling が固定するのはモデルの発話 — ツールがどこで動くか、どう発見されるか、認証がどう働くかではありません。Tool Calling エコシステムと MCP がそれを担います。

Tool Calling:1ターンあたり4往復の JSON

  1. 登録 — Host が JSON Schema 付きの tools[] をモデル API に送信;
  2. 決定 — API が idnamearguments(JSON 文字列)を含む tool_calls を返す;
  3. 実行 — Host が引数をパースし、ローカルコードまたは MCP を呼び出す;
  4. 書き戻しrole: tool メッセージで結果を返し、モデルがユーザー向け回答を生成。
json
{
  "tool_calls": [{
    "id": "call_abc123",
    "type": "function",
    "function": {
      "name": "get_weather",
      "arguments": "{\"city\":\"Tokyo\"}"
    }
  }]
}

arguments はネストしたオブジェクトではなく文字列です — ストリーミングと SDK 互換性のため。Host は実行前に JSON.parse(arguments) が必要です。DevTools で Ctrl + Shift + I を押すと、Network タブに同じ構造が見えます。

段階方向ペイロードパーサー
① 登録Host → APItools[] + JSON SchemaAPI ゲートウェイ
② 決定API → Hosttool_callsHost / SDK
③ 実行Host → Toolパース済みオブジェクトツール実装
④ 書き戻しHost → API{role:"tool", content:"..."}モデル

API スキーマの方言

OpenAI / 互換エンドポイント
tools + tool_choice;ストリーミングは delta.tool_calls チャンク。
Anthropic
input_schema 付きの tools;応答は tool_use ブロックと tool_result 返信。
Google Gemini
functionDeclarationsfunctionCall でフィールド名が異なる。
Ollama ローカル
OpenAI 互換の tools;能力はモデルの学習に依存。

LangGraph や DeepSeek Harness(Harness ガイド参照)のようなフレームワークは、これらの方言を1つの Tool 抽象に圧縮します — 根底は依然として JSON です。

MCP:JSON-RPC がツール層を標準化する

Model Context Protocol (MCP) は Function Calling の下位層に位置します — ツールプロセスの発見、パラメータ化、Host 間での再利用の方法です。転送は stdio または SSE ですが、メッセージは常に JSON-RPC 2.0 です。

プロトコル
モデル APIREST / OpenAI 互換chat/completions + tools
MCPJSON-RPC 2.0tools/list, tools/call
ビジネス任意ファイル、DB、HTTP

Host は起動時に tools/list を呼び、カタログを API の tools[] に変換し、モデルが決定した後に tools/call を送ります — 2回の方言変換、1本の意味的パイプラインです。

json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "read_file",
    "arguments": { "path": "/tmp/demo.txt" }
  }
}
stdio モードでは JSON フレームはどう区切られる?

MCP stdio は改行区切り JSON ではなく、Content-Length ヘッダー + JSON 本体(LSP と同様)を使います。大きなペイロード(base64 リソースなど)も1フレームに収まります。SSE は JSON-RPC を HTTP イベントストリームに包み、マルチクライアント Server 向けです。

データフロー全体:ユーザー入力からツール実行まで

Agent ツール呼び出しの JSON データフロー図
ユーザー入力から MCP 実行まで — 各ステップをログ・再生できます。
  • ログは各 tools/list のバージョンとツール数を記録しているか?
  • arguments は実行前にスキーマ検証されているか?
  • MCP タイムアウトは読みやすい tool メッセージにマッピングされているか?
  • ログ出力前にシークレットは除去されているか?

AI Coding Workflow の Verify 段階と同じ考え方です — パース可能な中間表現がなければ、Agent が正しいツールを実際に呼んだか自動検証できません。

なぜ Protobuf や XML ではないのか?

  • モデル API は JSON ファースト;バイナリはシリアライズ層を増やす;
  • デバッグ — エンジニアがログでパラメータを読める;
  • スキーマエコシステム — JSON Schema と OpenAPI が事実上の標準;
  • スクリプトとブラウザ — curl、n8n、フロントエンドデモは JSON を前提とする。

トレードオフはサイズと CPU。高 QPS の構成では内部キャッシュとログ圧縮を行い、大きな blob は JSON フィールド内で base64 化します — JSON エンベロープ自体は置き換えません。

JSON のコストとエンジニアリング上の対策

症状原因対策
arguments パースエラーモデルからの不正な JSON 文字列スキーマを厳格化、temperature を下げる、リトライ
誤ったツール選択ツール説明が曖昧または多すぎるツールを統合、ネガティブ例を追加
MCP ハング不完全な stdio フレームまたはデッドプロセスlaunchd スーパーバイザー、ヘルスチェック
ログへのシークレット混入ツール結果に環境変数が含まれる結果をマスク、実行用アカウントを分離

本番のヒント:隔離されたクラウド Mac で MCP を動かす — ノートPCの Cursor は SSH 越しに JSON-RPC を送り、Shell は日常使いのマシンに置きません。

Agent が JSON に依存するのは、自然言語による意思決定プログラムによる実行の間に、人間が読めて機械が検証できる、差し替え可能な契約が必要だからです。Function Calling はモデルが何を言うかを定義し、Tool Calling は Host が1ターンをどう回すかを定義し、MCP はツールプロセスをエコシステムにどう接続するかを定義します — JSON が3つを貫く糸です。

クラウド Mac で MCP の JSON 実行プレーンを動かす

M4 専用ノード、日単位レンタル、SSH 即利用可

シンガポール · 日本 · 韓国 · 香港 · 米国リージョン

tools/call を隔離されたクラウド Mac に着地させ、ローカル Host は JSON-RPC だけを送る。 ZekVPS クラウド Mac mini プランを見る

期間限定