AI エージェント

AI Agent が JSON なしでは動けない理由:Function Calling から MCP まで

ノートPCの画面にコードエディタとターミナルログ、キーボードを打つ両手
マルチディスプレイの開発デスク。Agent のツール呼び出しも最終的にはこの実行環境に落ちます。

症状: 会話はできるのに、ツール引数が検証で落ちる、再試行で注文が二重になる、MCPサーバーは起動しているのにツールが見えない。
最短の対処: JSONをモデルとツールの唯一の契約にする。入力は JSON Schema で縛り、結果は固定フィールドで返し、その契約をプロセスをまたいで発見できるようにするのが MCP です。

対象は、大規模言語モデルを実システムへつなぐ開発者、基盤担当、アーキテクトです。新しい用語を覚えることより、同じ JSON が Function Calling、Tool Calling、MCP のどこを流れ、どの段で止まるかを見極めることが先です。

フレームワーク選定が先なら AI Agent開発フレームワークの選び方 を先に読んでください。ツール実行時の隔離は AI SandboxとDocker、仮想ファイルシステムの比較 も参照できます。

AI Agent が JSON なしでは成立しない理由

モデルは自然言語を生成します。本番システムが受け取るのは構造化コマンドです。在庫照会、チケット更新、テスト実行、ブラウザ操作が必要になった瞬間、「意図」は検証・拒否・監査できるデータにならなければなりません。JSON はその隙間に収まります。人が読め、機械がパースでき、HTTP・ログ・キュー・データベースがすでに扱えます。

本質は検証可能性です。散文はゲートウェイに「order_id は文字列、amount は正の数、currency は列挙」と伝えられません。JSON Schema は伝えられます。OpenAI の Function Calling 案内は、関数パラメータを JSON Schema で定義し、サンプリング時点で合法な構造へ寄せます。OpenAI Function Calling ガイドを見る

型、必須、enum、additionalProperties は学術的な細部ではありません。モデルがフィールドを捏造したり、文字列を数値に押し込めたり、冪等キーを落とすのを止める最初の門です。JSON Schema の説明を見る

層は三つです。

  • 対話層:ユーザーが「上海倉庫のあの注文を急行にして」と言う。
  • 契約層:モデルが {"name":"update_order","arguments":{"order_id":"A938","priority":"expedited"}} を出す。
  • 実行層:スキーマ検証、権限確認、業務 API、結果 JSON をモデルへ戻す。

契約層が無ければ Agent はチャット窓です。あれば統治可能な実行器になり得ます。

⚠️ 現場の判断:引数をまだ「自由文+正規表現」で抜いているなら、プロトコルは無くプロンプト運だけです。スキーマを固めてから多ツール編成に進んでください。

Function Calling:モデルがフォームを埋める

Function Calling の本体は、ユーザーへ答える前に宣言済み関数を呼ぶか決め、スキーマに合う引数を出すことです。流れは五段で、各段でフィールドが落ちます。

  1. 登録:リクエストに name、description、JSON Schema の parameters を載せる。
  2. 判断:関数を呼ぶか、直接答えるか。
  3. 記入:tool_calls。arguments は JSON 文字列またはオブジェクト。
  4. 実行:パース、検証、認可、実システム呼び出し。
  5. 再注入:ツール結果を返し、モデルが最終回答を書く。

description は宣伝文ではなくルーティング信号です。「天気を調べる」と「配送を調べる」が衝突します。「都市名があるときだけ現在気温を取る。気候の歴史には使わない」と書けば誤発火が減ります。スキーマ内のフィールド説明もプロンプトなので、「order_id は業務注文番号であり決済 ID ではない」はシステムプロンプトだけに置かないでください。

strict / Structured Outputs は「JSON っぽい」を「スキーマ一致」に上げます。JSON mode は括弧がパースできることしか保証しません。欠落や型違いは通ります。スキーマ合法は業務合法ではありません。負の金額、存在しない倉庫、権限外の注文はアプリ側で落とします。

最小の実行可能な契約

次のスキーマは列挙と冪等キーを固定します。呼ばない選択はできますが、余分な倉庫フィールドの発明や idempotency_key の省略はできません。

