11import { useCallback , useMemo } from "react" ;
22import { Button } from "@/components/ui/button" ;
33import { DebugInspectorOAuthClientProvider } from "../lib/auth" ;
4- import {
5- auth ,
6- discoverOAuthMetadata ,
7- } from "@modelcontextprotocol/sdk/client/auth.js" ;
8- import { OAuthMetadataSchema } from "@modelcontextprotocol/sdk/shared/auth.js" ;
94import { AlertCircle } from "lucide-react" ;
105import { AuthDebuggerState } from "../lib/auth-types" ;
116import { OAuthFlowProgress } from "./OAuthFlowProgress" ;
@@ -124,22 +119,43 @@ const AuthDebugger = ({
124119
125120 updateAuthState ( { isInitiatingAuth : true , statusMessage : null } ) ;
126121 try {
127- const serverAuthProvider = new DebugInspectorOAuthClientProvider (
128- serverUrl ,
129- ) ;
130- // First discover OAuth metadata separately so we can save it
131- const metadata = await discoverOAuthMetadata ( serverUrl ) ;
132- if ( ! metadata ) {
133- throw new Error ( "Failed to discover OAuth metadata" ) ;
122+ // Step through the OAuth flow using the state machine instead of the auth() function
123+ let currentState : AuthDebuggerState = {
124+ ...authState ,
125+ oauthStep : "metadata_discovery" ,
126+ authorizationUrl : null ,
127+ latestError : null ,
128+ } ;
129+
130+ const oauthMachine = new OAuthStateMachine ( serverUrl , ( updates ) => {
131+ // Update our temporary state during the process
132+ currentState = { ...currentState , ...updates } ;
133+ // But don't call updateAuthState yet
134+ } ) ;
135+
136+ // Manually step through each stage of the OAuth flow
137+ while ( currentState . oauthStep !== "complete" ) {
138+ await oauthMachine . executeStep ( currentState ) ;
139+ // In quick mode, we'll just redirect to the authorization URL
140+ if (
141+ currentState . oauthStep === "authorization_code" &&
142+ currentState . authorizationUrl
143+ ) {
144+ // Open the authorization URL automatically
145+ window . location . href = currentState . authorizationUrl ;
146+ break ;
147+ }
134148 }
135- const parsedMetadata = await OAuthMetadataSchema . parseAsync ( metadata ) ;
136- serverAuthProvider . saveServerMetadata ( parsedMetadata ) ;
137149
138- await auth ( serverAuthProvider , { serverUrl : serverUrl } ) ;
150+ // After the flow completes or reaches a user-input step, update the app state
139151 updateAuthState ( {
152+ ...currentState ,
140153 statusMessage : {
141154 type : "info" ,
142- message : "Starting OAuth authentication process..." ,
155+ message :
156+ currentState . oauthStep === "complete"
157+ ? "Authentication completed successfully"
158+ : "Please complete authentication in the opened window and enter the code" ,
143159 } ,
144160 } ) ;
145161 } catch ( error ) {
@@ -153,7 +169,7 @@ const AuthDebugger = ({
153169 } finally {
154170 updateAuthState ( { isInitiatingAuth : false } ) ;
155171 }
156- } , [ serverUrl , updateAuthState ] ) ;
172+ } , [ serverUrl , updateAuthState , authState ] ) ;
157173
158174 const handleClearOAuth = useCallback ( ( ) => {
159175 if ( serverUrl ) {
0 commit comments