@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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +21 -4
- package/dist/auth-fetchproxy.js +1 -1
- package/dist/bundle.js +735 -133
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/server.json +2 -2
- package/skills/outlook-fpx/SKILL.md +11 -5
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-
|
|
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
|
|
20548
|
-
"node_modules/@modelcontextprotocol/core/dist/auth-
|
|
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
|
-
|
|
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-
|
|
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
|
|
24269
|
-
"node_modules/@modelcontextprotocol/server/dist/src-
|
|
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
|
-
|
|
24363
|
-
|
|
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
|
-
|
|
24375
|
-
|
|
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 (
|
|
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)
|
|
25889
|
-
|
|
25890
|
-
|
|
25891
|
-
|
|
25892
|
-
|
|
25893
|
-
|
|
25894
|
-
|
|
25895
|
-
|
|
25896
|
-
|
|
25897
|
-
|
|
25898
|
-
|
|
25899
|
-
|
|
25900
|
-
|
|
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 &&
|
|
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-
|
|
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
|
|
33342
|
-
"node_modules/@modelcontextprotocol/server/dist/mcp-
|
|
33343
|
-
|
|
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)
|
|
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
|
|
34444
|
-
|
|
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
|
-
|
|
35026
|
-
|
|
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.
|
|
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
|
-
|
|
35205
|
-
|
|
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
|
|
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 =
|
|
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*)([
|
|
35245
|
-
COOKIE_HEADER_RE = /((?<!set-)\bcookie\s*:\s*)((?:[
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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
|
|
35898
|
+
function readConfirmTtl(env) {
|
|
35800
35899
|
const raw = readEnvVar("MCP_CONFIRM_TTL_SECONDS", { env })?.trim();
|
|
35801
|
-
|
|
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, ...
|
|
35927
|
+
const { tool, account, confirmToken, subject, instruction, spent, args, env = process.env, ...rest } = options;
|
|
35812
35928
|
const mode = readConfirmMode(env);
|
|
35813
|
-
|
|
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} ${
|
|
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
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
42598
|
-
|
|
42599
|
-
|
|
42600
|
-
|
|
42601
|
-
|
|
42602
|
-
|
|
42603
|
-
|
|
42604
|
-
|
|
42605
|
-
|
|
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,
|
|
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
|
|
42714
|
-
const
|
|
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({
|
|
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({
|
|
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 = `
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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(
|
|
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 {
|
|
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 {
|
|
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-
|
|
48125
|
+
@modelcontextprotocol/server/dist/src-D-y6h4N7.mjs:
|
|
47524
48126
|
(*!
|
|
47525
48127
|
* content-type
|
|
47526
48128
|
* Copyright(c) 2015 Douglas Christopher Wilson
|