feat: add support for Gemini CLI integration#1709
Conversation
|
This looks great, I'm a big Gemini user -- I'll give this a shot tomorrow and report back! |
@strawgate let me know if you run into any issues 😄 |
|
Sorry, will try to find time today or by Monday at the latest |
|
Looks great; the only problem I ran into is not a problem with the Gemini CLI install command in particular but with the uv environment command building. In UVEnvironment: If it's determined it doesnt need setup, then the command becomes: I don't have fastmcp in my path and so direct invocation doesn't work for me and requires |
strawgate
left a comment
There was a problem hiding this comment.
Small cleanup on the doc, otherwise looks good
There was a problem hiding this comment.
Pull Request Overview
This PR adds support for Gemini CLI as an AI assistant integration to FastMCP, enabling users to install FastMCP servers directly into Gemini CLI using fastmcp install gemini-cli. The integration leverages Gemini CLI's recently added MCP support via the gemini mcp add command.
Key changes:
- New Gemini CLI integration module with command discovery and installation logic
- Comprehensive test coverage for the new integration command
- Complete documentation for the Gemini CLI integration
Reviewed Changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/fastmcp/cli/install/gemini_cli.py | Core implementation of Gemini CLI integration with command discovery, validation, and MCP server installation |
| src/fastmcp/cli/install/init.py | Registration of the new gemini-cli command in the install app |
| tests/cli/test_install.py | Test cases covering command parsing, options handling, and integration with existing test patterns |
| docs/integrations/gemini-cli.mdx | User documentation explaining installation methods, configuration options, and usage examples |
| def find_gemini_command() -> str | None: | ||
| """Find the Gemini CLI command.""" | ||
| # First try shutil.which() in case it's a real executable in PATH | ||
| gemini_in_path = shutil.which("gemini") | ||
| if gemini_in_path: | ||
| try: | ||
| # If 'gemini --version' fails, it's not the correct path | ||
| subprocess.run( | ||
| [gemini_in_path, "--version"], | ||
| check=True, | ||
| capture_output=True, | ||
| ) | ||
| return gemini_in_path | ||
| except (subprocess.CalledProcessError, FileNotFoundError): | ||
| pass | ||
|
|
||
| # Check common installation locations (aliases don't work with subprocess) | ||
| potential_paths = [ | ||
| # Default Gemini CLI installation location (after migration) | ||
| Path.home() / ".gemini" / "local" / "gemini", | ||
| # npm global installation on macOS/Linux (default) | ||
| Path("/usr/local/bin/gemini"), | ||
| # npm global installation with custom prefix | ||
| Path.home() / ".npm-global" / "bin" / "gemini", | ||
| # Homebrew installation on macOS | ||
| Path("/opt/homebrew/bin/gemini"), | ||
| ] | ||
|
|
||
| for path in potential_paths: | ||
| if path.exists(): | ||
| # If 'gemini --version' fails, it's not the correct path | ||
| try: | ||
| subprocess.run( | ||
| [str(path), "--version"], | ||
| check=True, | ||
| capture_output=True, | ||
| ) | ||
| return str(path) | ||
| except (subprocess.CalledProcessError, FileNotFoundError): | ||
| continue | ||
|
|
||
| return None |
There was a problem hiding this comment.
The function executes subprocess.run([path, '--version']) for each potential path and when checking shutil.which() result. This creates multiple subprocess calls during discovery. Consider adding a timeout parameter to prevent hanging on unresponsive executables, or implement early termination if the first successful validation is sufficient.
| subprocess.run(cmd_parts, check=True, capture_output=True, text=True) | ||
| return True |
There was a problem hiding this comment.
The subprocess call lacks a timeout parameter, which could cause the installation to hang indefinitely if the Gemini CLI command becomes unresponsive. Consider adding a reasonable timeout (e.g., 30-60 seconds) to prevent blocking.
| subprocess.run(cmd_parts, check=True, capture_output=True, text=True) | |
| return True | |
| subprocess.run(cmd_parts, check=True, capture_output=True, text=True, timeout=60) | |
| return True | |
| except subprocess.TimeoutExpired as e: | |
| print( | |
| f"[red]Gemini CLI command timed out after 60 seconds while installing '[bold]{name}[/bold]'.[/red]" | |
| ) | |
| return False |
|
Oh good call @strawgate. You're right, this should be a uv run command. I'll open a separate issue to fix. Let's merge this, thanks @jackwotherspoon!! |
|
Thank a ton @strawgate @jlowin 👏 Couple quick follow-up questions:
Super excited about this integration! 😄 |
|
Gemini CLI 🤝 FastMCP
Description
This adds support for Gemini CLI as an AI assistant integration to FastMCP via
fastmcp install gemini-cli.Gemini CLI now has support for
gemini mcp addcommands which has enabled this integration.fastmcp_gemini_cli.mp4
Contributors Checklist
Review Checklist