function schema(抜粋)
{
  "type": "function",
  "name": "update_shipment",
  "description": "配送優先度の変更をユーザーが明示したときだけ呼ぶ。",
  "strict": true,
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {"type": "string", "description": "業務注文番号"},
      "priority": {"type": "string", "enum": ["standard", "expedited"]},
      "idempotency_key": {"type": "string"}
    },
    "required": ["order_id", "priority", "idempotency_key"],
    "additionalProperties": false
  }
}

実行順は JSON parse → スキーマ検証 → 権限 → 冪等表 → 業務 API → {"ok":true,"shipment_id":"..."} または {"ok":false,"error":"not_found"}。スタックトレースや秘密情報を tool result に入れないでください。

Tool Calling:関数からツール平面へ

必要なのは自前関数だけではありません。検索、コード実行、ブラウザ、コンピュータ操作、ファイル検索もツールです。API は初期の function_call から統一の tools / Tool Calling へ進みました。名前は変わり、JSON 契約は name + schema + 呼び出し記録 + 結果返却のままです。

Anthropic は Tool use と呼び、input_schema を JSON Schema で表します。モデルは tool_use ブロックで構造化引数を返し、アプリは tool_result で返します。Anthropic Tool use ドキュメントを見る

エンジニアリング上の新しい問題も、JSON で運びます。

  • 並列呼び出し:読み取りは並列、在庫ロックと課金は直列。
  • 承認:高リスクツールは実行せず pending の JSON を返す。
  • 観測:trace にツール名、引数要約、レイテンシ、エラーコードを残す。

失敗の形も変わります。正しいツールを選んでも、文字列フィールドに危険なペイロードを隠せます。型はスキーマで防げますが意味攻撃は防げません。危険なツールは許可リスト、タイムアウト、サンドボックスが必須です。

MCP:JSON 契約を差し込み可能にする

Function / Tool Calling は一回の API リクエスト内の会話です。MCP はツールの発見、複数ホストでの再利用、別プロセスでの実行です。仕様は JSON-RPC 2.0 で initialize、tools/resources/prompts の一覧、呼び出し、通知を運びます。MCP 仕様を見る

  1. IDE や Agent ランタイムが MCP Client として起動する。
  2. stdio、SSE、Streamable HTTP で Server に接続する。
  3. initialize で版と能力を交渉する。
  4. tools/list で inputSchema(依然 JSON Schema)付きの一覧を得る。
  5. モデルは Tool Calling のまま。MCP ツールなら Client が JSON 引数で tools/call する。
  6. Server の content を tool result にしてモデルへ戻す。

MCP は JSON を置き換えません。アプリに直書きしていた tools 配列を実行時カタログにします。同じ Git、同じブラウザ自動化、同じチケット API を、Cursor や Claude Desktop、自作 Agent が共有できます。

「入れたのにツールが見えない」はほぼ契約障害です。initialize 失敗、list が空、strict 非互換、required 欠落、JSON-RPC error の代わりの自然文エラーです。

一連の流れ:一文から MCP 実行まで

  1. ユーザーが自然言語を入れる。
  2. ランタイムが messages、ローカル tools、MCP tools/list を組み立てる。
  3. モデルが Tool Calling で JSON 引数を出す。
  4. ローカル関数か JSON-RPC tools/call へ分岐する。
  5. 結果 JSON(または MCP content)が会話に戻る。
  6. 再呼び出し、ユーザー確認、最終回答のいずれか。

見落としやすい境界:モデルはデータベース接続を持ちません。出すのは JSON だけです。誰がパースし、どのマシンで実行し、SSH や VNC を使うか、外向き通信を許すかはランタイム方針です。クラウド Mac 上の Agent / MCP Server もプロトコルは同じで、権限平面が違います。

層JSON の役割止めるべき地点
Function Calling一回の関数引数schema、strict、業務検証
Tool Calling共通平面の呼び出し記録並列、承認、trace
MCPプロセスをまたぐ発見と呼び出し伝送、認証、list/call エラー

製品名に引っ張られないでください。一つのアプリ専用なら Function/Tool Calling で足ります。複数ホストで再利用するなら MCP Server の価値が出ます。スキーマも検証も無いまま MCP を足すと、混乱が別プロセスへ移るだけです。

