Fix: Use mcp-go transport for CLI token refresh#381
Merged
Conversation
… 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>
- 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 refreshtokens. 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 loginevery 30 minutes even thougha 30-day refresh token existed. Agent and REPL flows had the same issue.
Changes
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.
HasCredentialsreplacesHasValidTokenonAuthHandlerinterface: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).
InvalidateCacheadded toAuthHandlerinterface: clears stalein-memory token cache after mcp-go's transport refreshes tokens externally.
ensureAuthenticatedAndGetStatushelper: single-round-trip connectivitycheck + auth status fetch, avoiding double connections.
parseAuthStatusResourcehelper: extracted shared auth://statusparsing (DRY).
runAuthStatususescmd.Context()for properCtrl+C cancellation.
loginToAllfor non-auth errors restored.Test plan
make test)muster test --parallel 50)TestTokenStore_HasCredentialscovers valid token, expired+refresh, expired-onlyTestAuthAdapter_HasCredentialscovers no-token case