Context
Workspace: asi-nz
Integration: granola (official MCP at https://mcp.granola.ai/mcp)
Connection: tools.granola.user.daniel
OAuth client: org DCR dcr-mcp-auth-granola-ai to mcp-auth.granola.ai
Symptom
Connection lastHealth.status became expired. Live tool call returned oauth_reauth_required / invalid_grant (HTTP 400 from mcp-auth.granola.ai on refresh).
Access expiresAt was about 2026-09-02; refresh rejected when probed 2026-09-11 NZ.
Why we think this is refresh-token rotation / persistence
Executor already attempts access-token refresh. Granola MCP OAuth commonly rotates the refresh token on each successful refresh. If the client does not persist the latest refresh_token from that response, the next refresh uses a stale refresh token and Granola returns invalid_grant, forcing a full browser re-auth.
Ask
- Confirm whether Executor persists rotated refresh tokens from refresh_token grant responses for MCP/DCR OAuth connections (especially WorkOS Vault-backed ones).
- If not, please fix so the newest refresh_token from the token endpoint replaces the stored one atomically.
- Optional: surface refresh failing / reauth soon before lastHealth expired so bots can oauth.start earlier.
Not asking for
A headless forever-token. Granola MCP is browser OAuth per user. We only want refresh to keep working for the lifetime Granola actually grants.
Context
Workspace: asi-nz
Integration: granola (official MCP at https://mcp.granola.ai/mcp)
Connection: tools.granola.user.daniel
OAuth client: org DCR dcr-mcp-auth-granola-ai to mcp-auth.granola.ai
Symptom
Connection lastHealth.status became expired. Live tool call returned oauth_reauth_required / invalid_grant (HTTP 400 from mcp-auth.granola.ai on refresh).
Access expiresAt was about 2026-09-02; refresh rejected when probed 2026-09-11 NZ.
Why we think this is refresh-token rotation / persistence
Executor already attempts access-token refresh. Granola MCP OAuth commonly rotates the refresh token on each successful refresh. If the client does not persist the latest refresh_token from that response, the next refresh uses a stale refresh token and Granola returns invalid_grant, forcing a full browser re-auth.
Ask
Not asking for
A headless forever-token. Granola MCP is browser OAuth per user. We only want refresh to keep working for the lifetime Granola actually grants.