JSON が壊れると Agent 全体が壊れる

  • 合法 JSON でない:strict オフ、先に説明を書けという指示、Markdown フェンス。構造化ツール経路だけを使い、散文から引数を抜かない。
  • パースできるがスキーマ違反:required 欠落、enum 誤り、余分なプロパティ。検証エラーを tool result で返し、再試行回数を制限する。
  • スキーマは通るが業務失敗:注文なし、在庫不足、権限拒否。安定した error code を返す。
  • 再試行で二重書き込み:timeout のあと再呼び出し。idempotency_key と実行側の重複排除。
  • list と call の不一致:名前やスキーマがホットリロードで変わった。名前とスキーマハッシュを版管理し、変更時は initialize し直す。
  • 機密が JSON ログへ:共有 trace にフル引数。フィールド名とハッシュだけ残し、トークンと個人情報を伏せる。

タイムアウト、スキーマ失敗、権限拒否を一つの受入シナリオにしてください。無限再試行や引数の勝手な改変が残るなら、決済・出荷・本番 DB には繋がないでください。

公開前の JSON 契約チェックリスト

  • [ ] 各ツールに name、description、JSON Schema、additionalProperties: false がある。
  • [ ] 高リスク欄は enum / format / 最大長で、自由文字列にしない。
  • [ ] 書き込みは冪等キー付き。timeout と再試行はランタイムに置く。
  • [ ] tool result は ok / error / data。スタック原文は禁止。
  • [ ] 副作用で並列を分ける。決済・メール・削除は原則直列。
  • [ ] MCP の initialize / list / call に timeout、認証、エラーコードがある。
  • [ ] カタログ変更後にホストがスキーマを再取得する。
  • [ ] trace は呼び出し連鎖を復元でき、秘密は復元できない。
  • [ ] 固定入力は同じツール名と同じ必須フィールド集合に当たる。

これが通ってから多 Agent や重いワークフローを検討してください。不安定なプロトコルは壊れた JSON を速く複製するだけです。

FAQ

なぜ自然言語のままプログラムに読ませないのか

必須フィールドも型もありません。「急いで」を列挙値へ安定対応できず、余分なフィールドも拒否できません。JSON Schema はパースを検証に変え、失敗を構造化して返せます。

Function Calling と Tool Calling は実質違うのか

アプリ開発者から見ると「JSON のフォームを埋めてコードが実行する」点は同じです。Tool Calling は検索やコード実行などホストツール、並列呼び出し、統一の結果チャネルが広いです。移行ではスキーマとメッセージ役割を先に揃え、古いフィールド名で止まらないでください。

いつ MCP が必要で、いつ配列直書きで足りるのか

同じツールを複数ホストが使う、別プロセスで隔離する、別チームが配布する、というときに MCP が引き合います。一つの内部サービスと寿命を共にするなら Function/Tool Calling の方が単純です。

たまに壊れた JSON が出る。再試行か、プロトコル変更か

まず厳密な構造化出力を有効化し、散文から引数抽出をやめます。頻度が高ければスキーマの深さ、説明の衝突、ツール数を疑います。MCP に替えても引数は JSON のままなので、根は消えません。

共有ノート PC で Agent を動かしていると、環境が変わるたびにスキーマ回帰が壊れ、MCP プロセスが開発用ポートと衝突します。Kvmjet のベアメタル Mac クラウドなら macOS イメージを固定し、SSH または VNC で同じ Tool Calling / MCP 失敗を再現できます。公開情報では日次から四半期までの課金があり、契約を安定させてから長期利用を決められます。

チェックリストを持って Kvmjet ヘルプセンター で常時稼働、権限分離、遠隔接続を確認し、MCP Server をノート、ラック、クラウド Mac のどこに置くか決めてください。

Tool Calling と MCP を固定 Mac 環境で回す

スキーマ、冪等キー、MCP Server は再現可能なランタイムが前提です。共有ノートではディレクトリとポートがすぐ漂流します。

Kvmjet のベアメタル M4 Mac は本物の macOS と SSH/VNC を備え、同じ tools/call 失敗を何度でも再現できます。

プランを見る →

特別オファー