@chrischall/office-outlook-mcp 0.3.1 → 0.3.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/bundle.js CHANGED
@@ -20542,10 +20542,10 @@ var init_v4 = __esm({
20542
20542
  }
20543
20543
  });
20544
20544
 
20545
- // node_modules/@modelcontextprotocol/core/dist/auth-CUe6YdwF.mjs
20545
+ // node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/dist/auth-CGP0BDVq.mjs
20546
20546
  var LATEST_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, RELATED_TASK_META_KEY, PROTOCOL_VERSION_META_KEY, CLIENT_INFO_META_KEY, SERVER_INFO_META_KEY, CLIENT_CAPABILITIES_META_KEY, SUBSCRIPTION_ID_META_KEY, LOG_LEVEL_META_KEY, JSONRPC_VERSION, JSONValueSchema, JSONObjectSchema, JSONArraySchema, ProgressTokenSchema, CursorSchema, TaskMetadataSchema, RelatedTaskMetadataSchema, RequestMetaSchema, BaseRequestParamsSchema, TaskAugmentedRequestParamsSchema, RequestSchema, NotificationsParamsSchema, NotificationSchema, ResultMetaObjectSchema, ResultSchema, RequestIdSchema, JSONRPCRequestSchema, JSONRPCNotificationSchema, JSONRPCResultResponseSchema, JSONRPCErrorResponseSchema, JSONRPCMessageSchema, JSONRPCResponseSchema, EmptyResultSchema, CancelledNotificationParamsSchema, CancelledNotificationSchema, IconSchema, IconsSchema, BaseMetadataSchema, ImplementationSchema, FormElicitationCapabilitySchema, ElicitationCapabilitySchema, ClientTasksCapabilitySchema, ServerTasksCapabilitySchema, ClientCapabilitiesSchema, InitializeRequestParamsSchema, InitializeRequestSchema, ServerCapabilitiesSchema, InitializeResultSchema, InitializedNotificationSchema, DiscoverRequestSchema, DiscoverResultSchema, PingRequestSchema, ProgressSchema, ProgressNotificationParamsSchema, ProgressNotificationSchema, PaginatedRequestParamsSchema, PaginatedRequestSchema, PaginatedResultSchema, ResourceContentsSchema, TextResourceContentsSchema, Base64Schema, BlobResourceContentsSchema, RoleSchema, AnnotationsSchema, ResourceSchema, ResourceTemplateSchema, ListResourcesRequestSchema, ListResourcesResultSchema, ListResourceTemplatesRequestSchema, ListResourceTemplatesResultSchema, ResourceRequestParamsSchema, ReadResourceRequestParamsSchema, ReadResourceRequestSchema, ReadResourceResultSchema, ResourceListChangedNotificationSchema, SubscribeRequestParamsSchema, SubscribeRequestSchema, UnsubscribeRequestParamsSchema, UnsubscribeRequestSchema, SubscriptionFilterSchema, SubscriptionsListenRequestParamsSchema, SubscriptionsListenRequestSchema, SubscriptionsAcknowledgedNotificationParamsSchema, SubscriptionsAcknowledgedNotificationSchema, SubscriptionsListenResultMetaSchema, SubscriptionsListenResultSchema, ResourceUpdatedNotificationParamsSchema, ResourceUpdatedNotificationSchema, PromptArgumentSchema, PromptSchema, ListPromptsRequestSchema, ListPromptsResultSchema, GetPromptRequestParamsSchema, GetPromptRequestSchema, TextContentSchema, ImageContentSchema, AudioContentSchema, ToolUseContentSchema, EmbeddedResourceSchema, ResourceLinkSchema, ContentBlockSchema, PromptMessageSchema, GetPromptResultSchema, PromptListChangedNotificationSchema, ToolAnnotationsSchema, ToolExecutionSchema, ToolSchema, ListToolsRequestSchema, ListToolsResultSchema, CallToolResultSchema, CompatibilityCallToolResultSchema, CallToolRequestParamsSchema, CallToolRequestSchema, ToolListChangedNotificationSchema, ListChangedOptionsBaseSchema, LoggingLevelSchema, SetLevelRequestParamsSchema, SetLevelRequestSchema, LoggingMessageNotificationParamsSchema, LoggingMessageNotificationSchema, ModelHintSchema, ModelPreferencesSchema, ToolChoiceSchema, ToolResultContentSchema, SamplingContentSchema, SamplingMessageContentBlockSchema, SamplingMessageSchema, CreateMessageRequestParamsSchema, CreateMessageRequestSchema, CreateMessageResultSchema, CreateMessageResultWithToolsSchema, BooleanSchemaSchema, StringSchemaSchema, NumberSchemaSchema, UntitledSingleSelectEnumSchemaSchema, TitledSingleSelectEnumSchemaSchema, LegacyTitledEnumSchemaSchema, SingleSelectEnumSchemaSchema, UntitledMultiSelectEnumSchemaSchema, TitledMultiSelectEnumSchemaSchema, MultiSelectEnumSchemaSchema, EnumSchemaSchema, PrimitiveSchemaDefinitionSchema, ElicitRequestFormParamsSchema, ElicitRequestURLParamsSchema, ElicitRequestParamsSchema, ElicitRequestSchema, ElicitationCompleteNotificationParamsSchema, ElicitationCompleteNotificationSchema, ElicitResultSchema, ResourceTemplateReferenceSchema, PromptReferenceSchema, CompleteRequestParamsSchema, CompleteRequestSchema, CompleteResultSchema, RootSchema, ListRootsRequestSchema, ListRootsResultSchema, RootsListChangedNotificationSchema, TaskCreationParamsSchema, TaskStatusSchema, TaskSchema, CreateTaskResultSchema, TaskStatusNotificationParamsSchema, TaskStatusNotificationSchema, GetTaskRequestSchema, GetTaskResultSchema, GetTaskPayloadRequestSchema, GetTaskPayloadResultSchema, ListTasksRequestSchema, ListTasksResultSchema, CancelTaskRequestSchema, CancelTaskResultSchema, ClientRequestSchema, ClientNotificationSchema, ClientResultSchema, ServerRequestSchema, ServerNotificationSchema, ServerResultSchema, SafeUrlSchema, OAuthProtectedResourceMetadataSchema, OAuthMetadataSchema, OpenIdProviderMetadataSchema, OpenIdProviderDiscoveryMetadataSchema, OAuthTokensSchema, IdJagTokenExchangeResponseSchema, OAuthErrorResponseSchema, OptionalSafeUrlSchema, OAuthClientMetadataSchema, OAuthClientInformationSchema, OAuthClientInformationFullSchema, OAuthClientRegistrationErrorSchema, OAuthTokenRevocationRequestSchema;
