From 577483555c18b367fb4eb9bce3bef80160b2dd20 Mon Sep 17 00:00:00 2001 From: Arthur Jenoudet Date: Thu, 3 Sep 2026 19:16:09 +0000 Subject: [PATCH] Show skill scopes per agent --- src/ucode/cli.py | 35 +++++++++++++++++++++++++---------- tests/test_cli.py | 23 +++++++++++++++++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/ucode/cli.py b/src/ucode/cli.py index b6e6c68f..748aa40e 100644 --- a/src/ucode/cli.py +++ b/src/ucode/cli.py @@ -107,6 +107,7 @@ purge_cross_workspace_mcp_residue, remove_mcp_command, revert_mcp_configs, + skill_locations_for_client, ) from ucode.skills_download import ( configure_skills_download_command, @@ -1068,17 +1069,31 @@ def status() -> int: if not skill_mcp_entry: print_kv("Skills", "not configured") else: - locations = skill_mcp_entry.get("skill_locations") or [] - print_kv( - "Skill MCP Locations", - ", ".join(locations) if locations else "none — utility tools only", - ) - configured_agents = [ - str(MCP_CLIENTS[client]["display"]) - for client in (skill_mcp_entry.get("clients") or []) - if client in MCP_CLIENTS + configured_clients = [ + client for client in (skill_mcp_entry.get("clients") or []) if client in MCP_CLIENTS ] - print_kv("Configured", ", ".join(configured_agents) if configured_agents else "none") + scopes = { + client: skill_locations_for_client(skill_mcp_entry, client) + for client in configured_clients + } + if len({tuple(locations) for locations in scopes.values()}) <= 1: + locations = next( + iter(scopes.values()), list(skill_mcp_entry.get("skill_locations") or []) + ) + print_kv( + "Skill MCP Locations", + ", ".join(locations) if locations else "none — utility tools only", + ) + configured_agents = [ + str(MCP_CLIENTS[client]["display"]) for client in configured_clients + ] + print_kv("Configured", ", ".join(configured_agents) if configured_agents else "none") + else: + for client, locations in scopes.items(): + print_kv( + f"{MCP_CLIENTS[client]['display']} skill MCP locations", + ", ".join(locations) if locations else "none — utility tools only", + ) print_heading("Tracing") tracing = state.get("tracing") or {} diff --git a/tests/test_cli.py b/tests/test_cli.py index 0123c3b3..47f7c901 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1402,6 +1402,29 @@ def test_skills_entry_absent_from_per_client_mcp_lines(self): assert "databricks-skill-registry" not in line assert "Skill MCP Locations: main.default" in out + def test_renders_per_agent_locations_when_scopes_diverge(self): + state = { + **MINIMAL_STATE, + "mcp_servers": [ + { + "name": "databricks-skill-registry", + "kind": "skills", + "skill_locations": ["main.default"], + "skill_location_overrides": {"claude": ["main.default", "claude.only"]}, + "url": "https://example.databricks.com/ai-gateway/skills/?schema=main.default", + "auth": "proxy", + "clients": ["claude", "codex"], + } + ], + } + + result = self._run(state) + + assert result.exit_code == 0, result.output + out = _strip_ansi(result.output) + assert "Claude Code skill MCP locations: main.default, claude.only" in out + assert "Codex skill MCP locations: main.default" in out + class TestRevert: def test_reverts_mcp_configs_before_clearing_state(self):