@duo-director/cli 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/THIRD_PARTY_NOTICES.md +3 -3
- package/dist/{cli-WTCBCBVN.js → cli-QTN5SRNE.js} +61 -15
- package/dist/duoctl.js +1 -1
- package/dist/runtime-tree.json +12 -12
- package/dist/ui/app.js +2 -2
- package/node_modules/@modelcontextprotocol/client/dist/{index-CEk3qkZM.d.cts → index-D_CiY-T3.d.cts} +3 -1
- package/node_modules/@modelcontextprotocol/client/dist/index-D_CiY-T3.d.cts.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/{index-BCtJi0p5.d.mts → index-D_QDtbiv.d.mts} +3 -1
- package/node_modules/@modelcontextprotocol/client/dist/index-D_QDtbiv.d.mts.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/index.cjs +100 -55
- package/node_modules/@modelcontextprotocol/client/dist/index.cjs.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/index.d.cts +157 -30
- package/node_modules/@modelcontextprotocol/client/dist/index.d.cts.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/index.d.mts +157 -30
- package/node_modules/@modelcontextprotocol/client/dist/index.d.mts.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/index.mjs +100 -55
- package/node_modules/@modelcontextprotocol/client/dist/index.mjs.map +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.cjs +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/shimsWorkerd.mjs +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/{src-D0qEN74R.cjs → src-oZBjf3U1.cjs} +21 -4
- package/node_modules/@modelcontextprotocol/client/dist/src-oZBjf3U1.cjs.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/{src-DDAAhLnO.mjs → src-xKF0PJN-.mjs} +16 -5
- package/node_modules/@modelcontextprotocol/client/dist/src-xKF0PJN-.mjs.map +1 -0
- package/node_modules/@modelcontextprotocol/client/dist/stdio.cjs +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/client/dist/stdio.mjs +1 -1
- package/node_modules/@modelcontextprotocol/client/package.json +3 -3
- package/node_modules/@modelcontextprotocol/core/dist/{auth--n_Yzytt.d.cts → auth-Anm-lwWi.d.mts} +9 -8
- package/node_modules/@modelcontextprotocol/core/dist/{auth--n_Yzytt.d.cts.map → auth-Anm-lwWi.d.mts.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-CGP0BDVq.mjs → auth-BNDyLTqp.mjs} +5 -3
- package/node_modules/@modelcontextprotocol/core/dist/{auth-CGP0BDVq.mjs.map → auth-BNDyLTqp.mjs.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-4-zilcqg.cjs → auth-D1CeV_Jr.cjs} +5 -3
- package/node_modules/@modelcontextprotocol/core/dist/{auth-4-zilcqg.cjs.map → auth-D1CeV_Jr.cjs.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/{auth-YUQV3RRv.d.mts → auth-V9XJSCfa.d.cts} +9 -8
- package/node_modules/@modelcontextprotocol/core/dist/{auth-YUQV3RRv.d.mts.map → auth-V9XJSCfa.d.cts.map} +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.cjs +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/index.mjs +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.cjs +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/core/dist/internal.mjs +1 -1
- package/node_modules/@modelcontextprotocol/core/package.json +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-Bt6U_Fqb.d.mts → createMcpHandler-CfX6zgs1.d.mts} +3 -1
- package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-CfX6zgs1.d.mts.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-BLVe3qmU.d.cts → createMcpHandler-LSKhyqpU.d.cts} +3 -1
- package/node_modules/@modelcontextprotocol/server/dist/{createMcpHandler-BLVe3qmU.d.cts.map → createMcpHandler-LSKhyqpU.d.cts.map} +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.cjs +5 -3
- package/node_modules/@modelcontextprotocol/server/dist/index.cjs.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.d.mts.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/index.mjs +5 -3
- package/node_modules/@modelcontextprotocol/server/dist/index.mjs.map +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/{mcp-Dw2OlZ1f.mjs → mcp-DYuW2ZSs.mjs} +6 -2
- package/node_modules/@modelcontextprotocol/server/dist/mcp-DYuW2ZSs.mjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/{mcp-DUcCQSTW.cjs → mcp-TfXCpFsH.cjs} +6 -2
- package/node_modules/@modelcontextprotocol/server/dist/mcp-TfXCpFsH.cjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.cjs +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/shimsWorkerd.mjs +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/{src-D-y6h4N7.mjs → src-BHSMhZ_W.mjs} +8 -4
- package/node_modules/@modelcontextprotocol/server/dist/src-BHSMhZ_W.mjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/{src-CgFsfg3E.cjs → src-BtQ5YSyq.cjs} +8 -4
- package/node_modules/@modelcontextprotocol/server/dist/src-BtQ5YSyq.cjs.map +1 -0
- package/node_modules/@modelcontextprotocol/server/dist/stdio.cjs +2 -2
- package/node_modules/@modelcontextprotocol/server/dist/stdio.d.cts +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/stdio.d.mts +1 -1
- package/node_modules/@modelcontextprotocol/server/dist/stdio.mjs +2 -2
- package/node_modules/@modelcontextprotocol/server/package.json +3 -3
- package/package.json +3 -3
- package/node_modules/@modelcontextprotocol/client/dist/index-BCtJi0p5.d.mts.map +0 -1
- package/node_modules/@modelcontextprotocol/client/dist/index-CEk3qkZM.d.cts.map +0 -1
- package/node_modules/@modelcontextprotocol/client/dist/src-D0qEN74R.cjs.map +0 -1
- package/node_modules/@modelcontextprotocol/client/dist/src-DDAAhLnO.mjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/createMcpHandler-Bt6U_Fqb.d.mts.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/mcp-DUcCQSTW.cjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/mcp-Dw2OlZ1f.mjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/src-CgFsfg3E.cjs.map +0 -1
- package/node_modules/@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as legacyProtocolVersions, A as isInitializeRequest, At as
|
|
1
|
+
import { $ as legacyProtocolVersions, A as isInitializeRequest, At as SdkError, B as DiscoverResultSchema, C as mcpNameSource, Ct as IdJagTokenExchangeResponseSchema, D as assertCompleteRequestPrompt, Dt as OAuthProtectedResourceMetadataSchema, E as scanXMcpHeaderDeclarations, Et as OAuthMetadataSchema, F as isJSONRPCRequest, Ft as brandedHasInstance, G as MissingRequiredClientCapabilityError, H as ListChangedOptionsBaseSchema, I as isJSONRPCResponse, It as stampErrorBrands, J as UnsupportedProtocolVersionError, K as ProtocolError, L as isJSONRPCResultResponse, M as isInputRequiredResult, Mt as SdkHttpError, N as isJSONRPCErrorResponse, Nt as OAuthError, O as assertCompleteRequestResourceTemplate, Ot as OAuthTokensSchema, P as isJSONRPCNotification, Pt as OAuthErrorCode, Q as isModernProtocolVersion, R as isTaskAugmentedRequestParams, S as HEADER_MISMATCH_ERROR_CODE, St as withoutIssuer, T as encodeMcpParamValue, Tt as OAuthErrorResponseSchema, U as MODERN_WIRE_REVISION, V as JSONRPCMessageSchema, W as codecForVersion, X as ProtocolErrorCode, Y as UrlElicitationRequiredError, Z as SUPPORTED_MODERN_PROTOCOL_VERSIONS, _ as isSpecType, _t as SUPPORTED_PROTOCOL_VERSIONS, a as createFetchWithInit, at as INTERNAL_ERROR, b as withInputRequired, bt as checkResourceAllowed, c as deserializeMessage, ct as JSONRPC_VERSION, d as isJsonContentType, dt as METHOD_NOT_FOUND, et as modernProtocolVersions, f as mediaTypeEssence, ft as PARSE_ERROR, g as mergeCapabilities, gt as SUBSCRIPTION_ID_META_KEY, h as Protocol, ht as SERVER_INFO_META_KEY, i as UriTemplate, it as DEFAULT_NEGOTIATED_PROTOCOL_VERSION, j as isInitializedNotification, jt as SdkErrorCode, k as isCallToolResult, kt as OpenIdProviderDiscoveryMetadataSchema, l as serializeMessage, lt as LATEST_PROTOCOL_VERSION, m as DEFAULT_REQUEST_TIMEOUT_MSEC, mt as RELATED_TASK_META_KEY, n as preloadSchemas, nt as CLIENT_CAPABILITIES_META_KEY, o as ReadBuffer, ot as INVALID_PARAMS, p as runInputRequiredFlow, pt as PROTOCOL_VERSION_META_KEY, q as ResourceNotFoundError, r as InMemoryTransport, rt as CLIENT_INFO_META_KEY, s as STDIO_DEFAULT_MAX_BUFFER_SIZE, st as INVALID_REQUEST, t as fromJsonSchema$1, tt as BAGGAGE_META_KEY, u as getDisplayName, ut as LOG_LEVEL_META_KEY, v as specTypeSchemas, vt as TRACEPARENT_META_KEY, w as buildMcpParamHeaders, wt as OAuthClientInformationFullSchema, x as parseSchema, xt as resourceUrlFromServerUrl, y as resolveInputRequiredDriverConfig, yt as TRACESTATE_META_KEY, z as parseJSONRPCMessage } from "./src-xKF0PJN-.mjs";
|
|
2
2
|
import { CORS_IS_POSSIBLE, DefaultJsonSchemaValidator } from "@modelcontextprotocol/client/_shims";
|
|
3
3
|
import pkceChallenge from "pkce-challenge";
|
|
4
4
|
import { EventSource } from "eventsource";
|
|
@@ -112,10 +112,12 @@ var RegistrationRejectedError = class extends OAuthClientFlowError {
|
|
|
112
112
|
};
|
|
113
113
|
/**
|
|
114
114
|
* Thrown by the token-exchange and refresh paths when the resolved token
|
|
115
|
-
* endpoint is not `https:` and is not a loopback host
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
115
|
+
* endpoint is not `https:` and is not a loopback host. The MCP authorization
|
|
116
|
+
* specification requires authorization server endpoints to use HTTPS; loopback
|
|
117
|
+
* hosts are exempt here for local development. This is a configuration error —
|
|
118
|
+
* re-authorizing cannot fix it — so it intentionally does **not** extend
|
|
119
|
+
* `OAuthError` and `auth()`'s refresh branch rethrows it instead of falling
|
|
120
|
+
* through to a fresh `/authorize` redirect.
|
|
119
121
|
*/
|
|
120
122
|
var InsecureTokenEndpointError = class extends OAuthClientFlowError {
|
|
121
123
|
static {
|
|
@@ -124,7 +126,7 @@ var InsecureTokenEndpointError = class extends OAuthClientFlowError {
|
|
|
124
126
|
/** The token endpoint URL that was rejected. */
|
|
125
127
|
tokenEndpoint;
|
|
126
128
|
constructor(tokenEndpoint) {
|
|
127
|
-
super(`Refusing to send credentials to non-https token endpoint '${tokenEndpoint}'. OAuth token requests MUST use TLS (localhost / 127.0.0.1 / ::1 are exempt).`);
|
|
129
|
+
super(`Refusing to send credentials to non-https token endpoint '${tokenEndpoint}'. OAuth token requests MUST use TLS (localhost / *.localhost / 127.0.0.1 / ::1 are exempt).`);
|
|
128
130
|
this.tokenEndpoint = tokenEndpoint;
|
|
129
131
|
}
|
|
130
132
|
};
|
|
@@ -149,21 +151,25 @@ var InsecureTokenEndpointError = class extends OAuthClientFlowError {
|
|
|
149
151
|
* `requiredScope`, which appears in the error message).
|
|
150
152
|
*/
|
|
151
153
|
/**
|
|
152
|
-
* Thrown by `auth()`
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
154
|
+
* Thrown by `auth()` and `fetchToken()` when the authorization server in use differs
|
|
155
|
+
* from the one a credential is bound to and the flow cannot simply start over:
|
|
156
|
+
*
|
|
157
|
+
* - on the authorization-code callback leg, when it differs from the one recorded
|
|
158
|
+
* in `discoveryState()` at redirect time — the `authorization_code` and PKCE
|
|
159
|
+
* `code_verifier` are bound to the AS that minted the code (RFC 7636);
|
|
160
|
+
* - for client information whose `issuer` stamp names a different authorization
|
|
161
|
+
* server on a provider that cannot re-register (no `saveClientInformation()`,
|
|
162
|
+
* e.g. the bundled static-credential providers); `fetchToken()` throws for any provider.
|
|
163
|
+
*
|
|
164
|
+
* Stored tokens and re-registrable client information are protected structurally
|
|
165
|
+
* by the `issuer` stamp instead (they read back as absent).
|
|
160
166
|
*/
|
|
161
167
|
var AuthorizationServerMismatchError = class extends OAuthClientFlowError {
|
|
162
168
|
static {
|
|
163
169
|
Object.defineProperty(this, "mcpBrand", { value: "mcp.AuthorizationServerMismatchError" });
|
|
164
170
|
}
|
|
165
171
|
constructor(recordedIssuer, currentIssuer) {
|
|
166
|
-
super(`Authorization server
|
|
172
|
+
super(`Authorization server mismatch: credentials are bound to ${JSON.stringify(recordedIssuer)} but this call resolved ${JSON.stringify(currentIssuer)}; refusing to present them to a different authorization server`);
|
|
167
173
|
this.recordedIssuer = recordedIssuer;
|
|
168
174
|
this.currentIssuer = currentIssuer;
|
|
169
175
|
}
|
|
@@ -207,10 +213,13 @@ var InsufficientScopeError = class extends OAuthClientFlowError {
|
|
|
207
213
|
* "binding on first use" claim would be false and would fire on every call.
|
|
208
214
|
*/
|
|
209
215
|
function discardIfIssuerMismatch(stored, issuer, opts) {
|
|
210
|
-
if (stored
|
|
211
|
-
if (stored.issuer
|
|
216
|
+
if (!stored) return void 0;
|
|
217
|
+
if (typeof stored.issuer !== "string") {
|
|
212
218
|
if (opts?.canPersistStamp !== false) console.warn("[mcp-sdk] SEP-2352: stored OAuth credential has no 'issuer' stamp (pre-upgrade storage or provider not round-tripping the value). SEP-2352 isolation is inactive for this read; ensure your provider round-trips the issuer field.");
|
|
213
|
-
return stored
|
|
219
|
+
return stored.issuer === void 0 ? stored : {
|
|
220
|
+
...stored,
|
|
221
|
+
issuer: void 0
|
|
222
|
+
};
|
|
214
223
|
}
|
|
215
224
|
return issuersMatch(stored.issuer, issuer) ? stored : void 0;
|
|
216
225
|
}
|
|
@@ -518,13 +527,19 @@ function applyPostAuth(clientId, clientSecret, params) {
|
|
|
518
527
|
function applyPublicAuth(clientId, params) {
|
|
519
528
|
params.set("client_id", clientId);
|
|
520
529
|
}
|
|
521
|
-
/**
|
|
530
|
+
/**
|
|
531
|
+
* Loopback hosts exempt from the in-transit `https:` requirement (RFC 8252 §7.3).
|
|
532
|
+
* Includes bare `localhost` and any name ending in `.localhost` (RFC 6761 §6.3).
|
|
533
|
+
*/
|
|
522
534
|
function isLoopbackHost(hostname) {
|
|
523
|
-
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
|
|
535
|
+
return hostname === "localhost" || hostname.endsWith(".localhost") || hostname === "127.0.0.1" || hostname === "[::1]" || hostname === "::1";
|
|
524
536
|
}
|
|
525
537
|
/**
|
|
526
|
-
*
|
|
527
|
-
*
|
|
538
|
+
* Refuse to send credentials to a non-TLS token endpoint. The MCP authorization
|
|
539
|
+
* specification requires authorization server endpoints to use HTTPS. Loopback
|
|
540
|
+
* hosts are exempt here for local development.
|
|
541
|
+
*
|
|
542
|
+
* @throws {@linkcode InsecureTokenEndpointError} if the endpoint is insecure.
|
|
528
543
|
*/
|
|
529
544
|
function assertSecureTokenEndpoint(tokenEndpoint) {
|
|
530
545
|
const url = new URL(String(tokenEndpoint));
|
|
@@ -1265,7 +1280,7 @@ async function executeTokenRequest(authorizationServerUrl, { metadata, tokenRequ
|
|
|
1265
1280
|
if (!response.ok) throw await parseErrorResponse(response);
|
|
1266
1281
|
const json = await response.json();
|
|
1267
1282
|
try {
|
|
1268
|
-
return OAuthTokensSchema.parse(json);
|
|
1283
|
+
return OAuthTokensSchema.parse(withoutIssuer(json));
|
|
1269
1284
|
} catch (parseError) {
|
|
1270
1285
|
if (typeof json === "object" && json !== null && "error" in json) throw await parseErrorResponse(JSON.stringify(json));
|
|
1271
1286
|
throw parseError;
|
|
@@ -1361,6 +1376,14 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
|
|
|
1361
1376
|
expectedIssuer: metadata?.issuer,
|
|
1362
1377
|
issParameterSupported: isIssParameterSupported(metadata)
|
|
1363
1378
|
});
|
|
1379
|
+
const issuer = metadata?.issuer ?? String(authorizationServerUrl);
|
|
1380
|
+
const readClientInformation = async () => {
|
|
1381
|
+
const rawClientInfo = await provider.clientInformation({ issuer });
|
|
1382
|
+
const checked = discardIfIssuerMismatch(rawClientInfo, issuer, { canPersistStamp: false });
|
|
1383
|
+
if (rawClientInfo && checked === void 0) throw new AuthorizationServerMismatchError(String(rawClientInfo.issuer), issuer);
|
|
1384
|
+
return checked;
|
|
1385
|
+
};
|
|
1386
|
+
let clientInformation = await readClientInformation();
|
|
1364
1387
|
const effectiveScope = scope ?? provider.clientMetadata.scope;
|
|
1365
1388
|
let tokenRequestParams;
|
|
1366
1389
|
if (provider.prepareTokenRequest) tokenRequestParams = await provider.prepareTokenRequest(effectiveScope);
|
|
@@ -1369,11 +1392,11 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
|
|
|
1369
1392
|
if (!provider.redirectUrl) throw new Error("redirectUrl is required for authorization_code flow");
|
|
1370
1393
|
tokenRequestParams = prepareAuthorizationCodeRequest(authorizationCode, await provider.codeVerifier(), provider.redirectUrl);
|
|
1371
1394
|
}
|
|
1372
|
-
|
|
1395
|
+
clientInformation ??= await readClientInformation();
|
|
1373
1396
|
return executeTokenRequest(authorizationServerUrl, {
|
|
1374
1397
|
metadata,
|
|
1375
1398
|
tokenRequestParams,
|
|
1376
|
-
clientInformation
|
|
1399
|
+
clientInformation,
|
|
1377
1400
|
addClientAuthentication: provider.addClientAuthentication,
|
|
1378
1401
|
resource,
|
|
1379
1402
|
dpop: await provider.dpop?.(),
|
|
@@ -1389,10 +1412,17 @@ async function fetchToken(provider, authorizationServerUrl, { metadata, resource
|
|
|
1389
1412
|
* consistently across both DCR and the subsequent authorization request.
|
|
1390
1413
|
*
|
|
1391
1414
|
* @deprecated Dynamic Client Registration is deprecated as of protocol version
|
|
1392
|
-
* 2026-07-28
|
|
1393
|
-
*
|
|
1394
|
-
*
|
|
1395
|
-
*
|
|
1415
|
+
* 2026-07-28 in favor of Client ID Metadata Documents (SEP-991); the deprecation
|
|
1416
|
+
* landed via spec PR
|
|
1417
|
+
* {@link https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2858 | modelcontextprotocol#2858}
|
|
1418
|
+
* (SEP-2577 is the separate roots/sampling/logging deprecation). Remains
|
|
1419
|
+
* functional during the deprecation window — at least twelve months under the
|
|
1420
|
+
* feature lifecycle policy (SEP-2596), so 2027-07-28 is the earliest possible
|
|
1421
|
+
* removal date. Prefer a CIMD URL `client_id` when the authorization server
|
|
1422
|
+
* advertises `client_id_metadata_document_supported`: the built-in `auth()` flow
|
|
1423
|
+
* skips registration for you when that capability is advertised AND your
|
|
1424
|
+
* provider supplies `clientMetadataUrl`, but `registerClient` itself does not
|
|
1425
|
+
* gate — calling it directly always sends the registration request.
|
|
1396
1426
|
*/
|
|
1397
1427
|
async function registerClient(authorizationServerUrl, { metadata, clientMetadata, scope, fetchFn }) {
|
|
1398
1428
|
let registrationUrl;
|
|
@@ -1414,7 +1444,7 @@ async function registerClient(authorizationServerUrl, { metadata, clientMetadata
|
|
|
1414
1444
|
body: await response.text(),
|
|
1415
1445
|
submittedMetadata
|
|
1416
1446
|
});
|
|
1417
|
-
return OAuthClientInformationFullSchema.parse(await response.json());
|
|
1447
|
+
return OAuthClientInformationFullSchema.parse(withoutIssuer(await response.json()));
|
|
1418
1448
|
}
|
|
1419
1449
|
|
|
1420
1450
|
//#endregion
|
|
@@ -1469,6 +1499,15 @@ function createPrivateKeyJwtAuth(options) {
|
|
|
1469
1499
|
};
|
|
1470
1500
|
}
|
|
1471
1501
|
/**
|
|
1502
|
+
* The `issuer` stamp for constructor-supplied client information. Omitting `expectedIssuer` is
|
|
1503
|
+
* deprecated: nothing else says which authorization server such credentials belong to.
|
|
1504
|
+
*/
|
|
1505
|
+
function checkedExpectedIssuer(expectedIssuer) {
|
|
1506
|
+
if (expectedIssuer === void 0) console.warn("[mcp-sdk] Omitting `expectedIssuer` is deprecated. Without it, the MCP server decides which authorization server receives this client's credentials; pass your authorization server's issuer URL as `expectedIssuer` so they are only sent there.");
|
|
1507
|
+
else if (typeof expectedIssuer !== "string" || !expectedIssuer) throw new Error("expectedIssuer must be the authorization server's issuer URL");
|
|
1508
|
+
return expectedIssuer;
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1472
1511
|
* OAuth provider for `client_credentials` grant with `client_secret_basic` authentication.
|
|
1473
1512
|
*
|
|
1474
1513
|
* This provider is designed for machine-to-machine authentication where
|
|
@@ -1478,7 +1517,8 @@ function createPrivateKeyJwtAuth(options) {
|
|
|
1478
1517
|
* ```ts source="./authExtensions.examples.ts#ClientCredentialsProvider_basicUsage"
|
|
1479
1518
|
* const provider = new ClientCredentialsProvider({
|
|
1480
1519
|
* clientId: 'my-client',
|
|
1481
|
-
* clientSecret: 'my-secret'
|
|
1520
|
+
* clientSecret: 'my-secret',
|
|
1521
|
+
* expectedIssuer: 'https://auth.example.com'
|
|
1482
1522
|
* });
|
|
1483
1523
|
*
|
|
1484
1524
|
* const transport = new StreamableHTTPClientTransport(serverUrl, {
|
|
@@ -1494,7 +1534,7 @@ var ClientCredentialsProvider = class {
|
|
|
1494
1534
|
this._clientInfo = {
|
|
1495
1535
|
client_id: options.clientId,
|
|
1496
1536
|
client_secret: options.clientSecret,
|
|
1497
|
-
issuer: options.expectedIssuer
|
|
1537
|
+
issuer: checkedExpectedIssuer(options.expectedIssuer)
|
|
1498
1538
|
};
|
|
1499
1539
|
this._clientMetadata = {
|
|
1500
1540
|
client_name: options.clientName ?? "client-credentials-client",
|
|
@@ -1542,7 +1582,8 @@ var ClientCredentialsProvider = class {
|
|
|
1542
1582
|
* const provider = new PrivateKeyJwtProvider({
|
|
1543
1583
|
* clientId: 'my-client',
|
|
1544
1584
|
* privateKey: pemEncodedPrivateKey,
|
|
1545
|
-
* algorithm: 'RS256'
|
|
1585
|
+
* algorithm: 'RS256',
|
|
1586
|
+
* expectedIssuer: 'https://auth.example.com'
|
|
1546
1587
|
* });
|
|
1547
1588
|
*
|
|
1548
1589
|
* const transport = new StreamableHTTPClientTransport(serverUrl, {
|
|
@@ -1558,7 +1599,7 @@ var PrivateKeyJwtProvider = class {
|
|
|
1558
1599
|
constructor(options) {
|
|
1559
1600
|
this._clientInfo = {
|
|
1560
1601
|
client_id: options.clientId,
|
|
1561
|
-
issuer: options.expectedIssuer
|
|
1602
|
+
issuer: checkedExpectedIssuer(options.expectedIssuer)
|
|
1562
1603
|
};
|
|
1563
1604
|
this._clientMetadata = {
|
|
1564
1605
|
client_name: options.clientName ?? "private-key-jwt-client",
|
|
@@ -1617,7 +1658,7 @@ var StaticPrivateKeyJwtProvider = class {
|
|
|
1617
1658
|
constructor(options) {
|
|
1618
1659
|
this._clientInfo = {
|
|
1619
1660
|
client_id: options.clientId,
|
|
1620
|
-
issuer: options.expectedIssuer
|
|
1661
|
+
issuer: checkedExpectedIssuer(options.expectedIssuer)
|
|
1621
1662
|
};
|
|
1622
1663
|
this._clientMetadata = {
|
|
1623
1664
|
client_name: options.clientName ?? "static-private-key-jwt-client",
|
|
@@ -1689,7 +1730,8 @@ var StaticPrivateKeyJwtProvider = class {
|
|
|
1689
1730
|
* return result.jwtAuthGrant;
|
|
1690
1731
|
* },
|
|
1691
1732
|
* clientId: 'my-mcp-client',
|
|
1692
|
-
* clientSecret: 'my-mcp-secret'
|
|
1733
|
+
* clientSecret: 'my-mcp-secret',
|
|
1734
|
+
* expectedIssuer: 'https://auth.example.com'
|
|
1693
1735
|
* });
|
|
1694
1736
|
*
|
|
1695
1737
|
* const transport = new StreamableHTTPClientTransport(serverUrl, {
|
|
@@ -1710,7 +1752,7 @@ var CrossAppAccessProvider = class {
|
|
|
1710
1752
|
this._clientInfo = {
|
|
1711
1753
|
client_id: options.clientId,
|
|
1712
1754
|
client_secret: options.clientSecret,
|
|
1713
|
-
issuer: options.expectedIssuer
|
|
1755
|
+
issuer: checkedExpectedIssuer(options.expectedIssuer)
|
|
1714
1756
|
};
|
|
1715
1757
|
this._clientMetadata = {
|
|
1716
1758
|
client_name: options.clientName ?? "cross-app-access-client",
|
|
@@ -3632,7 +3674,7 @@ var Client = class extends Protocol {
|
|
|
3632
3674
|
}, options);
|
|
3633
3675
|
const hit = await this._serveFromCache("prompts/list", void 0, options);
|
|
3634
3676
|
if (hit !== void 0) return hit;
|
|
3635
|
-
return this._listAllPages("prompts/list", params, options, (
|
|
3677
|
+
return this._listAllPages("prompts/list", params, options, (r) => r.prompts);
|
|
3636
3678
|
}
|
|
3637
3679
|
/**
|
|
3638
3680
|
* Lists available resources.
|
|
@@ -3671,7 +3713,7 @@ var Client = class extends Protocol {
|
|
|
3671
3713
|
}, options);
|
|
3672
3714
|
const hit = await this._serveFromCache("resources/list", void 0, options);
|
|
3673
3715
|
if (hit !== void 0) return hit;
|
|
3674
|
-
return this._listAllPages("resources/list", params, options, (
|
|
3716
|
+
return this._listAllPages("resources/list", params, options, (r) => r.resources);
|
|
3675
3717
|
}
|
|
3676
3718
|
/**
|
|
3677
3719
|
* Lists available resource URI templates for dynamic resources.
|
|
@@ -3696,7 +3738,7 @@ var Client = class extends Protocol {
|
|
|
3696
3738
|
}, options);
|
|
3697
3739
|
const hit = await this._serveFromCache("resources/templates/list", void 0, options);
|
|
3698
3740
|
if (hit !== void 0) return hit;
|
|
3699
|
-
return this._listAllPages("resources/templates/list", params, options, (
|
|
3741
|
+
return this._listAllPages("resources/templates/list", params, options, (r) => r.resourceTemplates);
|
|
3700
3742
|
}
|
|
3701
3743
|
/**
|
|
3702
3744
|
* Walk every page of a paginated list verb, aggregate, and write ONE
|
|
@@ -3704,8 +3746,7 @@ var Client = class extends Protocol {
|
|
|
3704
3746
|
* methods' no-`cursor` auto-aggregate path. Page 1's result object is
|
|
3705
3747
|
* mutated in place (its items array is extended; `nextCursor` is
|
|
3706
3748
|
* cleared); page-1 metadata (`ttlMs`, `cacheScope`, `_meta`) is preserved.
|
|
3707
|
-
* A `nextCursor`
|
|
3708
|
-
* non-converging server, mcp.d's `drainList` guard);
|
|
3749
|
+
* A page with the same items and `nextCursor` as the previous page ends the walk;
|
|
3709
3750
|
* {@linkcode ClientOptions.listMaxPages} is a hard cap — hitting it
|
|
3710
3751
|
* throws, so a partial aggregate is never cached. The
|
|
3711
3752
|
* captured-generation guard skips the write when a `list_changed` landed
|
|
@@ -3720,7 +3761,7 @@ var Client = class extends Protocol {
|
|
|
3720
3761
|
* trace context) supplied to the public `list*()` reaches every wire
|
|
3721
3762
|
* request the walk issues.
|
|
3722
3763
|
*/
|
|
3723
|
-
async _listAllPages(method, baseParams, options,
|
|
3764
|
+
async _listAllPages(method, baseParams, options, items, finalize) {
|
|
3724
3765
|
const bypass = options?.cacheMode === "bypass";
|
|
3725
3766
|
const generation = this._cache.captureGeneration(method);
|
|
3726
3767
|
const acc = await this.request({
|
|
@@ -3728,14 +3769,13 @@ var Client = class extends Protocol {
|
|
|
3728
3769
|
...baseParams && { params: { ...baseParams } }
|
|
3729
3770
|
}, options);
|
|
3730
3771
|
let cursor = acc.nextCursor;
|
|
3731
|
-
|
|
3772
|
+
let previous = acc;
|
|
3732
3773
|
let pages = 1;
|
|
3733
|
-
while (cursor !== void 0
|
|
3774
|
+
while (cursor !== void 0) {
|
|
3734
3775
|
if (this._listMaxPages !== 0 && pages >= this._listMaxPages) throw new SdkError(SdkErrorCode.ListPaginationExceeded, `${method}: exceeded listMaxPages (${this._listMaxPages}); server pagination did not terminate`, {
|
|
3735
3776
|
method,
|
|
3736
3777
|
listMaxPages: this._listMaxPages
|
|
3737
3778
|
});
|
|
3738
|
-
seen.add(cursor);
|
|
3739
3779
|
const page = await this.request({
|
|
3740
3780
|
method,
|
|
3741
3781
|
params: {
|
|
@@ -3743,7 +3783,9 @@ var Client = class extends Protocol {
|
|
|
3743
3783
|
cursor
|
|
3744
3784
|
}
|
|
3745
3785
|
}, options);
|
|
3746
|
-
|
|
3786
|
+
if (page.nextCursor === cursor && JSON.stringify(items(page)) === JSON.stringify(items(previous))) break;
|
|
3787
|
+
items(acc).push(...items(page));
|
|
3788
|
+
previous = page;
|
|
3747
3789
|
cursor = page.nextCursor;
|
|
3748
3790
|
pages++;
|
|
3749
3791
|
}
|
|
@@ -4004,19 +4046,22 @@ var Client = class extends Protocol {
|
|
|
4004
4046
|
notifications: filter
|
|
4005
4047
|
}
|
|
4006
4048
|
};
|
|
4049
|
+
const routeSendFailure = (error) => {
|
|
4050
|
+
settle({
|
|
4051
|
+
cause: "remote",
|
|
4052
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
4053
|
+
});
|
|
4054
|
+
};
|
|
4007
4055
|
try {
|
|
4008
|
-
|
|
4056
|
+
this.transport.send(jsonrpcRequest, {
|
|
4009
4057
|
requestSignal: requestAbort.signal,
|
|
4010
4058
|
onRequestStreamEnd: () => settle({
|
|
4011
4059
|
cause: "remote",
|
|
4012
4060
|
error: /* @__PURE__ */ new Error("subscriptions/listen: stream ended")
|
|
4013
4061
|
})
|
|
4014
|
-
});
|
|
4062
|
+
}).catch(routeSendFailure);
|
|
4015
4063
|
} catch (error) {
|
|
4016
|
-
|
|
4017
|
-
cause: "remote",
|
|
4018
|
-
error: error instanceof Error ? error : new Error(String(error))
|
|
4019
|
-
});
|
|
4064
|
+
routeSendFailure(error);
|
|
4020
4065
|
}
|
|
4021
4066
|
return {
|
|
4022
4067
|
honoredFilter: await opening,
|
|
@@ -4268,7 +4313,7 @@ var Client = class extends Protocol {
|
|
|
4268
4313
|
}
|
|
4269
4314
|
const hit = await this._serveFromCache("tools/list", void 0, options);
|
|
4270
4315
|
if (hit !== void 0) return hit;
|
|
4271
|
-
return this._listAllPages("tools/list", params, options, (
|
|
4316
|
+
return this._listAllPages("tools/list", params, options, (r) => r.tools, (acc) => this._excludeInvalidXMcpHeaderTools(acc));
|
|
4272
4317
|
}
|
|
4273
4318
|
/**
|
|
4274
4319
|
* SEP-2243 (protocol revision 2026-07-28): a Streamable HTTP client MUST
|
|
@@ -4489,7 +4534,7 @@ async function exchangeJwtAuthGrant(options) {
|
|
|
4489
4534
|
throw new Error(`JWT grant exchange failed with status ${response.status}: ${JSON.stringify(errorBody)}`);
|
|
4490
4535
|
}
|
|
4491
4536
|
const responseBody = await response.json();
|
|
4492
|
-
const parseResult = OAuthTokensSchema.safeParse(responseBody);
|
|
4537
|
+
const parseResult = OAuthTokensSchema.safeParse(withoutIssuer(responseBody));
|
|
4493
4538
|
if (!parseResult.success) throw new Error(`Invalid token response: ${parseResult.error.message}`);
|
|
4494
4539
|
return parseResult.data;
|
|
4495
4540
|
}
|