MCPApp

TsgcHTMLComponent_MCPApp : un outil MCP qui répond par une page au lieu de texte, de sorte que les mêmes composants Delphi qui produisent n'importe quelle page web s'affichent dans ChatGPT, Claude et VS Code (MCP Apps).

TsgcHTMLComponent_MCPApp

Une MCP App est un outil dont l'hôte affiche le résultat au lieu de simplement le lire. Le composant publie l'outil, la ressource qui porte la page et un outil compagnon que la page appelle elle-même, sur le serveur MCP que vous avez déjà, et la page est construite avec les mêmes composants sgcHTML que toute autre. Il requiert l'édition Enterprise ou All-Access de sgcWebSockets, ou le pack sgcAI, car il s'exécute sur le serveur MCP.

Classe du composant

TsgcHTMLComponent_MCPApp, avec la collection TsgcHTMLMCPApps d'éléments TsgcHTMLMCPApp

Produit

Un document HTML que l'hôte affiche dans un cadre isolé (sandbox), avec ses ressources intégrées

Famille

Chat & IA

Langages

Delphi, C++ Builder, .NET

Déclarez une application, répondez à trois événements

Donnez au composant le MCPServer d'un TsgcWSAPIServer_MCP, ajoutez une application avec un nom d'outil et une description, répondez à OnRender, OnToolCall et OnFragment, puis appelez RegisterApps.

uses
  Classes, SysUtils, StrUtils,
  // sgc
  sgcWebSocket_Server, sgcAI, sgcHTML_Nodes, sgcHTML_Nodes_Bootstrap,
  sgcHTML_MCPApp;

// The MCP endpoint a host connects to
FMCP := TsgcWSAPIServer_MCP.Create(nil);
FMCP.Server := FHTTPServer;
FMCP.EndpointOptions.Endpoint := '/mcp';

// The apps, declared on the MCP server the endpoint owns
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"}}}';
  PreferredWidth := 720;
  PreferredHeight := 460;
end;
FApps.RegisterApps;   // the tool, the fragment tool and the resource

// What the model reads, and what the page reads
procedure TMyLogic.DoToolCall(Sender: TObject; aApp: TsgcHTMLMCPApp;
  const aArguments: string; var aText, aStructured: string);
begin
  aText := '3 open orders, 1420.50 in total.';
  aStructured := '{"orders":3,"total":1420.5}';
end;

// The page: ordinary sgcHTML components
procedure TMyLogic.DoRender(Sender: TObject; aApp: TsgcHTMLMCPApp;
  const aArguments: string; var aHTML: string);
var
  oCard: TsgcHTMLCard;
  oButton: TsgcHTMLContainer;
begin
  oCard := TsgcHTMLCard.Create;
  try
    oCard.Body.Add(TsgcHTMLHeading.Create('Orders', 5));

    oButton := TsgcHTMLContainer.Create('button');
    oButton.CSSClass := 'btn btn-outline-secondary';
    // inside a host, the bridge turns this hx-get into a call of the fragment tool
    oButton.Attributes := 'type="button" hx-get="orders?status=open" ' +
      'hx-target="#orders" hx-swap="outerHTML"';
    oButton.AddText('Open');
    oCard.Body.Add(oButton);

    oCard.Body.AddRaw(BuildOrdersTable(''));   // your markup: the element whose id is orders
    aHTML := oCard.HTML;
  finally
    oCard.Free;
  end;
end;

// The markup a control of the page asked for
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;
// includes: sgcAI.hpp, sgcHTML_MCPApp.hpp

// The MCP endpoint a host connects to
FMCP = new TsgcWSAPIServer_MCP(NULL);
FMCP->Server = FHTTP;
FMCP->EndpointOptions->Endpoint = "/mcp";

// The apps, declared on the MCP server the endpoint owns
FApps = new TsgcHTMLComponent_MCPApp(NULL);
FApps->MCPServer = FMCP->MCPServer;
FApps->OnRender = DoRender;
FApps->OnToolCall = DoToolCall;
FApps->OnFragment = DoFragment;

TsgcHTMLMCPApp *app = FApps->Apps->Add();
app->ToolName = "orders.board";
app->Title = "Orders board";
app->Description = "Shows the orders of the company as a board that can be filtered by status.";
app->InputSchema->Text = "{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"}}}";
app->PreferredWidth = 720;
app->PreferredHeight = 460;
FApps->RegisterApps();   // the tool, the fragment tool and the resource

