- Run Prettier on the 60 core/ files this PR touched — the deterministic import rewrite had collapsed multi-line imports and left throws unwrapped; core/ is in no format gate so it slipped past CI. Now Prettier-clean. - Default-path output-schema violation now throws ProtocolError(ProtocolErrorCode.InvalidParams, …) instead of a bare Error, matching the prior v1 contract (SDK threw a typed McpError with a code) so downstream `instanceof`/`.code` branching keeps working. - Document the "assumes serial construction" invariant on pollTaskToolCall's progress-subscription revival (the `_progressHandlers` new-key heuristic). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
54 lines
1.8 KiB
TypeScript
54 lines
1.8 KiB
TypeScript
import {
|
|
discoverAuthorizationServerMetadata,
|
|
discoverOAuthProtectedResourceMetadata,
|
|
} from "@modelcontextprotocol/client";
|
|
import type { OAuthClientInformation } from "@modelcontextprotocol/client";
|
|
import { getAuthorizationServerUrl } from "./discovery.js";
|
|
import type { BaseOAuthClientProvider } from "./providers.js";
|
|
|
|
/**
|
|
* When the authorization server supports URL-based client IDs (SEP-991 / CIMD),
|
|
* pre-register `{ client_id: clientMetadataUrl }` before SDK `auth()`.
|
|
*
|
|
* SDK `auth()` rejects non-HTTPS `clientMetadataUrl` during registration, but
|
|
* accepts an already-stored `client_id` (including `http://` URLs used by local
|
|
* dev/test metadata servers). Production CIMD metadata documents should still
|
|
* use HTTPS per SEP-991.
|
|
*/
|
|
export async function ensureCimdClientRegistration(params: {
|
|
serverUrl: string;
|
|
provider: BaseOAuthClientProvider;
|
|
fetchFn?: typeof fetch;
|
|
}): Promise<void> {
|
|
const clientMetadataUrl = params.provider.clientMetadataUrl?.trim();
|
|
if (!clientMetadataUrl) return;
|
|
|
|
const existing = await params.provider.clientInformation();
|
|
if (existing?.client_id) return;
|
|
|
|
let resourceMetadata;
|
|
try {
|
|
resourceMetadata = await discoverOAuthProtectedResourceMetadata(
|
|
params.serverUrl,
|
|
);
|
|
} catch {
|
|
resourceMetadata = undefined;
|
|
}
|
|
|
|
const authServerUrl = getAuthorizationServerUrl(
|
|
params.serverUrl,
|
|
resourceMetadata,
|
|
);
|
|
|
|
const metadata = await discoverAuthorizationServerMetadata(authServerUrl, {
|
|
...(params.fetchFn && { fetchFn: params.fetchFn }),
|
|
});
|
|
if (!metadata?.client_id_metadata_document_supported) return;
|
|
|
|
const clientInformation: OAuthClientInformation = {
|
|
client_id: clientMetadataUrl,
|
|
};
|
|
await params.provider.saveClientInformation(clientInformation, {
|
|
registrationKind: "cimd",
|
|
});
|
|
}
|