Skip to content

Commit 86ba9da

Browse files
authored
user-friendly genie-space server names displayed (#127)
1 parent 444e74f commit 86ba9da

2 files changed

Lines changed: 71 additions & 9 deletions

File tree

src/ucode/mcp.py

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -352,23 +352,50 @@ def discover_external_mcp_connection_names(workspace: str, profile: str | None =
352352
return external_mcp_connection_names(list_databricks_connections(workspace, profile))
353353

354354

355+
def _normalize_workspace_title(text: str) -> str:
356+
"""Collapse a Databricks workspace title to lowercase alphanumerics joined
357+
by single hyphens, trimmed at the edges. Output is safe to use as an MCP
358+
server-name token across every supported agent CLI."""
359+
chars: list[str] = []
360+
for ch in text.lower():
361+
if ch.isalnum():
362+
chars.append(ch)
363+
elif chars and chars[-1] != "-":
364+
chars.append("-")
365+
return "".join(chars).strip("-")
366+
367+
368+
def _genie_server_name(title: str, space_id: str, taken: set[str]) -> str:
369+
"""Prefer a friendly name derived from the Genie space title; fall back to
370+
the raw space_id when there is no title or the derived name collides with
371+
one we already emitted."""
372+
slug = _normalize_workspace_title(title) if title else ""
373+
if slug:
374+
candidate = f"databricks-genie-{slug}"
375+
if candidate not in taken:
376+
return candidate
377+
return f"databricks-genie-{space_id}"
378+
379+
355380
def genie_mcp_servers(spaces: list[dict], workspace: str) -> list[dict]:
356381
servers: list[dict] = []
357382
seen_names: set[str] = set()
358383
for space in spaces:
359384
space_id = space.get("space_id")
360385
if not isinstance(space_id, str) or not space_id.strip():
361386
continue
362-
title = space.get("title")
363-
server_name = f"databricks-genie-{space_id.strip()}"
387+
space_id = space_id.strip()
388+
raw_title = space.get("title")
389+
title = raw_title.strip() if isinstance(raw_title, str) and raw_title.strip() else ""
390+
server_name = _genie_server_name(title, space_id, seen_names)
364391
if server_name in seen_names:
365392
continue
366393
seen_names.add(server_name)
367394
servers.append(
368395
{
369396
"name": server_name,
370-
"title": title.strip() if isinstance(title, str) and title.strip() else space_id,
371-
"url": f"{workspace}/api/2.0/mcp/genie/{space_id.strip()}",
397+
"title": title or space_id,
398+
"url": f"{workspace}/api/2.0/mcp/genie/{space_id}",
372399
}
373400
)
374401
return sorted(servers, key=lambda server: str(server["title"]).lower())
@@ -731,6 +758,7 @@ def _resolve_mcp_selection(
731758
selection: str,
732759
workspace: str,
733760
available_app_servers: list[dict] | None = None,
761+
available_genie_servers: list[dict] | None = None,
734762
) -> tuple[str, str]:
735763
if selection.startswith(APP_MCP_SELECTION_PREFIX):
736764
app_name = selection.removeprefix(APP_MCP_SELECTION_PREFIX)
@@ -745,10 +773,17 @@ def _resolve_mcp_selection(
745773
return f"databricks-app-{app_name}", url
746774

747775
if selection.startswith(GENIE_SPACE_SELECTION_PREFIX):
748-
space_id = selection.removeprefix(GENIE_SPACE_SELECTION_PREFIX)
749-
if not space_id:
776+
suffix = selection.removeprefix(GENIE_SPACE_SELECTION_PREFIX)
777+
if not suffix:
750778
raise RuntimeError("missing Genie space id")
751-
return f"databricks-genie-{space_id}", f"{workspace}/api/2.0/mcp/genie/{space_id}"
779+
server_name = f"databricks-genie-{suffix}"
780+
server = _servers_by_name(available_genie_servers or []).get(server_name)
781+
if server:
782+
url = server.get("url")
783+
if isinstance(url, str) and url:
784+
return server_name, url
785+
# Fallback for legacy picker values that carried the raw space_id.
786+
return server_name, f"{workspace}/api/2.0/mcp/genie/{suffix}"
752787

753788
if selection.startswith(EXTERNAL_MCP_SELECTION_PREFIX):
754789
server_name = selection.removeprefix(EXTERNAL_MCP_SELECTION_PREFIX)
@@ -937,6 +972,7 @@ def configure_mcp_command() -> int:
937972
selection,
938973
workspace,
939974
available_app_mcp_servers,
975+
available_genie_mcp_servers,
940976
)
941977
except RuntimeError as exc:
942978
print_warning(f"Skipped MCP selection `{selection}`: {exc}.")

tests/test_mcp.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,17 +291,43 @@ def test_discovers_genie_spaces_as_mcp_servers(self):
291291
WS,
292292
) == [
293293
{
294-
"name": "databricks-genie-space-1",
294+
"name": "databricks-genie-first-space",
295295
"title": "First Space",
296296
"url": f"{WS}/api/2.0/mcp/genie/space-1",
297297
},
298298
{
299-
"name": "databricks-genie-space-2",
299+
"name": "databricks-genie-second-space",
300300
"title": "Second Space",
301301
"url": f"{WS}/api/2.0/mcp/genie/space-2",
302302
},
303303
]
304304

305+
def test_genie_server_name_falls_back_to_space_id_on_slug_collision(self):
306+
assert mcp.genie_mcp_servers(
307+
[
308+
{"space_id": "space-1", "title": "New Space"},
309+
{"space_id": "space-2", "title": "new space"},
310+
{"space_id": "space-3", "title": ""},
311+
],
312+
WS,
313+
) == [
314+
{
315+
"name": "databricks-genie-new-space",
316+
"title": "New Space",
317+
"url": f"{WS}/api/2.0/mcp/genie/space-1",
318+
},
319+
{
320+
"name": "databricks-genie-space-2",
321+
"title": "new space",
322+
"url": f"{WS}/api/2.0/mcp/genie/space-2",
323+
},
324+
{
325+
"name": "databricks-genie-space-3",
326+
"title": "space-3",
327+
"url": f"{WS}/api/2.0/mcp/genie/space-3",
328+
},
329+
]
330+
305331
def test_picker_lists_discovered_genie_spaces(self):
306332
choices = mcp.build_mcp_picker_choices(
307333
["github-mcp"],

0 commit comments

Comments
 (0)