MCP Fusion/Protocol and runtime/ワイヤー形式

ワイヤー形式

VinkiusについてAIに質問

Presenter が送信する正確なバイト列:順序立ったテキストブロック、ui_passthrough XML、ドメインルール、アクションの提案、_select のギロチン、embeds と TOON。

Presenter を使った tool call は JSON.stringify の結果を返しませんが、順序立ったテキストブロックの列を返します。各ブロックは、エージェント(およびクライアント側の UI)が解釈できる安定した形状を持っています。このページはそのフォーマットの仕様です。

ブロックのシーケンス

ResponseBuilder.build() は最大 6 つのブロックを、必ずこの順番で出力します:

#ブロック形状
1dataマスクしてシリアライズしたペイロード(JSON テキスト)
2UI blocksブロックごとに <ui_passthrough> 1 個
3embeds子 Presenter からの生ブロック
4directives<llm_directives> のリスト
5rules<domain_rules> のリスト
6suggestions<action_suggestions> のリスト

UI ブロックはワイヤー上でこのようになります:

xml
<ui_passthrough type="echarts" title="Revenue by month" width="full" priority="1">
  echarts-fenced-content: the chart config as formatted JSON
</ui_passthrough>

typetitlewidthfullhalfthird)、priority 属性は、クライアント側のレンダラーにフェンス内コンテンツが何かを伝えます。ui.tableui.list は markdown、ui.json は fenced json、ui.codeBlock は言語タグを保持します。ネイティブのテーブルブロック型は存在しません。フェンスこそが契約であり、MCP が UI ブロックを標準化した場合に変わるのは fence() のただ 1 か所です。

ルールと提案のブロックはシンプルな箇条書きです:

xml
<domain_rules>
- amount_cents is in CENTS. Divide by 100.
</domain_rules>
<action_suggestions>
- billing.remind: Send a payment reminder
</action_suggestions>

structuredContent は別系統の仕組み

MCP 2.0 の structuredContent フィールドは Presenter が生成するものではありません。出力するには successStructured(data) を使い、MCP 1.0 クライアント向けの JSON テキストブロックに加え、機械可読な structuredContent フィールドも送信してください。.withOutputSchema(schema) でワイヤー上の形状も宣言します。Presenter は人間と LLM 向けのテキストを担当し、successStructured はパース済みオブジェクトのチャネルを担当します。この 2 つを取り違えないでください。

_select:フィールドのギロチン

.enableSelect() は tool のすべてのアクションに配列パラメーター _select を追加します。その enum は、全アクションにわたるスキーマのルートキーの和集合です。エージェントが _select を渡すと、data ブロックはそのキーに絞られます。それ以外(UI ブロック、ルール、提案)は引き続き完全なオブジェクトに対して処理されるため、人間向けにレスポンスを描画するクライアントは全体を眺められ、モデルのコンテキストには要求された分だけが届きます。これは広いモデルで最も安大なトークン節約であり、ビルダー単位の opt-in です。

embed:リレーショナルな合成

.embed('lines', InvoiceLinesPresenter)data.lines を子 Presenter 経由で読み、そのブロックとルールを親のレスポンスにマージします。親が所有するのは 1 つのエンティティです。エンティティのグラフは Presenter のツリーとなり、各自が独自のスキーマ、マスキング、制限を持ちます。

TOON:説明をトークン半分で

.toonDescription()toonSuccess(data) は、統一されたコレクションにパイプ区切りの TOON 形式を使います。繰り返しのキーは 1 行のヘッダーに折りたたまれ、配列は値のテーブルになります。同じ形状のアイテム 1 万件のリストでは、トークン数はおよそ半分です。この形式はアクションのスキーマから生成されるため、エージェントは action|desc|required を第一層、データを第二層として目にします。

テスト用の裏口

Presenter のレスポンスには、{ data, systemRules, uiBlocks } を持つ non-enumerable な symbol が含まれます。@mcpfusion/testing は XML を逆パースするのではなく、この symbol 経由で構造化ビューを読み取ります。だからこそ Testingresult.dataresult.systemRulesresult.uiBlocks は正確です。JSON.stringify はこの symbol を決して見ません。

暗黙のラップルール

handler の戻り値は 1 つのルールで解釈されます。ブランド付きの ToolResponse オブジェクトはそのまま通過し、それ以外はすべて success(data) としてラップされます。nullundefined の戻り値はテキスト OK になります。だからこそ、{ content: [...] } の形を手作業で組み立てる必要はなく、Presenter を追加しても handler に触れることは一切ありません。

次のステップ

  • Errors<tool_error> エンベロープ。フォーマットのもう半分
  • Models and Presenters:形状を構築する
  • Testing:ブロックに対するアサーション