Repository navigation
Description
Description
When running opencode mcp auth gdrive to authenticate with the Google Drive MCP server, the command outputs "Authentication successful!" but the OAuth flow never completes. The browser never opens, and no tokens are saved.
- opencode mcp auth gdrive starts the OAuth flow but fails to open the browser (mcp.browser.open.failed in logs)
- Without the browser opening, the user can't authorize, so no tokens are received
- The command incorrectly says "Authentication successful!" even though it failed
- All GDrive operations return "Unauthorized"
Expected behavior:
- Browser should open with Google OAuth authorization URL
- After authorizing, tokens should be saved to ~/.local/share/opencode/mcp-auth.json
- opencode mcp auth list should show "authenticated"
Actual behavior: - Logs show mcp.browser.open.failed event
- No browser window opens
- Command prints "Authentication successful!" incorrectly
- Tokens file ends up as {"gdrive": {}} (empty)
- All GDrive operations return "Unauthorized"
Environment:
- OS: Ubuntu 24.04.4 LTS (Noble Numbat)
- Kernel: 6.17.0-22-generic
- OpenCode version: 1.14.39
- MCP server: Google Drive (https://drivemcp.googleapis.com/mcp/v1)
Logs:
INFO service=mcp.oauth-callback port=19876 path=/mcp/oauth/callback oauth callback server started
...
INFO service=bus type=mcp.browser.open.failed subscribing
...
◇ Authentication successful!
Additional context:
The opencode mcp debug gdrive command reports "Server responded successfully (no auth required or already authenticated)" because the Drive MCP server returns HTTP 200 even without authentication, so OpenCode doesn't detect that OAuth is needed until tools are actually called.
Plugins
MCP server: Google Drive (https://drivemcp.googleapis.com/mcp/v1)
OpenCode version
1.14.39
Steps to reproduce
-
Configure Google Drive MCP in opencode.json:
{
mcp: {
gdrive: {
type: remote,
url: https://drivemcp.googleapis.com/mcp/v1,
oauth: {
clientId: ...,
clientSecret: ...,
scope: https://www.googleapis.com/auth/drive.readonly https://www.googleapis.com/auth/drive.file
}
}
}
} -
Run opencode mcp auth gdrive --print-logs
Screenshot and/or share link
Operating System
Ubuntu 24.04.4 LTS (Noble Numbat)
Terminal
ps (bash)
Activity
github-actions commentedon May 7, 2026
This issue might be a duplicate of existing issues. Please check:
If your issue is indeed distinct (e.g., specific to the
mcp authCLI command rather than automatic OAuth triggering, or specific to the "Authentication successful!" false positive message), please add context clarifying how it differs.yanniznik commentedon May 11, 2026
I investigated this from the OpenCode binary and MCP protocol level. The core issue is that Google's MCP servers don't expose OAuth discovery, so OpenCode has no way to initiate the OAuth flow.
How OAuth works for servers that DO work (e.g., Slack)
Slack exposes
/.well-known/oauth-authorization-serverat its MCP URL:OpenCode discovers this → constructs the authorization URL → opens browser → user consents → callback delivers code → token exchange completes. This flow works reliably.
Why Google MCP servers fail
Google's MCP endpoints return 404 for OAuth discovery:
Additionally, Google's servers respond 200 to
initializeandtools/listwithout any authentication. Auth is only enforced ontools/call. So OpenCode:What OpenCode has available but doesn't use
The
opencode.jsonconfig already has the OAuth client config:Proposed fix
When a server doesn't expose
/.well-known/oauth-authorization-serverbut the config has anoauthblock withclientId/clientSecret/scope, OpenCode should fall back to client-side OAuth configuration using Google's standard endpoints:https://accounts.google.com/o/oauth2/v2/authhttps://oauth2.googleapis.com/tokenThis would also fix BigQuery MCP and any other Google MCP server.
Confirmed working services (once tokens are manually injected)
Using manually obtained tokens written to
mcp-auth.json, all Google MCP servers work:Environment
romybompart commentedon May 25, 2026
I have similar issue:
(base) PS C:\Users\Romy1> opencode mcp auth drive
T MCP OAuth Authentication
|
o Authentication successful!
|
— Done
(base) PS C:\Users\Romy1> opencode mcp auth list
T MCP OAuth Status
|
• ✗ drive not authenticated
| https://drivemcp.googleapis.com/mcp/v1
|
— 1 OAuth-capable server(s)
romybompart commentedon May 25, 2026
I was able to fix this by using the following script.
prior to that I make sure I logout from the mcp using;
opencode mcp logout google-drive-mcpScript:
``
<#
.SYNOPSIS
Configure and authenticate OpenCode's Google Drive MCP server.
.DESCRIPTION
OpenCode currently can report Google Drive MCP as connected before OAuth tokens
are stored, because the Drive MCP endpoint allows the initial MCP handshake
without user authorization. This script performs the Google OAuth flow directly,
then writes tokens to OpenCode's MCP auth store in the format OpenCode expects.
Required environment variables:
GOOGLE_DRIVE_MCP_CLIENT_ID
GOOGLE_DRIVE_MCP_CLIENT_SECRET
After this script succeeds, restart OpenCode so the running MCP client reloads
the token from ~/.local/share/opencode/mcp-auth.json.
#>
[CmdletBinding()]
param(
[string]$ServerName = "drive",
[string]$ServerUrl = "https://drivemcp.googleapis.com/mcp/v1",
[int]$CallbackPort = 19876,
[string]$CallbackPath = "/mcp/oauth/callback",
[string]$ConfigPath = (Join-Path $HOME ".config\opencode\opencode.json"),
[string]$AuthPath = (Join-Path $HOME ".local\share\opencode\mcp-auth.json"),
[switch]$SkipConfigUpdate
)
$ErrorActionPreference = "Stop"
$Scopes = @(
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/drive.file"
)
$Scope = $Scopes -join " "
function New-Base64UrlRandomString {
param([int]$ByteCount = 32)
}
function ConvertTo-Base64UrlSha256 {
param([Parameter(Mandatory = $true)][string]$Value)
}
function ConvertTo-UrlEncoded {
param([Parameter(Mandatory = $true)][string]$Value)
}
function Ensure-Directory {
param([Parameter(Mandatory = $true)][string]$Path)
}
function Add-OrSetProperty {
param(
[Parameter(Mandatory = $true)]$Object,
[Parameter(Mandatory = $true)][string]$Name,
[Parameter(Mandatory = $true)]$Value
)
}
function Write-JsonFile {
param(
[Parameter(Mandatory = $true)][string]$Path,
[Parameter(Mandatory = $true)]$Value
)
}
function Ensure-DriveMcpConfig {
param(
[Parameter(Mandatory = $true)][string]$Path,
[Parameter(Mandatory = $true)][string]$Name,
[Parameter(Mandatory = $true)][string]$Url,
[Parameter(Mandatory = $true)][string]$ScopeValue
)
}
function Update-McpAuthFile {
param(
[Parameter(Mandatory = $true)][string]$Path,
[Parameter(Mandatory = $true)][string]$Name,
[Parameter(Mandatory = $true)][string]$Url,
[Parameter(Mandatory = $true)]$TokenResponse
)
}
function Invoke-OpenCodeAuthStatus {
$command = Get-Command opencode -ErrorAction SilentlyContinue
if (-not $command) {
Write-Warning "opencode was not found on PATH. Tokens were written, but auth status could not be verified."
return
}
}
$clientId = $env:GOOGLE_DRIVE_MCP_CLIENT_ID
$clientSecret = $env:GOOGLE_DRIVE_MCP_CLIENT_SECRET
if (-not $clientId) {
throw "Missing GOOGLE_DRIVE_MCP_CLIENT_ID environment variable."
}
if (-not $clientSecret) {
throw "Missing GOOGLE_DRIVE_MCP_CLIENT_SECRET environment variable."
}
if (-not $SkipConfigUpdate) {
Ensure-DriveMcpConfig -Path $ConfigPath -Name $ServerName -Url $ServerUrl -ScopeValue $Scope
Write-Host "Updated OpenCode MCP config: $ConfigPath"
}
$redirectUri = "http://127.0.0.1:$CallbackPort$CallbackPath"
$state = New-Base64UrlRandomString
$codeVerifier = New-Base64UrlRandomString
$codeChallenge = ConvertTo-Base64UrlSha256 -Value $codeVerifier
$listener = [System.Net.HttpListener]::new()
try {
$listener.Prefixes.Add("http://127.0.0.1:$CallbackPort/")
$listener.Start()
}
finally {
if ($listener.IsListening) {
$listener.Stop()
}
$listener.Close()
}
aloussase commentedon Jun 23, 2026
Hi, is there any workaround?
I am having the same issue.
I am logged in to the GMAIL MCP but opencode always says it's unauthorized.
This is the output of debug:
kebab-casee commentedon Jul 27, 2026
Try composio
EgilSandfeld commentedon Aug 6, 2026
Still reproducible on OpenCode 1.18.10 on Windows 25H2, build 26200.8875.
I tested Google's official hosted MCP servers:
https://drivemcp.googleapis.com/mcp/v1https://docsmcp.googleapis.com/mcp/v1https://sheetsmcp.googleapis.com/mcp/v1Each uses a pre-registered Google Desktop OAuth client with explicit
clientId,clientSecret, read-only scopes, and callbackhttp://127.0.0.1:19876/mcp/oauth/callback.For all three:
opencode mcp auth <server>immediately reportsAuthentication successful!opencode mcp auth listreportsnot authenticated.mcp-auth.jsoncontains an entry for each server, but no token or server URL is stored.opencode mcp liststill reports the servers as connected because the unauthenticated MCP handshake returns HTTP 200.This confirms the issue remains present in 1.18.10 and is not Drive-specific; Docs and Sheets exhibit the same false-success behavior.
dr-kristau commentedon Aug 6, 2026
This is also a problem with Google GMail access. The following bug report was automatically created:
Bug:
opencode mcp auth gmailOAuth flow succeeds but token is not persistedEnvironment
gmail(remote, Google MCP —https://gmailmcp.googleapis.com/mcp/v1)Config (
~/.config/opencode/opencode.json)Steps to reproduce
opencode mcp debug gmail— showsAuth status: ✗ not authenticatedopencode mcp auth gmail— reportsAuthentication successful!andDoneopencode mcp debug gmailagain — still showsAuth status: ✗ not authenticatedgmail_search_threads) returnsUnauthorized~/.config/opencode/Expected behavior
After
opencode mcp auth gmailreports success, the OAuth token should be persisted so that:opencode mcp debug gmailreportsAuth status: ✓ authenticatedgmail_search_threadsreturns data, notUnauthorized)Actual behavior
The OAuth flow completes successfully on the browser side, and opencode prints
Authentication successful!, but no token is persisted. The auth state remainsnot authenticatedand all tool calls are rejected withUnauthorized.Additional notes
StatelessServer(debug output:{"name":"StatelessServer","version":"ESF"}), so it requires an auth token on every request — there is no session-level auth handshake.https://gmailmcp.googleapis.com/mcp/v1).mcp-atlassian) work correctly, so the issue is specific to the OAuth flow persistence.jonhydetitanbay commentedon Sep 10, 2026
Reproduced with Gmail on macOS
Environment
opencode-ainpm packagexterm-256color/bin/zshhttps://gmailmcp.googleapis.com/mcp/v1Reproduction
opencode mcp auth gmail.Authentication successful!, although no Google consent page is completed and the Gmail entry in~/.local/share/opencode/mcp-auth.jsonis empty.opencode mcp auth list; Gmail remainsnot authenticated.list_labelsorget_thread.Actual behaviour
Every Gmail tool call fails consistently with:
The MCP extensions screen shows only an enable/disable toggle, so it offers no route to enter the pre-registered OAuth client credentials that Google's hosted MCP servers require.
Google Calendar and Google Drive show the same unauthenticated state. Other remote MCP servers, including Notion, authenticate and execute correctly.
Expected behaviour
OpenCode should not report authentication success when no token was obtained or persisted. For an authorization server that does not support dynamic client registration, it should give an actionable error before claiming success, such as requiring
oauth.client_idandoauth.client_secretand pointing the user to configuration.Google documents that its hosted Workspace MCP servers do not support dynamic client registration, so the current success message leaves the user unable to distinguish a missing static OAuth client configuration from a completed login.
jethac commentedon Oct 6, 2026
Hit this today setting up Google's official MCP connectors — the first-party Gmail, Drive, and Calendar servers at
gmailmcp/drivemcp/calendarmcp.googleapis.com— using an OAuth client created in Google Cloud exactly as Google's own MCP setup docs instruct. So anyone following the official path lands on this bug. The mechanism, for whoever picks it up:Google's MCP endpoints accept
initialize— andpingandtools/list— without credentials (HTTP 200). Onlytools/callreturns 401, with a properWWW-Authenticate: Bearer resource_metadata=...challenge. Since opencode only triggers the OAuth flow on a connect-time 401,startAuth()'sclient.connect()succeeds,commit()stores nothing, and the CLI reports "Authentication successful!" — while every tool call dead-ends asUnauthorized.Repro (no opencode needed):
I've opened #53468 with a fix: persist the discovery state from 401 challenges via the SDK's
discoveryState/saveDiscoveryStatehooks, explicitly start the flow instartAuth()when there's evidence OAuth is required, flip request-time 401s toneeds_auth, and add anauthorizationServerUrlconfig escape hatch. Approach follows the one proposed in #26912.0xuwin commentedon Oct 9, 2026
Sharing a Python script that runs the OAuth PKCE flow directly against Google's standard endpoints and prints an entry in
mcp-auth.jsonformat. Note that you should addhttp://127.0.0.1:19876/mcp/oauth/callback(opencode's default callback, which the script listens on) to the Authorized redirect URIs of your Google OAuth client, otherwise Google rejects withredirect_uri_mismatch.thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