Custom MCP connector: token refresh fires on every chat turn, but the model says the tool is not connected (no MCP call made)

Setup: Gemini Enterprise trial, custom MCP connector (custom_mcp) to our own MCP server, OAuth 2.1 + PKCE against our own IdP. Actions were enabled via the public “PATCH dataConnector?updateMask=bapConfig” workaround (the console Reload custom actions 401 is covered in Gemini Enterprise Custom MCP: "Reload custom actions" always fails with 401 - UI uses API key instead of OAuth token ). Per-user Authorize works, tools/list is fetched, and in some chats the model calls our tools and we serve them.

The problem: in most chats the actions never reach the model. Repro (2026-08-20, UTC): three fresh chats, one prompt each naming the connector action, sent 15:23:28 / 15:25:07 / 15:26:13. Our IdP logged a successful refresh_token grant from Google infrastructure 4 seconds after each prompt (15:23:32, 15:25:11, 15:26:17). Each time the model replied the tool “is not currently connected” or “not available in my configured tools”. Our edge logs show zero requests from Google ranges in the window at any status. So the connector runtime engages and refreshes the token on every turn, while the model toolset never receives the actions. Binding looks nondeterministic per chat (earlier the same day 3 of 6 chats bound and worked).

Two more observations from the same day. The authorize flow once produced two logins one second apart, after which the backend redeemed one code and failed the other with pkce_verification_failed (racing OAuth legs). And in one unbound chat the UI rendered a tool activity step named after our connector with web citation chips attached, while our server received no request. For a data-source vendor, a fabricated tool step with mislabeled citations is worse than the binding failure itself.

Anyone else seeing per-chat binding roulette with custom MCP connectors, or found a way to force binding? Happy to share more repro detail.

Same symptom here on a Standard subscription with a custom MCP connector (Streamable HTTP, OAuth 2.0 with PKCE and refresh tokens), and it now works. For anyone landing here, what finally bound the tools for us, after everything else was already in place (connector Active, action state ACTIVE, Reload custom actions listing the tools, bapConfig.enabledActions set, per-user authorization stored):

  1. Make sure the Connectors API (connectors.googleapis.com) and the Secret Manager API are enabled BEFORE the connector is created. Ours was created with them off; the connector showed Active but its action state stayed empty and Reload custom actions did nothing. Enabling the two APIs and then using Re-authenticate on the data store page fixed the action state.

  2. The console button Enable actions does write bapConfig.enabledActions (verified by clearing the list via the API and reading it back after the click), but the Status column never changes from Disabled. Ignore the column.

  3. In the web app: open the chat source picker (the puzzle-piece button next to the plus in the input bar), click Authorise on the connector row, reload the page, open the picker again (the row now shows a switch, on), start a new chat and ask. That was the step that made the assistant receive the tools. It is the same cure as the disable/enable then refresh described in the 4 September thread.

We saw the token refresh on every turn with no MCP call, exactly as described, right up until step 3. Two fresh chats afterwards both called the tools without any further toggling. Google fetched our tools/list during Reload custom actions but never called a tool until the per-user Authorise plus reload. Scripted clicks on Verify Auth, Reload and Authorise do nothing; they need a real mouse click.