Merge branch 'main' into dcr-fallback-fix

This commit is contained in:
Ola Hungerford 2025-08-13 05:34:14 -07:00 • committed by GitHub
commit ddd06c207c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 75 additions and 27 deletions

View file

@ -8,6 +8,7 @@ import {
OAuthMetadata,
} from "@modelcontextprotocol/sdk/shared/auth.js";
import { SESSION_KEYS, getServerSpecificKey } from "./constants";
import { generateOAuthState } from "@/utils/oauthUtils";
export const getClientInformationFromSessionStorage = async ({
serverUrl,
@ -86,6 +87,10 @@ export class InspectorOAuthClientProvider implements OAuthClientProvider {
};
}
state(): string | Promise<string> {
return generateOAuthState();
}
async clientInformation() {
// Try to get the preregistered client information from session storage first
const preregisteredClientInformation =
@ -129,6 +134,12 @@ export class InspectorOAuthClientProvider implements OAuthClientProvider {
}
redirectToAuthorization(authorizationUrl: URL) {
if (
authorizationUrl.protocol !== "http:" &&
authorizationUrl.protocol !== "https:"
) {
throw new Error("Authorization URL must be HTTP or HTTPS");
}
window.location.href = authorizationUrl.href;
}

View file

@ -351,6 +351,7 @@ export function useConnection({
return;
}
let lastRequest = "";
try {
// Inject auth manually instead of using SSEClientTransport, because we're
// proxying through the inspector server first.
@ -564,7 +565,9 @@ export function useConnection({
}
if (capabilities?.logging && defaultLoggingLevel) {
lastRequest = "logging/setLevel";
await client.setLoggingLevel(defaultLoggingLevel);
lastRequest = "";
}
if (onElicitationRequest) {
@ -578,6 +581,17 @@ export function useConnection({
setMcpClient(client);
setConnectionStatus("connected");
} catch (e) {
if (
lastRequest === "logging/setLevel" &&
e instanceof McpError &&
e.code === ErrorCode.MethodNotFound
) {
toast({
title: "Error",
description: `Server declares logging capability but doesn't implement method: "${lastRequest}"`,
variant: "destructive",
});
}
console.error(e);
setConnectionStatus("error");
}

View file

@ -1,7 +1,7 @@
import { OAuthStep, AuthDebuggerState } from "./auth-types";
import { DebugInspectorOAuthClientProvider } from "./auth";
import {
discoverOAuthMetadata,
discoverAuthorizationServerMetadata,
registerClient,
startAuthorization,
exchangeAuthorization,
@ -12,6 +12,7 @@ import {
OAuthMetadataSchema,
OAuthProtectedResourceMetadata,
} from "@modelcontextprotocol/sdk/shared/auth.js";
import { generateOAuthState } from "@/utils/oauthUtils";
export interface StateMachineContext {
state: AuthDebuggerState;
@ -56,7 +57,7 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
resourceMetadata ?? undefined,
);
const metadata = await discoverOAuthMetadata(authServerUrl);
const metadata = await discoverAuthorizationServerMetadata(authServerUrl);
if (!metadata) {
throw new Error("Failed to discover OAuth metadata");
}
@ -117,13 +118,6 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
scope = metadata.scopes_supported.join(" ");
}
// Generate a random state
const array = new Uint8Array(32);
crypto.getRandomValues(array);
const state = Array.from(array, (byte) =>
byte.toString(16).padStart(2, "0"),
).join("");
const { authorizationUrl, codeVerifier } = await startAuthorization(
context.serverUrl,
{
@ -131,7 +125,7 @@ export const oauthTransitions: Record<OAuthStep, StateTransition> = {
clientInformation,
redirectUrl: context.provider.redirectUrl,
scope,
state: state,
state: generateOAuthState(),
resource: context.state.resource ?? undefined,
},
);