Address @claude review: format core/, typed output-validation error, document progress heuristic

- 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>
This commit is contained in:
cliffhall 2026-07-15 11:08:54 -04:00
commit f9f79fff54
5 changed files with 296 additions and 95 deletions

View file

@ -1,5 +1,12 @@
import { discoverAuthorizationServerMetadata, exchangeAuthorization, startAuthorization } from "@modelcontextprotocol/client";
import type { OAuthClientInformation, OAuthMetadata } from "@modelcontextprotocol/client";
import {
discoverAuthorizationServerMetadata,
exchangeAuthorization,
startAuthorization,
} from "@modelcontextprotocol/client";
import type {
OAuthClientInformation,
OAuthMetadata,
} from "@modelcontextprotocol/client";
import { OAuthMetadataSchema } from "@modelcontextprotocol/core";
import type { OAuthStorage } from "../storage.js";
import type { EnterpriseManagedAuthIdpConfig } from "../../client/types.js";
@ -44,7 +51,9 @@ export async function discoverIdpMetadata(
fetchFn,
});
if (!metadata) {
throw new Error(`Failed to discover OIDC metadata for IdP issuer ${issuer}`);
throw new Error(
`Failed to discover OIDC metadata for IdP issuer ${issuer}`,
);
}
return OAuthMetadataSchema.parse(metadata);
}
@ -56,7 +65,11 @@ export async function startIdpOidcAuthorization(params: {
fetchFn?: typeof fetch;
}): Promise<{ authorizationUrl: URL }> {
const issuer = normalizeIdpIssuer(params.idp.issuer);
const metadata = await resolveIdpMetadata(issuer, params.storage, params.fetchFn);
const metadata = await resolveIdpMetadata(
issuer,
params.storage,
params.fetchFn,
);
const clientInformation = idpClientInformation(params.idp);
const storageKey = idpOAuthStorageKey(issuer);
const state = generateOAuthState();

View file

@ -1,4 +1,8 @@
import { discoverAuthorizationServerMetadata, discoverOAuthProtectedResourceMetadata, selectResourceURL } from "@modelcontextprotocol/client";
import {
discoverAuthorizationServerMetadata,
discoverOAuthProtectedResourceMetadata,
selectResourceURL,
} from "@modelcontextprotocol/client";
import type { OAuthClientProvider } from "@modelcontextprotocol/client";
import type { OAuthProtectedResourceMetadata } from "@modelcontextprotocol/client";
import { getAuthorizationServerUrl } from "../discovery.js";

View file

@ -1,5 +1,8 @@
import { selectClientAuthMethod } from "@modelcontextprotocol/client";
import type { OAuthClientInformation, OAuthMetadata } from "@modelcontextprotocol/client";
import type {
OAuthClientInformation,
OAuthMetadata,
} from "@modelcontextprotocol/client";
export async function parseOAuthTokenErrorResponse(
response: Response,

View file

@ -1,5 +1,9 @@
import type { OAuthClientProvider } from "@modelcontextprotocol/client";
import type { OAuthClientInformationMixed, OAuthClientMetadata, OAuthTokens } from "@modelcontextprotocol/client";
import type {
OAuthClientInformationMixed,
OAuthClientMetadata,
OAuthTokens,
} from "@modelcontextprotocol/client";
import type { BaseOAuthClientProvider } from "../providers.js";
import {
refreshEmaResourceTokens,
@ -8,10 +12,7 @@ import {
} from "./emaFlow.js";
import { isJwtExpired } from "./jwt.js";
function isAccessTokenUsable(
tokens: OAuthTokens,
skewMs = 60_000,
): boolean {
function isAccessTokenUsable(tokens: OAuthTokens, skewMs = 60_000): boolean {
if (!tokens.access_token) return false;
return !isJwtExpired(tokens.access_token, skewMs);
}
@ -28,10 +29,7 @@ export class EmaTransportOAuthProvider implements OAuthClientProvider {
private readonly inner: BaseOAuthClientProvider;
private readonly emaConfig: EmaFlowConfig;
constructor(
inner: BaseOAuthClientProvider,
emaConfig: EmaFlowConfig,
) {
constructor(inner: BaseOAuthClientProvider, emaConfig: EmaFlowConfig) {
this.inner = inner;
this.emaConfig = emaConfig;
}

View file

@ -1,5 +1,8 @@
import { discoverAuthorizationServerMetadata } from "@modelcontextprotocol/client";
import type { OAuthClientInformation, OAuthTokens } from "@modelcontextprotocol/client";
import type {
OAuthClientInformation,
OAuthTokens,
} from "@modelcontextprotocol/client";
import { OAuthTokensSchema } from "@modelcontextprotocol/core";
import type { EnterpriseManagedAuthIdpConfig } from "../../client/types.js";
import {