Skip to content

Commit 5dca3ed

Browse files
committed
working with quick and guided
1 parent 5158c22 commit 5dca3ed

File tree

5 files changed

+79
-65
lines changed

5 files changed

+79
-65
lines changed

client/src/App.tsx

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ const App = () => {
142142
>
143143
>([]);
144144
const [isAuthDebuggerVisible, setIsAuthDebuggerVisible] = useState(false);
145-
145+
146146
// Auth debugger state (moved from AuthDebugger component)
147147
const [authState, setAuthState] = useState<AuthDebuggerState>({
148148
isInitiatingAuth: false,
@@ -265,11 +265,17 @@ const App = () => {
265265
);
266266

267267
// Auto-connect to previously saved serverURL after OAuth callback
268-
const onOAuthDebugConnect = useCallback(() => {
268+
const onOAuthDebugConnect = useCallback((serverUrl: string, authorizationCode?: string) => {
269269
setIsAuthDebuggerVisible(true);
270+
if (authorizationCode) {
271+
updateAuthState({
272+
authorizationCode,
273+
oauthStep: "token_request",
274+
});
275+
}
270276
}, []);
271277

272-
// Load OAuth tokens when sseUrl changes (moved from AuthDebugger)
278+
// Load OAuth tokens when sseUrl changes
273279
useEffect(() => {
274280
const loadOAuthTokens = async () => {
275281
try {
@@ -296,20 +302,6 @@ const App = () => {
296302
loadOAuthTokens();
297303
}, [sseUrl]);
298304

299-
// Check for debug callback code (moved from AuthDebugger)
300-
useEffect(() => {
301-
const debugCode = sessionStorage.getItem(SESSION_KEYS.DEBUG_CODE);
302-
if (debugCode && sseUrl) {
303-
updateAuthState({
304-
authorizationCode: debugCode,
305-
oauthStep: "token_request",
306-
});
307-
308-
// Now that we've processed it, clear the debug code
309-
sessionStorage.removeItem(SESSION_KEYS.DEBUG_CODE);
310-
}
311-
}, [sseUrl]);
312-
313305
useEffect(() => {
314306
fetch(`${getMCPProxyAddress(config)}/config`)
315307
.then((response) => response.json())
@@ -558,7 +550,7 @@ const App = () => {
558550
// Helper function to render OAuth callback components
559551
const renderOAuthCallback = (
560552
path: string,
561-
onConnect: (serverUrl: string) => void,
553+
onConnect: (serverUrl: string, authorizationCode?: string) => void,
562554
) => {
563555
const Component =
564556
path === "/oauth/callback"

client/src/components/AuthDebugger.tsx

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import {
88
startAuthorization,
99
exchangeAuthorization,
1010
} from "@modelcontextprotocol/sdk/client/auth.js";
11-
import { SESSION_KEYS } from "../lib/constants";
1211
import {
1312
OAuthMetadataSchema,
1413
OAuthMetadata,
1514
OAuthClientInformation,
1615
} from "@modelcontextprotocol/sdk/shared/auth.js";
1716
import { CheckCircle2, Circle, ExternalLink, AlertCircle } from "lucide-react";
1817
import { AuthDebuggerState } from "../lib/auth-types";
18+
import { SESSION_KEYS, getServerSpecificKey } from "../lib/constants";
1919

2020
interface AuthDebuggerProps {
2121
sseUrl: string;
@@ -24,38 +24,58 @@ interface AuthDebuggerProps {
2424
updateAuthState: (updates: Partial<AuthDebuggerState>) => void;
2525
}
2626

27-
// Enhanced version of the OAuth client provider specifically for debug flows
27+
// Overrides debug URL and allows saving server OAuth metadata to
28+
// display in debug UI.
2829
class DebugInspectorOAuthClientProvider extends InspectorOAuthClientProvider {
2930
get redirectUrl(): string {
3031
return `${window.location.origin}/oauth/callback/debug`;
3132
}
33+
34+
saveServerMetadata(metadata: OAuthMetadata) {
35+
const key = getServerSpecificKey(
36+
SESSION_KEYS.SERVER_METADATA,
37+
this.serverUrl,
38+
);
39+
sessionStorage.setItem(key, JSON.stringify(metadata));
40+
}
41+
42+
getServerMetadata(): OAuthMetadata | null {
43+
const key = getServerSpecificKey(
44+
SESSION_KEYS.SERVER_METADATA,
45+
this.serverUrl,
46+
);
47+
const metadata = sessionStorage.getItem(key);
48+
if (!metadata) {
49+
return null;
50+
}
51+
return JSON.parse(metadata);
52+
}
3253
}
3354

34-
const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebuggerProps) => {
35-
// Load client info asynchronously when we have a debug code
36-
useEffect(() => {
37-
const debugCode = sessionStorage.getItem(SESSION_KEYS.DEBUG_CODE);
38-
if (debugCode && sseUrl && authState.oauthStep === "token_request") {
39-
// Load client info asynchronously
40-
const provider = new DebugInspectorOAuthClientProvider(sseUrl);
41-
provider
42-
.clientInformation()
43-
.then((info) => {
44-
updateAuthState({ oauthClientInfo: info || null });
45-
})
46-
.catch((error) => {
47-
console.error("Failed to load client information:", error);
48-
});
55+
const AuthDebugger = ({
56+
sseUrl,
57+
onBack,
58+
authState,
59+
updateAuthState,
60+
}: AuthDebuggerProps) => {
61+
// Load client info asynchronously when we're at the token_request step
62+
63+
const validateOAuthMetadata = async (
64+
provider: DebugInspectorOAuthClientProvider,
65+
): Promise<OAuthMetadata> => {
66+
const metadata = provider.getServerMetadata();
67+
if (metadata) {
68+
return metadata;
4969
}
50-
}, [sseUrl, authState.oauthStep, updateAuthState]);
5170

52-
const validateOAuthMetadata = (
53-
metadata: OAuthMetadata | null,
54-
): OAuthMetadata => {
55-
if (!metadata) {
56-
throw new Error("Can't advance without successfully fetching metadata");
71+
const fetchedMetadata = await discoverOAuthMetadata(sseUrl);
72+
if (!fetchedMetadata) {
73+
throw new Error("Failed to discover OAuth metadata");
5774
}
58-
return metadata;
75+
const parsedMetadata =
76+
await OAuthMetadataSchema.parseAsync(fetchedMetadata);
77+
78+
return parsedMetadata;
5979
};
6080

6181
const validateClientInformation = async (
@@ -108,8 +128,9 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
108128
}
109129
const parsedMetadata = await OAuthMetadataSchema.parseAsync(metadata);
110130
updateAuthState({ oauthMetadata: parsedMetadata });
131+
provider.saveServerMetadata(parsedMetadata);
111132
} else if (authState.oauthStep === "metadata_discovery") {
112-
const metadata = validateOAuthMetadata(authState.oauthMetadata);
133+
const metadata = await validateOAuthMetadata(provider);
113134

114135
updateAuthState({ oauthStep: "client_registration" });
115136

@@ -127,7 +148,7 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
127148
provider.saveClientInformation(fullInformation);
128149
updateAuthState({ oauthClientInfo: fullInformation });
129150
} else if (authState.oauthStep === "client_registration") {
130-
const metadata = validateOAuthMetadata(authState.oauthMetadata);
151+
const metadata = await validateOAuthMetadata(provider);
131152
const clientInformation = await validateClientInformation(provider);
132153
updateAuthState({ oauthStep: "authorization_redirect" });
133154
try {
@@ -158,7 +179,10 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
158179
);
159180
}
160181
} else if (authState.oauthStep === "authorization_code") {
161-
if (!authState.authorizationCode || authState.authorizationCode.trim() === "") {
182+
if (
183+
!authState.authorizationCode ||
184+
authState.authorizationCode.trim() === ""
185+
) {
162186
updateAuthState({
163187
validationError: "You need to provide an authorization code",
164188
});
@@ -167,7 +191,7 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
167191
updateAuthState({ validationError: null, oauthStep: "token_request" });
168192
} else if (authState.oauthStep === "token_request") {
169193
const codeVerifier = provider.codeVerifier();
170-
const metadata = validateOAuthMetadata(authState.oauthMetadata);
194+
const metadata = await validateOAuthMetadata(provider);
171195
const clientInformation = await validateClientInformation(provider);
172196

173197
const tokens = await exchangeAuthorization(sseUrl, {
@@ -285,6 +309,7 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
285309
}, [authState.statusMessage]);
286310

287311
const renderOAuthFlow = useCallback(() => {
312+
const provider = new DebugInspectorOAuthClientProvider(sseUrl);
288313
const steps = [
289314
{
290315
key: "not_started",
@@ -294,14 +319,14 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
294319
{
295320
key: "metadata_discovery",
296321
label: "Metadata Discovery",
297-
metadata: authState.oauthMetadata && (
322+
metadata: provider.getServerMetadata() && (
298323
<details className="text-xs mt-2">
299324
<summary className="cursor-pointer text-muted-foreground font-medium">
300325
Retrieved OAuth Metadata from {sseUrl}
301326
/.well-known/oauth-authorization-server
302327
</summary>
303328
<pre className="mt-2 p-2 bg-muted rounded-md overflow-auto max-h-[300px]">
304-
{JSON.stringify(authState.oauthMetadata, null, 2)}
329+
{JSON.stringify(provider.getServerMetadata(), null, 2)}
305330
</pre>
306331
</details>
307332
),
@@ -491,15 +516,17 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
491516
authState.authorizationUrl && (
492517
<Button
493518
variant="outline"
494-
onClick={() => window.open(authState.authorizationUrl!, "_blank")}
519+
onClick={() =>
520+
window.open(authState.authorizationUrl!, "_blank")
521+
}
495522
>
496523
Open in New Tab
497524
</Button>
498525
)}
499526
</div>
500527
</div>
501528
);
502-
}, [authState, sseUrl]);
529+
}, [authState, sseUrl, proceedToNextStep, updateAuthState]);
503530

504531
return (
505532
<div className="w-full p-4">
@@ -581,4 +608,4 @@ const AuthDebugger = ({ sseUrl, onBack, authState, updateAuthState }: AuthDebugg
581608
);
582609
};
583610

584-
export default AuthDebugger;
611+
export default AuthDebugger;

client/src/components/OAuthDebugCallback.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
} from "@/utils/oauthUtils.ts";
88

99
interface OAuthCallbackProps {
10-
onConnect: (serverUrl: string) => void;
10+
onConnect: (serverUrl: string, authorizationCode?: string) => void;
1111
}
1212

1313
const OAuthDebugCallback = ({ onConnect }: OAuthCallbackProps) => {
@@ -50,18 +50,17 @@ const OAuthDebugCallback = ({ onConnect }: OAuthCallbackProps) => {
5050
return notifyError("Missing authorization code");
5151
}
5252

53-
sessionStorage.setItem(SESSION_KEYS.DEBUG_CODE, params.code);
53+
// Instead of storing in sessionStorage, pass the code directly
54+
// to the auth state manager through onConnect
55+
onConnect(serverUrl, params.code);
5456

55-
// Finally, trigger navigation back to auth debugger
57+
// Show success message
5658
toast({
5759
title: "Success",
5860
description:
59-
"Authorization code received. Please return to the Auth Debugger.",
61+
"Authorization code received. Returning to the Auth Debugger.",
6062
variant: "default",
6163
});
62-
63-
// Call onConnect to navigate back to the auth debugger
64-
onConnect(serverUrl);
6564
};
6665

6766
handleCallback().finally(() => {
@@ -99,4 +98,4 @@ const OAuthDebugCallback = ({ onConnect }: OAuthCallbackProps) => {
9998
);
10099
};
101100

102-
export default OAuthDebugCallback;
101+
export default OAuthDebugCallback;

client/src/lib/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
import { SESSION_KEYS, getServerSpecificKey } from "./constants";
99

1010
export class InspectorOAuthClientProvider implements OAuthClientProvider {
11-
constructor(private serverUrl: string) {
11+
constructor(protected serverUrl: string) {
1212
// Save the server URL to session storage
1313
sessionStorage.setItem(SESSION_KEYS.SERVER_URL, serverUrl);
1414
}

client/src/lib/constants.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ export const SESSION_KEYS = {
66
SERVER_URL: "mcp_server_url",
77
TOKENS: "mcp_tokens",
88
CLIENT_INFORMATION: "mcp_client_information",
9-
/**
10-
* Temporary storage for OAuth authorization code during debug flow
11-
* Used when authentication is done in a separate tab
12-
*/
13-
DEBUG_CODE: "mcp_code",
9+
SERVER_METADATA: "mcp_server_metadata",
1410
} as const;
1511

1612
// Generate server-specific session storage keys

0 commit comments

Comments
 (0)