Skip to content
11 changes: 11 additions & 0 deletions src/ucode/agents/claude.py
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,17 @@ def read_managed_mcp_urls() -> dict[str, str]:
}


def read_user_mcp_names() -> set[str] | None:
"""Names in Claude's user-scope ``mcpServers``; ``None`` when the config can't be parsed.

Read-only, so ug can tell a name is free before picking an entry name."""
config = _read_claude_config_for_rewrite(claude_mcp_config_path())
if config is None:
return None
servers = config.get("mcpServers")
return set(servers) if isinstance(servers, dict) else set()


def _register_web_search_mcp(
workspace: str,
search_model: str,
Expand Down
11 changes: 11 additions & 0 deletions src/ucode/agents/codex.py
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,17 @@ def _read_user_config_for_rewrite(path: Path) -> tomlkit.TOMLDocument | None:
return None


def read_user_mcp_names() -> set[str] | None:
"""Names in Codex's user-scope ``[mcp_servers]``; ``None`` when the config can't be parsed.

Read-only, so ug can tell a name is free before picking an entry name."""
doc = _read_user_config_for_rewrite(user_mcp_config_path())
if doc is None:
return None
servers = doc.get(MANAGED_MCP_CONFIG_KEY)
return set(servers) if isinstance(servers, dict) else set()


def write_user_mcp_servers(add: dict[str, dict], remove: set[str]) -> set[str]:
"""Apply ``add``/``remove`` to Codex's user-scope ``[mcp_servers]`` (``~/.codex/config.toml``,
or under ``$CODEX_HOME``) in a single read-modify-write, instead of one ``codex mcp`` subprocess
Expand Down
Loading
Loading