using ClawdDotNet.Core.Instances; using ClawdDotNet.Core.Mcp; namespace ClawdDotNet.Desktop; /// /// #713: ClawdDotNet --mcp-bridge --instance <dir> — the instance's MCP server /// over stdio, for a runtime that starts its MCP servers as child processes. In a sandbox /// (#712), where there is no instance directory, --socket <path> names the /// mounted MCP socket instead. /// /// No application is built here: no settings, no database, no engine. The bridge /// only carries messages to the running instance over its MCP socket; everything is /// decided there. Diagnostics go to stderr — stdout belongs to the protocol. /// internal static class McpBridgeRun { private const int ExitOk = 0; private const int ExitNoInstance = 2; private const int ExitNoToken = 5; public static async Task RunAsync(string[] args) { var socketPath = CommandLine.ReadValue(args, McpStdioBridge.SocketArgument); var instancePath = CommandLine.ReadInstancePath(args); if (socketPath is null && (string.IsNullOrWhiteSpace(instancePath) || !Directory.Exists(instancePath))) { await Console.Error.WriteLineAsync($"Expected {CommandLine.InstanceArgument} or {McpStdioBridge.SocketArgument} ."); return ExitNoInstance; } var (token, problem) = McpStdioBridge.ReadToken(Environment.GetEnvironmentVariable); if (token is null) { await Console.Error.WriteLineAsync(problem); return ExitNoToken; } using var client = socketPath is not null ? InstanceEndpoint.CreateMcpClientForSocket(socketPath) : InstanceEndpoint.CreateMcpClient(instancePath!); using var stdin = new StreamReader(Console.OpenStandardInput()); await using var stdout = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = false }; await McpStdioBridge.RunAsync(stdin, stdout, client, token, CancellationToken.None); return ExitOk; } }