// What the model reads, and what the page reads
void __fastcall TMyLogic::DoToolCall(TObject *Sender, TsgcHTMLMCPApp *aApp,
  const String aArguments, String &aText, String &aStructured)
{
  aText = "3 open orders, 1420.50 in total.";
  aStructured = "{\"orders\":3,\"total\":1420.5}";
}

// The markup a control of the page asked for
void __fastcall TMyLogic::DoFragment(TObject *Sender, TsgcHTMLMCPApp *aApp,
  const String aTarget, const String aArguments, String &aHTML)
{
  // aTarget is what the element asked for, for instance orders?status=open
  if (aTarget.Pos("orders") == 1)
    aHTML = BuildOrdersTable(StatusOf(aTarget));
}

// DoRender answers the page with sgcHTML components, as in the Delphi tab.
using esegece.sgcWebSockets;

// An MCP server over stdio, for a host that starts your program as a process
var host = new TsgcAI_MCP_Server_Stdio();

var apps = new TsgcHTMLComponent_MCPApp();
apps.MCPServer = host.MCPServer;

var app = apps.Apps.Add();
app.ToolName = "orders.board";
app.Title = "Orders board";
app.Description = "Shows the orders of the company as a board that can be filtered by status.";
app.InputSchema.Add("{\"type\":\"object\",\"properties\":{\"status\":{\"type\":\"string\"}}}");
app.PreferredWidth = 720;
app.PreferredHeight = 460;

// What the model reads, and what the page reads
apps.OnToolCall += (object sender, TsgcHTMLMCPApp a, string args,
    ref string text, ref string structured) =>
{
    text = "3 open orders, 1420.50 in total.";
    structured = "{\"orders\":3,\"total\":1420.5}";
};

// The page: ordinary sgcHTML components
apps.OnRender += (object sender, TsgcHTMLMCPApp a, string args, ref string html) =>
{
    var card = new TsgcHTMLCard();
    card.Body.Add(new TsgcHTMLHeading("Orders", 5));

    var button = new TsgcHTMLContainer("button");
    button.CSSClass = "btn btn-outline-secondary";
    // inside a host, the bridge turns this hx-get into a call of the fragment tool
    button.Attributes = "type=\"button\" hx-get=\"orders?status=open\" "
        + "hx-target=\"#orders\" hx-swap=\"outerHTML\"";
    button.AddText("Open");
    card.Body.Add(button);

    card.Body.AddRaw(BuildOrdersTable(""));   // your markup: the element whose id is orders
    html = card.HTML;
};

// The markup a control of the page asked for
apps.OnFragment += (object sender, TsgcHTMLMCPApp a, string target,
    string args, ref string html) =>
{
    // target is what the element asked for, for instance orders?status=open
    if (target.StartsWith("orders"))
        html = BuildOrdersTable(StatusOf(target));
};

apps.RegisterApps();   // the tool, the fragment tool and the resource
host.Run();

Propriétés & méthodes clés

Les membres que vous utilisez le plus souvent.

Applications

Apps est une collection TsgcHTMLMCPApps d'éléments TsgcHTMLMCPApp. ToolName est obligatoire : une application qui n'en a pas n'enregistre rien. Description est ce que le modèle lit pour décider s'il doit appeler l'outil, et InputSchema est le schéma JSON de ses arguments. Title, ResourceURI, PageBuilder, Enabled, PreferredWidth et PreferredHeight complètent une application, les deux derniers étant la taille à laquelle l'hôte est invité à ouvrir le cadre.

Ce que RegisterApps déclare

Trois éléments par application sur le serveur : l'outil, nommé par ToolName, dont _meta.ui.resourceUri indique à l'hôte quelle ressource porte la page ; l'outil compagnon <ToolName>.fragment, que la page appelle et que le modèle n'appelle jamais ; et la ressource ui://sgchtml/<toolname>, servie en text/html;profile=mcp-app. En Delphi, RegisterApps s'exécute depuis Loaded et le code qui ajoute une application l'appelle de nouveau ; en .NET, appelez-le vous-même. UnregisterApps les supprime.

Les deux moitiés d'un résultat

