72 lines
2.5 KiB
Python
72 lines
2.5 KiB
Python
import re
|
|
from typing import Any, Dict
|
|
|
|
_MCP_SERVER_NAME_RE = re.compile(r"[A-Za-z0-9][A-Za-z0-9._-]{0,63}")
|
|
|
|
|
|
def _normalize_mcp_servers(raw: Any) -> Dict[str, Dict[str, Any]]:
|
|
if not isinstance(raw, dict):
|
|
return {}
|
|
rows: Dict[str, Dict[str, Any]] = {}
|
|
for server_name, server_cfg in raw.items():
|
|
name = str(server_name or "").strip()
|
|
if not name or not _MCP_SERVER_NAME_RE.fullmatch(name):
|
|
continue
|
|
if not isinstance(server_cfg, dict):
|
|
continue
|
|
url = str(server_cfg.get("url") or "").strip()
|
|
if not url:
|
|
continue
|
|
transport_type = str(server_cfg.get("type") or "streamableHttp").strip()
|
|
if transport_type not in {"streamableHttp", "sse"}:
|
|
transport_type = "streamableHttp"
|
|
headers_raw = server_cfg.get("headers")
|
|
headers: Dict[str, str] = {}
|
|
if isinstance(headers_raw, dict):
|
|
for key, value in headers_raw.items():
|
|
header_key = str(key or "").strip()
|
|
if not header_key:
|
|
continue
|
|
headers[header_key] = str(value or "").strip()
|
|
timeout_raw = server_cfg.get("toolTimeout", 60)
|
|
try:
|
|
timeout = int(timeout_raw)
|
|
except Exception:
|
|
timeout = 60
|
|
rows[name] = {
|
|
"type": transport_type,
|
|
"url": url,
|
|
"headers": headers,
|
|
"toolTimeout": max(1, min(timeout, 600)),
|
|
}
|
|
return rows
|
|
|
|
|
|
def _merge_mcp_servers_preserving_extras(
|
|
current_raw: Any,
|
|
normalized: Dict[str, Dict[str, Any]],
|
|
) -> Dict[str, Dict[str, Any]]:
|
|
current_map = current_raw if isinstance(current_raw, dict) else {}
|
|
merged: Dict[str, Dict[str, Any]] = {}
|
|
for name, normalized_cfg in normalized.items():
|
|
base = current_map.get(name)
|
|
base_cfg = dict(base) if isinstance(base, dict) else {}
|
|
next_cfg = dict(base_cfg)
|
|
next_cfg.update(normalized_cfg)
|
|
merged[name] = next_cfg
|
|
return merged
|
|
|
|
|
|
def _sanitize_mcp_servers_in_config_data(config_data: Dict[str, Any]) -> Dict[str, Dict[str, Any]]:
|
|
if not isinstance(config_data, dict):
|
|
return {}
|
|
tools_cfg = config_data.get("tools")
|
|
if not isinstance(tools_cfg, dict):
|
|
tools_cfg = {}
|
|
current_raw = tools_cfg.get("mcpServers")
|
|
normalized = _normalize_mcp_servers(current_raw)
|
|
merged = _merge_mcp_servers_preserving_extras(current_raw, normalized)
|
|
tools_cfg["mcpServers"] = merged
|
|
config_data["tools"] = tools_cfg
|
|
return merged
|