ClawdDotNet als MCP-Server: durch dieselben Pruefstellen (#713)
Eine fremde Laufzeit oder der eigene Claude Code des Menschen spricht per MCP mit der Instanz. Der Server bietet genau die Werkzeuge des Agenten hinter dem Token an; jeder Aufruf laeuft durch die Engine wie ein Aufruf des eigenen Modells (Rechtetor, Vorpruefung, Werkzeugrechte, Staging, Audit mit Quelle mcp, Rahmung), und der Aufrufer gilt als Leser fremder Inhalte (#715). Eigener Socket mcp.sock statt manager.sock: ueber den Instanz-Socket antwortet die Verwaltung ohne Token, ueber mcp.sock gibt es nur /mcp und nur mit MCP-Token. Lauf-Tokens nur im Speicher, enden mit dem Lauf; persoenliche Tokens (hoechstens 90 Tage, widerrufbar, nur als SHA-256) in der Agentenansicht. Transporte: HTTP auf mcp.sock, Weboberflaeche und Manager (/mcp/{instanz}), stdio ueber ClawdDotNet --mcp-bridge (Token nur aus Umgebung oder 0600-Datei). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b5f65b8cf7
commit
cb46289bb6
@@ -47,6 +47,10 @@ internal static class CommandLine
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>#713: Only the stdio bridge to a running instance's MCP server — no application.</summary>
|
||||
public static bool IsMcpBridge(IReadOnlyList<string>? args)
|
||||
=> Has(args, Core.Mcp.McpStdioBridge.Argument);
|
||||
|
||||
public static bool IsHeadless(IReadOnlyList<string>? args)
|
||||
=> Has(args, HeadlessArgument);
|
||||
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
using ClawdDotNet.Core.Instances;
|
||||
using ClawdDotNet.Core.Mcp;
|
||||
|
||||
namespace ClawdDotNet.Desktop;
|
||||
|
||||
/// <summary>
|
||||
/// #713: <c>ClawdDotNet --mcp-bridge --instance <dir></c> — the instance's MCP server
|
||||
/// over stdio, for a runtime that starts its MCP servers as child processes.
|
||||
///
|
||||
/// <para>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.</para>
|
||||
/// </summary>
|
||||
internal static class McpBridgeRun
|
||||
{
|
||||
private const int ExitOk = 0;
|
||||
private const int ExitNoInstance = 2;
|
||||
private const int ExitNoToken = 5;
|
||||
|
||||
public static async Task<int> RunAsync(string[] args)
|
||||
{
|
||||
var instancePath = CommandLine.ReadInstancePath(args);
|
||||
if (string.IsNullOrWhiteSpace(instancePath) || !Directory.Exists(instancePath))
|
||||
{
|
||||
await Console.Error.WriteLineAsync($"Expected {CommandLine.InstanceArgument} <instance directory>.");
|
||||
return ExitNoInstance;
|
||||
}
|
||||
|
||||
var (token, problem) = McpStdioBridge.ReadToken(Environment.GetEnvironmentVariable);
|
||||
if (token is null)
|
||||
{
|
||||
await Console.Error.WriteLineAsync(problem);
|
||||
return ExitNoToken;
|
||||
}
|
||||
|
||||
using var client = 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;
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,11 @@ internal static class Program
|
||||
/// ohne Bildschirmsitzung gäbe es keines (#528, Stufe 2).
|
||||
/// </remarks>
|
||||
public static int Main(string[] args)
|
||||
=> CommandLine.IsHeadless(args)
|
||||
? HeadlessRun.RunAsync(args).GetAwaiter().GetResult()
|
||||
: BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
=> CommandLine.IsMcpBridge(args)
|
||||
? McpBridgeRun.RunAsync(args).GetAwaiter().GetResult()
|
||||
: CommandLine.IsHeadless(args)
|
||||
? HeadlessRun.RunAsync(args).GetAwaiter().GetResult()
|
||||
: BuildAvaloniaApp().StartWithClassicDesktopLifetime(args);
|
||||
|
||||
/// <summary>
|
||||
/// Auch vom Vorschau-Werkzeug des Editors aufgerufen — deshalb öffentlich und
|
||||
|
||||
Reference in New Issue
Block a user