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:
parent
19a6df7ad3
commit
f9f79fff54
31 changed files with 296 additions and 95 deletions
|
|
@ -1,4 +1,7 @@
|
||||||
import { discoverAuthorizationServerMetadata, discoverOAuthProtectedResourceMetadata } from "@modelcontextprotocol/client";
|
import {
|
||||||
|
discoverAuthorizationServerMetadata,
|
||||||
|
discoverOAuthProtectedResourceMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { OAuthClientInformation } from "@modelcontextprotocol/client";
|
import type { OAuthClientInformation } from "@modelcontextprotocol/client";
|
||||||
import { getAuthorizationServerUrl } from "./discovery.js";
|
import { getAuthorizationServerUrl } from "./discovery.js";
|
||||||
import type { BaseOAuthClientProvider } from "./providers.js";
|
import type { BaseOAuthClientProvider } from "./providers.js";
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,18 @@
|
||||||
import type { OAuthClientInformation, OAuthTokens } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthTokens,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { EnterpriseManagedAuthIdpConfig } from "../client/types.js";
|
import type { EnterpriseManagedAuthIdpConfig } from "../client/types.js";
|
||||||
import { getEmaIdpLoginState, normalizeIdpIssuer } from "./ema/idpSession.js";
|
import { getEmaIdpLoginState, normalizeIdpIssuer } from "./ema/idpSession.js";
|
||||||
import { idpOAuthStorageKey } from "./ema/storage.js";
|
import { idpOAuthStorageKey } from "./ema/storage.js";
|
||||||
import { isJwtExpired } from "./ema/jwt.js";
|
import { isJwtExpired } from "./ema/jwt.js";
|
||||||
import type { OAuthStorage } from "./storage.js";
|
import type { OAuthStorage } from "./storage.js";
|
||||||
import type { AuthProtocol, OAuthClientRegistrationKind, OAuthConnectionState, OAuthFlowState } from "./types.js";
|
import type {
|
||||||
|
AuthProtocol,
|
||||||
|
OAuthClientRegistrationKind,
|
||||||
|
OAuthConnectionState,
|
||||||
|
OAuthFlowState,
|
||||||
|
} from "./types.js";
|
||||||
import { authProtocolFromEnterpriseManaged } from "./types.js";
|
import { authProtocolFromEnterpriseManaged } from "./types.js";
|
||||||
|
|
||||||
export interface BuildOAuthConnectionStateParams {
|
export interface BuildOAuthConnectionStateParams {
|
||||||
|
|
@ -17,9 +25,7 @@ export interface BuildOAuthConnectionStateParams {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** True when persisted tokens include a non-expired access token (JWT exp when parseable). */
|
/** True when persisted tokens include a non-expired access token (JWT exp when parseable). */
|
||||||
export function isAccessTokenUsable(
|
export function isAccessTokenUsable(tokens: OAuthTokens | undefined): boolean {
|
||||||
tokens: OAuthTokens | undefined,
|
|
||||||
): boolean {
|
|
||||||
if (!tokens?.access_token) return false;
|
if (!tokens?.access_token) return false;
|
||||||
return !isJwtExpired(tokens.access_token);
|
return !isJwtExpired(tokens.access_token);
|
||||||
}
|
}
|
||||||
|
|
@ -27,10 +33,9 @@ export function isAccessTokenUsable(
|
||||||
function resolveClient(
|
function resolveClient(
|
||||||
preregistered: OAuthClientInformation | undefined,
|
preregistered: OAuthClientInformation | undefined,
|
||||||
dynamic: OAuthClientInformation | undefined,
|
dynamic: OAuthClientInformation | undefined,
|
||||||
dynamicRegistrationKind: Extract<
|
dynamicRegistrationKind:
|
||||||
OAuthClientRegistrationKind,
|
| Extract<OAuthClientRegistrationKind, "dcr" | "cimd">
|
||||||
"dcr" | "cimd"
|
| undefined,
|
||||||
> | undefined,
|
|
||||||
): OAuthConnectionState["client"] | undefined {
|
): OAuthConnectionState["client"] | undefined {
|
||||||
if (preregistered?.client_id) {
|
if (preregistered?.client_id) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -81,7 +86,7 @@ export async function buildOAuthConnectionState(
|
||||||
? flowTokens
|
? flowTokens
|
||||||
: storedTokens && isAccessTokenUsable(storedTokens)
|
: storedTokens && isAccessTokenUsable(storedTokens)
|
||||||
? storedTokens
|
? storedTokens
|
||||||
: flowTokens ?? storedTokens;
|
: (flowTokens ?? storedTokens);
|
||||||
|
|
||||||
const preregistered = await storage.getClientInformation(serverUrl, true);
|
const preregistered = await storage.getClientInformation(serverUrl, true);
|
||||||
const dynamic = await storage.getClientInformation(serverUrl);
|
const dynamic = await storage.getClientInformation(serverUrl);
|
||||||
|
|
@ -120,7 +125,9 @@ export async function buildOAuthConnectionState(
|
||||||
const idp = params.enterpriseManagedAuth.idp;
|
const idp = params.enterpriseManagedAuth.idp;
|
||||||
const issuer = normalizeIdpIssuer(idp.issuer);
|
const issuer = normalizeIdpIssuer(idp.issuer);
|
||||||
const idpSession = await getEmaIdpLoginState(storage, issuer);
|
const idpSession = await getEmaIdpLoginState(storage, issuer);
|
||||||
const idpMetadata = await storage.getServerMetadata(idpOAuthStorageKey(issuer));
|
const idpMetadata = await storage.getServerMetadata(
|
||||||
|
idpOAuthStorageKey(issuer),
|
||||||
|
);
|
||||||
state.ema = {
|
state.ema = {
|
||||||
idpIssuer: issuer,
|
idpIssuer: issuer,
|
||||||
idpClientId: idp.clientId,
|
idpClientId: idp.clientId,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
import { discoverAuthorizationServerMetadata, exchangeAuthorization, startAuthorization } from "@modelcontextprotocol/client";
|
import {
|
||||||
import type { OAuthClientInformation, OAuthMetadata } from "@modelcontextprotocol/client";
|
discoverAuthorizationServerMetadata,
|
||||||
|
exchangeAuthorization,
|
||||||
|
startAuthorization,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
|
import type {
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import { OAuthMetadataSchema } from "@modelcontextprotocol/core";
|
import { OAuthMetadataSchema } from "@modelcontextprotocol/core";
|
||||||
import type { OAuthStorage } from "../storage.js";
|
import type { OAuthStorage } from "../storage.js";
|
||||||
import type { EnterpriseManagedAuthIdpConfig } from "../../client/types.js";
|
import type { EnterpriseManagedAuthIdpConfig } from "../../client/types.js";
|
||||||
|
|
@ -44,7 +51,9 @@ export async function discoverIdpMetadata(
|
||||||
fetchFn,
|
fetchFn,
|
||||||
});
|
});
|
||||||
if (!metadata) {
|
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);
|
return OAuthMetadataSchema.parse(metadata);
|
||||||
}
|
}
|
||||||
|
|
@ -56,7 +65,11 @@ export async function startIdpOidcAuthorization(params: {
|
||||||
fetchFn?: typeof fetch;
|
fetchFn?: typeof fetch;
|
||||||
}): Promise<{ authorizationUrl: URL }> {
|
}): Promise<{ authorizationUrl: URL }> {
|
||||||
const issuer = normalizeIdpIssuer(params.idp.issuer);
|
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 clientInformation = idpClientInformation(params.idp);
|
||||||
const storageKey = idpOAuthStorageKey(issuer);
|
const storageKey = idpOAuthStorageKey(issuer);
|
||||||
const state = generateOAuthState();
|
const state = generateOAuthState();
|
||||||
|
|
|
||||||
|
|
@ -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 { OAuthClientProvider } from "@modelcontextprotocol/client";
|
||||||
import type { OAuthProtectedResourceMetadata } from "@modelcontextprotocol/client";
|
import type { OAuthProtectedResourceMetadata } from "@modelcontextprotocol/client";
|
||||||
import { getAuthorizationServerUrl } from "../discovery.js";
|
import { getAuthorizationServerUrl } from "../discovery.js";
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import { selectClientAuthMethod } from "@modelcontextprotocol/client";
|
import { selectClientAuthMethod } from "@modelcontextprotocol/client";
|
||||||
import type { OAuthClientInformation, OAuthMetadata } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
|
|
||||||
export async function parseOAuthTokenErrorResponse(
|
export async function parseOAuthTokenErrorResponse(
|
||||||
response: Response,
|
response: Response,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import type { OAuthClientProvider } from "@modelcontextprotocol/client";
|
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 type { BaseOAuthClientProvider } from "../providers.js";
|
||||||
import {
|
import {
|
||||||
refreshEmaResourceTokens,
|
refreshEmaResourceTokens,
|
||||||
|
|
@ -8,10 +12,7 @@ import {
|
||||||
} from "./emaFlow.js";
|
} from "./emaFlow.js";
|
||||||
import { isJwtExpired } from "./jwt.js";
|
import { isJwtExpired } from "./jwt.js";
|
||||||
|
|
||||||
function isAccessTokenUsable(
|
function isAccessTokenUsable(tokens: OAuthTokens, skewMs = 60_000): boolean {
|
||||||
tokens: OAuthTokens,
|
|
||||||
skewMs = 60_000,
|
|
||||||
): boolean {
|
|
||||||
if (!tokens.access_token) return false;
|
if (!tokens.access_token) return false;
|
||||||
return !isJwtExpired(tokens.access_token, skewMs);
|
return !isJwtExpired(tokens.access_token, skewMs);
|
||||||
}
|
}
|
||||||
|
|
@ -28,10 +29,7 @@ export class EmaTransportOAuthProvider implements OAuthClientProvider {
|
||||||
private readonly inner: BaseOAuthClientProvider;
|
private readonly inner: BaseOAuthClientProvider;
|
||||||
private readonly emaConfig: EmaFlowConfig;
|
private readonly emaConfig: EmaFlowConfig;
|
||||||
|
|
||||||
constructor(
|
constructor(inner: BaseOAuthClientProvider, emaConfig: EmaFlowConfig) {
|
||||||
inner: BaseOAuthClientProvider,
|
|
||||||
emaConfig: EmaFlowConfig,
|
|
||||||
) {
|
|
||||||
this.inner = inner;
|
this.inner = inner;
|
||||||
this.emaConfig = emaConfig;
|
this.emaConfig = emaConfig;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
import { discoverAuthorizationServerMetadata } from "@modelcontextprotocol/client";
|
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 { OAuthTokensSchema } from "@modelcontextprotocol/core";
|
||||||
import type { EnterpriseManagedAuthIdpConfig } from "../../client/types.js";
|
import type { EnterpriseManagedAuthIdpConfig } from "../../client/types.js";
|
||||||
import {
|
import {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,14 @@
|
||||||
* (the same path v2 `auth()` takes when refresh cannot widen scope).
|
* (the same path v2 `auth()` takes when refresh cannot widen scope).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { auth as sdkAuth, discoverOAuthServerInfo, isHttpsUrl, registerClient, selectResourceURL, startAuthorization } from "@modelcontextprotocol/client";
|
import {
|
||||||
|
auth as sdkAuth,
|
||||||
|
discoverOAuthServerInfo,
|
||||||
|
isHttpsUrl,
|
||||||
|
registerClient,
|
||||||
|
selectResourceURL,
|
||||||
|
startAuthorization,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { OAuthClientProvider } from "@modelcontextprotocol/client";
|
import type { OAuthClientProvider } from "@modelcontextprotocol/client";
|
||||||
import type { FetchLike } from "@modelcontextprotocol/client";
|
import type { FetchLike } from "@modelcontextprotocol/client";
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,12 @@
|
||||||
import type { OAuthClientInformation, OAuthTokens, OAuthMetadata } from "@modelcontextprotocol/client";
|
import type {
|
||||||
import { OAuthClientInformationSchema, OAuthTokensSchema } from "@modelcontextprotocol/core";
|
OAuthClientInformation,
|
||||||
|
OAuthTokens,
|
||||||
|
OAuthMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
|
import {
|
||||||
|
OAuthClientInformationSchema,
|
||||||
|
OAuthTokensSchema,
|
||||||
|
} from "@modelcontextprotocol/core";
|
||||||
import type { OAuthStorage } from "./storage.js";
|
import type { OAuthStorage } from "./storage.js";
|
||||||
import { type OAuthMemoryStore, type ServerOAuthState } from "./store.js";
|
import { type OAuthMemoryStore, type ServerOAuthState } from "./store.js";
|
||||||
import type { OAuthPersistBackend } from "./oauth-persist.js";
|
import type { OAuthPersistBackend } from "./oauth-persist.js";
|
||||||
|
|
@ -173,7 +180,9 @@ export class OAuthStorageBase implements OAuthStorage {
|
||||||
|
|
||||||
async clearCodeVerifier(serverUrl: string): Promise<void> {
|
async clearCodeVerifier(serverUrl: string): Promise<void> {
|
||||||
await this.ensureLoaded();
|
await this.ensureLoaded();
|
||||||
this.memory.getState().setServerState(serverUrl, { codeVerifier: undefined });
|
this.memory
|
||||||
|
.getState()
|
||||||
|
.setServerState(serverUrl, { codeVerifier: undefined });
|
||||||
await this.persist();
|
await this.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -206,7 +215,9 @@ export class OAuthStorageBase implements OAuthStorage {
|
||||||
metadata: OAuthMetadata,
|
metadata: OAuthMetadata,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.ensureLoaded();
|
await this.ensureLoaded();
|
||||||
this.memory.getState().setServerState(serverUrl, { serverMetadata: metadata });
|
this.memory
|
||||||
|
.getState()
|
||||||
|
.setServerState(serverUrl, { serverMetadata: metadata });
|
||||||
await this.persist();
|
await this.persist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,12 @@ import type {
|
||||||
OAuthClientProvider,
|
OAuthClientProvider,
|
||||||
OAuthClientInformationContext,
|
OAuthClientInformationContext,
|
||||||
} from "@modelcontextprotocol/client";
|
} from "@modelcontextprotocol/client";
|
||||||
import type { OAuthClientInformation, OAuthClientMetadata, OAuthTokens, OAuthMetadata } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthClientMetadata,
|
||||||
|
OAuthTokens,
|
||||||
|
OAuthMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { OAuthStorage, SaveClientInformationOptions } from "./storage.js";
|
import type { OAuthStorage, SaveClientInformationOptions } from "./storage.js";
|
||||||
import { generateOAuthState } from "./utils.js";
|
import { generateOAuthState } from "./utils.js";
|
||||||
|
|
||||||
|
|
@ -210,9 +215,13 @@ export class BaseOAuthClientProvider implements OAuthClientProvider {
|
||||||
options && "registrationKind" in options
|
options && "registrationKind" in options
|
||||||
? options.registrationKind
|
? options.registrationKind
|
||||||
: "dcr";
|
: "dcr";
|
||||||
await this.storage.saveClientInformation(this.serverUrl, clientInformation, {
|
await this.storage.saveClientInformation(
|
||||||
registrationKind,
|
this.serverUrl,
|
||||||
});
|
clientInformation,
|
||||||
|
{
|
||||||
|
registrationKind,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveScope(scope: string | undefined): Promise<void> {
|
async saveScope(scope: string | undefined): Promise<void> {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
import type { OAuthClientInformation, OAuthTokens, OAuthMetadata } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthTokens,
|
||||||
|
OAuthMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { OAuthClientRegistrationKind } from "./types.js";
|
import type { OAuthClientRegistrationKind } from "./types.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,11 @@
|
||||||
* Persisted via `OAuthStorageBase` + `OAuthPersistBackend` backends.
|
* Persisted via `OAuthStorageBase` + `OAuthPersistBackend` backends.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type { OAuthClientInformation, OAuthTokens, OAuthMetadata } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthTokens,
|
||||||
|
OAuthMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type {
|
import type {
|
||||||
IdpSessionState,
|
IdpSessionState,
|
||||||
OAuthClientRegistrationKind,
|
OAuthClientRegistrationKind,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
import type { OAuthMetadata, OAuthClientInformation, OAuthClientInformationFull, OAuthTokens, OAuthProtectedResourceMetadata } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
OAuthMetadata,
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthClientInformationFull,
|
||||||
|
OAuthTokens,
|
||||||
|
OAuthProtectedResourceMetadata,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
|
|
||||||
// OAuth flow steps
|
// OAuth flow steps
|
||||||
export type OAuthStep =
|
export type OAuthStep =
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { vi } from "vitest";
|
import { vi } from "vitest";
|
||||||
import type { ClientCapabilities, Implementation, LoggingLevel, Prompt, Resource, ResourceTemplateType as ResourceTemplate, ServerCapabilities, Task, Tool } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
ClientCapabilities,
|
||||||
|
Implementation,
|
||||||
|
LoggingLevel,
|
||||||
|
Prompt,
|
||||||
|
Resource,
|
||||||
|
ResourceTemplateType as ResourceTemplate,
|
||||||
|
ServerCapabilities,
|
||||||
|
Task,
|
||||||
|
Tool,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import { InspectorClientEventTarget } from "../inspectorClientEventTarget.js";
|
import { InspectorClientEventTarget } from "../inspectorClientEventTarget.js";
|
||||||
import type {
|
import type {
|
||||||
AppRendererClient,
|
AppRendererClient,
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,38 @@ import {
|
||||||
MessageTrackingTransport,
|
MessageTrackingTransport,
|
||||||
type MessageTrackingCallbacks,
|
type MessageTrackingCallbacks,
|
||||||
} from "./messageTrackingTransport.js";
|
} from "./messageTrackingTransport.js";
|
||||||
import type { CallToolRequest, JSONRPCRequest, JSONRPCNotification, JSONRPCResultResponse, JSONRPCErrorResponse, ServerCapabilities, ClientCapabilities, Implementation, LoggingLevel, Tool, Resource, ResourceTemplateType as ResourceTemplate, Prompt, Root, CreateMessageRequest, CreateMessageResult, ElicitRequest, ElicitResult, ElicitRequestURLParams, CallToolResult, Task, Progress, ProgressToken, ListToolsRequest, ListResourcesRequest, ListResourceTemplatesRequest, ListPromptsRequest, ReadResourceRequest, GetPromptRequest, CompleteRequest } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
CallToolRequest,
|
||||||
|
JSONRPCRequest,
|
||||||
|
JSONRPCNotification,
|
||||||
|
JSONRPCResultResponse,
|
||||||
|
JSONRPCErrorResponse,
|
||||||
|
ServerCapabilities,
|
||||||
|
ClientCapabilities,
|
||||||
|
Implementation,
|
||||||
|
LoggingLevel,
|
||||||
|
Tool,
|
||||||
|
Resource,
|
||||||
|
ResourceTemplateType as ResourceTemplate,
|
||||||
|
Prompt,
|
||||||
|
Root,
|
||||||
|
CreateMessageRequest,
|
||||||
|
CreateMessageResult,
|
||||||
|
ElicitRequest,
|
||||||
|
ElicitResult,
|
||||||
|
ElicitRequestURLParams,
|
||||||
|
CallToolResult,
|
||||||
|
Task,
|
||||||
|
Progress,
|
||||||
|
ProgressToken,
|
||||||
|
ListToolsRequest,
|
||||||
|
ListResourcesRequest,
|
||||||
|
ListResourceTemplatesRequest,
|
||||||
|
ListPromptsRequest,
|
||||||
|
ReadResourceRequest,
|
||||||
|
GetPromptRequest,
|
||||||
|
CompleteRequest,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { Transport } from "@modelcontextprotocol/client";
|
import type { Transport } from "@modelcontextprotocol/client";
|
||||||
import type {
|
import type {
|
||||||
RequestOptions,
|
RequestOptions,
|
||||||
|
|
@ -633,9 +664,7 @@ export class InspectorClient extends InspectorClientEventTarget {
|
||||||
internal._requestHandlers.set(method, (request, ctx) => {
|
internal._requestHandlers.set(method, (request, ctx) => {
|
||||||
const task = (request as { params?: { task?: unknown } })?.params?.task;
|
const task = (request as { params?: { task?: unknown } })?.params?.task;
|
||||||
if (this.receiverTasks && task != null) {
|
if (this.receiverTasks && task != null) {
|
||||||
return rawHandler(
|
return rawHandler(request as CreateMessageRequest & ElicitRequest);
|
||||||
request as CreateMessageRequest & ElicitRequest,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return validating(request, ctx);
|
return validating(request, ctx);
|
||||||
});
|
});
|
||||||
|
|
@ -723,7 +752,10 @@ export class InspectorClient extends InspectorClientEventTarget {
|
||||||
private async getReceiverTaskPayload(taskId: string): Promise<ClientResult> {
|
private async getReceiverTaskPayload(taskId: string): Promise<ClientResult> {
|
||||||
const record = this.receiverTaskRecords.get(taskId);
|
const record = this.receiverTaskRecords.get(taskId);
|
||||||
if (!record) {
|
if (!record) {
|
||||||
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unknown taskId: ${taskId}`);
|
throw new ProtocolError(
|
||||||
|
ProtocolErrorCode.InvalidParams,
|
||||||
|
`Unknown taskId: ${taskId}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return record.payloadPromise;
|
return record.payloadPromise;
|
||||||
}
|
}
|
||||||
|
|
@ -731,7 +763,10 @@ export class InspectorClient extends InspectorClientEventTarget {
|
||||||
private cancelReceiverTask(taskId: string): Task {
|
private cancelReceiverTask(taskId: string): Task {
|
||||||
const record = this.receiverTaskRecords.get(taskId);
|
const record = this.receiverTaskRecords.get(taskId);
|
||||||
if (!record) {
|
if (!record) {
|
||||||
throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unknown taskId: ${taskId}`);
|
throw new ProtocolError(
|
||||||
|
ProtocolErrorCode.InvalidParams,
|
||||||
|
`Unknown taskId: ${taskId}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (InspectorClient.isTerminalTaskStatus(record.task.status)) {
|
if (InspectorClient.isTerminalTaskStatus(record.task.status)) {
|
||||||
return record.task;
|
return record.task;
|
||||||
|
|
@ -1012,7 +1047,10 @@ export class InspectorClient extends InspectorClientEventTarget {
|
||||||
this.addPendingSample(samplingRequest);
|
this.addPendingSample(samplingRequest);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
this.client.setRequestHandler("sampling/createMessage", samplingHandler);
|
this.client.setRequestHandler(
|
||||||
|
"sampling/createMessage",
|
||||||
|
samplingHandler,
|
||||||
|
);
|
||||||
if (this.receiverTasks) {
|
if (this.receiverTasks) {
|
||||||
this.installReceiverTaskResponseBypass(
|
this.installReceiverTaskResponseBypass(
|
||||||
"sampling/createMessage",
|
"sampling/createMessage",
|
||||||
|
|
@ -2001,7 +2039,14 @@ export class InspectorClient extends InspectorClientEventTarget {
|
||||||
result as CallToolResult,
|
result as CallToolResult,
|
||||||
);
|
);
|
||||||
if (outputValidationError && !options?.skipOutputValidation) {
|
if (outputValidationError && !options?.skipOutputValidation) {
|
||||||
throw new Error(outputValidationError);
|
// Match the prior contract: on v1 a strict output-schema violation
|
||||||
|
// surfaced as the SDK's typed `McpError`/`ProtocolError` (code
|
||||||
|
// InvalidParams), not a bare Error — so downstream code that branches on
|
||||||
|
// `instanceof ProtocolError` / `error.code` keeps working.
|
||||||
|
throw new ProtocolError(
|
||||||
|
ProtocolErrorCode.InvalidParams,
|
||||||
|
outputValidationError,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const invocation: ToolCallInvocation = {
|
const invocation: ToolCallInvocation = {
|
||||||
|
|
@ -2161,6 +2206,14 @@ export class InspectorClient extends InspectorClientEventTarget {
|
||||||
);
|
);
|
||||||
// The SDK registers the progress handler synchronously while constructing
|
// The SDK registers the progress handler synchronously while constructing
|
||||||
// the request promise (before this await), so the new key is present now.
|
// the request promise (before this await), so the new key is present now.
|
||||||
|
// ASSUMES SERIAL CONSTRUCTION: `find` takes the first key not present in the
|
||||||
|
// pre-request snapshot, which is unambiguous only because no OTHER request
|
||||||
|
// registers a progress handler between the snapshot and this request's
|
||||||
|
// synchronous registration. Tool calls are user-driven and serial, so that
|
||||||
|
// holds today; if concurrent task-augmented calls are ever constructed in
|
||||||
|
// the same microtask window, two subscription ids could cross-wire and this
|
||||||
|
// must move to an SDK-supported correlation (see the delete-when-native note
|
||||||
|
// on `installReceiverTaskResponseBypass`).
|
||||||
const progressSubscriptionId = requestOptions.onprogress
|
const progressSubscriptionId = requestOptions.onprogress
|
||||||
? [...progressHandlers.keys()].find((k) => !keysBeforeRequest.has(k))
|
? [...progressHandlers.keys()].find((k) => !keysBeforeRequest.has(k))
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,17 @@ import type {
|
||||||
ResourceReadInvocation,
|
ResourceReadInvocation,
|
||||||
ResourceTemplateReadInvocation,
|
ResourceTemplateReadInvocation,
|
||||||
} from "./types.js";
|
} from "./types.js";
|
||||||
import type { Tool, ServerCapabilities, Implementation, Root, Progress, ProgressToken, Task, CallToolResult, ProtocolError } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
Tool,
|
||||||
|
ServerCapabilities,
|
||||||
|
Implementation,
|
||||||
|
Root,
|
||||||
|
Progress,
|
||||||
|
ProgressToken,
|
||||||
|
Task,
|
||||||
|
CallToolResult,
|
||||||
|
ProtocolError,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { SamplingCreateMessage } from "./samplingCreateMessage.js";
|
import type { SamplingCreateMessage } from "./samplingCreateMessage.js";
|
||||||
import type { ElicitationCreateMessage } from "./elicitationCreateMessage.js";
|
import type { ElicitationCreateMessage } from "./elicitationCreateMessage.js";
|
||||||
import type { JsonValue } from "../json/jsonUtils.js";
|
import type { JsonValue } from "../json/jsonUtils.js";
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,17 @@ import type {
|
||||||
PromptGetInvocation,
|
PromptGetInvocation,
|
||||||
ToolCallInvocation,
|
ToolCallInvocation,
|
||||||
} from "./types.js";
|
} from "./types.js";
|
||||||
import type { ClientCapabilities, Implementation, LoggingLevel, Prompt, Resource, ResourceTemplateType as ResourceTemplate, ServerCapabilities, Task, Tool } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
ClientCapabilities,
|
||||||
|
Implementation,
|
||||||
|
LoggingLevel,
|
||||||
|
Prompt,
|
||||||
|
Resource,
|
||||||
|
ResourceTemplateType as ResourceTemplate,
|
||||||
|
ServerCapabilities,
|
||||||
|
Task,
|
||||||
|
Tool,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { JsonValue } from "../json/jsonUtils.js";
|
import type { JsonValue } from "../json/jsonUtils.js";
|
||||||
import type { InspectorClientEventTarget } from "./inspectorClientEventTarget.js";
|
import type { InspectorClientEventTarget } from "./inspectorClientEventTarget.js";
|
||||||
import type { SamplingCreateMessage } from "./samplingCreateMessage.js";
|
import type { SamplingCreateMessage } from "./samplingCreateMessage.js";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,17 @@
|
||||||
import type { Transport, TransportSendOptions } from "@modelcontextprotocol/client";
|
import type {
|
||||||
import type { JSONRPCMessage, MessageExtraInfo } from "@modelcontextprotocol/client";
|
Transport,
|
||||||
import type { JSONRPCRequest, JSONRPCNotification, JSONRPCResultResponse, JSONRPCErrorResponse } from "@modelcontextprotocol/client";
|
TransportSendOptions,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
|
import type {
|
||||||
|
JSONRPCMessage,
|
||||||
|
MessageExtraInfo,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
|
import type {
|
||||||
|
JSONRPCRequest,
|
||||||
|
JSONRPCNotification,
|
||||||
|
JSONRPCResultResponse,
|
||||||
|
JSONRPCErrorResponse,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { MessageOrigin } from "./types.js";
|
import type { MessageOrigin } from "./types.js";
|
||||||
|
|
||||||
export interface MessageTrackingCallbacks {
|
export interface MessageTrackingCallbacks {
|
||||||
|
|
@ -21,10 +32,7 @@ export class MessageTrackingTransport implements Transport {
|
||||||
private callbacks: MessageTrackingCallbacks;
|
private callbacks: MessageTrackingCallbacks;
|
||||||
private negotiatedProtocolVersion?: string;
|
private negotiatedProtocolVersion?: string;
|
||||||
|
|
||||||
constructor(
|
constructor(baseTransport: Transport, callbacks: MessageTrackingCallbacks) {
|
||||||
baseTransport: Transport,
|
|
||||||
callbacks: MessageTrackingCallbacks,
|
|
||||||
) {
|
|
||||||
this.baseTransport = baseTransport;
|
this.baseTransport = baseTransport;
|
||||||
this.callbacks = callbacks;
|
this.callbacks = callbacks;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -286,8 +286,7 @@ export class OAuthManager {
|
||||||
try {
|
try {
|
||||||
if (this.isEnterpriseManaged()) {
|
if (this.isEnterpriseManaged()) {
|
||||||
const emaConfig = await this.getEmaFlowConfig();
|
const emaConfig = await this.getEmaFlowConfig();
|
||||||
const scopeForMint =
|
const scopeForMint = this.pendingAuthorizationScope ?? emaConfig.scope;
|
||||||
this.pendingAuthorizationScope ?? emaConfig.scope;
|
|
||||||
const config = scopeForMint
|
const config = scopeForMint
|
||||||
? { ...emaConfig, scope: scopeForMint }
|
? { ...emaConfig, scope: scopeForMint }
|
||||||
: emaConfig;
|
: emaConfig;
|
||||||
|
|
@ -449,7 +448,9 @@ export class OAuthManager {
|
||||||
*/
|
*/
|
||||||
async refreshEnterpriseManagedTokens(): Promise<boolean> {
|
async refreshEnterpriseManagedTokens(): Promise<boolean> {
|
||||||
if (!this.isEnterpriseManaged()) return false;
|
if (!this.isEnterpriseManaged()) return false;
|
||||||
const tokens = await refreshEmaResourceTokens(await this.getEmaFlowConfig());
|
const tokens = await refreshEmaResourceTokens(
|
||||||
|
await this.getEmaFlowConfig(),
|
||||||
|
);
|
||||||
return tokens !== undefined;
|
return tokens !== undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
import type { OAuthClientProvider } from "@modelcontextprotocol/client";
|
import type { OAuthClientProvider } from "@modelcontextprotocol/client";
|
||||||
import type { OAuthClientInformation, OAuthClientMetadata, OAuthTokens } from "@modelcontextprotocol/client";
|
import type {
|
||||||
|
OAuthClientInformation,
|
||||||
|
OAuthClientMetadata,
|
||||||
|
OAuthTokens,
|
||||||
|
} from "@modelcontextprotocol/client";
|
||||||
import type { RemoteAuthState } from "../types.js";
|
import type { RemoteAuthState } from "../types.js";
|
||||||
|
|
||||||
const REMOTE_OAUTH_STUB_METADATA: OAuthClientMetadata = {
|
const REMOTE_OAUTH_STUB_METADATA: OAuthClientMetadata = {
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue