Skip to content

Conversation

@philschmid
Copy link

This PR improves the authentication experience for users running the Google Workspace MCP server in headless or remote VM environments where traditional browser-based OAuth flows don't work well.

Problem

When running the Extension as standalone MCP server in a VM/headless environment:

  1. stdout pollution: Auth messages were printed to stdout, breaking MCP clients that expect only JSON-RPC
  2. Stuck terminal: When browser launch fails, the callback server waits forever for a redirect that never comes
  3. Poor manual flow UX: The credentials page lacked clear instructions for different operating systems

Changes

1. Redirect Auth Messages to stderr

Files: workspace-server/src/utils/open-wrapper.ts, workspace-server/src/auth/AuthManager.ts

  • Changed console.log to console.error for all auth-related messages
  • Auth URL is now always printed to stderr immediately (visible to users)
  • Keeps stdout clean for MCP JSON-RPC protocol

2. Add GEMINI_CLI_WORKSPACE_HEADLESS Environment Variable

Files: workspace-server/src/utils/secure-browser-launcher.ts, workspace-server/src/auth/AuthManager.ts

New environment variable for headless environments with port-forwarding:

env = {
  "GEMINI_CLI_WORKSPACE_HEADLESS": "true",
  "OAUTH_CALLBACK_PORT": "8585"
}

Behavior:

  • Prints auth URL to stderr (no browser launch attempt)
  • OAuth callback server still runs for redirect
  • Port-forwarding instructions printed to help remote users

3. Improved Manual Flow Instructions

Files: cloud_function/index.js

Enhanced the "Success! Credentials Ready" page with:

  • Linux CLI instructions (expanded by default) - secret-tool command for remote VMs
  • macOS instructions - Keychain Access step-by-step
  • Windows instructions - Credential Manager step-by-step
  • Collapsible sections for each OS
  • Clear "restart your MCP server" instruction

Usage

Option A: Headless Mode with Port-Forwarding

from mcp import StdioServerParameters

server_params = StdioServerParameters(
  command = "npx",
  args = ["-y", "github:gemini-cli-extensions/workspace"],
  env = {
    "GEMINI_CLI_WORKSPACE_HEADLESS": "true",
    "OAUTH_CALLBACK_PORT": "8585"
  }
)
  1. Port-forward 8585 from VM: ssh -L 8585:localhost:8585 your-vm
  2. Run your MCP client
  3. Copy the auth URL from stderr
  4. Authenticate in browser
  5. Callback completes automatically

Option B: Manual Flow (No Port-Forwarding)

  1. Run MCP client (without GEMINI_CLI_WORKSPACE_HEADLESS)
  2. Copy the auth URL from stderr
  3. Authenticate in browser
  4. Copy JSON credentials from the success page
  5. Store using secret-tool (Linux) or Keychain/Credential Manager
  6. Restart MCP server

In headless/VM environments, auth URL messages were printed to stdout
via console.log, breaking MCP clients that expect only JSON-RPC on stdout.

Changed console.log to console.error in:
- open-wrapper.ts (browser launch failure messages)
- AuthManager.ts (waiting for auth message)
Print the auth URL immediately before attempting browser launch,
ensuring the URL is always visible in headless/VM environments
even when DISPLAY is set for port-forwarding.
Changes:
- Redirect auth messages to stderr (keep stdout clean for MCP JSON-RPC)
- Add GEMINI_CLI_WORKSPACE_HEADLESS env var for port-forwarding setups
- Print port-forwarding instructions when in headless mode
- Improve manual flow credentials page with OS-specific instructions:
  - Linux CLI (secret-tool command, expanded by default)
  - macOS Keychain Access
  - Windows Credential Manager
- Add PR.md with full documentation
Added section explaining how to use GEMINI_CLI_WORKSPACE_HEADLESS
with port-forwarding for authentication on remote VMs.
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @philschmid, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the user experience for authenticating the Google Workspace MCP server, particularly for those operating in headless or remote virtual machine environments. It addresses several pain points by separating authentication messages to stderr to prevent stdout pollution, introducing a dedicated headless mode with port-forwarding support to avoid stuck terminals, and providing much clearer, OS-specific instructions for manual credential storage on the success page. These changes streamline the authentication process and make the server more robust and user-friendly in non-GUI settings.

Highlights

  • Auth Message Redirection: Changed console.log to console.error for auth-related messages, ensuring stdout remains clean for JSON-RPC and auth URLs are always visible to the user.
  • Headless Mode Environment Variable: Introduced GEMINI_CLI_WORKSPACE_HEADLESS and OAUTH_CALLBACK_PORT environment variables to enable authentication in headless/VM environments with port-forwarding, without attempting to launch a browser.
  • Improved Manual Flow Instructions: Enhanced the 'Success! Credentials Ready' page with detailed, OS-specific (Linux CLI, macOS, Windows) and collapsible instructions for storing credentials, including a clear server restart prompt.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request significantly improves the authentication experience for headless and remote VM environments. The changes are well-structured and address the key problems described. By redirecting authentication messages to stderr, you've cleanly separated them from the JSON-RPC protocol on stdout. The introduction of the GEMINI_CLI_WORKSPACE_HEADLESS environment variable provides a much-needed explicit way to handle non-GUI scenarios, and the updated instructions on the credentials page are a great improvement for user experience. My main feedback is a suggestion to refactor the duplicated logic for checking the headless mode environment variable into a shared utility function to improve code maintainability.

Comment on lines +160 to +161
const isHeadless = process.env['GEMINI_CLI_WORKSPACE_HEADLESS'] === 'true' ||
process.env['GEMINI_CLI_WORKSPACE_HEADLESS'] === '1';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This check for headless mode is duplicated in AuthManager.ts (here and on line 290) and in secure-browser-launcher.ts. To improve maintainability and avoid potential inconsistencies, it would be better to extract this logic into a single, shared utility function.

For example:

// In a shared utility file
export function isHeadlessMode(): boolean {
  const headlessEnv = process.env['GEMINI_CLI_WORKSPACE_HEADLESS'];
  return headlessEnv === 'true' || headlessEnv === '1';
}

You could then call isHeadlessMode() in all three places.

References
  1. Avoid duplicating code. Duplicated code makes the software harder to maintain. When a bug is found in a piece of duplicated code, it must be fixed in every place it appears.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant