MCP-Server: URL optional – URL-lose Einträge als reine Allowlist-Freigabe

Entkoppelt "Server erzeugen" von "Server erlauben": Ein MCP-Eintrag ohne
URL erzeugt keinen eigenen (kollidierenden) HTTP-Server mehr, steuert aber
weiterhin die Allowlist-Freigabe mcp__<name>__* bei. Gedacht für extern
(z.B. stdio via ~/.claude.json) laufende Server, die gott nur erlauben,
aber nicht selbst starten soll – sonst kollidiert gotts URL-Server mit dem
gleichnamigen externen und der Server verschwindet ganz.

- ParseMcpServers: Url optional (null erlaubt), nur Name+leer wird verworfen
- Frontend: Name genügt, URL-Placeholder + Hinweistext angepasst

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MelekiandClaude Opus 4.8 committed 2026-07-03 19:11:34 +02:00
1 parent 9d21138e62
commit 4d29b09488
3 files changed
+13 -9

No files matched your search

+8 -4
View File
@@ -259,8 +259,12 @@ public class ClaudeCliService
/// <summary> /// <summary>
/// Parst die in der Session hinterlegte MCP-Server-Liste (JSON-Array von {name,url,token}). /// Parst die in der Session hinterlegte MCP-Server-Liste (JSON-Array von {name,url,token}).
/// Säubert die Namen (glob-/config-tauglich), filtert reservierte Namen, Duplikate und /// Säubert die Namen (glob-/config-tauglich), filtert reservierte Namen und Duplikate.
/// Einträge ohne URL. Wirft nie – ungültige Eingaben ergeben eine leere Liste. /// Einträge OHNE URL sind erlaubt (Url = null): sie erzeugen KEINEN eigenen Server,
/// steuern aber die Allowlist-Freigabe mcp__&lt;name&gt;__* bei – gedacht für Server, die
/// bereits extern (z.B. stdio via ~/.claude.json) laufen und die gott nur erlauben, aber
/// nicht selbst starten soll (sonst kollidiert gotts URL-Server mit dem externen gleichen
/// Namens). Nur Name+leer wird verworfen. Wirft nie – ungültige Eingaben ergeben leere Liste.
/// </summary> /// </summary>
public static List<McpServerDef> ParseMcpServers(string json) public static List<McpServerDef> ParseMcpServers(string json)
{ {
@@ -278,10 +282,10 @@ public class ClaudeCliService
var url = el.TryGetProperty("url", out var u) && u.ValueKind == JsonValueKind.String ? u.GetString() : null; var url = el.TryGetProperty("url", out var u) && u.ValueKind == JsonValueKind.String ? u.GetString() : null;
var token = el.TryGetProperty("token", out var t) && t.ValueKind == JsonValueKind.String ? t.GetString() : null; var token = el.TryGetProperty("token", out var t) && t.ValueKind == JsonValueKind.String ? t.GetString() : null;
var name = SanitizeMcpName(rawName); var name = SanitizeMcpName(rawName);
if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(url)) continue; if (string.IsNullOrEmpty(name)) continue; // URL optional: ohne URL = reiner Allowlist-Eintrag
if (_reservedMcpNames.Contains(name)) continue; if (_reservedMcpNames.Contains(name)) continue;
if (!seen.Add(name)) continue; // doppelter Name → ignorieren if (!seen.Add(name)) continue; // doppelter Name → ignorieren
result.Add(new McpServerDef { Name = name, Url = url.Trim(), Token = string.IsNullOrWhiteSpace(token) ? null : token.Trim() }); result.Add(new McpServerDef { Name = name, Url = string.IsNullOrWhiteSpace(url) ? null : url.Trim(), Token = string.IsNullOrWhiteSpace(token) ? null : token.Trim() });
} }
} }
catch { /* ungültiges JSON → leere Liste */ } catch { /* ungültiges JSON → leere Liste */ }
+2 -2
View File
@@ -172,10 +172,10 @@
<label>Benutzerdefinierte Befehle</label> <label>Benutzerdefinierte Befehle</label>
<div class="custom-commands" id="customCommandsList"></div> <div class="custom-commands" id="customCommandsList"></div>
<button type="button" id="addCommandBtn" class="add-cmd-btn">+ Befehl hinzufügen</button> <button type="button" id="addCommandBtn" class="add-cmd-btn">+ Befehl hinzufügen</button>
<label>MCP-Server <small>(optional, URL-basiert)</small></label> <label>MCP-Server <small>(optional)</small></label>
<div class="mcp-servers" id="mcpServersList"></div> <div class="mcp-servers" id="mcpServersList"></div>
<button type="button" id="addMcpServerBtn" class="add-cmd-btn">+ MCP-Server hinzufügen</button> <button type="button" id="addMcpServerBtn" class="add-cmd-btn">+ MCP-Server hinzufügen</button>
<small class="form-hint">Pro Eintrag: Name, URL (http/sse) und optionaler Token. Der Name muss <b>exakt</b> dem Tool-Präfix entsprechen (z.B. <code>UnityMCP</code>, nicht <code>Unity</code>). Tools werden headless als <code>mcp__&lt;name&gt;__*</code> freigegeben.</small> <small class="form-hint">Pro Eintrag: Name, optionale URL (http/sse) und optionaler Token. Der Name muss <b>exakt</b> dem Tool-Präfix entsprechen (z.B. <code>UnityMCP</code>, nicht <code>Unity</code>); Tools werden headless als <code>mcp__&lt;name&gt;__*</code> freigegeben. <b>URL leer lassen</b>, wenn der Server bereits extern läuft (z.B. stdio via <code>~/.claude.json</code>) – dann gibt gott ihn nur frei und erzeugt <b>keinen</b> eigenen, kollidierenden Server.</small>
<label>Telegram Bot</label> <label>Telegram Bot</label>
<div id="telegramBotSelectCard" class="agent-select-card"> <div id="telegramBotSelectCard" class="agent-select-card">
<div class="agent-select-empty"><i class="fa fa-paper-plane"></i> Kein Bot zugewiesen</div> <div class="agent-select-empty"><i class="fa fa-paper-plane"></i> Kein Bot zugewiesen</div>
+3 -3
View File
@@ -12,7 +12,7 @@ function createMcpServerRow(container, name, url, token) {
item.innerHTML = ` item.innerHTML = `
<div class="mcp-server-fields"> <div class="mcp-server-fields">
<input type="text" class="mcp-name" placeholder="Name (z.B. UnityMCP)" value="${esc(name)}" autocomplete="off"> <input type="text" class="mcp-name" placeholder="Name (z.B. UnityMCP)" value="${esc(name)}" autocomplete="off">
<input type="text" class="mcp-url" placeholder="URL (z.B. http://localhost:8080)" value="${esc(url)}" autocomplete="off"> <input type="text" class="mcp-url" placeholder="URL (optional – leer = nur Freigabe)" value="${esc(url)}" autocomplete="off">
<input type="password" class="mcp-token" placeholder="Token (optional)" value="${esc(token)}" autocomplete="off"> <input type="password" class="mcp-token" placeholder="Token (optional)" value="${esc(token)}" autocomplete="off">
</div> </div>
<button type="button" class="remove-mcp-btn icon-btn"><i class="fa fa-times"></i></button> <button type="button" class="remove-mcp-btn icon-btn"><i class="fa fa-times"></i></button>
@@ -29,8 +29,8 @@ function getMcpServersFromUI(container) {
var name = item.querySelector('.mcp-name').value.trim(); var name = item.querySelector('.mcp-name').value.trim();
var url = item.querySelector('.mcp-url').value.trim(); var url = item.querySelector('.mcp-url').value.trim();
var token = item.querySelector('.mcp-token').value.trim(); var token = item.querySelector('.mcp-token').value.trim();
// Nur vollständige Einträge (Name + URL) übernehmen. // Name genügt. Ohne URL = reiner Freigabe-Eintrag (kein eigener Server, nur Allowlist).
if (name && url) servers.push({ name: name, url: url, token: token || null }); if (name) servers.push({ name: name, url: url || null, token: token || null });
} }
return servers.length > 0 ? servers : null; return servers.length > 0 ? servers : null;
} }