ChatGPTとClaudeの中でDelphiアプリを動かす

· コンポーネント
ChatGPTとClaudeの中でDelphiアプリを動かす

M C Pサーバーは、アシスタントがあなたのコードを呼び出せるようにします。しかし、これまで一度もできなかったのは、何かを見せることです。アシスタントが尋ね、あなたのツールがテキストで答え、ユーザーは段落を読みます。sgcWebSockets 2026.10はsgcHTMLにMCP Appsを追加し、ツールが代わりにページで応答できるようにします。アシスタントがそれをレンダリングし、ユーザーがその中でクリックし、そのクリックがあなたのDelphiアプリケーションに返ってきます。

このページは、他のすべてのページが使うのと同じsgcHTMLコンポーネントで構築されています。JavaScriptフレームワークも、独立したフロントエンドも、二つ目のコードベースも必要ありません。

ページで応答するツール

MCP Appは三つの要素から成ります。モデルが呼び出せるツール、ページを運ぶリソース、そして両者の意味を決めるイベントです。TsgcHTMLComponent_MCPAppは、すでにあるMCPサーバー上にこのすべてを宣言します。

uses
  sgcAI, sgcHTML_MCPApp;

FMCP := TsgcWSAPIServer_MCP.Create(nil);
FMCP.Server := FHTTPServer;
FMCP.EndpointOptions.Endpoint := '/mcp';

FApps := TsgcHTMLComponent_MCPApp.Create(nil);
FApps.MCPServer := FMCP.MCPServer;
FApps.OnRender := DoRender;
FApps.OnToolCall := DoToolCall;
FApps.OnFragment := DoFragment;

with FApps.Apps.Add do
begin
  ToolName := 'orders.board';
  Title := 'Orders board';
  Description := 'Shows the orders of the company as a board ' +
    'that can be filtered by status.';
  InputSchema.Text := '{"type":"object","properties":{"status":' +
    '{"type":"string","description":"open, shipped or closed"}}}';
end;

FApps.RegisterApps;

必要な登録作業はこれだけです。このコンポーネントは、ユーザーインターフェイスを持つことをホストに伝えるメタデータとともにツールを宣言し、ホストがページを取得するために読み取るリソースを宣言し、ページ自体が使う付随ツールを宣言します。

モデルが読むもの、ユーザーが見るもの

ツールの結果には二つの側面があり、それぞれ異なる相手に向けたものです。OnToolCallは両方を書き込みます。モデルが推論するための一文と、ページが読み取る構造化されたコンテンツです。

procedure TMyLogic.DoToolCall(Sender: TObject; aApp: TsgcHTMLMCPApp;
  const aArguments: string; var aText, aStructured: string);
begin
  aText := Format('%d open orders, %s in total.', [vCount, vTotal]);
  aStructured := '{"orders":' + IntToStr(vCount) + '}';
end;

OnRenderはページそのものを返します。それは普通のsgcHTMLです。カード、テーブル、いくつかのボタン。アシスタント専用のものは何もありません。

サーバーがない場所でも動くボタン

ここが普通なら壊れる部分です。ページは自身のネットワークを持たないサンドボックス化されたiframeの中で動作するため、hx-getには到達先がありません。sgcHTMLは、htmx拡張を登録するブリッジでこれを解決します。ページ上のすべてのhx-gethx-postは付随ツールの呼び出しになり、返ってきたマークアップは、htmxがHTTPレスポンスを差し替えるのとまったく同じように差し替えられます。

procedure TMyLogic.DoFragment(Sender: TObject; aApp: TsgcHTMLMCPApp;
  const aTarget, aArguments: string; var aHTML: string);
begin
  { aTarget is what the element asked for, for instance orders?status=open }
  if StartsText('orders', aTarget) then
    aHTML := BuildOrdersTable(StatusOf(aTarget));
end;

HTTP経由で提供される同じマークアップは、普通のhtmxリクエストです。ページは一度書けば、両方の場所で動作します。

一つのドキュメント、何もリンクされていない

フレームにはネットワークがないため、ドキュメントはすべてを運びます。ページ、スタイルシート、スクリプト、そしてブリッジが一つのファイルにまとまっています。ページテンプレートの新しいInlineAssetsオプションがこれを行い、MCP Appsではデフォルトで有効になっています。典型的なアプリのドキュメントは約360KBで、レンダリングに他には何も必要としません。

ホストには、PreferredWidthPreferredHeightを通じてフレームをどのサイズで開くかも伝えられ、ページはコンテンツが変わるたびに自身の高さを報告します。

アシスタントをインストールせずに見ることができる

新しいデモ19.MCPAppは、ポート5725で動作し二つのアプリを公開するコンソールサーバーで、独自のリファレンスホストも備えています。http://localhost:5725/ を開くと、左側のパネルがモデルの役割を果たします。ツールを呼び出し、リソースを読み取り、サンドボックス化されたフレームの中でレンダリングし、ハンドシェイクに応答し、ページが求めればフレームのサイズを変更し、ページが呼び出す内容を転送します。その下のログには、双方向のすべてのメッセージが表示されます。

本物を試したいときは、Claude、ChatGPT、VS Codeを http://localhost:5725/mcp に向けてください。ツールとリソースはすでにそこに宣言されています。

これではないもの

このコンポーネントは状態を一切保持しません。誰がツールを呼び出せるか、レコードが何を意味するか、フラグメントリクエストが何を返してよいかは、Webアプリケーションのルートと同じように、あなたのアプリケーション自身が決めることです。そしてページは何も密輸できません。モデルがトリガーできるのは、あなたが登録したツールであり、あなたが構築したマークアップで応答するだけです。

アップグレード

MCP AppsはsgcHTMLの一部であり、SGC_AI_MCP、つまりEnterpriseエディションとAll-Accessエディション、そしてsgcAIパックを必要とします。既存のMCPサーバーには何も変わりません。このコンポーネントはすでにあるサーバーに接続し、すでに公開しているツールにはそのまま手を触れません。

次に読む

動画で見る

この内容についての短い動画eSeGeCeチャンネルにあります。

質問、フィードバック、移行のお手伝いが必要ですか?お問い合わせください — コードを書いた本人たちから返信が届きます。