# Modell-Kontext-Protokoll

Source: https://docs.sisk-framework.org/de/docs/extensions/mcp.html

Es ist möglich, Anwendungen zu erstellen, die Agentenmodellen Kontext mithilfe großer Sprachmodelle (LLMs) bereitstellen, und zwar mit dem Paket [Sisk.ModelContextProtocol](https://www.nuget.org/packages/Sisk.ModelContextProtocol/) :

    dotnet add package Sisk.ModelContextProtocol --prerelease

Dieses Paket stellt nützliche Klassen und Methoden zum Aufbau von MCP‑Servern bereit, die über [Streamable HTTP](https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/streamable-http) arbeiten und einzelne Anfrage‑/Antwort‑Nachrichten unterstützen. Seit Version 1.7.0‑rc1 unterstützt es zustandslose Anfragen der Protokollversion `2026-07-28` und behält den Legacy‑Initialisierungsablauf für Clients bei, die die Versionen `2025-11-25`, `2025-06-18` und `2025-03-26` verwenden. Es unterstützt Werkzeuge und Skills.

> [!NOTE]
>
> Bevor Sie beginnen, beachten Sie bitte, dass dieses Paket sich noch in der Entwicklung befindet und Verhaltensweisen zeigen kann, die nicht der Spezifikation entsprechen. Lesen Sie die [Paketdetails](https://github.com/sisk-http/core/tree/main/extensions/Sisk.ModelContextProtocol), um zu erfahren, was sich noch in Entwicklung befindet und was noch nicht funktioniert.

## Erste Schritte mit MCP

Die Klasse [McpProvider](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpProvider.md) ist der Einstiegspunkt zur Definition eines MCP‑Servers. Es handelt sich um ein versiegeltes Provider‑Objekt, das beim Start konfiguriert werden kann. Ihre Sisk‑Anwendung kann einen oder mehrere MCP‑Provider besitzen.

```csharp
McpProvider mcp = new McpProvider(
    serverName: "math-server",
    serverTitle: "Mathematics server",
    serverVersion: new Version(1, 0));

mcp.Tools.Add(new McpTool(
    name: "math_sum",
    description: "Sums one or more numbers.",
    schema: JsonSchema.CreateObjectSchema(
        properties: new Dictionary<string, JsonSchema>()
        {
            { "numbers",
                JsonSchema.CreateArraySchema(
                    itemsSchema: JsonSchema.CreateNumberSchema(),
                    minItems: 1,
                    description: "The numbers to sum.")
            }
        },
        requiredProperties: ["numbers"]),
    executionHandler: async (McpToolContext context) =>
    {
        var numbers = context.Arguments["numbers"].GetJsonArray().ToArray<double>();
        var sum = numbers.Sum();
        return await Task.FromResult(McpToolResult.CreateText($"Sum result: {sum:N4}"));
    }));
```

Wenn Ihre Anwendung nur einen MCP‑Provider bereitstellt, können Sie das Singleton des Builders verwenden:

```csharp
static void Main(string[] args)
{
    using var host = HttpServer.CreateBuilder()
        .UseMcp(mcp =>
        {
            mcp.ServerName = "math-server";
            mcp.ServerTitle = "Mathematics server";

            mcp.Tools.Add(new McpTool(
                name: "math_sum",
                description: "Sums one or more numbers.",
                schema: JsonSchema.CreateObjectSchema(
                    properties: new Dictionary<string, JsonSchema>()
                    {
                        { "numbers",
                            JsonSchema.CreateArraySchema(
                                itemsSchema: JsonSchema.CreateNumberSchema(),
                                minItems: 1,
                                description: "The numbers to sum.")
                        }
                    },
                    requiredProperties: ["numbers"]),
                executionHandler: async (McpToolContext context) =>
                {
                    var numbers = context.Arguments["numbers"].GetJsonArray().ToArray<double>();
                    var sum = numbers.Sum();
                    return await Task.FromResult(McpToolResult.CreateText($"Sum result: {sum:N4}"));
                }));
        })
        .UseRouter(router =>
        {
            router.MapAny("/mcp", async (HttpRequest req) =>
            {
                return await req.HandleMcpRequestAsync();
            });
        })
        .Build();

    host.Start();
}
```

Der Endpunkt muss sowohl `GET`‑ als auch `POST`‑Anfragen akzeptieren, daher ist `MapAny` die einfachste Routen‑Zuordnung. `HandleMcpRequestAsync` gibt eine [HttpResponse](https://docs.sisk-framework.org/api/Sisk.Core.Http.HttpResponse.md) zurück, und Ihre Route muss diese zurückgeben. Wenn Sie mehrere Provider in einer Anwendung benötigen, überspringen Sie das Singleton und rufen Sie [McpProvider.HandleRequestAsync](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpProvider.HandleRequestAsync.md) direkt aus jeder Route auf:

```csharp
var mathProvider = new McpProvider("math-server", "Mathematics server", new Version(1, 0));

router.MapAny("/mcp/math", async request =>
{
    return await mathProvider.HandleRequestAsync(request);
});
```

## Erstellen von JSON-Schemas für Funktionen

Die Bibliothek [Sisk.ModelContextProtocol] verwendet einen Fork von [LightJson](https://github.com/CypherPotato/LightJson) für die Manipulation von JSON und JSON‑Schemas. Diese Implementierung bietet einen fluenten JSON‑Schema‑Builder für verschiedene Objekte:

- JsonSchema.CreateObjectSchema
- JsonSchema.CreateArraySchema
- JsonSchema.CreateBooleanSchema
- JsonSchema.CreateNumberSchema
- JsonSchema.CreateStringSchema
- JsonSchema.Empty

Beispiel:

```csharp
JsonSchema.CreateObjectSchema(
    properties: new Dictionary<string, JsonSchema>()
    {
        { "numbers",
            JsonSchema.CreateArraySchema(
                itemsSchema: JsonSchema.CreateNumberSchema(),
                minItems: 1,
                description: "The numbers to sum.")
        }
    },
    requiredProperties: ["numbers"]);
```

Erzeugt das folgende Schema:

```json
{
  "type": "object",
  "properties": {
    "numbers": {
      "type": "array",
      "items": {
        "type": "number"
      },
      "minItems": 1,
      "description": "The numbers to sum."
    }
  },
  "required": ["numbers"]
}
```

## Umgang mit Funktionsaufrufen

Die im Parameter `executionHandler` von [McpTool](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpTool.md) definierte Funktion liefert ein JsonObject, das die Aufrufargumente enthält und das fluently gelesen werden kann:

```csharp
mcp.Tools.Add(new McpTool(
    name: "browser_do_action",
    description: "Run an browser action, such as scrolling, refreshing or navigating.",
    schema: JsonSchema.CreateObjectSchema(
        properties: new Dictionary<string, JsonSchema>()
        {
            { "action_name",
                JsonSchema.CreateStringSchema(
                    enums: ["go_back", "refresh", "scroll_bottom", "scroll_top"],
                    description: "The action name.")
            },
            { "action_data",
                JsonSchema.CreateStringSchema(
                    description: "Action parameter."
                ) }
        },
        requiredProperties: ["action_name"]),
    executionHandler: async (McpToolContext context) =>
    {
        // Lese den Aktionsnamen. Wirft eine Ausnahme, wenn null oder kein expliziter String
        string actionName = context.Arguments["action_name"].GetString();
        
        // action_data ist als nicht erforderlich definiert, daher kann es hier null sein
        string? actionData = context.Arguments["action_data"].MaybeNull()?.GetString();
        
        // Verarbeite die Browseraktion basierend auf dem actionName
        return await Task.FromResult(
            McpToolResult.CreateText($"Performed browser action: {actionName}"));
    }));
```

Tool‑Argumente werden vor dem Aufruf Ihres Handlers anhand des Schemas validiert. Bei einer fehlgeschlagenen Validierung gibt der Provider ein Fehl­ergebnis an den MCP‑Client zurück und ruft den Tool‑Handler nicht auf.

## Funktionsresultate

Das Objekt [McpToolResult](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpToolResult.md) stellt drei Methoden zum Erzeugen von Inhalten für eine Tool‑Antwort bereit:

- [CreateAudio(ReadOnlySpan<byte>, string)](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpToolResult.CreateAudio.md): erstellt eine audio‑basierte Antwort für den MCP‑Client.
- [CreateImage(ReadOnlySpan<byte>, string)](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpToolResult.CreateImage.md): erstellt eine bild‑basierte Antwort für den MCP‑Client.
- [CreateText(string)](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpToolResult.CreateText.md): erstellt eine text‑basierte Antwort (Standard) für den MCP‑Client.

Zusätzlich ist es möglich, mehrere unterschiedliche Inhalte zu einer einzigen JSON‑Tool‑Antwort zu kombinieren:

```csharp
mcp.Tools.Add(new McpTool(
    ...
    executionHandler: async (McpToolContext context) =>
    {
        // simulate real work

        byte[] browserScreenshot = await browser.ScreenshotAsync();
        
        return McpToolResult.Combine(
            McpToolResult.CreateText("Heres the screenshot of the browser:"),
            McpToolResult.CreateImage(browserScreenshot, "image/png")
        )
    }));
```

Der Provider unterstützt derzeit `server/discover`, die Legacy‑Methoden `initialize` und `ping`, `tools/list`, `tools/call`, `skills/list`, `skills/get`, `resources/list`, `resources/read` sowie Benachrichtigungen. Nicht unterstützte JSON‑RPC‑Methoden liefern eine JSON‑RPC‑Fehlerantwort.

## Veröffentlichen von Skills

Ein MCP‑Provider kann außerdem [Agent Skills](https://github.com/modelcontextprotocol/ext-skills) über die Erweiterung `io.modelcontextprotocol/skills` veröffentlichen. Fügen Sie [McpSkill](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpSkill.md)-Objekte zu [McpProvider.Skills](https://docs.sisk-framework.org/api/Sisk.ModelContextProtocol.McpProvider.Skills.md) hinzu, bevor der Provider beginnt, Anfragen zu bearbeiten:

```csharp
mcp.Skills.Add(new McpSkill(
    path: "acme/refunds",
    frontmatter: new JsonObject
    {
        ["name"] = "refunds",
        ["description"] = "Follow the refund workflow."
    },
    body: "# Refunds\nRead references/policy.md before using the refund tools.",
    files: new Dictionary<string, byte[]>
    {
        ["references/policy.md"] = File.ReadAllBytes("skills/refunds/references/policy.md")
    }));
```

`McpSkill` erzeugt die Datei `SKILL.md` aus dem Frontmatter und dem Markdown‑Body. Das letzte Segment von `path` muss dem Feld `name` im Frontmatter entsprechen. Die Skill‑Dateien werden beim Erstellen des Skills kopiert und vom Provider nie wieder von der Festplatte gelesen. Clients listen und lesen Skills mit `skills/list`, `skills/get` und `resources/read` unter Verwendung der Protokollversion `2026-07-28`. Siehe die [Paketdetails](https://github.com/sisk-http/core/tree/main/extensions/Sisk.ModelContextProtocol) für Limits und Validierungsregeln.

## Weiterführende Arbeit

Das Model Context Protocol ist ein Kommunikationsprotokoll für Agentenmodelle und Anwendungen, die Inhalte für diese bereitstellen. Es ist ein neues Protokoll, sodass seine Spezifikation häufig mit Deprecations, neuen Features und Breaking Changes aktualisiert wird.

Es ist entscheidend, die Probleme zu verstehen, die das [Model Context Protocol](https://modelcontextprotocol.io/docs/getting-started/intro) löst, bevor Sie mit dem Bau von Agenten‑Anwendungen beginnen.

Lesen Sie außerdem die Spezifikation des [Sisk.ModelContextProtocol](https://github.com/sisk-http/core/tree/main/extensions/Sisk.ModelContextProtocol)-Pakets, um dessen Fortschritt, Status und mögliche Anwendungsbereiche zu verstehen.
