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;
}
}