Skip to content

Fix: Use mcp-go transport for CLI token refresh#381

Merged
teemow merged 4 commits intomainfrom
fix/cli-token-refresh-via-mcp
Feb 24, 2026
Merged

Fix: Use mcp-go transport for CLI token refresh#381
teemow merged 4 commits intomainfrom
fix/cli-token-refresh-via-mcp

Conversation

@teemow
Copy link
Member

@teemow teemow commented Feb 24, 2026

Summary

Leverage mcp-go's built-in token refresh in CLI auth commands to eliminate
unnecessary interactive re-login when a valid refresh token exists.

Problem

The CLI's local token validity check (HasValidToken) could not refresh
tokens. Token refresh only worked through mcp-go's transport layer (used
during MCP tool calls), but the CLI's auth commands bypassed that path
entirely. Users had to muster auth login every 30 minutes even though
a 30-day refresh token existed. Agent and REPL flows had the same issue.

Changes

  • CLI auth commands (status, login, login --server, login --all)
    now connect via mcp-go transport first, which refreshes expired tokens
    transparently before falling back to interactive browser login.
  • HasCredentials replaces HasValidToken on AuthHandler interface:
    returns true when a valid access token OR an expired token with a refresh
    token exists, preventing unnecessary login prompts in agent/REPL flows.
    Implemented across the full stack (TokenStore -> Client -> AuthManager ->
    AuthAdapter -> AuthHandler).
  • InvalidateCache added to AuthHandler interface: clears stale
    in-memory token cache after mcp-go's transport refreshes tokens externally.
  • ensureAuthenticatedAndGetStatus helper: single-round-trip connectivity
    check + auth status fetch, avoiding double connections.
  • parseAuthStatusResource helper: extracted shared auth://status
    parsing (DRY).
  • Context propagation: runAuthStatus uses cmd.Context() for proper
    Ctrl+C cancellation.
  • Soft-failure in loginToAll for non-auth errors restored.

Test plan

  • All unit tests pass (make test)
  • All 164 BDD scenarios pass (muster test --parallel 50)
  • TestTokenStore_HasCredentials covers valid token, expired+refresh, expired-only
  • TestAuthAdapter_HasCredentials covers no-token case

… checks

When the access token expires (30-minute TTL), CLI commands like `muster auth
status` reported "Not authenticated" even when a valid refresh token (30-day TTL)
existed. This happened because the CLI's local token validity check
(HasValidToken) couldn't refresh tokens -- only mcp-go's transport layer could.

Instead of duplicating refresh logic in the CLI, this change leverages the
existing mcp-go transport for all auth checks:

- `muster auth status` now connects via mcp-go first, which refreshes expired
  access tokens transparently. Falls back to local-only status when the server
  is unreachable.
- `muster auth login` tries mcp-go connection before opening the browser. If
  token refresh succeeds, reports "Already authenticated" without requiring
  user interaction.
- `muster auth login --server` and `--all` use the same approach.
- Added AuthAdapter.InvalidateCache() to clear stale in-memory token cache
  after mcp-go refreshes tokens to a different TokenStore instance.

Co-authored-by: Cursor <cursoragent@cursor.com>
@teemow teemow requested a review from a team as a code owner February 24, 2026 11:19
teemow and others added 3 commits February 24, 2026 12:29
- Add InvalidateCache to api.AuthHandler interface to eliminate type
  assertion against concrete cli.AuthAdapter (service locator pattern)
- Replace misleading "token refreshed" message with "Already authenticated"
- Use authPrint consistently instead of raw fmt.Printf (respects --quiet)
- Remove dead ShortAuthCheckTimeout constant
- Add logging.Debug on tryMCPConnection error path for debuggability
- Restore handler.Logout on 401 in auth status to clean up stale tokens
- Replace HasValidToken with mcp-go transport in logout guidance for
  consistent token refresh handling
- Introduce ensureAuthenticatedAndGetStatus to avoid double connections
  in loginToAll, loginToMCPServer, and showMCPServerLogoutGuidance

Co-authored-by: Cursor <cursoragent@cursor.com>
…terface

HasValidToken only checked for non-expired access tokens, causing
unnecessary interactive login prompts when a refresh token was available
that mcp-go's transport could use automatically. HasCredentials returns
true when either a valid access token or an expired token with a refresh
token exists, letting the transport handle refresh transparently.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Extract shared auth://status parsing into parseAuthStatusResource (DRY)
- Use cmd.Context() instead of context.Background() in runAuthStatus
- Remove trivial invalidateAuthCache wrapper, inline calls (KISS)
- Return error from tryMCPConnection for caller visibility
- Restore soft-failure in loginToAll for non-auth errors
- Remove unused logging import

Co-authored-by: Cursor <cursoragent@cursor.com>
@teemow teemow enabled auto-merge (squash) February 24, 2026 12:22
@teemow teemow disabled auto-merge February 24, 2026 12:28
@teemow teemow merged commit 4ce5281 into main Feb 24, 2026
5 of 6 checks passed
@teemow teemow deleted the fix/cli-token-refresh-via-mcp branch February 24, 2026 12:28
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