Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/ucode/mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from __future__ import annotations

import json
import os
import shutil
import string
import subprocess
Expand All @@ -23,7 +24,7 @@
from questionary.question import Question
from questionary.styles import merge_styles_default

from ucode.agents import copilot, opencode
from ucode.agents import copilot, gemini, opencode
from ucode.config_io import restore_file
from ucode.databricks import (
ensure_databricks_auth,
Expand Down Expand Up @@ -177,6 +178,13 @@ def remove_codex_mcp_server(name: str) -> bool:
return True


def _gemini_cli_env() -> dict[str, str]:
# Pin GEMINI_CLI_HOME to the same directory the launcher.
env = os.environ.copy()
env["GEMINI_CLI_HOME"] = str(gemini.GEMINI_HOME_DIR)
return env


def add_gemini_mcp_server(name: str, url: str) -> None:
try:
subprocess.run(
Expand All @@ -197,6 +205,7 @@ def add_gemini_mcp_server(name: str, url: str) -> None:
capture_output=True,
text=True,
timeout=30,
env=_gemini_cli_env(),
)
except subprocess.CalledProcessError as exc:
raise RuntimeError(f"Failed to add MCP server '{name}' via gemini CLI.") from exc
Expand All @@ -210,6 +219,7 @@ def remove_gemini_mcp_server(name: str) -> bool:
capture_output=True,
text=True,
timeout=30,
env=_gemini_cli_env(),
)
except subprocess.TimeoutExpired as exc:
raise RuntimeError(f"Timed out removing MCP server '{name}' via gemini CLI.") from exc
Expand Down
44 changes: 22 additions & 22 deletions tests/test_mcp.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,29 @@ def fake_run(args, **kwargs):

mcp.add_gemini_mcp_server("github", f"{WS}/api/2.0/mcp/external/github")

assert calls == [
{
"args": [
"gemini",
"mcp",
"add",
"github",
f"{WS}/api/2.0/mcp/external/github",
"--type",
"http",
"--scope",
"user",
"--header",
"Authorization: Bearer ${OAUTH_TOKEN}",
],
"kwargs": {
"check": True,
"capture_output": True,
"text": True,
"timeout": 30,
},
}
assert len(calls) == 1
call = calls[0]
assert call["args"] == [
"gemini",
"mcp",
"add",
"github",
f"{WS}/api/2.0/mcp/external/github",
"--type",
"http",
"--scope",
"user",
"--header",
"Authorization: Bearer ${OAUTH_TOKEN}",
]
kwargs = call["kwargs"]
assert kwargs["check"] is True
assert kwargs["capture_output"] is True
assert kwargs["text"] is True
assert kwargs["timeout"] == 30
# GEMINI_CLI_HOME must point at the launcher's home so `gemini mcp
# add` writes the same settings.json the ucode session reads from.
assert kwargs["env"]["GEMINI_CLI_HOME"] == str(mcp.gemini.GEMINI_HOME_DIR)


class TestRemoveClaudeMcpServer:
Expand Down
Loading