Blog • Claude Code / MCP
Nach Upgrade auf Claude Code 2.1.318 mit deniedMcpServers URL-Regeln: JSON-Logs für Anthropic-gehostetes MCP und cloud connectors?
Am 4. November 2026 lieferte Anthropic Claude Code 2.1.318. serverUrl in deniedMcpServers blockiert auch Anthropic-gehostetes MCP per upstreamUrl; Connectors in cloud und self-hosted runner vergleichen connectorUrl zuerst, sonst serverName.
Session-Server-Metadaten-JSON: serverKind, upstreamUrl, connectorUrl, serverName, sessionSurface. Verweigerte MCP tool calls: decision denied, reason mcp_server_denied, matchedRule, matchedPattern, upstreamUrl. mcp_url_deny_gate spiegelt schema, deny_by_url, deny_by_connector_url, deny_by_name, allow, nicht serverCommand env-only.
serverCommand-Deny in MCP env allowlist und serverCommand; MCP-Sicherheitsbaseline in MCP-Sicherheit; Elicitation-Timeout-Stops in MCP elicitation timeout JSON. Dieser Artikel behandelt nur die deniedMcpServers URL-Erweiterung 2.1.318, managed settings JSON, Session-Server-Metadaten, MCP tool call, mcp_server_denied Audit-Felder und fünf mcp_url_deny_gate-Zweige.
- deniedMcpServers in managed settings darf serverUrl-Globs und serverName kombinieren; ab 2.1.318 trifft serverUrl auch upstreamUrl bei Anthropic-gehostetem MCP.
- Session-Metadaten-JSON braucht serverKind, upstreamUrl, connectorUrl, serverName, sessionSurface; fehlende Felder oder enum → schema vor URL- oder Namensmatch.
- Audit-Logs in deny-Zweigen: decision denied, reason mcp_server_denied, matchedRule, matchedPattern, upstreamUrl; SIEM nach matchedRule, nicht serverCommand deny mischen.
- In cloud und self-hosted runner zuerst connectorUrl gegen serverUrl, sonst serverName für deny_by_name; kein Treffer → allow.
Zuerst dies: 2.1.318 erweitert deniedMcpServers URL-Matching für gehostetes MCP und cloud connectors plus mcp_server_denied Audit; keine Neuschreibung der serverCommand env-only Deny-Tabelle. Unten: Changelog, managed settings JSON, Metadaten, MCP-Beispiel, Audit-Tabelle, mcp_url_deny_gate, JSONNote.
Wie erweitert 2.1.318 deniedMcpServers URL auf gehostetes MCP und cloud connectors
Änderungen stehen in Claude Code changelog, Tag-Seite Release v2.1.318. Früher vor allem user-konfiguriertes MCP; 2.1.318 gilt serverUrl auch für upstreamUrl bei Anthropic-gehostetem MCP; cloud und self-hosted runner prüfen connectorUrl zuerst, sonst serverName.
Verweigerung vor dem MCP tool call. Audit-JSON: decision denied, reason mcp_server_denied, matchedRule, matchedPattern, upstreamUrl für SIEM-Attribution zur URL-Regel.
Wie schreibt man serverUrl und serverName in deniedMcpServers der managed settings
In managed settings trägt deniedMcpServers serverUrl-Globs und serverName. Ab 2.1.318 matcht serverUrl upstreamUrl bei Anthropic-gehostetem MCP und connectorUrl bei cloud connectors.
{
"deniedMcpServers": [
{
"serverUrl": "https://mcp.example.com/v1/*"
},
{
"serverName": "slack-connector"
}
]
}
serverUrl kein String oder deniedMcpServers kein Array → schema zuerst, nicht allow bei Formfehlern.
Wie upstreamUrl und sessionSurface im Session-Server-Metadaten-JSON stehen
Beim Auflösen von MCP-Servern schreibt der Client Metadaten-JSON: serverKind, upstreamUrl, connectorUrl, serverName, sessionSurface.
{
"serverKind": "anthropic_hosted",
"upstreamUrl": "https://mcp.example.com/v1/tools",
"connectorUrl": "https://connect.example.com/slack",
"serverName": "analytics-mcp",
"sessionSurface": "cloud"
}
upstreamUrl und connectorUrl non-leer; sessionSurface in enum; fehlendes serverKind → schema; kein Regeltreffer → allow.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"additionalProperties": false,
"required": ["serverKind", "upstreamUrl", "connectorUrl", "serverName", "sessionSurface"],
"properties": {
"serverKind": { "type": "string", "enum": ["anthropic_hosted", "user_configured", "connector"] },
"upstreamUrl": { "type": "string", "minLength": 1 },
"connectorUrl": { "type": "string", "minLength": 1 },
"serverName": { "type": "string", "minLength": 1 },
"sessionSurface": { "type": "string", "enum": ["cloud", "local", "self_hosted_runner"] }
}
}
Wie MCP tool call JSON zu Server-Metadaten ohne Regeltreffer passt
Trifft upstreamUrl serverUrl, tool JSON mit mcp__analytics-mcp__search; kein MCP tool, decision denied. CALL_OUTSIDE → allow.
{
"tool": "mcp__analytics-mcp__search",
"arguments": {
"query": "quarterly revenue"
}
}
{
"serverKind": "anthropic_hosted",
"upstreamUrl": "https://other.example.com/v1/tools",
"connectorUrl": "https://connect.example.com/other",
"serverName": "other-mcp",
"sessionSurface": "cloud"
}
Wie decision denied und mcp_server_denied in Audit-Logs stehen
Trifft upstreamUrl oder connectorUrl eine Regel: decision denied, reason mcp_server_denied, matchedRule, matchedPattern, upstreamUrl; connectorUrl für cloud. serverCommand env-only und URL deny nicht in einer reason-Enum mischen.
{
"decision": "denied",
"reason": "mcp_server_denied",
"matchedRule": "serverUrl",
"matchedPattern": "https://mcp.example.com/v1/*",
"upstreamUrl": "https://mcp.example.com/v1/tools"
}
| Session- oder URL-Signal | mcp_url_deny_gate liefert | Operator-Aktion |
|---|---|---|
| upstreamUrl trifft serverUrl-Glob | deny_by_url | Audit an decision denied, matchedRule serverUrl, matchedPattern, upstreamUrl anpassen. |
| connectorUrl trifft serverUrl, upstream nicht | deny_by_connector_url | matchedRule serverUrl loggen, connectorUrl für cloud-Attribution behalten. |
| serverName trifft deniedMcpServers-Namensregel | deny_by_name | reason mcp_server_denied und matchedRule serverName schreiben. |
| Schlechte Metadaten-JSON-Form oder fehlende Deny-Liste | schema | Managed settings oder ctx fixen vor deny-Zweigen. |
Wie mcp_url_deny_gate zwischen schema und fünf deny-Zweigen wählt
Reihenfolge: CTX_SCHEMA für serverKind, upstreamUrl, connectorUrl, serverName, sessionSurface; deniedMcpServers durchlaufen; upstreamUrl trifft serverUrl → deny_by_url; connectorUrl trifft serverUrl → deny_by_connector_url; serverName trifft Namensregel → deny_by_name; sonst allow.
deny_by_url und deny_by_connector_url nicht zu einem mcp_denied zusammenlegen. deny_by_connector_url für cloud connectors, deny_by_url für gehostetes MCP, deny_by_name für Namen.
def actual_type(data: object) -> str:
if data is None:
return "null"
if isinstance(data, bool):
return "boolean"
if isinstance(data, list):
return "array"
if isinstance(data, int):
return "integer"
if isinstance(data, float):
return "number"
if isinstance(data, str):
return "string"
if isinstance(data, dict):
return "object"
raise TypeError(type(data))
def validate(data: object, schema: dict) -> list[str]:
errors: list[str] = []
if not isinstance(schema, dict):
return errors
types = schema.get("type")
if isinstance(types, str):
types = [types]
actual = actual_type(data)
if types and not any(t == actual or (t == "number" and actual == "integer") for t in types):
errors.append("type")
if "enum" in schema and not any(value == data for value in schema["enum"]):
errors.append("enum")
if isinstance(data, str) and "minLength" in schema and len(data) < schema["minLength"]:
errors.append("minLength")
if isinstance(data, dict) and schema.get("properties"):
for key in schema.get("required") or []:
if key not in data:
errors.append(f"required:{key}")
if schema.get("additionalProperties") is False:
for key in data:
if key not in schema["properties"]:
errors.append(f"additional:{key}")
for key, sub in schema["properties"].items():
if key in data and data[key] is not None:
errors.extend(validate(data[key], sub))
return errors
def url_match(url: str, pattern: str) -> bool:
return fnmatch(url, pattern)
def mcp_url_deny_gate(ctx: dict, deny_doc: dict, schema: dict) -> str:
if validate(ctx, schema):
return "schema"
entries = deny_doc.get("deniedMcpServers")
if not isinstance(entries, list):
return "schema"
upstream = ctx.get("upstreamUrl", "")
connector = ctx.get("connectorUrl", "")
name = ctx.get("serverName", "")
for entry in entries:
if not isinstance(entry, dict):
continue
pat = entry.get("serverUrl")
if isinstance(pat, str):
if upstream and url_match(upstream, pat):
return "deny_by_url"
if connector and url_match(connector, pat):
return "deny_by_connector_url"
rule_name = entry.get("serverName")
if isinstance(rule_name, str) and rule_name and rule_name == name:
return "deny_by_name"
return "allow"
Wie validiert man managed settings, Session-Metadaten und Audit-Logs in JSONNote
- 1Deny-Listen-Form per Schema fixieren
Öffnen Sie JSON Schema. deniedMcpServers-Schema ins erste Feld, serverUrl und serverName ins zweite. required oder Typ zuerst; bei schlechter Form kein deny_by_url oder allow.
- 2Format für MCP tool calls
Öffnen Sie JSON formatieren, MCP tool call JSON einfügen. tool und arguments prüfen, dann deny_by_url oder allow für mcp_url_deny_gate.
- 3Diff: allow vs denied Audit-Logs
Öffnen Sie JSON Diff. Links CALL_OUTSIDE allow, rechts decision denied und reason mcp_server_denied. Hervorgehobenes matchedPattern ist die SIEM-Schlüsselzeile.
Häufige Fragen
Worin unterscheiden sich serverUrl-Regeln vom alten nur user-konfiguriert?
Früher traf serverUrl vor allem user-konfiguriertes HTTP MCP. Ab 2.1.318 auch upstreamUrl bei Anthropic-gehostetem MCP plus connectorUrl dann serverName.
Wie unterscheiden Logs deny_by_url und deny_by_connector_url?
deny_by_url: matchedRule serverUrl, upstreamUrl passt. deny_by_connector_url: connectorUrl trifft, upstream evtl. nicht, connectorUrl und sessionSurface behalten.
Was wird zuerst geprüft, serverName oder serverUrl?
mcp_url_deny_gate prüft serverUrl zuerst: upstreamUrl→deny_by_url, connectorUrl→deny_by_connector_url, dann serverName→deny_by_name. Keine URL-Globs in serverName.
Wie hängt URL deny mit serverCommand env-only deny zusammen?
serverCommand für stdio und env-Platzhalter ersetzt kein serverUrl-upstream-Deny. JSON getrennt; mcp_url_deny_gate nur URL und serverName.
Enthält dieser Artikel Angriffs- oder Bypass-Tutorials?
Nein. Der Artikel erklärt nur JSON-Formen der deniedMcpServers URL-Erweiterung 2.1.318, mcp_server_denied Audit-Felder und fünf mcp_url_deny_gate-Zweige. Keine Bypass-Schritte via URL oder connector.
Fazit
Claude Code 2.1.318 erweitert deniedMcpServers URL-Matching und schreibt decision denied, reason mcp_server_denied, matchedRule, matchedPattern, upstreamUrl ins Audit-JSON. mcp_url_deny_gate mit managed settings, Metadaten, MCP-Aufrufen und denied Audit füttern.
Entscheidung: Metadaten-JSON scheitert schema → schema; upstreamUrl trifft serverUrl → deny_by_url; connectorUrl trifft serverUrl → deny_by_connector_url; serverName → deny_by_name; kein Treffer → allow; deny Audit wie decision denied, reason mcp_server_denied, matchedRule, matchedPattern, upstreamUrl.
Als Nächstes: deniedMcpServers und Metadaten per Schema, Format für MCP-Aufrufe, Diff allow vs denied Audit-Logs, deny_by_url, deny_by_connector_url, deny_by_name und allow getrennt berichten.