using LehrerApp.McpBridge; using ModelContextProtocol.Protocol; using ModelContextProtocol.Server; // Resilienter Bridge-Prozess (Nutzer-Feedback): meldet sich gegenüber dem KI-Client (z.B. Claude // Desktop) IMMER erfolgreich als MCP-Server, unabhängig davon, ob LehrerApp.Desktop beim Start // dieses Prozesses bereits läuft - Claude Desktop startet oft per Windows-Autostart, bevor der // Nutzer LehrerApp geöffnet hat. Die eigentliche Weiterleitung an den echten Server sowie das // Nachladen der echten Werkzeugliste, sobald LehrerApp erreichbar ist, übernimmt // RealServerBridge - Details und Begründung siehe dort. var bridge = new RealServerBridge(); await bridge.TryReconnectAsync(CancellationToken.None); bridge.EnsureFallbackTool(); using var cts = new CancellationTokenSource(); var reconnectLoop = bridge.RunBackgroundReconnectLoopAsync(TimeSpan.FromSeconds(5), cts.Token); var serverOptions = new McpServerOptions { ServerInfo = new Implementation { Name = "LehrerApp", Version = "1.0.0" }, // ListChanged = true: Voraussetzung dafür, dass Claude Desktop reagiert, wenn RealServerBridge // das Status-Werkzeug nachträglich durch die echte Werkzeugliste ersetzt (oder umgekehrt, falls // LehrerApp während der Sitzung beendet wird). Capabilities = new ServerCapabilities { Tools = new ToolsCapability { ListChanged = true } }, ToolCollection = bridge.Tools, }; await using var stdin = Console.OpenStandardInput(); await using var stdout = Console.OpenStandardOutput(); await using var transport = new StreamServerTransport(stdin, stdout, "LehrerApp.McpBridge"); await using var server = McpServer.Create(transport, serverOptions, loggerFactory: null, serviceProvider: null); try { // Läuft, bis der KI-Client stdin schließt (Sitzungsende) - danach ist nichts mehr zu tun. await server.RunAsync(cts.Token); } finally { await cts.CancelAsync(); try { await reconnectLoop; } catch { /* Beenden über Cancellation ist der Normalfall hier */ } await bridge.DisposeAsync(); }