Un résultat d'outil a deux destinataires. Dans OnToolCall, aText est la phrase que lit le modèle et aStructured le JSON que lit la page. Les deux sont facultatifs, et lorsque le texte est vide, le Title de l'application est utilisé. Répondez aux deux quand ils diffèrent, ce qui est généralement le cas : le modèle veut une phrase et la page veut des chiffres.

La page

OnRender répond avec la page sous forme de balisage sgcHTML ordinaire. aHTML arrive contenant la page que construit le PageBuilder de l'application, s'il y en a un d'affecté, de sorte qu'un gestionnaire peut la remplacer ou la laisser. GetAppHTML renvoie le document complet d'une application, c'est ce que la ressource renvoie et ce que lit un test.

Fragments et pont

Un cadre isolé n'a aucun serveur HTTP pour répondre à un hx-get. Chaque document embarque window.sgcMCPApp : il envoie ui/initialize quand la page est prête, applique le thème avec lequel l'hôte répond, signale la hauteur de la page pour que l'hôte puisse dimensionner le cadre, et enregistre une extension htmx qui transforme chaque hx-get et hx-post en un tools/call de l'outil de fragment. OnFragment y répond : aTarget est ce que l'élément a demandé, aArguments le JSON du formulaire ou de la chaîne de requête, et aHTML le balisage inséré. Le même balisage servi en HTTP est une requête htmx ordinaire.

Un seul document

Le cadre est isolé et n'a généralement pas de réseau propre, donc rien ne peut être référencé par un lien. InlineAssets est activé par défaut et fait voyager la feuille de style, les scripts et la page dans un seul fichier. Ne le désactivez que pour un hôte situé sur la même machine et capable de servir les ressources.

Le serveur MCP

MCPServer est le TsgcAI_MCP_Server sur lequel les applications sont déclarées. TsgcWSAPIServer_MCP l'expose comme propriété publique, de sorte que FApps.MCPServer := FMCP.MCPServer place les applications sur le point de terminaison d'un serveur web. Le composant s'abonne aux événements d'outil et de ressource et chaîne les gestionnaires qui s'y trouvaient, de sorte que les outils que vous publiez déjà continuent de fonctionner. Un hôte qui gère lui-même ces événements appelle ProcessToolsCall et ProcessResourcesRead, qui répondent False lorsque la requête n'était pas celle d'une application. En .NET, donnez-lui le TsgcAI_MCP_Server que vous avez, par exemple celui que possède TsgcAI_MCP_Server_Stdio.

Aucun état

Le composant ne conserve aucun état propre. Ce que signifie un appel d'outil, qui peut l'appeler et ce qu'une requête de fragment peut renvoyer sont des décisions de votre application, exactement comme pour une route d'une application web. Ce que le modèle peut déclencher est un outil que vous avez enregistré, qui répond avec un balisage que vous avez construit.

Le voir sans assistant

Demos\60.HTML\01.RunTime\19.MCPApp est un serveur console sur le port 5725 qui publie deux applications, orders.board et sales.summary, sur un même point de terminaison, et fournit un hôte de référence. Ouvrez http://localhost:5725/ et le panneau de gauche fait ce que fait un vrai hôte : il appelle l'outil, lit la ressource, l'affiche dans un cadre isolé et transmet les appels de la page. Pointez Claude, ChatGPT ou VS Code vers http://localhost:5725/mcp pour l'essayer en conditions réelles.

Disponibilité

L'unité se compile là où SGC_HTML et SGC_AI_MCP sont tous deux définis. SGC_AI_MCP est fourni avec les éditions Enterprise et All-Access et avec le pack sgcAI. SGC_HTML est fourni avec sgcHTML, qui est vendu indépendamment de sgcWebSockets, sur toutes les plateformes sauf Android et iOS.

Continuez l'exploration

Aide en ligneGuide d'utilisation des MCP Apps : l'outil, la ressource, l'outil de fragment et le pont.
Tous les composants sgcHTMLParcourez la matrice complète des fonctionnalités de plus de 80 composants.
Télécharger la version d'essai gratuiteLa version d'essai de 30 jours fournit les projets de démonstration 60.HTML.
TarifsLicences Single, Team et Site avec code source complet.
Meilleur rapport qualité-prix : All-AccessTous les produits eSeGeCe, Support Premium inclus, à partir de €1,059/an.
Voir les tarifs All-Access

Prêt à démarrer ?

Téléchargez la version d'essai gratuite et commencez à créer des interfaces web en Delphi, C++ Builder et .NET.