feat: LehrerApp.McpBridge zu resilientem MCP-Proxy umgebaut
Claude Desktop deaktivierte den ganzen MCP-Server, sobald der Initialize-Handshake beim Bridge-Start fehlschlug - der Regelfall, wenn LehrerApp.Desktop (z.B. nach Windows-Autostart von Claude Desktop) noch nicht läuft. Die Bridge ist jetzt selbst ein MCP-Server gegenüber Claude Desktop und gleichzeitig ein MCP-Client gegenüber dem echten Server in LehrerApp.Desktop: der Handshake gelingt dadurch immer. Verbunden spiegelt sie die echte Werkzeugliste 1:1; ohne Verbindung bietet sie nur ein lehrerapp_status-Werkzeug an, das den Grund erklärt und erneut verbindet. Ein Hintergrund-Loop versucht unabhängig davon alle 5s zu reconnecten und schaltet per notifications/tools/list_changed automatisch auf die echten Werkzeuge um, sobald LehrerApp erreichbar ist. Bricht die Verbindung während eines laufenden Aufrufs ab, kommt ein normales Tool-Fehlerergebnis statt eines Prozessabsturzes zurück. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
using System.Text.Json;
|
||||
using ModelContextProtocol.Protocol;
|
||||
using ModelContextProtocol.Server;
|
||||
|
||||
namespace LehrerApp.McpBridge;
|
||||
|
||||
/// <summary>
|
||||
/// Einziges Werkzeug, das die Bridge anbietet, solange keine Verbindung zu LehrerApp besteht (siehe
|
||||
/// <see cref="RealServerBridge"/>). Ohne dieses Werkzeug hätte ein KI-Client keine Möglichkeit zu
|
||||
/// erfahren, WARUM gerade keine LehrerApp-Werkzeuge da sind, sondern sähe nur eine leere
|
||||
/// Werkzeugliste - der Assistent könnte dem Nutzer dann nicht erklären, dass LehrerApp erst
|
||||
/// gestartet werden muss. Versucht bei jedem Aufruf aktiv erneut zu verbinden; klappt das, ersetzt
|
||||
/// <see cref="RealServerBridge"/> dieses Werkzeug automatisch durch die echte Werkzeugliste, und der
|
||||
/// Client wird per "notifications/tools/list_changed" benachrichtigt (siehe
|
||||
/// <see cref="McpServerPrimitiveCollection{T}"/>).
|
||||
/// </summary>
|
||||
internal sealed class StatusMcpServerTool(RealServerBridge bridge) : McpServerTool
|
||||
{
|
||||
public override Tool ProtocolTool { get; } = new()
|
||||
{
|
||||
Name = "lehrerapp_status",
|
||||
Description = "Prüft, ob LehrerApp erreichbar ist, und versucht bei Bedarf erneut zu " +
|
||||
"verbinden. Solange keine Verbindung besteht, sind alle anderen LehrerApp-Werkzeuge " +
|
||||
"(Schüler, Noten, Stundenplanung, Kompetenzen, ...) nicht verfügbar - sie erscheinen erst " +
|
||||
"nach einer erfolgreichen Verbindung in der Werkzeugliste. Bei einer Fehlermeldung eines " +
|
||||
"anderen LehrerApp-Werkzeugs, die auf eine fehlende Verbindung hindeutet, dieses Werkzeug " +
|
||||
"aufrufen, um den Grund zu klären, statt den Nutzer ohne Erklärung zu vertrösten.",
|
||||
InputSchema = JsonDocument.Parse("""{"type":"object","properties":{}}""").RootElement,
|
||||
};
|
||||
public override IReadOnlyList<object> Metadata { get; } = [];
|
||||
|
||||
public override async ValueTask<CallToolResult> InvokeAsync(
|
||||
RequestContext<CallToolRequestParams> request, CancellationToken cancellationToken)
|
||||
{
|
||||
var connected = await bridge.TryReconnectAsync(cancellationToken);
|
||||
return new CallToolResult
|
||||
{
|
||||
Content =
|
||||
[
|
||||
new TextContentBlock
|
||||
{
|
||||
Text = connected
|
||||
? "Verbindung zu LehrerApp hergestellt. Die eigentlichen LehrerApp-Werkzeuge " +
|
||||
"sind jetzt verfügbar."
|
||||
: "LehrerApp läuft nicht oder der MCP-Server ist in den Einstellungen nicht " +
|
||||
"aktiviert. Bitte den Nutzer bitten, LehrerApp zu starten und den " +
|
||||
"MCP-Server in den Einstellungen zu aktivieren - dieses Werkzeug danach " +
|
||||
"erneut aufrufen, um zu prüfen, ob die Verbindung jetzt klappt.",
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user