20547
- var init_auth_CUe6YdwF = __esm({
20548
- "node_modules/@modelcontextprotocol/core/dist/auth-CUe6YdwF.mjs"() {
20547
+ var init_auth_CGP0BDVq = __esm({
20548
+ "node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/dist/auth-CGP0BDVq.mjs"() {
20549
20549
  init_v4();
20550
20550
  LATEST_PROTOCOL_VERSION = "2025-11-25";
20551
20551
  SUPPORTED_PROTOCOL_VERSIONS = [
@@ -21383,7 +21383,8 @@ var init_auth_CUe6YdwF = __esm({
21383
21383
  introspection_endpoint_auth_signing_alg_values_supported: array(string2()).optional(),
21384
21384
  code_challenge_methods_supported: array(string2()).optional(),
21385
21385
  client_id_metadata_document_supported: boolean2().optional(),
21386
- authorization_response_iss_parameter_supported: boolean2().optional().catch(void 0)
21386
+ authorization_response_iss_parameter_supported: boolean2().optional().catch(void 0),
21387
+ dpop_signing_alg_values_supported: array(string2()).optional()
21387
21388
  });
21388
21389
  OpenIdProviderMetadataSchema = looseObject({
21389
21390
  issuer: string2(),
@@ -21486,14 +21487,14 @@ var init_auth_CUe6YdwF = __esm({
21486
21487
  }
21487
21488
  });
21488
21489
 
21489
- // node_modules/@modelcontextprotocol/core/dist/internal.mjs
21490
+ // node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/dist/internal.mjs
21490
21491
  var init_internal = __esm({
21491
- "node_modules/@modelcontextprotocol/core/dist/internal.mjs"() {
21492
- init_auth_CUe6YdwF();
21492
+ "node_modules/@modelcontextprotocol/server/node_modules/@modelcontextprotocol/core/dist/internal.mjs"() {
21493
+ init_auth_CGP0BDVq();
21493
21494
  }
21494
21495
  });
21495
21496
 
21496
- // node_modules/@modelcontextprotocol/server/dist/src-CX2iR2pK.mjs
21497
+ // node_modules/@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs
21497
21498
  function stampErrorBrands(instance, ctor) {
21498
21499
  const brands = /* @__PURE__ */ new Set();
21499
21500
  let current = ctor;
@@ -24265,8 +24266,8 @@ function normalizeRawShapeSchema(schema) {
24265
24266
  return schema;
24266
24267
  }
24267
24268
  var BRANDS, OAuthError, SdkErrorCode, SdkError, SdkHttpError, FIRST_MODERN_PROTOCOL_VERSION, SUPPORTED_MODERN_PROTOCOL_VERSIONS, TOOL_RESULT_FOREIGN_FAMILY_KEYS, memo$1, REF_REWRITE_DATA_POSITION_KEYS, REF_REWRITE_NAME_MAP_KEYS, requestMethodKeys$1, notificationMethodKeys$1, resultMethodKeys, maps$1, rev2025RequestMethods, rev2025NotificationMethods, NOT_IN_ERA$1, rev2025Codec, memo2, CACHEABLE_RESULT_METHODS, RESULT_CACHE_HINT_FALLBACK, ProtocolErrorCode, ProtocolError, ResourceNotFoundError, UrlElicitationRequiredError, UnsupportedProtocolVersionError, MissingRequiredClientCapabilityError, DEFAULT_CACHE_TTL_MS, DEFAULT_CACHE_SCOPE, EXTENDED_RESULT_TYPE_METHODS, INPUT_REQUEST_METHODS_2026, maps, requestMethodKeys, notificationMethodKeys, rev2026RequestMethods, rev2026NotificationMethods, NOT_IN_ERA, REQUIRED_ENVELOPE_KEYS, rev2026Codec, wireResultSchemasMemo, MODERN_WIRE_REVISION, ALL_CODECS, schemas_exports3, isJSONRPCRequest, isJSONRPCNotification, isJSONRPCResultResponse, isJSONRPCErrorResponse, isInputRequiredResult, X_MCP_HEADER_KEY, RFC9110_TOKEN, PERMITTED_X_MCP_HEADER_TYPES, NON_REACHABLE_SUBSCHEMA_KEYWORDS, OBJECT_VALUED_SUBSCHEMA_KEYWORDS, HEADER_MISMATCH_ERROR_CODE, INBOUND_VALIDATION_LADDER, LADDER_ERROR_HTTP_STATUS, warnedZodFallback, JSON_SCHEMA_CONVERSION_TARGET, DATETIME_FRACTION_DIGITS, ANNOTATION_ONLY_JSON_SCHEMA_KEYWORDS, ROOT_KEYS, PROPERTY_KEYS_BY_TYPE, SUPPORTED_STRING_FORMATS, inputRequired, REQUEST_STATE_ONLY_LEG_PACING_MS, SPEC_SCHEMA_KEYS, authSchemas, _specTypeSchemas, _isSpecType, specTypeSchemas, isSpecType, DEFAULT_REQUEST_TIMEOUT_MSEC, RESERVED_ENVELOPE_META_KEYS, RETRY_PARAMS_KEYS, NO_REQUEST_STATE, writeNegotiatedProtocolVersion, Protocol, require_content_type, import_content_type, STDIO_DEFAULT_MAX_BUFFER_SIZE, ReadBuffer, TOOL_NAME_REGEX;
24268
- var init_src_CX2iR2pK = __esm({
24269
- "node_modules/@modelcontextprotocol/server/dist/src-CX2iR2pK.mjs"() {
24269
+ var init_src_D_y6h4N7 = __esm({
24270
+ "node_modules/@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs"() {
24270
24271
  init_chunk_Br0eD_fh();
24271
24272
  init_dialects_DoSzNhcb();
24272
24273
  init_internal();
@@ -24359,8 +24360,18 @@ var init_src_CX2iR2pK = __esm({
24359
24360
  if (typeof this !== "function") throw new TypeError("isInstance must be called on the class (e.g. `SdkError.isInstance(value)`); for callbacks use `v => SdkError.isInstance(v)`");
24360
24361
  return brandedHasInstance(this, value);
24361
24362
  }
24362
- constructor(code, message, data) {
24363
- super(message);
24363
+ /**
24364
+ * @param code - Stable string code identifying the failure ({@linkcode SdkErrorCode}).
24365
+ * @param message - Human-readable description.
24366
+ * @param data - Optional structured payload (for example the HTTP status carried by
24367
+ * {@linkcode SdkHttpError}). Opaque to the SDK: a `cause` key inside `data` is not
24368
+ * promoted to `Error.cause`.
24369
+ * @param options - Standard `ErrorOptions`, forwarded to `Error`. Pass the underlying
24370
+ * failure as `{ cause }` so it is reachable through the `Error.cause` chain that
24371
+ * loggers and error trackers walk.
24372
+ */
24373
+ constructor(code, message, data, options) {
24374
+ super(message, options);
24364
24375
  this.code = code;
24365
24376
  this.data = data;
24366
24377
  this.name = "SdkError";
@@ -24371,8 +24382,11 @@ var init_src_CX2iR2pK = __esm({
24371
24382
  static {
24372
24383
  Object.defineProperty(this, "mcpBrand", { value: "mcp.SdkHttpError" });
24373
24384
  }
24374
- constructor(code, message, data) {
24375
- super(code, message, data);
24385
+ /**
24386
+ * @param options - Standard `ErrorOptions`, forwarded to `Error` (see {@linkcode SdkError}).
24387
+ */
24388
+ constructor(code, message, data, options) {
24389
+ super(code, message, data, options);
24376
24390
  this.name = "SdkHttpError";
24377
24391
  }
24378
24392
  get status() {
@@ -25070,7 +25084,7 @@ var init_src_CX2iR2pK = __esm({
25070
25084
  evaluatedAt: "pre-dispatch",
25071
25085
  codes: [HEADER_MISMATCH_ERROR_CODE],
25072
25086
  conformance: ["http-header-validation"],
25073
- rationale: "SEP-2243 standard `Mcp-Method` / `Mcp-Name` headers \u2014 presence, sentinel decoding, and `Mcp-Name` \u2194 body cross-check \u2014 are validated by the HTTP entry on a modern-classified request after the supported-revision gate and before dispatch. The classifier\u2019s own header-mismatch cells (protocol-version, `Mcp-Method` mismatch) stay on the edge `era-classification` rung; this rung carries the entry-layer presence/`Mcp-Name` half. Evaluated before the capability gate, the factory call, and the `Mcp-Param-*` rung so a request that fails several rungs is answered by the standard-header rung first. The documented order (after method-registry 5 and request-params 6) is NOT the observed precedence: serveModern evaluates this rung immediately after the supported-revision gate, so a request that also fails a dispatch rung is answered here before the dispatch rungs (5\u20136) are consulted."
25087
+ rationale: "SEP-2243 standard `MCP-Protocol-Version` / `Mcp-Method` / `Mcp-Name` headers \u2014 presence, sentinel decoding, and `Mcp-Name` \u2194 body cross-check \u2014 are validated by the HTTP entry on a modern-classified request after the supported-revision gate and before dispatch. The spec requires `MCP-Protocol-Version` and `Mcp-Method` on every modern *request* POST (`Mcp-Name` only for the methods that mirror `params.name` / `params.uri` / `params.taskId`, see `MCP_NAME_HEADER_SOURCE`) and names them in that order, so a request missing several is answered by the earliest. Notification POSTs are exempt: the presence half runs on requests only, so a modern-enveloped notification is dispatched even with no standard headers at all. The classifier\u2019s own header-mismatch cells (protocol-version, `Mcp-Method` mismatch) stay on the edge `era-classification` rung; this rung carries the entry-layer presence/`Mcp-Name` half \u2014 including the missing `MCP-Protocol-Version` cell, which cannot live on the edge rung without breaking body-primary classification. Evaluated before the capability gate, the factory call, and the `Mcp-Param-*` rung so a request that fails several rungs is answered by the standard-header rung first. The documented order (after method-registry 5 and request-params 6) is NOT the observed precedence: serveModern evaluates this rung immediately after the supported-revision gate, so a request that also fails a dispatch rung is answered here before the dispatch rungs (5\u20136) are consulted."
25074
25088
  },
25075
25089
  {
25076
25090
  rung: "client-capabilities",
@@ -25486,7 +25500,7 @@ var init_src_CX2iR2pK = __esm({
25486
25500
  return this._requestHandlers.get(method);
25487
25501
  }
25488
25502
  async _oncancel(notification) {
25489
- if (!notification.params.requestId) return;
25503
+ if (notification.params.requestId === void 0) return;
25490
25504
  this._requestHandlerAbortControllers.get(notification.params.requestId)?.abort(notification.params.reason);
25491
25505
  }
25492
25506
  _setupTimeout(messageId, timeout, maxTotalTimeout, onTimeout, resetTimeoutOnProgress = false) {
@@ -25885,19 +25899,20 @@ var init_src_CX2iR2pK = __esm({
25885
25899
  const cancel = (reason) => {
25886
25900
  if (responseReceived) return;
25887
25901
  this._progressHandlers.delete(messageId);
25888
- if (requestAbort === void 0) this._transport?.send(this._envelopeOutbound({
25889
- jsonrpc: "2.0",
25890
- method: "notifications/cancelled",
25891
- params: {
25892
- requestId: messageId,
25893
- reason: String(reason)
25894
- }
25895
- }), {
25896
- relatedRequestId,
25897
- resumptionToken,
25898
- onresumptiontoken
25899
- }).catch((error62) => this._onerror(/* @__PURE__ */ new Error(`Failed to send cancellation: ${error62}`)));
25900
- else requestAbort.abort();
25902
+ if (requestAbort === void 0) {
25903
+ if (request.method !== "initialize") this._transport?.send(this._envelopeOutbound({
25904
+ jsonrpc: "2.0",
25905
+ method: "notifications/cancelled",
25906
+ params: {
25907
+ requestId: messageId,
25908
+ reason: String(reason)
25909
+ }
25910
+ }), {
25911
+ relatedRequestId,
25912
+ resumptionToken,
25913
+ onresumptiontoken
25914
+ }).catch((error62) => this._onerror(/* @__PURE__ */ new Error(`Failed to send cancellation: ${error62}`)));
25915
+ } else requestAbort.abort();
25901
25916
  reject(reason instanceof SdkError ? reason : new SdkError(SdkErrorCode.RequestTimeout, String(reason)));
25902
25917
  };
25903
25918
  this._responseHandlers.set(messageId, (response) => {
@@ -25977,7 +25992,7 @@ var init_src_CX2iR2pK = __esm({
25977
25992
  jsonrpc: "2.0",
25978
25993
  ...notification
25979
25994
  });
25980
- if ((this._options?.debouncedNotificationMethods ?? []).includes(notification.method) && !notification.params && !options?.relatedRequestId) {
25995
+ if ((this._options?.debouncedNotificationMethods ?? []).includes(notification.method) && !notification.params && options?.relatedRequestId === void 0) {
25981
25996
  if (this._pendingDebouncedNotifications.has(notification.method)) return;
25982
25997
  this._pendingDebouncedNotifications.add(notification.method);
25983
25998
  Promise.resolve().then(() => {
@@ -33181,7 +33196,7 @@ var init_shimsNode = __esm({
33181
33196
  }
33182
33197
  });
33183
33198
 
33184
- // node_modules/@modelcontextprotocol/server/dist/mcp-DXXb3Vv3.mjs
33199
+ // node_modules/@modelcontextprotocol/server/dist/mcp-Dw2OlZ1f.mjs
33185
33200
  function isCompletable(schema) {
33186
33201
  return !!schema && typeof schema === "object" && COMPLETABLE_SYMBOL in schema;
33187
33202
  }
@@ -33240,6 +33255,9 @@ function notificationToServerEvent(method, uri) {
33240
33255
  };
33241
33256
  }
33242
33257
  }
33258
+ function supportsScopeChallengeResolver(transport) {
33259
+ return typeof transport === "object" && transport !== null && "setScopeChallengeResolver" in transport && typeof transport.setScopeChallengeResolver === "function";
33260
+ }
33243
33261
  function resolveLegacyShimOptions(options) {
33244
33262
  if (options?.maxRounds !== void 0 && (!Number.isInteger(options.maxRounds) || options.maxRounds < 1)) throw new RangeError(`inputRequired.maxRounds must be a positive integer (got ${options.maxRounds})`);
33245
33263
  if (options?.roundTimeoutMs !== void 0 && (!Number.isFinite(options.roundTimeoutMs) || options.roundTimeoutMs <= 0)) throw new RangeError(`inputRequired.roundTimeoutMs must be a positive number (got ${options.roundTimeoutMs})`);
@@ -33338,9 +33356,9 @@ function unwrapOptionalSchema(schema) {
33338
33356
  return schema.def?.innerType ?? schema;
33339
33357
  }
33340
33358
  var COMPLETABLE_SYMBOL, MAX_TIMER_DELAY_MS, DEFAULT_MAX_SUBSCRIPTIONS, CHANGE_NOTIFICATION_METHODS, StdioListenRouter, DEFAULT_LEGACY_SHIM_MAX_ROUNDS, DEFAULT_LEGACY_SHIM_ROUND_TIMEOUT_MS, LegacyInputRequiredShim, INPUT_REQUIRED_CAPABLE_METHODS, writeClientIdentity, installDiscoverHandler, readServerIdentity, Server, McpServer, EMPTY_OBJECT_JSON_SCHEMA, EMPTY_COMPLETION_RESULT;
33341
- var init_mcp_DXXb3Vv3 = __esm({
33342
- "node_modules/@modelcontextprotocol/server/dist/mcp-DXXb3Vv3.mjs"() {
33343
- init_src_CX2iR2pK();
33359
+ var init_mcp_Dw2OlZ1f = __esm({
33360
+ "node_modules/@modelcontextprotocol/server/dist/mcp-Dw2OlZ1f.mjs"() {
33361
+ init_src_D_y6h4N7();
33344
33362
  init_shimsNode();
33345
33363
  COMPLETABLE_SYMBOL = /* @__PURE__ */ Symbol.for("mcp.completable");
33346
33364
  MAX_TIMER_DELAY_MS = 2 ** 31 - 1;
@@ -34235,6 +34253,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34235
34253
  * ```
34236
34254
  */
34237
34255
  async connect(transport) {
34256
+ if (supportsScopeChallengeResolver(transport)) transport.setScopeChallengeResolver((context) => this.resolveScopeChallenge(context));
34238
34257
  return await this.server.connect(transport);
34239
34258
  }
34240
34259
  /**
@@ -34243,6 +34262,41 @@ var init_mcp_DXXb3Vv3 = __esm({
34243
34262
  async close() {
34244
34263
  await this.server.close();
34245
34264
  }
34265
+ /** @internal */
34266
+ resolveScopeChallenge = (context) => {
34267
+ switch (context.request.method) {
34268
+ case "tools/call": {
34269
+ const toolName = context.request.params?.name;
34270
+ if (typeof toolName !== "string") return;
34271
+ const tool = this._registeredTools[toolName];
34272
+ if (tool === void 0 || !tool.enabled) return;
34273
+ return tool.scopeChallenge?.(context);
34274
+ }
34275
+ case "resources/read": {
34276
+ const resourceUri = context.request.params?.uri;
34277
+ if (typeof resourceUri !== "string") return;
34278
+ let uri;
34279
+ try {
34280
+ uri = new URL(resourceUri);
34281
+ } catch {
34282
+ return;
34283
+ }
34284
+ const resource = this._registeredResources[uri.toString()];
34285
+ if (resource !== void 0) return resource.enabled ? resource.scopeChallenge?.(context) : void 0;
34286
+ for (const template of Object.values(this._registeredResourceTemplates)) if (template.resourceTemplate.uriTemplate.match(uri.toString())) return template.enabled ? template.scopeChallenge?.(context) : void 0;
34287
+ return;
34288
+ }
34289
+ case "prompts/get": {
34290
+ const promptName = context.request.params?.name;
34291
+ if (typeof promptName !== "string") return;
34292
+ const prompt = this._registeredPrompts[promptName];
34293
+ if (prompt === void 0 || !prompt.enabled) return;
34294
+ return prompt.scopeChallenge?.(context);
34295
+ }
34296
+ default:
34297
+ return;
34298
+ }
34299
+ };
34246
34300
  _toolHandlersInitialized = false;
34247
34301
  setToolRequestHandlers() {
34248
34302
  if (this._toolHandlersInitialized) return;
@@ -34409,7 +34463,10 @@ var init_mcp_DXXb3Vv3 = __esm({
34409
34463
  }
34410
34464
  for (const template of Object.values(this._registeredResourceTemplates)) {
34411
34465
  const variables = template.resourceTemplate.uriTemplate.match(uri.toString());
34412
- if (variables) return attachCacheHintFallback(await template.readCallback(uri, variables, ctx), template.cacheHint);
34466
+ if (variables) {
34467
+ if (!template.enabled) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Resource template ${template.resourceTemplate.uriTemplate} disabled`);
34468
+ return attachCacheHintFallback(await template.readCallback(uri, variables, ctx), template.cacheHint);
34469
+ }
34413
34470
  }
34414
34471
  throw new ResourceNotFoundError(request.params.uri);
34415
34472
  });
@@ -34440,36 +34497,32 @@ var init_mcp_DXXb3Vv3 = __esm({
34440
34497
  this._promptHandlersInitialized = true;
34441
34498
  }
34442
34499
  registerResource(name, uriOrTemplate, config2, readCallback) {
34443
- const cacheHint = config2.cacheHint;
34444
- let metadata = config2;
34445
- if (cacheHint !== void 0) {
34446
- assertValidCacheHint(cacheHint, `resource ${name}`);
34447
- const rest = { ...config2 };
34448
- delete rest.cacheHint;
34449
- metadata = rest;
34450
- }
34500
+ const { cacheHint, scopeChallenge, ...resourceMetadata } = config2;
34501
+ const metadata = resourceMetadata;
34502
+ if (cacheHint !== void 0) assertValidCacheHint(cacheHint, `resource ${name}`);
34451
34503
  if (typeof uriOrTemplate === "string") {
34452
34504
  if (this._registeredResources[uriOrTemplate]) throw new Error(`Resource ${uriOrTemplate} is already registered`);
34453
- const registeredResource = this._createRegisteredResource(name, config2.title, uriOrTemplate, metadata, readCallback);
34505
+ const registeredResource = this._createRegisteredResource(name, config2.title, uriOrTemplate, metadata, scopeChallenge, readCallback);
34454
34506
  if (cacheHint !== void 0) registeredResource.cacheHint = cacheHint;
34455
34507
  this.setResourceRequestHandlers();
34456
34508
  this.sendResourceListChanged();
34457
34509
  return registeredResource;
34458
34510
  } else {
34459
34511
  if (this._registeredResourceTemplates[name]) throw new Error(`Resource template ${name} is already registered`);
34460
- const registeredResourceTemplate = this._createRegisteredResourceTemplate(name, config2.title, uriOrTemplate, metadata, readCallback);
34512
+ const registeredResourceTemplate = this._createRegisteredResourceTemplate(name, config2.title, uriOrTemplate, metadata, scopeChallenge, readCallback);
34461
34513
  if (cacheHint !== void 0) registeredResourceTemplate.cacheHint = cacheHint;
34462
34514
  this.setResourceRequestHandlers();
34463
34515
  this.sendResourceListChanged();
34464
34516
  return registeredResourceTemplate;
34465
34517
  }
34466
34518
  }
34467
- _createRegisteredResource(name, title, uri, metadata, readCallback) {
34519
+ _createRegisteredResource(name, title, uri, metadata, scopeChallenge, readCallback) {
34468
34520
  const registeredResource = {
34469
34521
  name,
34470
34522
  title,
34471
34523
  metadata,
34472
34524
  readCallback,
34525
+ scopeChallenge,
34473
34526
  enabled: true,
34474
34527
  disable: () => registeredResource.update({ enabled: false }),
34475
34528
  enable: () => registeredResource.update({ enabled: true }),
@@ -34483,6 +34536,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34483
34536
  if (updates.title !== void 0) registeredResource.title = updates.title;
34484
34537
  if (updates.metadata !== void 0) registeredResource.metadata = updates.metadata;
34485
34538
  if (updates.callback !== void 0) registeredResource.readCallback = updates.callback;
34539
+ if (updates.scopeChallenge !== void 0) registeredResource.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
34486
34540
  if (updates.enabled !== void 0) registeredResource.enabled = updates.enabled;
34487
34541
  this.sendResourceListChanged();
34488
34542
  }
@@ -34490,12 +34544,13 @@ var init_mcp_DXXb3Vv3 = __esm({
34490
34544
  this._registeredResources[uri] = registeredResource;
34491
34545
  return registeredResource;
34492
34546
  }
34493
- _createRegisteredResourceTemplate(name, title, template, metadata, readCallback) {
34547
+ _createRegisteredResourceTemplate(name, title, template, metadata, scopeChallenge, readCallback) {
34494
34548
  const registeredResourceTemplate = {
34495
34549
  resourceTemplate: template,
34496
34550
  title,
34497
34551
  metadata,
34498
34552
  readCallback,
34553
+ scopeChallenge,
34499
34554
  enabled: true,
34500
34555
  disable: () => registeredResourceTemplate.update({ enabled: false }),
34501
34556
  enable: () => registeredResourceTemplate.update({ enabled: true }),
@@ -34509,6 +34564,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34509
34564
  if (updates.template !== void 0) registeredResourceTemplate.resourceTemplate = updates.template;
34510
34565
  if (updates.metadata !== void 0) registeredResourceTemplate.metadata = updates.metadata;
34511
34566
  if (updates.callback !== void 0) registeredResourceTemplate.readCallback = updates.callback;
34567
+ if (updates.scopeChallenge !== void 0) registeredResourceTemplate.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
34512
34568
  if (updates.enabled !== void 0) registeredResourceTemplate.enabled = updates.enabled;
34513
34569
  this.sendResourceListChanged();
34514
34570
  }
@@ -34518,7 +34574,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34518
34574
  if (Array.isArray(variableNames) && variableNames.some((v) => !!template.completeCallback(v))) this.setCompletionRequestHandler();
34519
34575
  return registeredResourceTemplate;
34520
34576
  }
34521
- _createRegisteredPrompt(name, title, description, argsSchema, callback, icons, _meta) {
34577
+ _createRegisteredPrompt(name, title, description, argsSchema, callback, icons, scopeChallenge, _meta) {
34522
34578
  let currentArgsSchema = argsSchema;
34523
34579
  let currentCallback = callback;
34524
34580
  const registeredPrompt = {
@@ -34526,6 +34582,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34526
34582
  description,
34527
34583
  argsSchema,
34528
34584
  icons,
34585
+ scopeChallenge,
34529
34586
  _meta,
34530
34587
  handler: createPromptHandler(name, argsSchema, callback),
34531
34588
  enabled: true,
@@ -34540,6 +34597,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34540
34597
  if (updates.title !== void 0) registeredPrompt.title = updates.title;
34541
34598
  if (updates.description !== void 0) registeredPrompt.description = updates.description;
34542
34599
  if (updates.icons !== void 0) registeredPrompt.icons = updates.icons;
34600
+ if (updates.scopeChallenge !== void 0) registeredPrompt.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
34543
34601
  if (updates._meta !== void 0) registeredPrompt._meta = updates._meta;
34544
34602
  let needsHandlerRegen = false;
34545
34603
  if (updates.argsSchema !== void 0) {
@@ -34567,7 +34625,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34567
34625
  }
34568
34626
  return registeredPrompt;
34569
34627
  }
34570
- _createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, icons, execution, _meta, handler) {
34628
+ _createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, icons, execution, scopeChallenge, _meta, handler) {
34571
34629
  validateAndWarnToolName(name);
34572
34630
  if (inputSchema !== void 0) try {
34573
34631
  const json2 = standardSchemaToJsonSchema(inputSchema, "input");
@@ -34586,6 +34644,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34586
34644
  annotations,
34587
34645
  icons,
34588
34646
  execution,
34647
+ scopeChallenge,
34589
34648
  _meta,
34590
34649
  handler,
34591
34650
  executor: createToolExecutor(inputSchema, handler),
@@ -34624,6 +34683,7 @@ var init_mcp_DXXb3Vv3 = __esm({
34624
34683
  }
34625
34684
  if (updates.annotations !== void 0) registeredTool.annotations = updates.annotations;
34626
34685
  if (updates.icons !== void 0) registeredTool.icons = updates.icons;
34686
+ if (updates.scopeChallenge !== void 0) registeredTool.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
34627
34687
  if (updates._meta !== void 0) registeredTool._meta = updates._meta;
34628
34688
  if (updates.enabled !== void 0) registeredTool.enabled = updates.enabled;
34629
34689
  this.sendToolListChanged();
@@ -34636,13 +34696,13 @@ var init_mcp_DXXb3Vv3 = __esm({
34636
34696
  }
34637
34697
  registerTool(name, config2, cb) {
34638
34698
  if (this._registeredTools[name]) throw new Error(`Tool ${name} is already registered`);
34639
- const { title, description, inputSchema, outputSchema, annotations, icons, _meta } = config2;
34640
- return this._createRegisteredTool(name, title, description, normalizeRawShapeSchema(inputSchema), normalizeRawShapeSchema(outputSchema), annotations, icons, void 0, _meta, cb);
34699
+ const { title, description, inputSchema, outputSchema, annotations, icons, scopeChallenge, _meta } = config2;
34700
+ return this._createRegisteredTool(name, title, description, normalizeRawShapeSchema(inputSchema), normalizeRawShapeSchema(outputSchema), annotations, icons, void 0, scopeChallenge, _meta, cb);
34641
34701
  }
34642
34702
  registerPrompt(name, config2, cb) {
34643
34703
  if (this._registeredPrompts[name]) throw new Error(`Prompt ${name} is already registered`);
34644
- const { title, description, argsSchema, icons, _meta } = config2;
34645
- const registeredPrompt = this._createRegisteredPrompt(name, title, description, normalizeRawShapeSchema(argsSchema), cb, icons, _meta);
34704
+ const { title, description, argsSchema, icons, scopeChallenge, _meta } = config2;
34705
+ const registeredPrompt = this._createRegisteredPrompt(name, title, description, normalizeRawShapeSchema(argsSchema), cb, icons, scopeChallenge, _meta);
34646
34706
  this.setPromptRequestHandlers();
34647
34707
  this.sendPromptListChanged();
34648
34708
  return registeredPrompt;
@@ -34868,6 +34928,7 @@ function serveStdio(factory, options = {}) {
34868
34928
  return;
34869
34929
  }
34870
34930
  if (state.era === "modern" && await tryServeListen(message)) return;
34931
+ if (isTornDown()) return;
34871
34932
  state.instance.channel.deliver(message);
34872
34933
  return;
34873
34934
  }
@@ -34934,6 +34995,7 @@ function serveStdio(factory, options = {}) {
34934
34995
  };
34935
34996
  }
34936
34997
  if (await tryServeListen(message)) return;
34998
+ if (isTornDown()) return;
34937
34999
  state.instance.channel.deliver(message, { classification: opening.classification });
34938
35000
  return;
34939
35001
  case "legacy": {
@@ -35019,12 +35081,13 @@ function serveStdio(factory, options = {}) {
35019
35081
  function toError(value) {
35020
35082
  return value instanceof Error ? value : new Error(String(value));
35021
35083
  }
35022
- var StdioServerTransport, DISCARD_ANSWER_TIMEOUT_MS, StdioConnectionChannel;
35084
+ var swallowsErrorsAfterClose, StdioServerTransport, DISCARD_ANSWER_TIMEOUT_MS, StdioConnectionChannel;
35023
35085
  var init_stdio = __esm({
35024
35086
  "node_modules/@modelcontextprotocol/server/dist/stdio.mjs"() {
35025
- init_mcp_DXXb3Vv3();
35026
- init_src_CX2iR2pK();
35087
+ init_mcp_Dw2OlZ1f();
35088
+ init_src_D_y6h4N7();
35027
35089
  init_shimsNode();
35090
+ swallowsErrorsAfterClose = /* @__PURE__ */ Symbol("swallowsErrorsAfterClose");
35028
35091
  StdioServerTransport = class {
35029
35092
  _readBuffer;
35030
35093
  _started = false;
@@ -35051,18 +35114,27 @@ var init_stdio = __esm({
35051
35114
  this.onerror?.(error62);
35052
35115
  };
35053
35116
  _onstdouterror = (error62) => {
35117
+ if (this._closed) return;
35054
35118
  this.onerror?.(error62);
35055
35119
  this.close().catch(() => {
35056
35120
  });
35057
35121
  };
35122
+ _onstdinclose = () => {
35123
+ this.close().catch(() => {
35124
+ });
35125
+ };
35058
35126
  /**
35059
35127
  * Starts listening for messages on `stdin`.
35060
35128
  */
35061
35129
  async start() {
35062
35130
  if (this._started) throw new Error("StdioServerTransport already started! If using Server class, note that connect() calls start() automatically.");
35063
35131
  this._started = true;
35132
+ for (const listener of this._stdout.listeners("error")) if (listener[swallowsErrorsAfterClose]) this._stdout.off("error", listener);
35133
+ if (this._stdin.readableEnded || this._stdin.destroyed) setImmediate(this._onstdinclose);
35064
35134
  this._stdin.on("data", this._ondata);
35065
35135
  this._stdin.on("error", this._onerror);
35136
+ this._stdin.on("end", this._onstdinclose);
35137
+ this._stdin.on("close", this._onstdinclose);
35066
35138
  this._stdout.on("error", this._onstdouterror);
35067
35139
  }
35068
35140
  processReadBuffer() {
@@ -35079,7 +35151,9 @@ var init_stdio = __esm({
35079
35151
  this._closed = true;
35080
35152
  this._stdin.off("data", this._ondata);
35081
35153
  this._stdin.off("error", this._onerror);
35082
- this._stdout.off("error", this._onstdouterror);
35154
+ this._stdin.off("end", this._onstdinclose);
35155
+ this._stdin.off("close", this._onstdinclose);
35156
+ this._onstdouterror[swallowsErrorsAfterClose] = true;
35083
35157
  if (this._stdin.listenerCount("data") === 0) this._stdin.pause();
35084
35158
  this._readBuffer.clear();
35085
35159
  this.onclose?.();
@@ -35199,21 +35273,35 @@ var init_stdio = __esm({
35199
35273
  });
35200
35274
 
35201
35275
  // node_modules/@modelcontextprotocol/server/dist/index.mjs
35276
+ var DEFAULT_MAX_REQUEST_BODY_SIZE;
35202
35277
  var init_dist = __esm({
35203
35278
  "node_modules/@modelcontextprotocol/server/dist/index.mjs"() {
35204
- init_mcp_DXXb3Vv3();
35205
- init_src_CX2iR2pK();
35279
+ init_mcp_Dw2OlZ1f();
35280
+ init_src_D_y6h4N7();
35206
35281
  init_shimsNode();
35282
+ DEFAULT_MAX_REQUEST_BODY_SIZE = 4 * 1024 * 1024;
35207
35283
  }
35208
35284
  });
35209
35285
 
35210
35286
  // node_modules/@chrischall/mcp-utils/dist/errors/index.js
35287
+ function redactJsonCookie(quote) {
35288
+ const stringRe = quote === '"' ? DQ_STRING_RE : SQ_STRING_RE;
35289
+ return (_m, prefix, key, value) => {
35290
+ const setCookie = key.toLowerCase() === "set-cookie";
35291
+ const redacted = value.replace(stringRe, (_s, body) => {
35292
+ const out = setCookie ? body.replace(/^(\s*[^=;]+)=[^;]*/, "$1=[REDACTED]") : body.replace(/=[^;]*/g, "=[REDACTED]");
35293
+ return `${quote}${out}${quote}`;
35294
+ });
35295
+ return `${prefix}${redacted}`;
35296
+ };
35297
+ }
35211
35298
  function redactSecrets(text) {
35212
- return text.replace(BEARER_RE, "$1[REDACTED]").replace(BASIC_AUTH_RE, "$1[REDACTED]").replace(SET_COOKIE_RE, "$1$2=[REDACTED]").replace(COOKIE_HEADER_RE, (_m, prefix, pairs) => `${prefix}${pairs.replace(/=[^;,\s]*/g, "=[REDACTED]")}`).replace(API_KEY_RE, "[REDACTED]").replace(HEADER_SECRET_RE, "$1[REDACTED]").replace(QUERY_SECRET_RE, "$1[REDACTED]").replace(OAUTH_CODE_RE, "$1[REDACTED]").replace(FORM_PASSWORD_RE, "$1[REDACTED]").replace(AWS_SIGV4_RE, "$1[REDACTED]").replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JWT_RE, "[REDACTED]");
35299
+ return text.replace(BEARER_RE, "$1[REDACTED]").replace(BASIC_AUTH_RE, "$1[REDACTED]").replace(SET_COOKIE_RE, "$1$2=[REDACTED]").replace(COOKIE_HEADER_RE, (_m, prefix, pairs) => `${prefix}${pairs.replace(/=[^;,\s]*/g, "=[REDACTED]")}`).replace(API_KEY_RE, "[REDACTED]").replace(HEADER_SECRET_RE, "$1[REDACTED]").replace(QUERY_SECRET_RE, "$1[REDACTED]").replace(OAUTH_CODE_RE, "$1[REDACTED]").replace(FORM_PASSWORD_RE, "$1[REDACTED]").replace(AWS_SIGV4_RE, "$1[REDACTED]").replace(JSON_COOKIE_DQ_RE, redactJsonCookie('"')).replace(JSON_COOKIE_SQ_RE, redactJsonCookie("'")).replace(JSON_SECRET_DQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_SQ_RE, "$1[REDACTED]$2").replace(JSON_SECRET_NUM_RE, "$1[REDACTED]").replace(JWT_RE, "[REDACTED]");
35213
35300
  }
35214
35301
  function truncateErrorMessage(text, max = DEFAULT_ERROR_MESSAGE_MAX) {
35215
35302
  const str = text === null || text === void 0 ? "" : String(text);
35216
- const redacted = redactSecrets(str);
35303
+ const cap = Math.max(ERROR_REDACTION_INPUT_MAX, max);
35304
+ const redacted = redactSecrets(str.length > cap ? str.slice(0, cap) : str);
35217
35305
  if (redacted.length <= max)
35218
35306
  return redacted;
35219
35307
  return `${redacted.slice(0, max)}\u2026 [truncated]`;
@@ -35223,7 +35311,7 @@ function messageOf(err) {
35223
35311
  return err.message;
35224
35312
  return String(err);
35225
35313
  }
35226
- var DEFAULT_ERROR_MESSAGE_MAX, McpToolError, BEARER_RE, JWT_RE, BASIC_AUTH_RE, SET_COOKIE_RE, COOKIE_HEADER_RE, API_KEY_RE, QUERY_SECRET_RE, OAUTH_CODE_RE, FORM_PASSWORD_RE, HEADER_SECRET_RE, AWS_SIGV4_RE, JSON_SECRET_KEYS, JSON_SECRET_DQ_RE, JSON_SECRET_SQ_RE;
35314
+ var DEFAULT_ERROR_MESSAGE_MAX, McpToolError, HEADER_NAME_RUN, BEARER_RE, JWT_RE, BASIC_AUTH_RE, SET_COOKIE_RE, COOKIE_HEADER_RE, API_KEY_RE, QUERY_SECRET_RE, OAUTH_CODE_RE, FORM_PASSWORD_RE, HEADER_SECRET_RE, AWS_SIGV4_RE, JSON_SECRET_KEYS, JSON_SECRET_DQ_RE, JSON_SECRET_SQ_RE, JSON_SECRET_NUM_RE, JSON_COOKIE_DQ_RE, JSON_COOKIE_SQ_RE, DQ_STRING_RE, SQ_STRING_RE, ERROR_REDACTION_INPUT_MAX;
35227
35315
  var init_errors3 = __esm({
35228
35316
  "node_modules/@chrischall/mcp-utils/dist/errors/index.js"() {
35229
35317
  DEFAULT_ERROR_MESSAGE_MAX = 500;
@@ -35238,11 +35326,12 @@ var init_errors3 = __esm({
35238
35326
  Object.setPrototypeOf(this, new.target.prototype);
35239
35327
  }
35240
35328
  };
35329
+ HEADER_NAME_RUN = "[a-z0-9_-]{0,40}";
35241
35330
  BEARER_RE = /(bearer\s+)[A-Za-z0-9._~+/=-]{8,}/gi;
35242
- JWT_RE = /\b[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{8,}\b/g;
35331
+ JWT_RE = /(?<![A-Za-z0-9_-])[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{8,}(?![A-Za-z0-9_-])/g;
35243
35332
  BASIC_AUTH_RE = /(authorization\s*:\s*basic\s+)[A-Za-z0-9+/=_-]{6,}/gi;
35244
- SET_COOKIE_RE = /(\bset-cookie\s*:\s*)([^=;,\s]+)=[^;,\s]*/gi;
35245
- COOKIE_HEADER_RE = /((?<!set-)\bcookie\s*:\s*)((?:[^=;,\s]+=[^;,\s]*)(?:;\s*[^=;,\s]+=[^;,\s]*)*)/gi;
35333
+ SET_COOKIE_RE = /(\bset-cookie\s*:\s*)([^=;,:\s]+)=[^;,\s]*/gi;
35334
+ COOKIE_HEADER_RE = /((?<!set-)\bcookie\s*:\s*)((?:[^=;,:\s]+=[^;,\s]*)(?:;\s*[^=;,:\s]+=[^;,\s]*)*)/gi;
35246
35335
  API_KEY_RE = new RegExp([
35247
35336
  "sk-[A-Za-z0-9_-]{20,}(?![A-Za-z0-9_-])",
35248
35337
  // OpenAI / Anthropic (incl. sk-ant-…)
@@ -35257,10 +35346,10 @@ var init_errors3 = __esm({
35257
35346
  "whsec_[A-Za-z0-9]{16,}\\b"
35258
35347
  // webhook signing secret (Stripe-style)
35259
35348
  ].map((p) => `\\b${p}`).join("|"), "g");
35260
- QUERY_SECRET_RE = /([?&](?:(?:access|refresh|id|auth|session|csrf|xsrf)[_-]?token|client[_-]?secret|api[_-]?secret|api[_-]?key|password|passwd|signature|token|key|sig)=)[^&#\s"'<>`]+/gi;
35349
+ QUERY_SECRET_RE = new RegExp(`([?&](?:(?:access|refresh|id|auth|session|csrf|xsrf)[_-]?token|client[_-]?secret|api[_-]?secret|api[_-]?key|password|passwd|signature|token|key|sig|(?:php|j)?sess(?:ion)?[_-]?id|sid|x[-_]${HEADER_NAME_RUN}?(?:api[-_]?key|token|secret|auth)${HEADER_NAME_RUN})=)[^&#\\s"'<>\`]+`, "gi");
35261
35350
  OAUTH_CODE_RE = /([?&]code=)(?=[^&#\s"'<>`]{16,})[^&#\s"'<>`]+/gi;
35262
35351
  FORM_PASSWORD_RE = /((?:^|[\s,;:"'(\[{])(?:password|passwd)=)[^&#\s"'<>`]+/gim;
35263
- HEADER_SECRET_RE = /(\b(?:x[-_][a-z0-9_-]*?(?:api[-_]?key|token|secret|auth)[a-z0-9_-]*|api[-_]?key)\s*:\s*)[^\s,;"'<>`]+/gi;
35352
+ HEADER_SECRET_RE = new RegExp(`(\\b(?:x[-_]${HEADER_NAME_RUN}?(?:api[-_]?key|token|secret|auth)${HEADER_NAME_RUN}|api[-_]?key)\\s*:\\s*)[^\\s,;"'<>\`]+`, "gi");
35264
35353
  AWS_SIGV4_RE = /([?&]X-Amz-(?:Signature|Security-Token|Credential)=)[^&#\s"'<>`]+/gi;
35265
35354
  JSON_SECRET_KEYS = [
35266
35355
  "(?:access|refresh|id|auth|session|bearer|csrf|xsrf)[_-]?token",
@@ -35268,7 +35357,8 @@ var init_errors3 = __esm({
35268
35357
  "api[_-]?secret",
35269
35358
  "(?:x[_-])?api[_-]?key",
35270
35359
  "private[_-]?key",
35271
- "x[_-][a-z0-9_-]*?(?:api[_-]?key|token|secret|auth)[a-z0-9_-]*",
35360
+ `x[_-]${HEADER_NAME_RUN}?(?:api[_-]?key|token|secret|auth)${HEADER_NAME_RUN}`,
35361
+ // bounded like HEADER_SECRET_RE
35272
35362
  "(?:proxy-)?authorization",
35273
35363
  "password",
35274
35364
  "passwd",
@@ -35277,6 +35367,12 @@ var init_errors3 = __esm({
35277
35367
  ].join("|");
35278
35368
  JSON_SECRET_DQ_RE = new RegExp(`("(?:${JSON_SECRET_KEYS})"\\s*:\\s*")(?:[^"\\\\]|\\\\.)*(")`, "gi");
35279
35369
  JSON_SECRET_SQ_RE = new RegExp(`('(?:${JSON_SECRET_KEYS})'\\s*:\\s*')(?:[^'\\\\]|\\\\.)*(')`, "gi");
35370
+ JSON_SECRET_NUM_RE = new RegExp(`(["'](?:${JSON_SECRET_KEYS})["']\\s*:\\s*)-?\\d+(?:\\.\\d+)?(?![\\d.])`, "gi");
35371
+ JSON_COOKIE_DQ_RE = /("((?:set-)?cookie)"\s*:\s*)("(?:[^"\\]|\\.)*"|\[\s*"(?:[^"\\]|\\.)*"(?:\s*,\s*"(?:[^"\\]|\\.)*")*)/gi;
35372
+ JSON_COOKIE_SQ_RE = /('((?:set-)?cookie)'\s*:\s*)('(?:[^'\\]|\\.)*'|\[\s*'(?:[^'\\]|\\.)*'(?:\s*,\s*'(?:[^'\\]|\\.)*')*)/gi;
35373
+ DQ_STRING_RE = /"((?:[^"\\]|\\.)*)"/g;
35374
+ SQ_STRING_RE = /'((?:[^'\\]|\\.)*)'/g;
35375
+ ERROR_REDACTION_INPUT_MAX = 64 * 1024;
35280
35376
  }
35281
35377
  });
35282
35378
 
@@ -35635,6 +35731,9 @@ async function tokenConfirmation(action, fb) {
35635
35731
  const subject = await fb.subject();
35636
35732
  if (isToolResult(subject))
35637
35733
  return subject;
35734
+ if (subject.payload === void 0) {
35735
+ throw new TypeError(`confirm token: ${fb.tool}'s subject() returned no payload. Bind what the call will do (the arguments or the request body), or pass \`args\` to confirmationFromEnv.`);
35736
+ }
35638
35737
  const binding = {
35639
35738
  tool: fb.tool,
35640
35739
  ...fb.account === void 0 ? {} : { account: fb.account },
@@ -35796,9 +35895,19 @@ function readConfirmMode(env = process.env) {
35796
35895
  }
35797
35896
  return "refuse";
35798
35897
  }
35799
- function confirmTtlFromEnv(env = process.env) {
35898
+ function readConfirmTtl(env) {
35800
35899
  const raw = readEnvVar("MCP_CONFIRM_TTL_SECONDS", { env })?.trim();
35801
- return raw && /^[1-9]\d*$/.test(raw) ? Number(raw) : DEFAULT_TTL_SECONDS2;
35900
+ if (!raw)
35901
+ return DEFAULT_TTL_SECONDS2;
35902
+ if (/^[1-9]\d*$/.test(raw))
35903
+ return Number(raw);
35904
+ const key = `ttl:${raw}`;
35905
+ if (!warned.has(key)) {
35906
+ warned.add(key);
35907
+ process.stderr.write(`MCP_CONFIRM_TTL_SECONDS="${raw}" is not a positive whole number of seconds; gated writes will refuse on clients that cannot show a confirmation prompt until it is fixed.
35908
+ `);
35909
+ }
35910
+ return void 0;
35802
35911
  }
35803
35912
  function confirmKeyFromEnv(env = process.env) {
35804
35913
  const secret = readEnvVar("MCP_CONFIRM_SECRET", { env });
@@ -35807,15 +35916,32 @@ function confirmKeyFromEnv(env = process.env) {
35807
35916
  processKey ??= randomBytes2(32);
35808
35917
  return processKey;
35809
35918
  }
35919
+ function boundArgs(args) {
35920
+ if (args === null || typeof args !== "object" || Array.isArray(args) || !("confirmToken" in args))
35921
+ return args;
35922
+ const { confirmToken, ...rest } = args;
35923
+ void confirmToken;
35924
+ return rest;
35925
+ }
35810
35926
  function confirmationFromEnv(options) {
35811
- const { tool, account, confirmToken, subject, instruction, spent, env = process.env, ...confirmation } = options;
35927
+ const { tool, account, confirmToken, subject, instruction, spent, args, env = process.env, ...rest } = options;
35812
35928
  const mode = readConfirmMode(env);
35813
- if (mode === "refuse") {
35929
+ const ttlSeconds = readConfirmTtl(env);
35930
+ const bound = args === void 0 ? void 0 : boundArgs(args);
35931
+ const confirmation = bound === void 0 || rest.binding ? rest : { ...rest, binding: { key: confirmKeyFromEnv(env), args: bound, ttlSeconds: ttlSeconds ?? DEFAULT_TTL_SECONDS2 } };
35932
+ if (mode === "refuse" || ttlSeconds === void 0) {
35933
+ const hint = mode === "refuse" ? REFUSE_HINT : BAD_TTL_HINT;
35814
35934
  return {
35815
35935
  ...confirmation,
35816
- unsupportedNote: confirmation.unsupportedNote ? `${confirmation.unsupportedNote} ${REFUSE_HINT}` : REFUSE_HINT
35936
+ unsupportedNote: confirmation.unsupportedNote ? `${confirmation.unsupportedNote} ${hint}` : hint
35817
35937
  };
35818
35938
  }
35939
+ const boundSubject = bound === void 0 ? subject : async () => {
35940
+ const read = await subject();
35941
+ if ("content" in read)
35942
+ return read;
35943
+ return { ...read, payload: { payload: read.payload, args: bound } };
35944
+ };
35819
35945
  return {
35820
35946
  ...confirmation,
35821
35947
  tokenFallback: {
@@ -35823,14 +35949,14 @@ function confirmationFromEnv(options) {
35823
35949
  tool,
35824
35950
  ...account === void 0 ? {} : { account },
35825
35951
  ...confirmToken === void 0 ? {} : { confirmToken },
35826
- subject,
35827
- ttlSeconds: confirmTtlFromEnv(env),
35952
+ subject: boundSubject,
35953
+ ttlSeconds,
35828
35954
  instruction: mode === "auto" ? CONFIRM_TOKEN_AUTO_INSTRUCTION : instruction ?? CONFIRM_TOKEN_INSTRUCTION,
35829
35955
  ...spent === void 0 ? {} : { spent }
35830
35956
  }
35831
35957
  };
35832
35958
  }
35833
- var MODES, DEFAULT_TTL_SECONDS2, warned, processKey, CONFIRM_TOKEN_AUTO_INSTRUCTION, REFUSE_HINT;
35959
+ var MODES, DEFAULT_TTL_SECONDS2, warned, processKey, CONFIRM_TOKEN_AUTO_INSTRUCTION, REFUSE_HINT, BAD_TTL_HINT;
35834
35960
  var init_confirm_env = __esm({
35835
35961
  "node_modules/@chrischall/mcp-utils/dist/server/confirm-env.js"() {
35836
35962
  init_config();
@@ -35840,6 +35966,7 @@ var init_confirm_env = __esm({
35840
35966
  warned = /* @__PURE__ */ new Set();
35841
35967
  CONFIRM_TOKEN_AUTO_INSTRUCTION = "Nothing has been done yet. Review this preview; if it is what was intended, call again with the same arguments plus confirmToken. (This server runs with MCP_CONFIRM_MODE=auto, so the user's approval in chat is not required.)";
35842
35968
  REFUSE_HINT = "Set MCP_CONFIRM_MODE=ask-user on the server to allow two-step confirmation instead.";
35969
+ BAD_TTL_HINT = "MCP_CONFIRM_TTL_SECONDS on the server is not a positive whole number of seconds; fix it to allow two-step confirmation.";
35843
35970
  }
35844
35971
  });
35845
35972
 
@@ -35954,6 +36081,8 @@ function withGracefulShutdown(target, opts = {}) {
35954
36081
  };
35955
36082
  const handler = (signal) => {
35956
36083
  if (shuttingDown) {
36084
+ if (signal === "stdin-eof")
36085
+ return;
35957
36086
  if (Date.now() - firstSignalAt < repeatGraceMs)
35958
36087
  return;
35959
36088
  if (shouldExit) {
@@ -35989,6 +36118,10 @@ function withGracefulShutdown(target, opts = {}) {
35989
36118
  };
35990
36119
  process.on("SIGINT", () => handler("SIGINT"));
35991
36120
  process.on("SIGTERM", () => handler("SIGTERM"));
36121
+ if (opts.stdin) {
36122
+ opts.stdin.once("end", () => handler("stdin-eof"));
36123
+ opts.stdin.once("close", () => handler("stdin-eof"));
36124
+ }
35992
36125
  }
35993
36126
  function runMcp(opts) {
35994
36127
  if (opts.banner !== void 0) {
@@ -36007,7 +36140,8 @@ function runMcp(opts) {
36007
36140
  });
36008
36141
  const shutdown = opts.shutdown ?? true;
36009
36142
  if (shutdown !== false) {
36010
- withGracefulShutdown(handle, shutdown === true ? {} : shutdown);
36143
+ const stdinDefault = spec === "stdio" ? { stdin: process.stdin } : {};
36144
+ withGracefulShutdown(handle, { ...stdinDefault, ...shutdown === true ? {} : shutdown });
36011
36145
  }
36012
36146
  return handle;
36013
36147
  }
@@ -36480,7 +36614,7 @@ var init_version = __esm({
36480
36614
  "src/version.ts"() {
36481
36615
  "use strict";
36482
36616
  PACKAGE_NAME = "office-outlook-mcp";
36483
- VERSION = "0.3.1";
36617
+ VERSION = "0.3.2";
36484
36618
  }
36485
36619
  });
36486
36620
 
@@ -36703,6 +36837,35 @@ var init_frames = __esm({
36703
36837
  }
36704
36838
  });
36705
36839
 
36840
+ // node_modules/@fetchproxy/protocol/dist/capability-availability.js
36841
+ function capabilityUnavailableMessage(capability, platform) {
36842
+ return `capability ${JSON.stringify(capability)} is not available in this browser (${platform})`;
36843
+ }
36844
+ function parseCapabilityUnavailable(error62) {
36845
+ const m = UNAVAILABLE_RE.exec(error62);
36846
+ if (!m)
36847
+ return null;
36848
+ return { capability: m[1], platform: m[2] ?? null };
36849
+ }
36850
+ function parseUnsupportedCapabilityReason(reason) {
36851
+ if (!reason.startsWith(UNSUPPORTED_CAPABILITY_REASON_PREFIX))
36852
+ return null;
36853
+ const rest = reason.slice(UNSUPPORTED_CAPABILITY_REASON_PREFIX.length).replace(/\s*\(not available in this browser\)\s*$/, "").trim();
36854
+ if (rest === "")
36855
+ return [];
36856
+ return rest.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
36857
+ }
36858
+ var CAPABILITY_UNAVAILABLE_CODE, MAX_UNAVAILABLE_CAPABILITIES, MAX_CAPABILITY_NAME_LENGTH, UNSUPPORTED_CAPABILITY_REASON_PREFIX, UNAVAILABLE_RE;
36859
+ var init_capability_availability = __esm({
36860
+ "node_modules/@fetchproxy/protocol/dist/capability-availability.js"() {
36861
+ CAPABILITY_UNAVAILABLE_CODE = "capability_unavailable";
36862
+ MAX_UNAVAILABLE_CAPABILITIES = 32;
36863
+ MAX_CAPABILITY_NAME_LENGTH = 64;
36864
+ UNSUPPORTED_CAPABILITY_REASON_PREFIX = "unsupported-capability:";
36865
+ UNAVAILABLE_RE = /^capability "([^"]{1,64})" is not available in this browser(?: \(([^)]{1,32})\))?/;
36866
+ }
36867
+ });
36868
+
36706
36869
  // node_modules/@fetchproxy/protocol/dist/mcp-id.js
36707
36870
  function generateMcpId(serverName, version2) {
36708
36871
  if (serverName.includes(":")) {
@@ -37415,6 +37578,9 @@ function validateHello(raw) {
37415
37578
  assertBase64(raw.sessionNonce, "hello.sessionNonce");
37416
37579
  if (raw.accepts !== void 0)
37417
37580
  assertAcceptsList(raw.accepts);
37581
+ if (raw.unavailableCapabilities !== void 0) {
37582
+ assertUnavailableCapabilities(raw.unavailableCapabilities);
37583
+ }
37418
37584
  return raw;
37419
37585
  }
37420
37586
  throw new ProtocolError3(`hello.role: must be 'server' or 'extension', got ${String(role)}`);
@@ -37479,6 +37645,22 @@ function assertAcceptsList(accepts) {
37479
37645
  }
37480
37646
  }
37481
37647
  }
37648
+ function assertUnavailableCapabilities(list) {
37649
+ const label = "hello.unavailableCapabilities";
37650
+ if (!Array.isArray(list))
37651
+ throw new ProtocolError3(`${label}: expected array`);
37652
+ if (list.length > MAX_UNAVAILABLE_CAPABILITIES) {
37653
+ throw new ProtocolError3(`${label}: at most ${MAX_UNAVAILABLE_CAPABILITIES} entries, got ${list.length}`);
37654
+ }
37655
+ for (const c of list) {
37656
+ if (typeof c !== "string") {
37657
+ throw new ProtocolError3(`${label}: entry must be string, got ${typeof c}`);
37658
+ }
37659
+ if (c.length < 1 || c.length > MAX_CAPABILITY_NAME_LENGTH) {
37660
+ throw new ProtocolError3(`${label}: entry must be 1-${MAX_CAPABILITY_NAME_LENGTH} characters, got ${c.length}`);
37661
+ }
37662
+ }
37663
+ }
37482
37664
  function validatePeerGone(raw) {
37483
37665
  assertString(raw.mcpId, "peer-gone.mcpId");
37484
37666
  if (!isValidMcpId(raw.mcpId))
@@ -37950,6 +38132,8 @@ function validateInnerResponse(raw) {
37950
38132
  }
37951
38133
  if (raw.ok === false) {
37952
38134
  assertString(raw.error, "inner.error");
38135
+ if (raw.code !== void 0)
38136
+ assertString(raw.code, "inner.code");
37953
38137
  if (raw.op !== void 0) {
37954
38138
  if (typeof raw.op !== "string" || !KNOWN_RESPONSE_OPS.has(raw.op)) {
37955
38139
  throw new ProtocolError3(`inner.op: unknown response op ${JSON.stringify(raw.op)}`);
@@ -37963,6 +38147,7 @@ var ProtocolError3, FORBIDDEN_KEYS, BASE64_RE, SCOPE_KEY_RE, SCOPE_KEY_GLOB_RE,
37963
38147
  var init_validate = __esm({
37964
38148
  "node_modules/@fetchproxy/protocol/dist/validate.js"() {
37965
38149
  init_frames();
38150
+ init_capability_availability();
37966
38151
  init_mcp_id();
37967
38152
  init_json_pointer();
37968
38153
  init_public_suffix();
@@ -38094,6 +38279,7 @@ var init_seal = __esm({
38094
38279
  var init_dist3 = __esm({
38095
38280
  "node_modules/@fetchproxy/protocol/dist/index.js"() {
38096
38281
  init_frames();
38282
+ init_capability_availability();
38097
38283
  init_validate();
38098
38284
  init_crypto();
38099
38285
  init_mcp_id();
@@ -38105,6 +38291,43 @@ var init_dist3 = __esm({
38105
38291
  }
38106
38292
  });
38107
38293
 
38294
+ // node_modules/@fetchproxy/server/dist/session-info.js
38295
+ function sessionInfoFromHello(hello) {
38296
+ const raw = hello.unavailableCapabilities;
38297
+ const known = /* @__PURE__ */ new Set();
38298
+ if (Array.isArray(raw)) {
38299
+ for (const c of raw) {
38300
+ if (typeof c === "string" && KNOWN_CAPABILITIES.has(c))
38301
+ known.add(c);
38302
+ }
38303
+ }
38304
+ return { platform: hello.platform, unavailableCapabilities: [...known].sort() };
38305
+ }
38306
+ function capabilitiesForRequest(inner) {
38307
+ if (inner.type !== "request")
38308
+ return [];
38309
+ if (inner.op === "graphql_query")
38310
+ return ["graphql"];
38311
+ if (inner.op === "fetch") {
38312
+ return inner.init.inPage === true ? ["fetch", "fetch_in_page"] : ["fetch"];
38313
+ }
38314
+ return [inner.op];
38315
+ }
38316
+ function unavailableCapabilityFor(inner, info) {
38317
+ if (!info || info.unavailableCapabilities.length === 0)
38318
+ return null;
38319
+ for (const c of capabilitiesForRequest(inner)) {
38320
+ if (info.unavailableCapabilities.includes(c))
38321
+ return c;
38322
+ }
38323
+ return null;
38324
+ }
38325
+ var init_session_info = __esm({
38326
+ "node_modules/@fetchproxy/server/dist/session-info.js"() {
38327
+ init_dist3();
38328
+ }
38329
+ });
38330
+
38108
38331
  // node_modules/@fetchproxy/server/dist/election.js
38109
38332
  import { createServer, Server as HttpServer } from "node:http";
38110
38333
  async function electRole(opts) {
@@ -42059,9 +42282,10 @@ async function awaitSessionReady(ready, opts) {
42059
42282
  clearTimeout(timer);
42060
42283
  }
42061
42284
  }
42062
- var SESSION_READY_TIMEOUT_MS, FetchproxySessionNotReadyError, FetchproxyHelloRejectedError, MIN_VERSION, FetchproxyProtocolVersionError;
42285
+ var SESSION_READY_TIMEOUT_MS, FetchproxySessionNotReadyError, FetchproxyHelloRejectedError, MIN_SERVER_VERSION, FetchproxyProtocolVersionError;
42063
42286
  var init_session_ready = __esm({
42064
42287
  "node_modules/@fetchproxy/server/dist/session-ready.js"() {
42288
+ init_dist3();
42065
42289
  SESSION_READY_TIMEOUT_MS = 3e4;
42066
42290
  FetchproxySessionNotReadyError = class extends Error {
42067
42291
  reason;
@@ -42070,7 +42294,7 @@ var init_session_ready = __esm({
42070
42294
  hint;
42071
42295
  constructor(info) {
42072
42296
  const pairing = info.pairCode !== null && info.pairCode !== "";
42073
- const hint = pairing ? `Open the Transporter extension popup and approve pair code ${info.pairCode} for "${info.mcpId}", then retry.` : `The extension is connected but hasn't confirmed a session for "${info.mcpId}" \u2014 sign in to the target site in that browser (and approve the requested scope if it changed), then retry.`;
42297
+ const hint = pairing ? `Open the ContextMint Bridge extension popup and approve pair code ${info.pairCode} for "${info.mcpId}", then retry.` : `The extension is connected but hasn't confirmed a session for "${info.mcpId}" \u2014 sign in to the target site in that browser (and approve the requested scope if it changed), then retry.`;
42074
42298
  super(`fetchproxy: ${pairing ? "pairing not yet approved" : "no confirmed browser session"} for "${info.mcpId}". ${hint}`);
42075
42299
  this.name = "FetchproxySessionNotReadyError";
42076
42300
  this.reason = pairing ? "pair-required" : "not-ready";
@@ -42083,15 +42307,35 @@ var init_session_ready = __esm({
42083
42307
  FetchproxyHelloRejectedError = class extends Error {
42084
42308
  mcpId;
42085
42309
  reason;
42310
+ /**
42311
+ * #418: when the reason is `unsupported-capability: a, b (not available in
42312
+ * this browser)` — every capability this MCP declared is one the browser
42313
+ * cannot serve — those capabilities, parsed out of it. Empty otherwise.
42314
+ */
42315
+ unavailableCapabilities;
42316
+ /** #418: the refusing browser's platform, when this bridge knew it. */
42317
+ platform;
42318
+ /**
42319
+ * #418: the remedy, when the reason is one this package knows how to
42320
+ * explain — today only `unsupported-capability`, which blames the browser
42321
+ * rather than the MCP. `null` otherwise.
42322
+ */
42323
+ hint;
42086
42324
  constructor(info) {
42087
- super(`fetchproxy: the extension refused the connection for "${info.mcpId}": ${info.reason}. This is the extension's own reason \u2014 it is not a timeout, and retrying unchanged will be refused the same way.`);
42325
+ const unavailable = parseUnsupportedCapabilityReason(info.reason);
42326
+ const platform = info.platform ?? null;
42327
+ const hint = unavailable !== null ? `${platform ? `this browser (${platform})` : "this browser"} cannot serve any of the capabilities this MCP needs (${unavailable.join(", ")}) \u2014 ContextMint Bridge checked for the browser APIs and they are missing. Nothing is wrong with the MCP or your pairing, and updating will not change it: use this MCP from a browser that provides them (for example Chrome).` : null;
42328
+ super(`fetchproxy: the extension refused the connection for "${info.mcpId}": ${info.reason}. ` + (hint !== null ? hint : `This is the extension's own reason \u2014 it is not a timeout, and retrying unchanged will be refused the same way.`));
42088
42329
  this.name = "FetchproxyHelloRejectedError";
42089
42330
  this.mcpId = info.mcpId;
42090
42331
  this.reason = info.reason;
42332
+ this.unavailableCapabilities = unavailable ?? [];
42333
+ this.platform = platform;
42334
+ this.hint = hint;
42091
42335
  Object.setPrototypeOf(this, new.target.prototype);
42092
42336
  }
42093
42337
  };
42094
- MIN_VERSION = "3.0.0";
42338
+ MIN_SERVER_VERSION = "3.0.0";
42095
42339
  FetchproxyProtocolVersionError = class extends Error {
42096
42340
  /** The protocol version this process speaks. */
42097
42341
  ourVersion;
@@ -42099,7 +42343,7 @@ var init_session_ready = __esm({
42099
42343
  theirVersion;
42100
42344
  peer;
42101
42345
  constructor(info) {
42102
- const far = info.peer === "extension" ? `the attached browser extension speaks ${info.theirVersion} \u2014 update Transporter (the fetchproxy extension) to ${MIN_VERSION} or later` : `the MCP holding the bridge port speaks ${info.theirVersion} \u2014 upgrade @fetchproxy/server to ${MIN_VERSION} or later in that MCP`;
42346
+ const far = info.peer === "extension" ? `the attached browser extension speaks ${info.theirVersion} \u2014 update ContextMint Bridge to a release that speaks fetchproxy protocol ${info.ourVersion}` : `the MCP holding the bridge port speaks ${info.theirVersion} \u2014 upgrade @fetchproxy/server to ${MIN_SERVER_VERSION} or later in that MCP`;
42103
42347
  super(`protocol version mismatch: this MCP speaks fetchproxy protocol ${info.ourVersion}, ${far}`);
42104
42348
  this.name = "FetchproxyProtocolVersionError";
42105
42349
  this.ourVersion = info.ourVersion;
@@ -42207,6 +42451,7 @@ async function loadOrCreateIdentity(serverName, dir = defaultIdentityDir()) {
42207
42451
  throw e;
42208
42452
  }
42209
42453
  let unreadable = null;
42454
+ let recovered = false;
42210
42455
  for (let attempt = 0; attempt < 5; attempt++) {
42211
42456
  const id = await generateIdentity();
42212
42457
  if (await publishIdentityIfAbsent(dir, serverName, id))
@@ -42220,6 +42465,11 @@ async function loadOrCreateIdentity(serverName, dir = defaultIdentityDir()) {
42220
42465
  if (!(e instanceof SyntaxError))
42221
42466
  throw e;
42222
42467
  unreadable = e;
42468
+ if (!recovered && await removeAbandonedIdentity(path)) {
42469
+ recovered = true;
42470
+ attempt--;
42471
+ continue;
42472
+ }
42223
42473
  await new Promise((r) => setTimeout(r, 20 * (attempt + 1)));
42224
42474
  }
42225
42475
  }
@@ -42260,7 +42510,60 @@ async function publishIdentityIfAbsent(dir, serverName, id) {
42260
42510
  await rm(tmp, { force: true });
42261
42511
  }
42262
42512
  }
42263
- var SAFE_PLAIN, SAFE_SCOPED, STAGING_BYTES, NO_HARD_LINKS;
42513
+ function looksAbandoned(text) {
42514
+ const t = text.trim();
42515
+ return t === "" || t.startsWith("{") && !t.endsWith("}");
42516
+ }
42517
+ function sameFile(a, b) {
42518
+ return a.dev === b.dev && a.ino === b.ino && a.size === b.size && a.mtimeMs === b.mtimeMs;
42519
+ }
42520
+ async function takeRecoveryLock(lock) {
42521
+ for (let attempt = 0; attempt < 2; attempt++) {
42522
+ try {
42523
+ await writeFile(lock, `${process.pid}
42524
+ `, { mode: 384, flag: "wx" });
42525
+ return await lstat(lock);
42526
+ } catch (e) {
42527
+ if (e.code !== "EEXIST")
42528
+ return null;
42529
+ const st = await lstat(lock).catch(() => null);
42530
+ if (st === null)
42531
+ continue;
42532
+ if (Date.now() - st.mtimeMs < RECOVERY_LOCK_STALE_MS)
42533
+ return null;
42534
+ const again = await lstat(lock).catch(() => null);
42535
+ if (again === null || !sameFile(st, again))
42536
+ continue;
42537
+ await unlink(lock).catch(() => void 0);
42538
+ }
42539
+ }
42540
+ return null;
42541
+ }
42542
+ async function removeAbandonedIdentity(path) {
42543
+ const lock = `${path}.recover.lock`;
42544
+ const held = await takeRecoveryLock(lock);
42545
+ if (held === null)
42546
+ return false;
42547
+ try {
42548
+ const before = await lstat(path);
42549
+ if (!before.isFile() || Date.now() - before.mtimeMs < ABANDONED_IDENTITY_MS)
42550
+ return false;
42551
+ if (!looksAbandoned(await readFile(path, "utf8")))
42552
+ return false;
42553
+ const now = await lstat(path);
42554
+ if (!sameFile(before, now))
42555
+ return false;
42556
+ await unlink(path);
42557
+ return true;
42558
+ } catch {
42559
+ return false;
42560
+ } finally {
42561
+ const st = await lstat(lock).catch(() => null);
42562
+ if (st !== null && sameFile(held, st))
42563
+ await unlink(lock).catch(() => void 0);
42564
+ }
42565
+ }
42566
+ var SAFE_PLAIN, SAFE_SCOPED, STAGING_BYTES, NO_HARD_LINKS, ABANDONED_IDENTITY_MS, RECOVERY_LOCK_STALE_MS;
42264
42567
  var init_identity = __esm({
42265
42568
  "node_modules/@fetchproxy/server/dist/identity.js"() {
42266
42569
  init_dist3();
@@ -42268,13 +42571,153 @@ var init_identity = __esm({
42268
42571
  SAFE_SCOPED = /^@[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
42269
42572
  STAGING_BYTES = 6;
42270
42573
  NO_HARD_LINKS = /* @__PURE__ */ new Set(["EPERM", "ENOTSUP", "EOPNOTSUPP", "ENOSYS"]);
42574
+ ABANDONED_IDENTITY_MS = 5e3;
42575
+ RECOVERY_LOCK_STALE_MS = 3e4;
42576
+ }
42577
+ });
42578
+
42579
+ // node_modules/@fetchproxy/server/dist/extension-pins.js
42580
+ import { readFile as readFile2 } from "node:fs/promises";
42581
+ import { join as join3 } from "node:path";
42582
+ function malformed(why) {
42583
+ return new ExtensionPinsError("EXTENSION_PINS_MALFORMED", `malformed extension pin set: ${why}`);
42584
+ }
42585
+ function isKey(x) {
42586
+ if (typeof x !== "string" || x === "")
42587
+ return false;
42588
+ let raw;
42589
+ try {
42590
+ raw = fromB64(x);
42591
+ } catch {
42592
+ return false;
42593
+ }
42594
+ return raw.length === 32 && toB64(raw) === x;
42595
+ }
42596
+ function parseExtensionPins(text) {
42597
+ let parsed;
42598
+ try {
42599
+ parsed = JSON.parse(text);
42600
+ } catch {
42601
+ throw malformed("not JSON");
42602
+ }
42603
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
42604
+ throw malformed("not an object");
42605
+ }
42606
+ const r = parsed;
42607
+ if (r.v !== EXTENSION_PINS_FILE_VERSION) {
42608
+ throw malformed(`"v" is not ${EXTENSION_PINS_FILE_VERSION}`);
42609
+ }
42610
+ if (r.managed !== true)
42611
+ throw malformed('"managed" is not true');
42612
+ if (r.managedBy !== void 0 && typeof r.managedBy !== "string") {
42613
+ throw malformed('"managedBy" is not a string');
42614
+ }
42615
+ if (!Array.isArray(r.extensions))
42616
+ throw malformed('"extensions" is not an array');
42617
+ const extensions = r.extensions.map((e, i) => {
42618
+ if (!e || typeof e !== "object" || Array.isArray(e)) {
42619
+ throw malformed(`extensions[${i}] is not an object`);
42620
+ }
42621
+ const x = e;
42622
+ if (!isKey(x.x25519Pub)) {
42623
+ throw malformed(`extensions[${i}].x25519Pub is not canonical base64 of 32 bytes`);
42624
+ }
42625
+ if (!isKey(x.ed25519Pub)) {
42626
+ throw malformed(`extensions[${i}].ed25519Pub is not canonical base64 of 32 bytes`);
42627
+ }
42628
+ if (x.label !== void 0 && typeof x.label !== "string") {
42629
+ throw malformed(`extensions[${i}].label is not a string`);
42630
+ }
42631
+ return {
42632
+ x25519Pub: x.x25519Pub,
42633
+ ed25519Pub: x.ed25519Pub,
42634
+ ...x.label !== void 0 ? { label: x.label } : {}
42635
+ };
42636
+ });
42637
+ return {
42638
+ v: EXTENSION_PINS_FILE_VERSION,
42639
+ managed: true,
42640
+ ...r.managedBy !== void 0 ? { managedBy: r.managedBy } : {},
42641
+ extensions
42642
+ };
42643
+ }
42644
+ function extensionPinsPath(serverName, trustDir) {
42645
+ return join3(trustDir, `${safeIdentityFileBase(serverName)}.extension-pins.json`);
42646
+ }
42647
+ async function readExtensionPinsAt(path) {
42648
+ let text;
42649
+ try {
42650
+ text = await readFile2(path, "utf8");
42651
+ } catch (e) {
42652
+ const code = e.code ?? "read failed";
42653
+ throw new ExtensionPinsError("EXTENSION_PINS_MISSING", `no managed extension pin set at ${path} (${code})`);
42654
+ }
42655
+ try {
42656
+ return parseExtensionPins(text);
42657
+ } catch (e) {
42658
+ const why = e instanceof ExtensionPinsError ? e.message : "malformed extension pin set";
42659
+ throw new ExtensionPinsError("EXTENSION_PINS_MALFORMED", `${why} at ${path}`);
42660
+ }
42661
+ }
42662
+ function decideManagedExtensionTrust(args) {
42663
+ const { set: set2, hello, serverName } = args;
42664
+ const listed = set2.extensions.some((e) => e.x25519Pub === hello.identityX25519Pub && e.ed25519Pub === hello.identityEd25519Pub);
42665
+ if (listed)
42666
+ return { decision: "pinned" };
42667
+ return {
42668
+ decision: "refused",
42669
+ code: "EXTENSION_NOT_PINNED",
42670
+ message: `[fetchproxy] ${serverName}: refusing an extension that is not in the host-managed pin set${args.location ? ` (${args.location})` : ""}. The host that runs this MCP decides which browsers it accepts; confirm this browser there.`
42671
+ };
42672
+ }
42673
+ async function evaluateManagedExtensionTrust(port, hello, serverName) {
42674
+ let set2;
42675
+ try {
42676
+ set2 = await port.read();
42677
+ } catch (e) {
42678
+ const code = e instanceof ExtensionPinsError ? e.code : "EXTENSION_PINS_MISSING";
42679
+ const detail = e instanceof ExtensionPinsError ? e.message : `could not read ${port.location}`;
42680
+ return {
42681
+ decision: "refused",
42682
+ code,
42683
+ message: `[fetchproxy] ${serverName}: ${code}: ${detail} \u2014 refusing every extension until the host that manages this MCP's pins writes a valid set.`
42684
+ };
42685
+ }
42686
+ return decideManagedExtensionTrust({ set: set2, hello, serverName, location: port.location });
42687
+ }
42688
+ function resolveExtensionPinsMode(explicit, env = process.env) {
42689
+ if (explicit === "managed")
42690
+ return "managed";
42691
+ const raw = env[EXTENSION_PINS_ENV];
42692
+ if (raw === void 0 || raw.trim() === "")
42693
+ return "first-use";
42694
+ if (raw === "managed")
42695
+ return "managed";
42696
+ console.warn(`[fetchproxy] ${EXTENSION_PINS_ENV}=${JSON.stringify(raw)} is not "managed" \u2014 treating it as managed anyway, because a set variable means a host manages this MCP's extension pins. Unset it for trust on first use.`);
42697
+ return "managed";
42698
+ }
42699
+ var EXTENSION_PINS_FILE_VERSION, EXTENSION_PINS_ENV, ExtensionPinsError;
42700
+ var init_extension_pins = __esm({
42701
+ "node_modules/@fetchproxy/server/dist/extension-pins.js"() {
42702
+ init_dist3();
42703
+ init_identity();
42704
+ EXTENSION_PINS_FILE_VERSION = 1;
42705
+ EXTENSION_PINS_ENV = "FETCHPROXY_EXTENSION_PINS";
42706
+ ExtensionPinsError = class extends Error {
42707
+ code;
42708
+ constructor(code, message) {
42709
+ super(message);
42710
+ this.name = "ExtensionPinsError";
42711
+ this.code = code;
42712
+ }
42713
+ };
42271
42714
  }
42272
42715
  });
42273
42716
 
42274
42717
  // node_modules/@fetchproxy/server/dist/extension-trust.js
42275
- import { readFile as readFile2, writeFile as writeFile2, rename as rename2, unlink as unlink2, mkdir as mkdir2, chmod as chmod2, rm as rm2 } from "node:fs/promises";
42718
+ import { readFile as readFile3, writeFile as writeFile2, rename as rename2, unlink as unlink2, mkdir as mkdir2, chmod as chmod2, rm as rm2 } from "node:fs/promises";
42276
42719
  import { randomBytes as randomBytes5 } from "node:crypto";
42277
- import { isAbsolute as isAbsolute2, join as join3 } from "node:path";
42720
+ import { isAbsolute as isAbsolute2, join as join4 } from "node:path";
42278
42721
  function envTrustDir(env = process.env) {
42279
42722
  const raw = env[TRUST_DIR_ENV];
42280
42723
  if (raw === void 0)
@@ -42295,6 +42738,22 @@ function defaultTrustDir() {
42295
42738
  }
42296
42739
  function fileExtensionTrust(args) {
42297
42740
  const dir = resolveTrustDir(args.trustDir, args.dir);
42741
+ if (args.extensionPins === "managed") {
42742
+ const location = extensionPinsPath(args.serverName, dir);
42743
+ return {
42744
+ // Managed mode has no first-use pin: nothing to read, nothing to write,
42745
+ // and no operator override. `write` REJECTS rather than no-ops, so a
42746
+ // path that ever reached it would log the attempt instead of silently
42747
+ // pretending to have pinned.
42748
+ allowNew: false,
42749
+ location,
42750
+ read: async () => null,
42751
+ write: async () => {
42752
+ throw new Error(`refusing to write an extension pin: ${location} is host-managed and this MCP never pins on first use`);
42753
+ },
42754
+ managed: { location, read: () => readExtensionPinsAt(location) }
42755
+ };
42756
+ }
42298
42757
  return {
42299
42758
  allowNew: args.allowNew,
42300
42759
  location: extensionTrustPath(args.serverName, dir),
@@ -42327,13 +42786,13 @@ function decideExtensionTrust(args) {
42327
42786
  };
42328
42787
  }
42329
42788
  function extensionTrustPath(serverName, dir = defaultTrustDir()) {
42330
- return join3(dir, `${safeIdentityFileBase(serverName)}.extension-trust.json`);
42789
+ return join4(dir, `${safeIdentityFileBase(serverName)}.extension-trust.json`);
42331
42790
  }
42332
42791
  function extensionTrustPathHint(serverName) {
42333
42792
  try {
42334
42793
  return extensionTrustPath(serverName);
42335
42794
  } catch {
42336
- return join3(defaultTrustDir(), "<server-name>.extension-trust.json");
42795
+ return join4(defaultTrustDir(), "<server-name>.extension-trust.json");
42337
42796
  }
42338
42797
  }
42339
42798
  function isPin(x) {
@@ -42346,7 +42805,7 @@ async function readExtensionPin(serverName, dir = defaultTrustDir()) {
42346
42805
  const path = extensionTrustPath(serverName, dir);
42347
42806
  let raw;
42348
42807
  try {
42349
- raw = await readFile2(path, "utf8");
42808
+ raw = await readFile3(path, "utf8");
42350
42809
  } catch (e) {
42351
42810
  if (e.code === "ENOENT")
42352
42811
  return null;
@@ -42384,6 +42843,7 @@ var TRUST_DIR_ENV, TRUST_NEW_EXTENSION_ENV;
42384
42843
  var init_extension_trust = __esm({
42385
42844
  "node_modules/@fetchproxy/server/dist/extension-trust.js"() {
42386
42845
  init_identity();
42846
+ init_extension_pins();
42387
42847
  TRUST_DIR_ENV = "FETCHPROXY_TRUST_DIR";
42388
42848
  TRUST_NEW_EXTENSION_ENV = "FETCHPROXY_TRUST_NEW_EXTENSION";
42389
42849
  }
@@ -42518,6 +42978,7 @@ async function startHost(opts) {
42518
42978
  return true;
42519
42979
  }
42520
42980
  let extensionHello = null;
42981
+ let ownSessionInfo = null;
42521
42982
  let extensionClaim = null;
42522
42983
  const pairCodeFor = async (hello, mint) => {
42523
42984
  if (!mint)
@@ -42536,6 +42997,7 @@ async function startHost(opts) {
42536
42997
  return;
42537
42998
  console.warn(`[fetchproxy] ${opts.ownServerName}: ${OWN_DECRYPT_FAILURES_BEFORE_REHANDSHAKE} frames in a row from the extension failed authentication under this MCP's session key \u2014 re-handshaking this MCP's session (the extension stays connected).`);
42538
42999
  ownSession = dropOwnSessionAndEphemeral();
43000
+ ownSessionInfo = null;
42539
43001
  resetSessionPromise();
42540
43002
  const mintedKeypair = await generateSessionKeypair();
42541
43003
  const mintedHello = await buildServerHello({
@@ -42594,28 +43056,39 @@ async function startHost(opts) {
42594
43056
  return;
42595
43057
  }
42596
43058
  extensionClaim = ws;
42597
- let pin;
42598
- try {
42599
- pin = await opts.extensionTrust.read();
42600
- } catch (e) {
42601
- console.error(`[fetchproxy] ${String(e)}`);
42602
- if (extensionClaim === ws)
42603
- extensionClaim = null;
42604
- ws.close(1008, "extension pin unreadable");
42605
- return;
43059
+ const managed = opts.extensionTrust.managed;
43060
+ let outcome;
43061
+ let refusalReason = "extension identity is not the pinned one";
43062
+ if (managed) {
43063
+ const decided = await evaluateManagedExtensionTrust(managed, frame, opts.ownServerName);
43064
+ outcome = decided;
43065
+ if (decided.decision === "refused") {
43066
+ refusalReason = decided.code === "EXTENSION_NOT_PINNED" ? "extension identity is not in the managed pin set" : "extension pin set unavailable";
43067
+ }
43068
+ } else {
43069
+ let pin;
43070
+ try {
43071
+ pin = await opts.extensionTrust.read();
43072
+ } catch (e) {
43073
+ console.error(`[fetchproxy] ${String(e)}`);
43074
+ if (extensionClaim === ws)
43075
+ extensionClaim = null;
43076
+ ws.close(1008, "extension pin unreadable");
43077
+ return;
43078
+ }
43079
+ outcome = decideExtensionTrust({
43080
+ pin,
43081
+ hello: frame,
43082
+ allowNew: opts.extensionTrust.allowNew,
43083
+ serverName: opts.ownServerName,
43084
+ location: opts.extensionTrust.location
43085
+ });
42606
43086
  }
42607
- const outcome = decideExtensionTrust({
42608
- pin,
42609
- hello: frame,
42610
- allowNew: opts.extensionTrust.allowNew,
42611
- serverName: opts.ownServerName,
42612
- location: opts.extensionTrust.location
42613
- });
42614
43087
  if (outcome.decision === "refused") {
42615
43088
  console.warn(outcome.message);
42616
43089
  if (extensionClaim === ws)
42617
43090
  extensionClaim = null;
42618
- ws.close(1008, "extension identity is not the pinned one");
43091
+ ws.close(1008, refusalReason);
42619
43092
  return;
42620
43093
  }
42621
43094
  if (outcome.decision === "replace")
@@ -42710,8 +43183,9 @@ async function startHost(opts) {
42710
43183
  console.warn("[fetchproxy] discarding a ready for a session ephemeral this host no longer holds (the extension reconnected while a hello was in flight)");
42711
43184
  return;
42712
43185
  }
42713
- const extEdPub = fromB64(extensionHello.identityEd25519Pub);
42714
- const extNonce = fromB64(extensionHello.sessionNonce);
43186
+ const verifiedHello = extensionHello;
43187
+ const extEdPub = fromB64(verifiedHello.identityEd25519Pub);
43188
+ const extNonce = fromB64(verifiedHello.sessionNonce);
42715
43189
  const msg = readySignaturePayload(held.nonce, extNonce, fromB64(frame.extensionSessionPub), held.pub);
42716
43190
  const sig = fromB64(frame.sessionSig);
42717
43191
  let sigOk = false;
@@ -42744,6 +43218,7 @@ async function startHost(opts) {
42744
43218
  if (extensionWs !== ws)
42745
43219
  return;
42746
43220
  ownSession = new SessionState(key);
43221
+ ownSessionInfo = sessionInfoFromHello(verifiedHello);
42747
43222
  ownDecryptFailures = 0;
42748
43223
  ownPendingPairCode = null;
42749
43224
  resolveOwnSession(ownSession);
@@ -42814,7 +43289,11 @@ async function startHost(opts) {
42814
43289
  }
42815
43290
  if (frame.type === "hello-rejected" && identified === "extension") {
42816
43291
  if (frame.mcpId === opts.ownMcpId) {
42817
- rejectOwnSession(new FetchproxyHelloRejectedError({ mcpId: frame.mcpId, reason: frame.reason }));
43292
+ rejectOwnSession(new FetchproxyHelloRejectedError({
43293
+ mcpId: frame.mcpId,
43294
+ reason: frame.reason,
43295
+ platform: extensionHello?.platform ?? null
43296
+ }));
42818
43297
  } else {
42819
43298
  const slot = peers.get(frame.mcpId);
42820
43299
  if (slot?.helloFrame.accepts?.includes("hello-rejected")) {
@@ -42860,6 +43339,7 @@ async function startHost(opts) {
42860
43339
  rejectOwnSession(new Error("extension disconnected before ready"));
42861
43340
  }
42862
43341
  ownSession = dropOwnSessionAndEphemeral();
43342
+ ownSessionInfo = null;
42863
43343
  ownDecryptFailures = 0;
42864
43344
  ownPendingPairCode = null;
42865
43345
  resetSessionPromise();
@@ -42906,6 +43386,7 @@ async function startHost(opts) {
42906
43386
  });
42907
43387
  if (!extensionWs)
42908
43388
  throw new Error("host: no extension connected");
43389
+ opts.refuseOutbound?.(inner, ownSessionInfo);
42909
43390
  const plaintext = encodeOutboundInnerFrame(opts.ownMcpId, inner);
42910
43391
  const sealed = await sealInnerFrame(session.sessionKey, opts.ownMcpId, session.nextOutboundSeq(), plaintext, "s2e");
42911
43392
  extensionWs.send(JSON.stringify(sealed));
@@ -42921,7 +43402,8 @@ async function startHost(opts) {
42921
43402
  },
42922
43403
  pendingPairCode: () => ownPendingPairCode,
42923
43404
  extensionConnected: () => extensionWs !== null,
42924
- sessionLinked: () => ownSession !== null
43405
+ sessionLinked: () => ownSession !== null,
43406
+ sessionInfo: () => ownSession !== null ? ownSessionInfo : null
42925
43407
  };
42926
43408
  }
42927
43409
  var HTTP_ORIGIN_RE, PUBLIC_ORIGIN_RE, EXTENSION_ORIGIN_RE, OPAQUE_ORIGIN, ALLOW_LOCAL_ORIGINS_ENV, HANDSHAKE_TIMEOUT_MS, MAX_PAYLOAD_BYTES, enc4, OWN_DECRYPT_FAILURES_BEFORE_REHANDSHAKE;
@@ -42934,6 +43416,8 @@ var init_host = __esm({
42934
43416
  init_session();
42935
43417
  init_session_ready();
42936
43418
  init_extension_trust();
43419
+ init_extension_pins();
43420
+ init_session_info();
42937
43421
  HTTP_ORIGIN_RE = /^https?:\/\//i;
42938
43422
  PUBLIC_ORIGIN_RE = /^https?:\/\/(?!(127\.0\.0\.1|localhost|\[::1\])(:|$))/i;
42939
43423
  EXTENSION_ORIGIN_RE = /^(chrome-extension|moz-extension|safari-web-extension):\/\//i;
@@ -43025,6 +43509,7 @@ async function startPeer(opts) {
43025
43509
  const closeListeners = [];
43026
43510
  const extensionDisconnectListeners = [];
43027
43511
  let session = null;
43512
+ let sessionInfo = null;
43028
43513
  let sessionEphemeral = null;
43029
43514
  function dropSessionEphemeral() {
43030
43515
  if (sessionEphemeral)
@@ -43090,6 +43575,15 @@ async function startPeer(opts) {
43090
43575
  console.warn(`[fetchproxy] ${opts.serverName}: extension session signature invalid \u2014 refusing (the concentrator may be answering in the browser's place)`);
43091
43576
  return null;
43092
43577
  }
43578
+ const managed = opts.extensionTrust.managed;
43579
+ if (managed) {
43580
+ const decided = await evaluateManagedExtensionTrust(managed, hello2, opts.serverName);
43581
+ if (decided.decision === "refused") {
43582
+ console.warn(decided.message);
43583
+ return null;
43584
+ }
43585
+ return hello2;
43586
+ }
43093
43587
  if (cachedPin === void 0) {
43094
43588
  try {
43095
43589
  cachedPin = await opts.extensionTrust.read();
@@ -43157,6 +43651,7 @@ async function startPeer(opts) {
43157
43651
  extensionGone = true;
43158
43652
  dropSessionEphemeral();
43159
43653
  pendingPairCode = null;
43654
+ sessionInfo = null;
43160
43655
  if (session !== null) {
43161
43656
  session = null;
43162
43657
  if (sessionPromiseSettled)
@@ -43189,6 +43684,7 @@ async function startPeer(opts) {
43189
43684
  }
43190
43685
  const isRenegotiation = session !== null;
43191
43686
  session = new SessionState(sessionKey);
43687
+ sessionInfo = sessionInfoFromHello(authenticated);
43192
43688
  extensionGone = false;
43193
43689
  pendingPairCode = null;
43194
43690
  if (isRenegotiation) {
@@ -43199,7 +43695,11 @@ async function startPeer(opts) {
43199
43695
  return;
43200
43696
  }
43201
43697
  if (frame.type === "hello-rejected" && frame.mcpId === opts.mcpId) {
43202
- rejectFirstReady(new FetchproxyHelloRejectedError({ mcpId: frame.mcpId, reason: frame.reason }));
43698
+ rejectFirstReady(new FetchproxyHelloRejectedError({
43699
+ mcpId: frame.mcpId,
43700
+ reason: frame.reason,
43701
+ platform: extensionHello?.platform ?? null
43702
+ }));
43203
43703
  }
43204
43704
  if (frame.type === "pair-pending" && frame.mcpId === opts.mcpId) {
43205
43705
  const hello2 = extensionHello;
@@ -43299,6 +43799,7 @@ async function startPeer(opts) {
43299
43799
  const s = session;
43300
43800
  if (s === null)
43301
43801
  throw new Error("peer: extension disconnected");
43802
+ opts.refuseOutbound?.(inner, sessionInfo);
43302
43803
  const plaintext = encodeOutboundInnerFrame(opts.mcpId, inner);
43303
43804
  const sealed = await sealInnerFrame(s.sessionKey, opts.mcpId, s.nextOutboundSeq(), plaintext, "s2e");
43304
43805
  if (ws.readyState !== import_websocket.default.OPEN)
@@ -43317,6 +43818,7 @@ async function startPeer(opts) {
43317
43818
  pendingPairCode: () => pendingPairCode,
43318
43819
  extensionConnected: () => extensionHello !== null,
43319
43820
  sessionLinked: () => session !== null && !extensionGone,
43821
+ sessionInfo: () => session !== null && !extensionGone ? sessionInfo : null,
43320
43822
  onClose: (cb) => {
43321
43823
  closeListeners.push(cb);
43322
43824
  },
@@ -43337,14 +43839,18 @@ var init_peer = __esm({
43337
43839
  init_host();
43338
43840
  init_session();
43339
43841
  init_session_ready();
43842
+ init_session_info();
43340
43843
  init_extension_trust();
43844
+ init_extension_pins();
43341
43845
  PEER_DIAL_TIMEOUT_MS = 5e3;
43342
43846
  enc5 = new TextEncoder();
43343
43847
  }
43344
43848
  });
43345
43849
 
43346
43850
  // node_modules/@fetchproxy/server/dist/error-kind.js
43347
- function classifyFetchError(error62) {
43851
+ function classifyFetchError(error62, code) {
43852
+ if (code === CAPABILITY_UNAVAILABLE_CODE)
43853
+ return "capability_unavailable";
43348
43854
  if (/^(in-page )?fetch threw:/.test(error62)) {
43349
43855
  return "tab_fetch_failed";
43350
43856
  }
@@ -43360,6 +43866,9 @@ function classifyFetchError(error62) {
43360
43866
  if (/not in domains \[/.test(error62)) {
43361
43867
  return "domain_denied";
43362
43868
  }
43869
+ if (parseCapabilityUnavailable(error62) !== null) {
43870
+ return "capability_unavailable";
43871
+ }
43363
43872
  if (/^capability .+ not granted/.test(error62)) {
43364
43873
  return "capability_denied";
43365
43874
  }
@@ -43370,6 +43879,7 @@ function classifyFetchError(error62) {
43370
43879
  }
43371
43880
  var init_error_kind = __esm({
43372
43881
  "node_modules/@fetchproxy/server/dist/error-kind.js"() {
43882
+ init_dist3();
43373
43883
  }
43374
43884
  });
43375
43885
 
@@ -43430,7 +43940,15 @@ function waitedHint(op) {
43430
43940
  }
43431
43941
  return "the extension waited and nothing arrived. Is a tab open on the declared domain and signed in?" + tail;
43432
43942
  }
43433
- function protocolErrorFrom(error62, op) {
43943
+ function protocolErrorFrom(error62, op, response) {
43944
+ const unavailable = parseCapabilityUnavailable(error62);
43945
+ if (unavailable !== null || response?.code === CAPABILITY_UNAVAILABLE_CODE) {
43946
+ const fromOp = response?.op === "graphql_query" ? "graphql" : response?.op ?? "unknown";
43947
+ return new FetchproxyCapabilityUnavailableError(error62, {
43948
+ capability: unavailable?.capability ?? fromOp,
43949
+ platform: unavailable?.platform ?? null
43950
+ });
43951
+ }
43434
43952
  if (error62 === "timeout")
43435
43953
  return new FetchproxyWaitedError(error62, op);
43436
43954
  if (SCOPE_REJECTION.test(error62))
@@ -43446,6 +43964,9 @@ function verbDeadlineMs(transportMs, requestedMs, graceMs = VERB_DEADLINE_GRACE_
43446
43964
  return transportMs;
43447
43965
  return Math.max(requestedMs + graceMs, transportMs);
43448
43966
  }
43967
+ function withNotResentNote(message) {
43968
+ return `${message}${message.endsWith(".") ? " " : ". "}${TIMEOUT_NOT_RESENT_NOTE}`;
43969
+ }
43449
43970
  function normalizeCookiePath(path) {
43450
43971
  if (path === void 0 || path === "")
43451
43972
  return void 0;
@@ -43506,15 +44027,17 @@ function isResendableRequest(inner) {
43506
44027
  return true;
43507
44028
  }
43508
44029
  }
43509
- var FetchproxyProtocolError, FetchproxyHttpError, FetchproxyBridgeDownError, FetchproxyHintedError, FetchproxyScopeError, FetchproxyNoTabError, FetchproxyTabOpeningError, FetchproxyWaitedError, SCOPE_REJECTION, NO_TAB_REJECTION, TAB_OPENING_REJECTION, VERB_DEADLINE_GRACE_MS, FetchproxyTimeoutError, SUBDOMAIN_LABEL_RE, DEFAULT_JSON_OK_STATUSES, TIMEOUT_RETRY_SAFE_METHODS, FetchproxyServer;
44030
+ var FetchproxyProtocolError, FetchproxyHttpError, FetchproxyBridgeDownError, FetchproxyHintedError, FetchproxyScopeError, FetchproxyNoTabError, FetchproxyTabOpeningError, FetchproxyWaitedError, FetchproxyCapabilityUnavailableError, SCOPE_REJECTION, NO_TAB_REJECTION, TAB_OPENING_REJECTION, VERB_DEADLINE_GRACE_MS, FetchproxyTimeoutError, TIMEOUT_NOT_RESENT_NOTE, SUBDOMAIN_LABEL_RE, DEFAULT_JSON_OK_STATUSES, TIMEOUT_RETRY_SAFE_METHODS, FetchproxyServer;
43510
44031
  var init_ws_server = __esm({
43511
44032
  "node_modules/@fetchproxy/server/dist/ws-server.js"() {
43512
44033
  init_dist3();
44034
+ init_session_info();
43513
44035
  init_election();
43514
44036
  init_host();
43515
44037
  init_peer();
43516
44038
  init_identity();
43517
44039
  init_extension_trust();
44040
+ init_extension_pins();
43518
44041
  init_error_kind();
43519
44042
  init_classify_bridge_error();
43520
44043
  FetchproxyProtocolError = class extends Error {
@@ -43545,7 +44068,7 @@ var init_ws_server = __esm({
43545
44068
  const retryAttempted = args.retryAttempted ?? false;
43546
44069
  const op = args.op ?? "fetch";
43547
44070
  const retryClause = retryAttempted ? `Server already burned a one-shot lazy-revive retry; SW is still down. ` : `Server lazy-revive retry was disabled (bridgeReviveDelayMs unset/0). `;
43548
- const hint = `the fetchproxy extension's service worker is not responding ("${args.originalError}"). Chrome evicts extension service workers after ~30s idle by default. ${retryClause}Make sure a tab for this domain is open, fully loaded, and signed in (the bridge fetches through that tab) \u2014 then retry. If it keeps happening, reload the extension from chrome://extensions and reload the tab.`;
44071
+ const hint = `ContextMint Bridge's service worker is not responding ("${args.originalError}"). Chrome evicts extension service workers after ~30s idle by default. ${retryClause}Make sure a tab for this domain is open, fully loaded, and signed in (the bridge fetches through that tab) \u2014 then retry. If it keeps happening, reload the extension from chrome://extensions and reload the tab.`;
43549
44072
  super(`fetchproxy bridge down during ${op}${args.url ? ` (${args.url})` : ""}. ${hint}`);
43550
44073
  this.name = "FetchproxyBridgeDownError";
43551
44074
  this.originalError = args.originalError;
@@ -43572,7 +44095,7 @@ var init_ws_server = __esm({
43572
44095
  };
43573
44096
  FetchproxyScopeError = class extends FetchproxyHintedError {
43574
44097
  constructor(originalError) {
43575
- super(originalError, "the declared scope changed since you paired, so the extension is refusing the request. Revoke this MCP in the Transporter extension popup, then re-run \u2014 you will be asked to approve the new scope. This is not a version problem and does not need an update.");
44098
+ super(originalError, "the declared scope changed since you paired, so the extension is refusing the request. Revoke this MCP in the ContextMint Bridge extension popup, then re-run \u2014 you will be asked to approve the new scope. This is not a version problem and does not need an update.");
43576
44099
  this.name = "FetchproxyScopeError";
43577
44100
  }
43578
44101
  };
@@ -43594,6 +44117,19 @@ var init_ws_server = __esm({
43594
44117
  this.name = "FetchproxyWaitedError";
43595
44118
  }
43596
44119
  };
44120
+ FetchproxyCapabilityUnavailableError = class extends FetchproxyHintedError {
44121
+ /** The capability the browser cannot serve (`graphql` for a `graphql_query`). */
44122
+ capability;
44123
+ /** The browser, when known (`'safari'`); `null` when the extension did not say. */
44124
+ platform;
44125
+ constructor(originalError, info) {
44126
+ const where = info.platform ? `this browser (${info.platform})` : "this browser";
44127
+ super(originalError, `${where} cannot serve the "${info.capability}" capability \u2014 ContextMint Bridge checked for the browser API it needs and it is missing. The rest of this MCP still works here. Nothing is wrong with the MCP's code or your pairing, and neither updating nor re-approving will change it: use this tool from a browser that provides the API (for example Chrome).`);
44128
+ this.name = "FetchproxyCapabilityUnavailableError";
44129
+ this.capability = info.capability;
44130
+ this.platform = info.platform;
44131
+ }
44132
+ };
43597
44133
  SCOPE_REJECTION = /not in declared/;
43598
44134
  NO_TAB_REJECTION = /no tab matching (?!.*(content script loaded|one is still opening))/;
43599
44135
  TAB_OPENING_REJECTION = /no tab matching .*one is still opening/;
@@ -43640,7 +44176,8 @@ var init_ws_server = __esm({
43640
44176
  constructor(args) {
43641
44177
  const graceMs = args.graceMs ?? VERB_DEADLINE_GRACE_MS;
43642
44178
  const callerChose = args.requestedTimeoutMs !== void 0 && args.timeoutMs === args.requestedTimeoutMs + graceMs;
43643
- super(`fetchproxy: ${args.url} did not respond within ${args.timeoutMs}ms` + (callerChose ? ` \u2014 the ${args.requestedTimeoutMs}ms this call asked for, plus ${graceMs}ms for the reply to reach this server. The extension runs its own timer on the value you passed, so a window that is genuinely too short reports what did not happen rather than this.` : ""));
44179
+ const base = `fetchproxy: ${args.url} did not respond within ${args.timeoutMs}ms` + (callerChose ? ` \u2014 the ${args.requestedTimeoutMs}ms this call asked for, plus ${graceMs}ms for the reply to reach this server. The extension runs its own timer on the value you passed, so a window that is genuinely too short reports what did not happen rather than this.` : "");
44180
+ super(args.retrySafe === false ? withNotResentNote(base) : base);
43644
44181
  this.name = "FetchproxyTimeoutError";
43645
44182
  this.url = args.url;
43646
44183
  this.timeoutMs = args.timeoutMs;
@@ -43652,6 +44189,7 @@ var init_ws_server = __esm({
43652
44189
  this.retrySafe = args.retrySafe ?? true;
43653
44190
  }
43654
44191
  };
44192
+ TIMEOUT_NOT_RESENT_NOTE = "It was not re-sent because it may already have run in the browser \u2014 check before retrying.";
43655
44193
  SUBDOMAIN_LABEL_RE = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*$/i;
43656
44194
  DEFAULT_JSON_OK_STATUSES = [200, 201, 202, 204];
43657
44195
  TIMEOUT_RETRY_SAFE_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD", "OPTIONS"]);
@@ -43851,6 +44389,7 @@ var init_ws_server = __esm({
43851
44389
  identityDir: opts.identityDir,
43852
44390
  trustDir: opts.trustDir,
43853
44391
  allowNewExtensionIdentity: opts.allowNewExtensionIdentity,
44392
+ extensionPins: opts.extensionPins,
43854
44393
  requireExtensionIdentity: opts.requireExtensionIdentity,
43855
44394
  onPairCode: opts.onPairCode
43856
44395
  };
@@ -43936,6 +44475,7 @@ var init_ws_server = __esm({
43936
44475
  this.role = "host";
43937
44476
  this.hostHandle = await startHost({
43938
44477
  httpServer: el.server,
44478
+ refuseOutbound: (inner, info) => this.refuseIfUnavailable(inner, info),
43939
44479
  ownIdentity: identity,
43940
44480
  ownMcpId: mcpId,
43941
44481
  ownServerName: this.opts.serverName,
@@ -43966,6 +44506,7 @@ var init_ws_server = __esm({
43966
44506
  } else {
43967
44507
  this.role = "peer";
43968
44508
  this.peerHandle = await startPeer({
44509
+ refuseOutbound: (inner, info) => this.refuseIfUnavailable(inner, info),
43969
44510
  host: this.opts.host,
43970
44511
  port: this.opts.port,
43971
44512
  identity,
@@ -44014,7 +44555,7 @@ var init_ws_server = __esm({
44014
44555
  }
44015
44556
  }
44016
44557
  pairingErrorMessage(code) {
44017
- return `fetchproxy transport error: pairing required for ${this.opts.serverName}. Tell the user to open the Transporter browser extension popup and approve the pair request. The pair code is: ${code} \u2014 display this code to the user so they can verify it matches.`;
44558
+ return `fetchproxy transport error: pairing required for ${this.opts.serverName}. Tell the user to open the ContextMint Bridge browser extension popup and approve the pair request. The pair code is: ${code} \u2014 display this code to the user so they can verify it matches.`;
44018
44559
  }
44019
44560
  /**
44020
44561
  * Raw single-shot fetch through the bridge. Most callers should prefer
@@ -44144,13 +44685,28 @@ var init_ws_server = __esm({
44144
44685
  * every one of them.
44145
44686
  */
44146
44687
  extensionTrust() {
44688
+ const allowNew = allowNewExtensionIdentity(this.opts.allowNewExtensionIdentity);
44689
+ if (resolveExtensionPinsMode(this.opts.extensionPins) === "managed") {
44690
+ if (allowNew && !this.warnedAllowNewIgnored) {
44691
+ this.warnedAllowNewIgnored = true;
44692
+ console.warn(`[fetchproxy] ${this.opts.serverName}: ignoring ${TRUST_NEW_EXTENSION_ENV} / allowNewExtensionIdentity \u2014 this MCP's extension pins are host-managed (${EXTENSION_PINS_ENV}=managed), so only the host's pin set decides which browsers it accepts.`);
44693
+ }
44694
+ return fileExtensionTrust({
44695
+ serverName: this.opts.serverName,
44696
+ dir: this.opts.identityDir,
44697
+ trustDir: this.opts.trustDir,
44698
+ allowNew: false,
44699
+ extensionPins: "managed"
44700
+ });
44701
+ }
44147
44702
  return fileExtensionTrust({
44148
44703
  serverName: this.opts.serverName,
44149
44704
  dir: this.opts.identityDir,
44150
44705
  trustDir: this.opts.trustDir,
44151
- allowNew: allowNewExtensionIdentity(this.opts.allowNewExtensionIdentity)
44706
+ allowNew
44152
44707
  });
44153
44708
  }
44709
+ warnedAllowNewIgnored = false;
44154
44710
  noteActivityForKeepalive() {
44155
44711
  const intervalMs = this.opts.keepAliveIntervalMs;
44156
44712
  if (intervalMs <= 0)
@@ -44244,6 +44800,15 @@ var init_ws_server = __esm({
44244
44800
  resendable: isRetrySafeOnTimeout(init.method, fetchOpts.retryOnTimeout)
44245
44801
  });
44246
44802
  } catch (err) {
44803
+ if (err instanceof FetchproxyCapabilityUnavailableError) {
44804
+ return {
44805
+ ok: false,
44806
+ error: err.originalError,
44807
+ kind: "capability_unavailable",
44808
+ retryAttempted: false,
44809
+ cause: err
44810
+ };
44811
+ }
44247
44812
  return {
44248
44813
  ok: false,
44249
44814
  error: err instanceof Error ? err.message : String(err),
@@ -44264,7 +44829,8 @@ var init_ws_server = __esm({
44264
44829
  timer = setTimeout(() => {
44265
44830
  this.pending.delete(id);
44266
44831
  const elapsedMs = Date.now() - start;
44267
- const error62 = `fetchproxy: ${init.url} did not respond within ${timeoutMs}ms`;
44832
+ const base = `fetchproxy: ${init.url} did not respond within ${timeoutMs}ms`;
44833
+ const error62 = isRetrySafeOnTimeout(init.method, fetchOpts.retryOnTimeout) ? base : withNotResentNote(base);
44268
44834
  resolve2({
44269
44835
  ok: false,
44270
44836
  error: error62,
@@ -44386,6 +44952,9 @@ var init_ws_server = __esm({
44386
44952
  port: this.opts.port
44387
44953
  });
44388
44954
  }
44955
+ if (result.kind === "capability_unavailable") {
44956
+ return protocolErrorFrom(result.error, void 0, { code: CAPABILITY_UNAVAILABLE_CODE, op });
44957
+ }
44389
44958
  return protocolErrorFrom(result.error);
44390
44959
  }
44391
44960
  /**
@@ -44452,6 +45021,9 @@ var init_ws_server = __esm({
44452
45021
  if (result.kind === "session_not_ready" && result.cause instanceof Error) {
44453
45022
  throw result.cause;
44454
45023
  }
45024
+ if (result.kind === "capability_unavailable" && result.cause instanceof FetchproxyCapabilityUnavailableError) {
45025
+ throw result.cause;
45026
+ }
44455
45027
  throw this._typedErrorFor(result, init.url, "fetch", result.retryAttempted ?? false, isRetrySafeOnTimeout(method, opts.retryOnTimeout));
44456
45028
  }
44457
45029
  const response = {
@@ -44634,7 +45206,9 @@ var init_ws_server = __esm({
44634
45206
  session_state: health.session.state,
44635
45207
  pending_pair_code: health.session.pairCode,
44636
45208
  extension_connected: health.session.extensionConnected,
44637
- last_extension_message_at: health.lastExtensionMessageAt
45209
+ last_extension_message_at: health.lastExtensionMessageAt,
45210
+ unavailable_capabilities: health.session.unavailableCapabilities,
45211
+ platform: health.session.platform
44638
45212
  },
44639
45213
  ...error62 ? { error: error62 } : {}
44640
45214
  };
@@ -45280,7 +45854,7 @@ var init_ws_server = __esm({
45280
45854
  fetchCb({
45281
45855
  ok: false,
45282
45856
  error: inner.error,
45283
- kind: classifyFetchError(inner.error),
45857
+ kind: classifyFetchError(inner.error, inner.code),
45284
45858
  retryAttempted: false
45285
45859
  });
45286
45860
  }
@@ -45296,7 +45870,7 @@ var init_ws_server = __esm({
45296
45870
  storageCb.reject(new FetchproxyProtocolError(`unexpected ${String(inner.op)} response on storage awaiter`));
45297
45871
  }
45298
45872
  } else {
45299
- storageCb.reject(protocolErrorFrom(inner.error));
45873
+ storageCb.reject(protocolErrorFrom(inner.error, void 0, inner));
45300
45874
  }
45301
45875
  return;
45302
45876
  }
@@ -45310,7 +45884,7 @@ var init_ws_server = __esm({
45310
45884
  captureCb.reject(new FetchproxyProtocolError(`unexpected ${String(inner.op)} response on capture awaiter`));
45311
45885
  }
45312
45886
  } else {
45313
- captureCb.reject(protocolErrorFrom(inner.error, "capture"));
45887
+ captureCb.reject(protocolErrorFrom(inner.error, "capture", inner));
45314
45888
  }
45315
45889
  return;
45316
45890
  }
@@ -45324,7 +45898,7 @@ var init_ws_server = __esm({
45324
45898
  redirectCb.reject(new FetchproxyProtocolError(`unexpected ${String(inner.op)} response on capture_redirect awaiter`));
45325
45899
  }
45326
45900
  } else {
45327
- redirectCb.reject(protocolErrorFrom(inner.error, "capture_redirect"));
45901
+ redirectCb.reject(protocolErrorFrom(inner.error, "capture_redirect", inner));
45328
45902
  }
45329
45903
  return;
45330
45904
  }
@@ -45338,7 +45912,7 @@ var init_ws_server = __esm({
45338
45912
  idbCb.reject(new FetchproxyProtocolError(`unexpected ${String(inner.op)} response on read_indexed_db awaiter`));
45339
45913
  }
45340
45914
  } else {
45341
- idbCb.reject(protocolErrorFrom(inner.error));
45915
+ idbCb.reject(protocolErrorFrom(inner.error, void 0, inner));
45342
45916
  }
45343
45917
  return;
45344
45918
  }
@@ -45352,7 +45926,7 @@ var init_ws_server = __esm({
45352
45926
  domListCb.reject(new FetchproxyProtocolError(`unexpected ${String(inner.op)} response on read_dom_list awaiter`));
45353
45927
  }
45354
45928
  } else {
45355
- domListCb.reject(protocolErrorFrom(inner.error));
45929
+ domListCb.reject(protocolErrorFrom(inner.error, void 0, inner));
45356
45930
  }
45357
45931
  return;
45358
45932
  }
@@ -45366,7 +45940,7 @@ var init_ws_server = __esm({
45366
45940
  downloadCb.reject(new FetchproxyProtocolError(`unexpected ${String(inner.op)} response on download awaiter`));
45367
45941
  }
45368
45942
  } else {
45369
- downloadCb.reject(protocolErrorFrom(inner.error, "download"));
45943
+ downloadCb.reject(protocolErrorFrom(inner.error, "download", inner));
45370
45944
  }
45371
45945
  return;
45372
45946
  }
@@ -45380,7 +45954,7 @@ var init_ws_server = __esm({
45380
45954
  graphqlCb.reject(new FetchproxyProtocolError(`unexpected ${String(inner.op)} response on graphql_query awaiter`));
45381
45955
  }
45382
45956
  } else {
45383
- graphqlCb.reject(protocolErrorFrom(inner.error));
45957
+ graphqlCb.reject(protocolErrorFrom(inner.error, void 0, inner));
45384
45958
  }
45385
45959
  return;
45386
45960
  }
@@ -45390,7 +45964,7 @@ var init_ws_server = __esm({
45390
45964
  if (inner.ok && inner.op === "write_cookies") {
45391
45965
  writeCookiesCb.resolve([...inner.written]);
45392
45966
  } else {
45393
- writeCookiesCb.reject(protocolErrorFrom(inner.ok ? "write_cookies response had the wrong op" : inner.error));
45967
+ writeCookiesCb.reject(inner.ok ? protocolErrorFrom("write_cookies response had the wrong op") : protocolErrorFrom(inner.error, void 0, inner));
45394
45968
  }
45395
45969
  return;
45396
45970
  }
@@ -45580,11 +46154,38 @@ var init_ws_server = __esm({
45580
46154
  const handle = this.hostHandle ?? this.peerHandle;
45581
46155
  const pairCode = this.currentPendingPairCode();
45582
46156
  if (!handle || this.role === null) {
45583
- return { state: "not_listening", pairCode, extensionConnected: false };
46157
+ return {
46158
+ state: "not_listening",
46159
+ pairCode,
46160
+ extensionConnected: false,
46161
+ unavailableCapabilities: [],
46162
+ platform: null
46163
+ };
45584
46164
  }
46165
+ const info = handle.sessionInfo?.() ?? null;
45585
46166
  const extensionConnected = handle.extensionConnected();
45586
46167
  const state = handle.sessionLinked() ? "linked" : pairCode !== null ? "pair_pending" : !extensionConnected ? "extension_disconnected" : "no_session";
45587
- return { state, pairCode, extensionConnected };
46168
+ return {
46169
+ state,
46170
+ pairCode,
46171
+ extensionConnected,
46172
+ unavailableCapabilities: info ? [...info.unavailableCapabilities] : [],
46173
+ platform: info?.platform ?? null
46174
+ };
46175
+ }
46176
+ /**
46177
+ * #418: refuse, before a seq is claimed, a request whose capability the
46178
+ * extension said this browser cannot serve. Called by the host / peer
46179
+ * handle once the session is ready, so it judges against the list from the
46180
+ * hello that session was verified against. Advisory: the list is unsigned,
46181
+ * so it may only ever make this MCP refuse MORE — the extension still
46182
+ * enforces from its own runtime check for anything that gets through.
46183
+ */
46184
+ refuseIfUnavailable(inner, info) {
46185
+ const cap = unavailableCapabilityFor(inner, info);
46186
+ if (cap === null || info === null)
46187
+ return;
46188
+ throw new FetchproxyCapabilityUnavailableError(capabilityUnavailableMessage(cap, info.platform), { capability: cap, platform: info.platform });
45588
46189
  }
45589
46190
  /**
45590
46191
  * 0.5.2+: throw `FetchproxyProtocolError` with the actionable pair-code
@@ -45684,6 +46285,7 @@ var init_dist4 = __esm({
45684
46285
  init_parse_html();
45685
46286
  init_batch();
45686
46287
  init_extension_trust();
46288
+ init_extension_pins();
45687
46289
  init_identity();
45688
46290
  }
45689
46291
  });
@@ -47520,7 +48122,7 @@ await runMcp({
47520
48122
  });
47521
48123
  /*! Bundled license information:
47522
48124
 
47523
- @modelcontextprotocol/server/dist/src-CX2iR2pK.mjs:
48125
+ @modelcontextprotocol/server/dist/src-D-y6h4N7.mjs:
47524
48126
  (*!
47525
48127
  * content-type
47526
48128
  * Copyright(c) 2015 Douglas Christopher Wilson