@fruggr/zendesk-mcp-server 3.7.0 → 3.9.0
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/README.md +32 -22
- package/dist/THIRD-PARTY-NOTICES.md +5 -5
- package/dist/{article-sections-CzTODYsS.js → article-sections-DA7_Jm2H.js} +65 -34
- package/dist/{http-D-Xy9BWD.js → http-DuRcQrOc.js} +2809 -388
- package/dist/index.js +1370 -779
- package/dist/sbom.cdx.json +19 -19
- package/dist/{token-store-BqwB-30K.js → token-store-EwRwZiJO.js} +1 -1
- package/package.json +9 -9
package/dist/index.js
CHANGED
|
@@ -7911,6 +7911,11 @@ const ConfigSchema = object({
|
|
|
7911
7911
|
oauthMasterSecretFile: string().min(1).optional(),
|
|
7912
7912
|
/** HTTP only: the grant store URI; defaults to a file in the config dir. */
|
|
7913
7913
|
oauthStore: string().url().optional(),
|
|
7914
|
+
/**
|
|
7915
|
+
* HTTP only: where the admins' instructions, prompts and skills live
|
|
7916
|
+
* (`file://<dir>` or `memory://`); defaults to a folder in the config dir.
|
|
7917
|
+
*/
|
|
7918
|
+
customizationStore: string().url().optional(),
|
|
7914
7919
|
/** HTTP only: CIMD client ids added to the consent-skip allowlist. */
|
|
7915
7920
|
oauthTrustedClients: array(string().url()).default([]),
|
|
7916
7921
|
/** HTTP only: whether the built-in allowlist (claude.ai, ChatGPT) applies. */
|
|
@@ -7975,21 +7980,42 @@ const portEnv = (name) => {
|
|
|
7975
7980
|
return env.value === void 0 ? void 0 : parsePort(env.value, env.name);
|
|
7976
7981
|
};
|
|
7977
7982
|
/**
|
|
7978
|
-
* Split a raw
|
|
7979
|
-
*
|
|
7980
|
-
*
|
|
7981
|
-
*
|
|
7982
|
-
* whether an id/subdomain exists is decided lazily, on first use (no token is
|
|
7983
|
-
* available at startup on either transport).
|
|
7983
|
+
* Split a raw comma-separated value (`ZENDESK_BRAND_IDS`, `MCP_NAMESPACES`) into
|
|
7984
|
+
* its entries, trimmed. An empty entry (from `a,,b`, a leading/trailing comma,
|
|
7985
|
+
* or a whitespace-only value) is a misconfiguration, not an ignored blank: it
|
|
7986
|
+
* fails at startup naming the knob, unlike the lenient `splitList`.
|
|
7984
7987
|
*/
|
|
7988
|
+
const splitStrictList = (raw, emptyEntryMessage) => {
|
|
7989
|
+
const entries = raw.split(",").map((entry) => entry.trim());
|
|
7990
|
+
if (entries.some((entry) => entry.length === 0)) throw createStartupError(emptyEntryMessage, STARTUP_DOCS.environment);
|
|
7991
|
+
return entries;
|
|
7992
|
+
};
|
|
7985
7993
|
const parseBrandIds = (raw) => {
|
|
7986
7994
|
if (raw === void 0) return void 0;
|
|
7987
|
-
const
|
|
7988
|
-
if (entries.some((entry) => entry.length === 0)) throw createStartupError("Invalid --brand-ids / ZENDESK_BRAND_IDS value: empty entry. Expected a comma-separated list of brand ids or subdomains, or \"all\".", STARTUP_DOCS.environment);
|
|
7989
|
-
const normalized = entries.map((entry) => entry.toLowerCase());
|
|
7995
|
+
const normalized = splitStrictList(raw, "Invalid --brand-ids / ZENDESK_BRAND_IDS value: empty entry. Expected a comma-separated list of brand ids or subdomains, or \"all\".").map((entry) => entry.toLowerCase());
|
|
7990
7996
|
if (normalized.length > 1 && normalized.includes("all")) throw createStartupError("Invalid --brand-ids / ZENDESK_BRAND_IDS value: \"all\" cannot be combined with brand ids or subdomains.", STARTUP_DOCS.environment);
|
|
7991
7997
|
return [...new Set(normalized)];
|
|
7992
7998
|
};
|
|
7999
|
+
const ALL_NAMESPACES = "all";
|
|
8000
|
+
const expandAllNamespaces = (named, docs) => {
|
|
8001
|
+
const entries = [...new Set(named)];
|
|
8002
|
+
if (!entries.includes(ALL_NAMESPACES)) return entries;
|
|
8003
|
+
if (entries.length > 1) throw createStartupError("Invalid --namespace / MCP_NAMESPACES value: \"all\" cannot be combined with named namespaces.", docs);
|
|
8004
|
+
return [...Namespace.options];
|
|
8005
|
+
};
|
|
8006
|
+
/**
|
|
8007
|
+
* The namespaces the operator asked for, or undefined when neither
|
|
8008
|
+
* `--namespace` nor `MCP_NAMESPACES` is set. The flag wins and leaves the variable
|
|
8009
|
+
* unread. Entries stay strings: the `Namespace` enum in ConfigSchema rejects an
|
|
8010
|
+
* unknown one.
|
|
8011
|
+
*/
|
|
8012
|
+
const resolveNamespaces = (cliValues) => {
|
|
8013
|
+
if (cliValues !== void 0) return expandAllNamespaces(cliValues, STARTUP_DOCS.cliReference);
|
|
8014
|
+
const raw = requireNonEmptyEnv("MCP_NAMESPACES");
|
|
8015
|
+
if (raw === void 0) return void 0;
|
|
8016
|
+
const entries = splitStrictList(raw, "Invalid MCP_NAMESPACES value: empty entry. Expected a comma-separated list of namespaces, or \"all\".");
|
|
8017
|
+
return expandAllNamespaces(entries, STARTUP_DOCS.environment);
|
|
8018
|
+
};
|
|
7993
8019
|
const CLI_OPTIONS = {
|
|
7994
8020
|
mode: { type: "string" },
|
|
7995
8021
|
"brand-ids": { type: "string" },
|
|
@@ -8014,6 +8040,7 @@ const CLI_OPTIONS = {
|
|
|
8014
8040
|
"callback-port": { type: "string" },
|
|
8015
8041
|
"oauth-master-secret-file": { type: "string" },
|
|
8016
8042
|
"oauth-store": { type: "string" },
|
|
8043
|
+
"customization-store": { type: "string" },
|
|
8017
8044
|
"oauth-trusted-client": {
|
|
8018
8045
|
type: "string",
|
|
8019
8046
|
multiple: true
|
|
@@ -8045,6 +8072,7 @@ const FIELD_BY_FLAG = /* @__PURE__ */ new Map([
|
|
|
8045
8072
|
["cors-origin", "corsOrigins"],
|
|
8046
8073
|
["oauth-master-secret-file", "oauthMasterSecretFile"],
|
|
8047
8074
|
["oauth-store", "oauthStore"],
|
|
8075
|
+
["customization-store", "customizationStore"],
|
|
8048
8076
|
["oauth-trusted-client", "oauthTrustedClients"],
|
|
8049
8077
|
["sla-reply-thresholds", "slaReplyThresholds"],
|
|
8050
8078
|
["sla-wait-thresholds", "slaWaitThresholds"],
|
|
@@ -8112,6 +8140,7 @@ const resolveOAuthServerSettings = (cli) => ({
|
|
|
8112
8140
|
oauthMasterSecret: requireNonEmptyEnv("OAUTH_MASTER_SECRET"),
|
|
8113
8141
|
oauthMasterSecretFile: cli.oauthMasterSecretFile ?? requireNonEmptyEnv("OAUTH_MASTER_SECRET_FILE"),
|
|
8114
8142
|
oauthStore: cli.oauthStore ?? requireNonEmptyEnv("OAUTH_STORE"),
|
|
8143
|
+
customizationStore: cli.customizationStore ?? requireNonEmptyEnv("CUSTOMIZATION_STORE"),
|
|
8115
8144
|
oauthTrustedClients: [...cli.oauthTrustedClients ?? [], ...splitList(readEnv("OAUTH_TRUSTED_CLIENTS").value)],
|
|
8116
8145
|
defaultTrustedClients: cli.defaultTrustedClients
|
|
8117
8146
|
});
|
|
@@ -8173,7 +8202,7 @@ const loadConfig = (argv = process.argv.slice(2)) => {
|
|
|
8173
8202
|
const subdomain = cli.subdomain ?? requireNonEmptyEnv("ZENDESK_SUBDOMAIN") ?? "";
|
|
8174
8203
|
const oauthClientId = requireNonEmptyEnv("ZENDESK_OAUTH_CLIENT_ID") ?? `${subdomain}_zendesk`;
|
|
8175
8204
|
const mode = cli.tools?.length ? "all" : cli.mode ?? "namespace";
|
|
8176
|
-
const namespaces = cli.namespaces ?? (cli.tools?.length ? [...Namespace.options] : void 0);
|
|
8205
|
+
const namespaces = resolveNamespaces(cli.namespaces) ?? (cli.tools?.length ? [...Namespace.options] : void 0);
|
|
8177
8206
|
const callbackPort = cli.callbackPort ?? portEnv("OAUTH_CALLBACK_PORT");
|
|
8178
8207
|
const brandIds = cli.brandIds ?? requireNonEmptyEnv("ZENDESK_BRAND_IDS");
|
|
8179
8208
|
const hcResourceScheme = cli.hcResourceScheme ?? requireNonEmptyEnv("HC_RESOURCE_SCHEME");
|
|
@@ -8383,7 +8412,7 @@ const buildHelpCenterInstructions = (config) => {
|
|
|
8383
8412
|
].join("\n");
|
|
8384
8413
|
};
|
|
8385
8414
|
//#endregion
|
|
8386
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
8415
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/chunk-vYduTEsO.mjs
|
|
8387
8416
|
var __create = Object.create;
|
|
8388
8417
|
var __defProp = Object.defineProperty;
|
|
8389
8418
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -8415,7 +8444,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
8415
8444
|
enumerable: true
|
|
8416
8445
|
}) : target, mod));
|
|
8417
8446
|
//#endregion
|
|
8418
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
8447
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/dialects-CDpMbily.mjs
|
|
8419
8448
|
/**
|
|
8420
8449
|
* Canonical `$schema` URIs per supported dialect (http + https variants, trailing-`#` stripped).
|
|
8421
8450
|
*/
|
|
@@ -9875,6 +9904,8 @@ const ServerResultSchema = union([
|
|
|
9875
9904
|
ListToolsResultSchema,
|
|
9876
9905
|
SubscriptionsListenResultSchema
|
|
9877
9906
|
]);
|
|
9907
|
+
//#endregion
|
|
9908
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+core@2.4.0/node_modules/@modelcontextprotocol/core/dist/auth-UMQCo-ad.mjs
|
|
9878
9909
|
/**
|
|
9879
9910
|
* Reusable URL validation that disallows `javascript:` scheme
|
|
9880
9911
|
*/
|
|
@@ -10078,7 +10109,7 @@ const OAuthTokenRevocationRequestSchema = object({
|
|
|
10078
10109
|
token_type_hint: string().optional()
|
|
10079
10110
|
}).strip();
|
|
10080
10111
|
//#endregion
|
|
10081
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
10112
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/src-DdvbAHrR.mjs
|
|
10082
10113
|
/**
|
|
10083
10114
|
* Cross-bundle `instanceof` support for the SDK error classes.
|
|
10084
10115
|
*
|
|
@@ -14457,25 +14488,22 @@ const X_MCP_HEADER_KEY = "x-mcp-header";
|
|
|
14457
14488
|
*/
|
|
14458
14489
|
const RFC9110_TOKEN = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
14459
14490
|
/**
|
|
14460
|
-
* JSON Schema `type` values the spec admits on an `x-mcp-header` property
|
|
14461
|
-
*
|
|
14462
|
-
*
|
|
14463
|
-
* `number
|
|
14464
|
-
* `
|
|
14465
|
-
* parameters and expects the client to mirror them, so `number` is accepted
|
|
14466
|
-
* here so that the conformance gate passes; the discrepancy is tracked
|
|
14467
|
-
* upstream. Everything else (`object`, `array`, `null`, absent) is rejected.
|
|
14491
|
+
* JSON Schema `type` values the spec admits on an `x-mcp-header` property:
|
|
14492
|
+
* `integer`, `string` and `boolean`. `number` is explicitly not permitted
|
|
14493
|
+
* (2026-07-28 Streamable HTTP, "Schema Extension"), so a tool that annotates a
|
|
14494
|
+
* `number`-typed property is invalid (the server still checks its headers).
|
|
14495
|
+
* Everything else (`object`, `array`, `null`, absent) is rejected too.
|
|
14468
14496
|
*/
|
|
14469
14497
|
const PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
|
|
14470
14498
|
"string",
|
|
14471
14499
|
"integer",
|
|
14472
|
-
"boolean"
|
|
14473
|
-
"number"
|
|
14500
|
+
"boolean"
|
|
14474
14501
|
]);
|
|
14475
14502
|
/**
|
|
14476
14503
|
* Scan a tool's JSON-serialized `inputSchema` for `x-mcp-header` declarations
|
|
14477
14504
|
* and validate every constraint the spec places on them. Returns either the
|
|
14478
|
-
* collected declarations (possibly empty) or the first violated constraint
|
|
14505
|
+
* collected declarations (possibly empty) or the first violated constraint
|
|
14506
|
+
* (with the declarations too, when `number`-typed declarations are the only fault).
|
|
14479
14507
|
*
|
|
14480
14508
|
* The walk descends through `properties` at any depth (the spec's "any nesting
|
|
14481
14509
|
* depth" clause). The static-reachability MUST is enforced as a structural
|
|
@@ -14488,6 +14516,7 @@ const PERMITTED_X_MCP_HEADER_TYPES = /* @__PURE__ */ new Set([
|
|
|
14488
14516
|
function scanXMcpHeaderDeclarations(inputSchema) {
|
|
14489
14517
|
const declarations = [];
|
|
14490
14518
|
const seenLower = /* @__PURE__ */ new Map();
|
|
14519
|
+
let numberFault;
|
|
14491
14520
|
const visit = (node, path, reachable) => {
|
|
14492
14521
|
if (node === null || typeof node !== "object") return void 0;
|
|
14493
14522
|
const schema = node;
|
|
@@ -14497,7 +14526,11 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
14497
14526
|
if (typeof raw !== "string" || raw.length === 0) return `${pathName(path)}: x-mcp-header MUST be a non-empty string`;
|
|
14498
14527
|
if (!RFC9110_TOKEN.test(raw)) return `${pathName(path)}: x-mcp-header '${raw}' is not a valid RFC 9110 token (no spaces, control characters or HTTP delimiters)`;
|
|
14499
14528
|
const type = typeof schema.type === "string" ? schema.type : void 0;
|
|
14500
|
-
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type))
|
|
14529
|
+
if (type === void 0 || !PERMITTED_X_MCP_HEADER_TYPES.has(type)) {
|
|
14530
|
+
const fault$1 = `${pathName(path)}: x-mcp-header is only permitted on primitive-typed properties (string, integer, boolean); got ${type ?? "<none>"}`;
|
|
14531
|
+
if (type !== "number") return fault$1;
|
|
14532
|
+
numberFault ??= fault$1;
|
|
14533
|
+
}
|
|
14501
14534
|
const lower = raw.toLowerCase();
|
|
14502
14535
|
const prior = seenLower.get(lower);
|
|
14503
14536
|
if (prior !== void 0) return `x-mcp-header '${raw}' is not case-insensitively unique (also declared as '${prior}')`;
|
|
@@ -14524,12 +14557,17 @@ function scanXMcpHeaderDeclarations(inputSchema) {
|
|
|
14524
14557
|
}
|
|
14525
14558
|
};
|
|
14526
14559
|
const fault = visit(inputSchema, [], true);
|
|
14527
|
-
|
|
14560
|
+
if (fault !== void 0) return {
|
|
14561
|
+
valid: false,
|
|
14562
|
+
reason: numberFault ?? fault
|
|
14563
|
+
};
|
|
14564
|
+
return numberFault === void 0 ? {
|
|
14528
14565
|
valid: true,
|
|
14529
14566
|
declarations
|
|
14530
14567
|
} : {
|
|
14531
14568
|
valid: false,
|
|
14532
|
-
reason:
|
|
14569
|
+
reason: numberFault,
|
|
14570
|
+
declarations
|
|
14533
14571
|
};
|
|
14534
14572
|
}
|
|
14535
14573
|
/**
|
|
@@ -14632,7 +14670,7 @@ function valueAtPath(root, path) {
|
|
|
14632
14670
|
* A sentinel-carrying header whose payload is not canonical Base64 / valid
|
|
14633
14671
|
* UTF-8 is rejected as invalid characters.
|
|
14634
14672
|
*
|
|
14635
|
-
* Integer-typed declarations are compared numerically (the spec's SHOULD —
|
|
14673
|
+
* Integer- and number-typed declarations are compared numerically (the spec's SHOULD —
|
|
14636
14674
|
* `42.0` and `42` are equal); everything else is compared as decoded strings.
|
|
14637
14675
|
*
|
|
14638
14676
|
* Returns `undefined` when every check passes, or an
|
|
@@ -15202,22 +15240,26 @@ function standardSchemaToJsonSchema(schema, io = "input") {
|
|
|
15202
15240
|
...result
|
|
15203
15241
|
};
|
|
15204
15242
|
}
|
|
15243
|
+
const LOCAL_DEFINITION_REF = /^#\/(\$defs|definitions)\/([^/~%]+)$/;
|
|
15205
15244
|
/**
|
|
15206
15245
|
* A typeless JSON Schema root is "provably object-shaped" when either it carries object keywords
|
|
15207
15246
|
* directly (`properties`/`patternProperties`/`additionalProperties`/`required`), or it is a
|
|
15208
15247
|
* composition (`oneOf`/`anyOf`/`allOf`) whose every member is itself `type:'object'` or recursively
|
|
15209
|
-
* provably object-shaped (e.g. a nested `discriminatedUnion`). `$ref` is
|
|
15248
|
+
* provably object-shaped (e.g. a nested `discriminatedUnion`). A `$ref` is followed one hop, to an
|
|
15249
|
+
* entry of the root's `$defs`/`definitions` that is itself `type:'object'`. Used to
|
|
15210
15250
|
* decide whether stamping `type:'object'` is safe (redundant-but-valid) versus self-contradictory.
|
|
15211
15251
|
*/
|
|
15212
|
-
function isProvablyObjectShapedRoot(schema) {
|
|
15252
|
+
function isProvablyObjectShapedRoot(schema, root = schema) {
|
|
15213
15253
|
if ("properties" in schema || "patternProperties" in schema || "additionalProperties" in schema || "required" in schema) return true;
|
|
15254
|
+
const ref = typeof schema.$ref === "string" && LOCAL_DEFINITION_REF.exec(schema.$ref);
|
|
15255
|
+
if (ref && root[ref[1]]?.[ref[2]]?.type === "object") return true;
|
|
15214
15256
|
for (const key of [
|
|
15215
15257
|
"oneOf",
|
|
15216
15258
|
"anyOf",
|
|
15217
15259
|
"allOf"
|
|
15218
15260
|
]) {
|
|
15219
15261
|
const members = schema[key];
|
|
15220
|
-
if (Array.isArray(members) && members.length > 0) return members.every((m) => m !== null && typeof m === "object" && (m.type === "object" || isProvablyObjectShapedRoot(m)));
|
|
15262
|
+
if (Array.isArray(members) && members.length > 0) return members.every((m) => m !== null && typeof m === "object" && (m.type === "object" || isProvablyObjectShapedRoot(m, "$id" in m ? {} : root)));
|
|
15221
15263
|
}
|
|
15222
15264
|
return false;
|
|
15223
15265
|
}
|
|
@@ -17187,7 +17229,7 @@ function normalizeRawShapeSchema(schema) {
|
|
|
17187
17229
|
return schema;
|
|
17188
17230
|
}
|
|
17189
17231
|
//#endregion
|
|
17190
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
17232
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/ajvProvider-DyjnscPj.mjs
|
|
17191
17233
|
var require_code$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
17192
17234
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17193
17235
|
exports.regexpCode = exports.getEsmExportName = exports.getProperty = exports.safeStringify = exports.stringify = exports.strConcat = exports.addCodeArg = exports.str = exports._ = exports.nil = exports._Code = exports.Name = exports.IDENTIFIER = exports._CodeOrName = void 0;
|
|
@@ -19865,6 +19907,28 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
19865
19907
|
const isUUID = RegExp.prototype.test.bind(/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/iu);
|
|
19866
19908
|
/** @type {(value: string) => boolean} */
|
|
19867
19909
|
const isIPv4 = RegExp.prototype.test.bind(/^(?:(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d{2}|[1-9]\d|\d)$/u);
|
|
19910
|
+
/** @type {(value: string) => boolean} */
|
|
19911
|
+
const isPort = RegExp.prototype.test.bind(/^\d*$/u);
|
|
19912
|
+
/** @type {(value: string) => boolean} */
|
|
19913
|
+
const isHexPair = RegExp.prototype.test.bind(/^[\da-f]{2}$/iu);
|
|
19914
|
+
/** @type {(value: string) => boolean} */
|
|
19915
|
+
const isUnreserved = RegExp.prototype.test.bind(/^[\da-z\-._~]$/iu);
|
|
19916
|
+
/** @type {(value: string) => boolean} */
|
|
19917
|
+
const isPathCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/]$/u);
|
|
19918
|
+
/** @type {(value: string) => boolean} */
|
|
19919
|
+
const isQueryFragmentCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:@/?]$/u);
|
|
19920
|
+
/** @type {(value: string) => boolean} */
|
|
19921
|
+
const isUserinfoCharacter = RegExp.prototype.test.bind(/^[A-Za-z0-9\-._~!$&'()*+,;=:]$/u);
|
|
19922
|
+
const BYTE_HEX = new Array(256);
|
|
19923
|
+
{
|
|
19924
|
+
const HEX_DIGITS = "0123456789ABCDEF";
|
|
19925
|
+
for (let i = 0; i < 256; i++) BYTE_HEX[i] = "%" + HEX_DIGITS[i >> 4] + HEX_DIGITS[i & 15];
|
|
19926
|
+
}
|
|
19927
|
+
function percentEncodeNonAscii(cp) {
|
|
19928
|
+
if (cp < 2048) return BYTE_HEX[192 | cp >> 6] + BYTE_HEX[128 | cp & 63];
|
|
19929
|
+
if (cp < 65536) return BYTE_HEX[224 | cp >> 12] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
19930
|
+
return BYTE_HEX[240 | cp >> 18] + BYTE_HEX[128 | cp >> 12 & 63] + BYTE_HEX[128 | cp >> 6 & 63] + BYTE_HEX[128 | cp & 63];
|
|
19931
|
+
}
|
|
19868
19932
|
/**
|
|
19869
19933
|
* @param {Array<string>} input
|
|
19870
19934
|
* @returns {string}
|
|
@@ -19887,119 +19951,162 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
19887
19951
|
}
|
|
19888
19952
|
return acc;
|
|
19889
19953
|
}
|
|
19890
|
-
/**
|
|
19891
|
-
|
|
19892
|
-
|
|
19893
|
-
|
|
19894
|
-
|
|
19895
|
-
|
|
19954
|
+
/** @type {(value: string) => boolean} */
|
|
19955
|
+
const isHextet = RegExp.prototype.test.bind(/^[\dA-Fa-f]{1,4}$/);
|
|
19956
|
+
/** @type {(value: string) => boolean} */
|
|
19957
|
+
const isIPvFuture = RegExp.prototype.test.bind(/^[vV][\dA-Fa-f]+\.[A-Za-z\d\-._~!$&'()*+,;=:]+$/);
|
|
19958
|
+
/** @type {(value: string) => boolean} */
|
|
19959
|
+
const isZoneCharacter = RegExp.prototype.test.bind(/^[A-Za-z\d\-._~]$/);
|
|
19896
19960
|
/**
|
|
19897
19961
|
* @param {string} value
|
|
19898
19962
|
* @returns {boolean}
|
|
19899
19963
|
*/
|
|
19900
19964
|
const nonSimpleDomain = RegExp.prototype.test.bind(/[^!"$&'()*+,\-.;=_`a-z{}~]/u);
|
|
19901
19965
|
/**
|
|
19902
|
-
* @param {
|
|
19966
|
+
* @param {string} zone
|
|
19903
19967
|
* @returns {boolean}
|
|
19904
19968
|
*/
|
|
19905
|
-
function
|
|
19906
|
-
|
|
19969
|
+
function isZoneIdentifier(zone) {
|
|
19970
|
+
if (zone.length === 0) return false;
|
|
19971
|
+
for (let i = 0; i < zone.length; i++) {
|
|
19972
|
+
if (isZoneCharacter(zone[i])) continue;
|
|
19973
|
+
if (zone[i] === "%" && i + 2 < zone.length && isHexPair(zone.slice(i + 1, i + 3))) {
|
|
19974
|
+
i += 2;
|
|
19975
|
+
continue;
|
|
19976
|
+
}
|
|
19977
|
+
return false;
|
|
19978
|
+
}
|
|
19907
19979
|
return true;
|
|
19908
19980
|
}
|
|
19909
19981
|
/**
|
|
19910
|
-
*
|
|
19911
|
-
*
|
|
19912
|
-
*
|
|
19913
|
-
* @
|
|
19982
|
+
* Compresses the longest run of zero hextets to "::" per RFC 5952. A run of a
|
|
19983
|
+
* single zero hextet is left uncompressed. On ties the leftmost run wins.
|
|
19984
|
+
*
|
|
19985
|
+
* @param {string[]} hextets
|
|
19986
|
+
* @returns {string}
|
|
19914
19987
|
*/
|
|
19915
|
-
function
|
|
19916
|
-
|
|
19917
|
-
|
|
19918
|
-
|
|
19919
|
-
|
|
19920
|
-
|
|
19921
|
-
|
|
19988
|
+
function compressIPv6ZeroRun(hextets) {
|
|
19989
|
+
let bestStart = -1;
|
|
19990
|
+
let bestLength = 0;
|
|
19991
|
+
let runStart = -1;
|
|
19992
|
+
let runLength = 0;
|
|
19993
|
+
for (let i = 0; i < hextets.length; i++) if (hextets[i] === "0") {
|
|
19994
|
+
if (runStart === -1) runStart = i;
|
|
19995
|
+
runLength++;
|
|
19996
|
+
if (runLength > bestLength) {
|
|
19997
|
+
bestLength = runLength;
|
|
19998
|
+
bestStart = runStart;
|
|
19922
19999
|
}
|
|
19923
|
-
|
|
20000
|
+
} else {
|
|
20001
|
+
runStart = -1;
|
|
20002
|
+
runLength = 0;
|
|
19924
20003
|
}
|
|
19925
|
-
return
|
|
20004
|
+
if (bestLength < 2) return hextets.join(":");
|
|
20005
|
+
const head = hextets.slice(0, bestStart).join(":");
|
|
20006
|
+
const tail = hextets.slice(bestStart + bestLength).join(":");
|
|
20007
|
+
return head + "::" + tail;
|
|
19926
20008
|
}
|
|
19927
20009
|
/**
|
|
20010
|
+
* Validates an IPv6 address against the alternatives in RFC 3986 section
|
|
20011
|
+
* 3.2.2 and returns the same address with leading hextet zeroes removed.
|
|
20012
|
+
* An embedded IPv4 address counts as two hextets and is only valid at the end.
|
|
20013
|
+
*
|
|
19928
20014
|
* @param {string} input
|
|
19929
|
-
* @returns {
|
|
19930
|
-
*/
|
|
19931
|
-
function
|
|
19932
|
-
|
|
19933
|
-
|
|
19934
|
-
|
|
19935
|
-
|
|
19936
|
-
|
|
19937
|
-
|
|
19938
|
-
|
|
19939
|
-
|
|
19940
|
-
|
|
19941
|
-
|
|
19942
|
-
let
|
|
19943
|
-
|
|
19944
|
-
|
|
19945
|
-
|
|
19946
|
-
|
|
19947
|
-
|
|
19948
|
-
if (cursor === ":") {
|
|
19949
|
-
if (endipv6Encountered === true) endIpv6 = true;
|
|
19950
|
-
if (!consume(buffer, address, output)) break;
|
|
19951
|
-
if (++tokenCount > 7) {
|
|
19952
|
-
output.error = true;
|
|
19953
|
-
break;
|
|
19954
|
-
}
|
|
19955
|
-
if (i > 0 && input[i - 1] === ":") endipv6Encountered = true;
|
|
19956
|
-
address.push(":");
|
|
19957
|
-
continue;
|
|
19958
|
-
} else if (cursor === "%") {
|
|
19959
|
-
if (!consume(buffer, address, output)) break;
|
|
19960
|
-
consume = consumeIsZone;
|
|
19961
|
-
} else {
|
|
19962
|
-
buffer.push(cursor);
|
|
20015
|
+
* @returns {string|undefined}
|
|
20016
|
+
*/
|
|
20017
|
+
function normalizeIPv6Address(input) {
|
|
20018
|
+
const compression = input.indexOf("::");
|
|
20019
|
+
if (compression !== -1 && input.indexOf("::", compression + 1) !== -1) return void 0;
|
|
20020
|
+
const left = compression === -1 ? input.split(":") : input.slice(0, compression).split(":");
|
|
20021
|
+
const right = compression === -1 ? [] : input.slice(compression + 2).split(":");
|
|
20022
|
+
if (compression !== -1) {
|
|
20023
|
+
if (left.length === 1 && left[0] === "") left.length = 0;
|
|
20024
|
+
if (right.length === 1 && right[0] === "") right.length = 0;
|
|
20025
|
+
}
|
|
20026
|
+
const parts = left.concat(right);
|
|
20027
|
+
let hextetCount = 0;
|
|
20028
|
+
for (let i = 0; i < parts.length; i++) {
|
|
20029
|
+
const part = parts[i];
|
|
20030
|
+
if (part === "") return void 0;
|
|
20031
|
+
if (part.indexOf(".") !== -1) {
|
|
20032
|
+
if (i !== parts.length - 1 || compression !== -1 && right.length === 0 || !isIPv4(part)) return void 0;
|
|
20033
|
+
hextetCount += 2;
|
|
19963
20034
|
continue;
|
|
19964
20035
|
}
|
|
20036
|
+
if (!isHextet(part)) return void 0;
|
|
20037
|
+
parts[i] = parseInt(part, 16).toString(16);
|
|
20038
|
+
hextetCount++;
|
|
19965
20039
|
}
|
|
19966
|
-
if (
|
|
19967
|
-
|
|
19968
|
-
|
|
19969
|
-
|
|
19970
|
-
return
|
|
20040
|
+
if (compression === -1) {
|
|
20041
|
+
if (hextetCount !== 8) return void 0;
|
|
20042
|
+
return compressIPv6ZeroRun(parts);
|
|
20043
|
+
}
|
|
20044
|
+
if (hextetCount >= 8) return void 0;
|
|
20045
|
+
const expanded = parts.slice(0, left.length);
|
|
20046
|
+
for (let i = hextetCount; i < 8; i++) expanded.push("0");
|
|
20047
|
+
for (let i = left.length; i < parts.length; i++) expanded.push(parts[i]);
|
|
20048
|
+
return compressIPv6ZeroRun(expanded);
|
|
19971
20049
|
}
|
|
19972
20050
|
/**
|
|
19973
20051
|
* @typedef {Object} NormalizeIPv6Result
|
|
19974
20052
|
* @property {string} host - The normalized host.
|
|
19975
20053
|
* @property {string} [escapedHost] - The escaped host.
|
|
19976
20054
|
* @property {boolean} isIPV6 - Indicates if the host is an IPv6 address.
|
|
20055
|
+
* @property {boolean} [isIPVFuture] - Indicates if the host is an IPvFuture literal.
|
|
20056
|
+
* @property {boolean} [error] - Indicates if a bracketed IP literal is malformed.
|
|
19977
20057
|
*/
|
|
19978
20058
|
/**
|
|
20059
|
+
* Validates and normalizes a bracketed IP literal. Raw zone separators remain
|
|
20060
|
+
* accepted for backwards compatibility, while encoded separators and zone
|
|
20061
|
+
* contents follow RFC 6874.
|
|
20062
|
+
*
|
|
19979
20063
|
* @param {string} host
|
|
19980
20064
|
* @returns {NormalizeIPv6Result}
|
|
19981
20065
|
*/
|
|
19982
20066
|
function normalizeIPv6(host) {
|
|
19983
|
-
|
|
20067
|
+
const bracketed = host[0] === "[" && host[host.length - 1] === "]";
|
|
20068
|
+
if ((host[0] === "[" || host[host.length - 1] === "]") && !bracketed) return {
|
|
19984
20069
|
host,
|
|
19985
|
-
isIPV6: false
|
|
20070
|
+
isIPV6: false,
|
|
20071
|
+
error: true
|
|
19986
20072
|
};
|
|
19987
|
-
|
|
19988
|
-
if (
|
|
19989
|
-
|
|
19990
|
-
let escapedHost = ipv6.address;
|
|
19991
|
-
if (ipv6.zone) {
|
|
19992
|
-
newHost += "%" + ipv6.zone;
|
|
19993
|
-
escapedHost += "%25" + ipv6.zone;
|
|
19994
|
-
}
|
|
20073
|
+
let input = bracketed ? host.slice(1, -1) : host;
|
|
20074
|
+
if (bracketed && isIPvFuture(input)) {
|
|
20075
|
+
input = input.toLowerCase();
|
|
19995
20076
|
return {
|
|
19996
|
-
host:
|
|
19997
|
-
|
|
19998
|
-
|
|
20077
|
+
host: `[${input}]`,
|
|
20078
|
+
escapedHost: input,
|
|
20079
|
+
isIPV6: false,
|
|
20080
|
+
isIPVFuture: true
|
|
20081
|
+
};
|
|
20082
|
+
}
|
|
20083
|
+
if (findToken(input, ":") < 2) return {
|
|
20084
|
+
host,
|
|
20085
|
+
isIPV6: false,
|
|
20086
|
+
error: bracketed
|
|
20087
|
+
};
|
|
20088
|
+
let zoneIdentifier = "";
|
|
20089
|
+
const zoneSeparator = input.indexOf("%");
|
|
20090
|
+
if (zoneSeparator !== -1) {
|
|
20091
|
+
const separatorLength = input.slice(zoneSeparator, zoneSeparator + 3).toLowerCase() === "%25" ? 3 : 1;
|
|
20092
|
+
zoneIdentifier = input.slice(zoneSeparator + separatorLength);
|
|
20093
|
+
if (!isZoneIdentifier(zoneIdentifier)) return {
|
|
20094
|
+
host,
|
|
20095
|
+
isIPV6: false,
|
|
20096
|
+
error: true
|
|
19999
20097
|
};
|
|
20000
|
-
|
|
20098
|
+
input = input.slice(0, zoneSeparator);
|
|
20099
|
+
}
|
|
20100
|
+
const address = normalizeIPv6Address(input);
|
|
20101
|
+
if (address === void 0) return {
|
|
20001
20102
|
host,
|
|
20002
|
-
isIPV6: false
|
|
20103
|
+
isIPV6: false,
|
|
20104
|
+
error: true
|
|
20105
|
+
};
|
|
20106
|
+
return {
|
|
20107
|
+
host: address + (zoneIdentifier ? "%" + zoneIdentifier : ""),
|
|
20108
|
+
escapedHost: address + (zoneIdentifier ? "%25" + zoneIdentifier : ""),
|
|
20109
|
+
isIPV6: true
|
|
20003
20110
|
};
|
|
20004
20111
|
}
|
|
20005
20112
|
/**
|
|
@@ -20087,19 +20194,264 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20087
20194
|
return output.join("");
|
|
20088
20195
|
}
|
|
20089
20196
|
/**
|
|
20090
|
-
*
|
|
20091
|
-
*
|
|
20092
|
-
*
|
|
20197
|
+
* Re-escape RFC 3986 gen-delims that must not appear literally in the host.
|
|
20198
|
+
* After the URI regex parses, these characters cannot be literal in the host
|
|
20199
|
+
* field, so any that appear after decoding came from percent-encoding and
|
|
20200
|
+
* must be restored to prevent authority structure changes.
|
|
20201
|
+
*
|
|
20202
|
+
* @param {string} host
|
|
20203
|
+
* @param {boolean} isIP - true for IPv4/IPv6 hosts (skip colon re-escaping)
|
|
20204
|
+
* @returns {string}
|
|
20093
20205
|
*/
|
|
20094
|
-
|
|
20095
|
-
|
|
20096
|
-
|
|
20097
|
-
|
|
20098
|
-
|
|
20099
|
-
|
|
20100
|
-
|
|
20101
|
-
|
|
20102
|
-
|
|
20206
|
+
const HOST_DELIMS = {
|
|
20207
|
+
"@": "%40",
|
|
20208
|
+
"/": "%2F",
|
|
20209
|
+
"?": "%3F",
|
|
20210
|
+
"#": "%23",
|
|
20211
|
+
":": "%3A"
|
|
20212
|
+
};
|
|
20213
|
+
const HOST_DELIM_RE = /[@/?#:]/g;
|
|
20214
|
+
const HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
|
|
20215
|
+
function reescapeHostDelimiters(host, isIP) {
|
|
20216
|
+
const re = isIP ? HOST_DELIM_NO_COLON_RE : HOST_DELIM_RE;
|
|
20217
|
+
re.lastIndex = 0;
|
|
20218
|
+
return host.replace(re, (ch) => HOST_DELIMS[ch]);
|
|
20219
|
+
}
|
|
20220
|
+
/**
|
|
20221
|
+
* Normalizes percent escapes and optionally decodes only unreserved ASCII bytes.
|
|
20222
|
+
* Reserved delimiters such as `%2F` stay escaped; `%2E` is unreserved.
|
|
20223
|
+
*
|
|
20224
|
+
* @param {string} input
|
|
20225
|
+
* @param {boolean} [decodeUnreserved=false]
|
|
20226
|
+
* @returns {string}
|
|
20227
|
+
*/
|
|
20228
|
+
function normalizePercentEncoding(input, decodeUnreserved = false) {
|
|
20229
|
+
if (input.indexOf("%") === -1) return input;
|
|
20230
|
+
let output = "";
|
|
20231
|
+
for (let i = 0; i < input.length; i++) {
|
|
20232
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
20233
|
+
const hex = input.slice(i + 1, i + 3);
|
|
20234
|
+
if (isHexPair(hex)) {
|
|
20235
|
+
const normalizedHex = hex.toUpperCase();
|
|
20236
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
20237
|
+
if (decodeUnreserved && isUnreserved(decoded)) output += decoded;
|
|
20238
|
+
else output += "%" + normalizedHex;
|
|
20239
|
+
i += 2;
|
|
20240
|
+
continue;
|
|
20241
|
+
}
|
|
20242
|
+
}
|
|
20243
|
+
output += input[i];
|
|
20244
|
+
}
|
|
20245
|
+
return output;
|
|
20246
|
+
}
|
|
20247
|
+
/**
|
|
20248
|
+
* Normalizes path data without turning reserved escapes into live path syntax.
|
|
20249
|
+
* Valid escapes are uppercased, raw unsafe characters are escaped, and only
|
|
20250
|
+
* unreserved bytes that are not `.` are decoded.
|
|
20251
|
+
*
|
|
20252
|
+
* @param {string} input
|
|
20253
|
+
* @returns {string}
|
|
20254
|
+
*/
|
|
20255
|
+
function normalizePathEncoding(input) {
|
|
20256
|
+
let output = "";
|
|
20257
|
+
for (let i = 0; i < input.length; i++) {
|
|
20258
|
+
const ch = input[i];
|
|
20259
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
20260
|
+
const hex = input.slice(i + 1, i + 3);
|
|
20261
|
+
if (isHexPair(hex)) {
|
|
20262
|
+
const normalizedHex = hex.toUpperCase();
|
|
20263
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
20264
|
+
if (decoded !== "." && isUnreserved(decoded)) output += decoded;
|
|
20265
|
+
else output += "%" + normalizedHex;
|
|
20266
|
+
i += 2;
|
|
20267
|
+
continue;
|
|
20268
|
+
}
|
|
20269
|
+
}
|
|
20270
|
+
if (isPathCharacter(ch)) output += ch;
|
|
20271
|
+
else {
|
|
20272
|
+
const code = input.charCodeAt(i);
|
|
20273
|
+
if (code < 128) output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
20274
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
20275
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
20276
|
+
const low = input.charCodeAt(i + 1);
|
|
20277
|
+
if (low >= 56320 && low <= 57343) {
|
|
20278
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
20279
|
+
i++;
|
|
20280
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20281
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20282
|
+
}
|
|
20283
|
+
}
|
|
20284
|
+
return output;
|
|
20285
|
+
}
|
|
20286
|
+
/**
|
|
20287
|
+
* Serializes a path without rewriting reserved data. Raw RFC 3986 path
|
|
20288
|
+
* characters remain literal, valid escapes are preserved and uppercased, and
|
|
20289
|
+
* everything else is UTF-8 percent-encoded. In a path-noscheme, a colon in the
|
|
20290
|
+
* first segment must be escaped so the result cannot be parsed as a scheme.
|
|
20291
|
+
*
|
|
20292
|
+
* @param {string} input
|
|
20293
|
+
* @param {boolean} [pathNoScheme=false]
|
|
20294
|
+
* @returns {string}
|
|
20295
|
+
*/
|
|
20296
|
+
function serializePathEncoding(input, pathNoScheme = false) {
|
|
20297
|
+
let output = "";
|
|
20298
|
+
let firstSegment = pathNoScheme && input[0] !== "/";
|
|
20299
|
+
for (let i = 0; i < input.length; i++) {
|
|
20300
|
+
const ch = input[i];
|
|
20301
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
20302
|
+
const hex = input.slice(i + 1, i + 3);
|
|
20303
|
+
if (isHexPair(hex)) {
|
|
20304
|
+
output += "%" + hex.toUpperCase();
|
|
20305
|
+
i += 2;
|
|
20306
|
+
continue;
|
|
20307
|
+
}
|
|
20308
|
+
}
|
|
20309
|
+
if (ch === "/") firstSegment = false;
|
|
20310
|
+
if (isPathCharacter(ch) && (ch !== ":" || !firstSegment)) output += ch;
|
|
20311
|
+
else {
|
|
20312
|
+
const code = input.charCodeAt(i);
|
|
20313
|
+
if (code < 128) output += BYTE_HEX[code];
|
|
20314
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
20315
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
20316
|
+
const low = input.charCodeAt(i + 1);
|
|
20317
|
+
if (low >= 56320 && low <= 57343) {
|
|
20318
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
20319
|
+
i++;
|
|
20320
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20321
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20322
|
+
}
|
|
20323
|
+
}
|
|
20324
|
+
return output;
|
|
20325
|
+
}
|
|
20326
|
+
/**
|
|
20327
|
+
* Percent-encodes a URI component using its RFC 3986 literal character set.
|
|
20328
|
+
* Existing valid escapes are preserved and normalized to uppercase hex.
|
|
20329
|
+
*
|
|
20330
|
+
* @param {string} input
|
|
20331
|
+
* @param {(value: string) => boolean} isAllowed
|
|
20332
|
+
* @returns {string}
|
|
20333
|
+
*/
|
|
20334
|
+
function encodeComponent(input, isAllowed) {
|
|
20335
|
+
let output = "";
|
|
20336
|
+
for (let i = 0; i < input.length; i++) {
|
|
20337
|
+
const ch = input[i];
|
|
20338
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
20339
|
+
const hex = input.slice(i + 1, i + 3);
|
|
20340
|
+
if (isHexPair(hex)) {
|
|
20341
|
+
output += "%" + hex.toUpperCase();
|
|
20342
|
+
i += 2;
|
|
20343
|
+
continue;
|
|
20344
|
+
}
|
|
20345
|
+
}
|
|
20346
|
+
if (isAllowed(ch)) output += ch;
|
|
20347
|
+
else {
|
|
20348
|
+
const code = input.charCodeAt(i);
|
|
20349
|
+
if (code < 128) output += BYTE_HEX[code];
|
|
20350
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
20351
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
20352
|
+
const low = input.charCodeAt(i + 1);
|
|
20353
|
+
if (low >= 56320 && low <= 57343) {
|
|
20354
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
20355
|
+
i++;
|
|
20356
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20357
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20358
|
+
}
|
|
20359
|
+
}
|
|
20360
|
+
return output;
|
|
20361
|
+
}
|
|
20362
|
+
/**
|
|
20363
|
+
* Encodes userinfo while preserving its RFC 3986 §3.2.1 literal characters.
|
|
20364
|
+
* In particular, authority delimiters such as `@`, `/`, `?`, and `#` are data.
|
|
20365
|
+
*
|
|
20366
|
+
* @param {string} input
|
|
20367
|
+
* @returns {string}
|
|
20368
|
+
*/
|
|
20369
|
+
function encodeUserinfo(input) {
|
|
20370
|
+
return encodeComponent(input, isUserinfoCharacter);
|
|
20371
|
+
}
|
|
20372
|
+
/**
|
|
20373
|
+
* Encodes query data using the RFC 3986 §3.4 grammar. A literal `#` must be
|
|
20374
|
+
* escaped because it would otherwise begin the fragment component.
|
|
20375
|
+
*
|
|
20376
|
+
* @param {string} input
|
|
20377
|
+
* @returns {string}
|
|
20378
|
+
*/
|
|
20379
|
+
function encodeQuery(input) {
|
|
20380
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
20381
|
+
}
|
|
20382
|
+
/**
|
|
20383
|
+
* Encodes fragment data using the RFC 3986 §3.5 grammar.
|
|
20384
|
+
*
|
|
20385
|
+
* @param {string} input
|
|
20386
|
+
* @returns {string}
|
|
20387
|
+
*/
|
|
20388
|
+
function encodeFragment(input) {
|
|
20389
|
+
return encodeComponent(input, isQueryFragmentCharacter);
|
|
20390
|
+
}
|
|
20391
|
+
function isEscapeSafe(cp) {
|
|
20392
|
+
return cp >= 48 && cp <= 57 || cp >= 65 && cp <= 90 || cp >= 97 && cp <= 122 || cp === 42 || cp === 43 || cp === 45 || cp === 46 || cp === 47 || cp === 64 || cp === 95;
|
|
20393
|
+
}
|
|
20394
|
+
/**
|
|
20395
|
+
* Normalizes the percent-encoding of a query or fragment component.
|
|
20396
|
+
*
|
|
20397
|
+
* Like `normalizePathEncoding`, but uses the query/fragment character set
|
|
20398
|
+
* (which additionally allows `?`) and decodes `.` since it has no dot-segment
|
|
20399
|
+
* meaning outside of a path.
|
|
20400
|
+
*
|
|
20401
|
+
* @param {string} input
|
|
20402
|
+
* @returns {string}
|
|
20403
|
+
*/
|
|
20404
|
+
function normalizeQueryFragmentEncoding(input) {
|
|
20405
|
+
let output = "";
|
|
20406
|
+
for (let i = 0; i < input.length; i++) {
|
|
20407
|
+
const ch = input[i];
|
|
20408
|
+
if (ch === "%" && i + 2 < input.length) {
|
|
20409
|
+
const hex = input.slice(i + 1, i + 3);
|
|
20410
|
+
if (isHexPair(hex)) {
|
|
20411
|
+
const normalizedHex = hex.toUpperCase();
|
|
20412
|
+
const decoded = String.fromCharCode(parseInt(normalizedHex, 16));
|
|
20413
|
+
if (isUnreserved(decoded)) output += decoded;
|
|
20414
|
+
else output += "%" + normalizedHex;
|
|
20415
|
+
i += 2;
|
|
20416
|
+
continue;
|
|
20417
|
+
}
|
|
20418
|
+
}
|
|
20419
|
+
if (isQueryFragmentCharacter(ch)) output += ch;
|
|
20420
|
+
else {
|
|
20421
|
+
const code = input.charCodeAt(i);
|
|
20422
|
+
if (code < 128) output += isEscapeSafe(code) ? ch : BYTE_HEX[code];
|
|
20423
|
+
else if (code < 55296 || code > 57343) output += percentEncodeNonAscii(code);
|
|
20424
|
+
else if (code <= 56319 && i + 1 < input.length) {
|
|
20425
|
+
const low = input.charCodeAt(i + 1);
|
|
20426
|
+
if (low >= 56320 && low <= 57343) {
|
|
20427
|
+
output += percentEncodeNonAscii(65536 + (code - 55296 << 10) + (low - 56320));
|
|
20428
|
+
i++;
|
|
20429
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20430
|
+
} else output += percentEncodeNonAscii(65533);
|
|
20431
|
+
}
|
|
20432
|
+
}
|
|
20433
|
+
return output;
|
|
20434
|
+
}
|
|
20435
|
+
/**
|
|
20436
|
+
* Escapes a component while preserving existing valid percent escapes.
|
|
20437
|
+
*
|
|
20438
|
+
* @param {string} input
|
|
20439
|
+
* @returns {string}
|
|
20440
|
+
*/
|
|
20441
|
+
function escapePreservingEscapes(input) {
|
|
20442
|
+
let output = "";
|
|
20443
|
+
for (let i = 0; i < input.length; i++) {
|
|
20444
|
+
if (input[i] === "%" && i + 2 < input.length) {
|
|
20445
|
+
const hex = input.slice(i + 1, i + 3);
|
|
20446
|
+
if (isHexPair(hex)) {
|
|
20447
|
+
output += "%" + hex.toUpperCase();
|
|
20448
|
+
i += 2;
|
|
20449
|
+
continue;
|
|
20450
|
+
}
|
|
20451
|
+
}
|
|
20452
|
+
output += escape(input[i]);
|
|
20453
|
+
}
|
|
20454
|
+
return output;
|
|
20103
20455
|
}
|
|
20104
20456
|
/**
|
|
20105
20457
|
* @param {import('../types/index').URIComponent} component
|
|
@@ -20108,28 +20460,42 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20108
20460
|
function recomposeAuthority(component) {
|
|
20109
20461
|
const uriTokens = [];
|
|
20110
20462
|
if (component.userinfo !== void 0) {
|
|
20111
|
-
uriTokens.push(component.userinfo);
|
|
20463
|
+
uriTokens.push(encodeUserinfo(component.userinfo));
|
|
20112
20464
|
uriTokens.push("@");
|
|
20113
20465
|
}
|
|
20114
20466
|
if (component.host !== void 0) {
|
|
20115
|
-
let host =
|
|
20467
|
+
let host = component.host;
|
|
20116
20468
|
if (!isIPv4(host)) {
|
|
20117
|
-
|
|
20118
|
-
if (ipV6res.isIPV6
|
|
20119
|
-
|
|
20469
|
+
let ipV6res = normalizeIPv6(host);
|
|
20470
|
+
if (ipV6res.isIPV6 !== true && ipV6res.isIPVFuture !== true) {
|
|
20471
|
+
host = normalizePercentEncoding(host, true);
|
|
20472
|
+
ipV6res = normalizeIPv6(host);
|
|
20473
|
+
}
|
|
20474
|
+
if (ipV6res.isIPV6 === true || ipV6res.isIPVFuture === true) host = `[${ipV6res.escapedHost}]`;
|
|
20475
|
+
else host = reescapeHostDelimiters(host, false);
|
|
20120
20476
|
}
|
|
20121
20477
|
uriTokens.push(host);
|
|
20122
20478
|
}
|
|
20123
20479
|
if (typeof component.port === "number" || typeof component.port === "string") {
|
|
20480
|
+
const port = String(component.port);
|
|
20481
|
+
if (!isPort(port)) throw new TypeError("URI port is malformed.");
|
|
20124
20482
|
uriTokens.push(":");
|
|
20125
|
-
uriTokens.push(
|
|
20483
|
+
uriTokens.push(port);
|
|
20126
20484
|
}
|
|
20127
20485
|
return uriTokens.length ? uriTokens.join("") : void 0;
|
|
20128
20486
|
}
|
|
20129
20487
|
module.exports = {
|
|
20130
20488
|
nonSimpleDomain,
|
|
20131
20489
|
recomposeAuthority,
|
|
20132
|
-
|
|
20490
|
+
reescapeHostDelimiters,
|
|
20491
|
+
normalizePercentEncoding,
|
|
20492
|
+
normalizePathEncoding,
|
|
20493
|
+
serializePathEncoding,
|
|
20494
|
+
normalizeQueryFragmentEncoding,
|
|
20495
|
+
encodeUserinfo,
|
|
20496
|
+
encodeQuery,
|
|
20497
|
+
encodeFragment,
|
|
20498
|
+
escapePreservingEscapes,
|
|
20133
20499
|
removeDotSegments,
|
|
20134
20500
|
isIPv4,
|
|
20135
20501
|
isUUID,
|
|
@@ -20139,7 +20505,7 @@ var require_utils = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20139
20505
|
}));
|
|
20140
20506
|
var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
20141
20507
|
const { isUUID } = require_utils();
|
|
20142
|
-
const URN_REG =
|
|
20508
|
+
const URN_REG = /^([\da-z][\d\-a-z]{0,31}):((?:[\w!$'()*+,\-./:;=@]|%[\da-f]{2})+)$/iu;
|
|
20143
20509
|
const supportedSchemeNames = [
|
|
20144
20510
|
"http",
|
|
20145
20511
|
"https",
|
|
@@ -20210,9 +20576,10 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20210
20576
|
wsComponent.secure = void 0;
|
|
20211
20577
|
}
|
|
20212
20578
|
if (wsComponent.resourceName) {
|
|
20213
|
-
const
|
|
20579
|
+
const queryIndex = wsComponent.resourceName.indexOf("?");
|
|
20580
|
+
const path = queryIndex === -1 ? wsComponent.resourceName : wsComponent.resourceName.slice(0, queryIndex);
|
|
20214
20581
|
wsComponent.path = path && path !== "/" ? path : void 0;
|
|
20215
|
-
wsComponent.query =
|
|
20582
|
+
wsComponent.query = queryIndex === -1 ? void 0 : wsComponent.resourceName.slice(queryIndex + 1);
|
|
20216
20583
|
wsComponent.resourceName = void 0;
|
|
20217
20584
|
}
|
|
20218
20585
|
wsComponent.fragment = void 0;
|
|
@@ -20225,7 +20592,7 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20225
20592
|
return urnComponent;
|
|
20226
20593
|
}
|
|
20227
20594
|
const matches = urnComponent.path.match(URN_REG);
|
|
20228
|
-
if (matches) {
|
|
20595
|
+
if (matches && matches[0] === urnComponent.path) {
|
|
20229
20596
|
const scheme = options.scheme || urnComponent.scheme || "urn";
|
|
20230
20597
|
urnComponent.nid = matches[1].toLowerCase();
|
|
20231
20598
|
urnComponent.nss = matches[2];
|
|
@@ -20319,8 +20686,19 @@ var require_schemes = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20319
20686
|
};
|
|
20320
20687
|
}));
|
|
20321
20688
|
var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
20322
|
-
const { normalizeIPv6, removeDotSegments, recomposeAuthority,
|
|
20689
|
+
const { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils();
|
|
20323
20690
|
const { SCHEMES, getSchemeHandler } = require_schemes();
|
|
20691
|
+
const VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
|
|
20692
|
+
const MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
|
|
20693
|
+
/**
|
|
20694
|
+
* @param {string} scheme
|
|
20695
|
+
* @returns {string}
|
|
20696
|
+
*/
|
|
20697
|
+
function decodeValidScheme(scheme) {
|
|
20698
|
+
const decodedScheme = unescape(String(scheme));
|
|
20699
|
+
if (!VALID_SCHEME.test(decodedScheme)) throw new TypeError(MALFORMED_SCHEME_ERROR);
|
|
20700
|
+
return decodedScheme;
|
|
20701
|
+
}
|
|
20324
20702
|
/**
|
|
20325
20703
|
* @template {import('./types/index').URIComponent|string} T
|
|
20326
20704
|
* @param {T} uri
|
|
@@ -20328,7 +20706,7 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20328
20706
|
* @returns {T}
|
|
20329
20707
|
*/
|
|
20330
20708
|
function normalize(uri, options) {
|
|
20331
|
-
if (typeof uri === "string") uri =
|
|
20709
|
+
if (typeof uri === "string") uri = normalizeString(uri, options);
|
|
20332
20710
|
else if (typeof uri === "object") uri = parse(serialize(uri, options), options);
|
|
20333
20711
|
return uri;
|
|
20334
20712
|
}
|
|
@@ -20340,7 +20718,16 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20340
20718
|
*/
|
|
20341
20719
|
function resolve(baseURI, relativeURI, options) {
|
|
20342
20720
|
const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
|
|
20343
|
-
const
|
|
20721
|
+
const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed, malformedPercentEncoding: baseMalformedPercentEncoding, malformedSchemeSpecific: baseMalformedSchemeSpecific, malformedHost: baseMalformedHost, malformedScheme: baseMalformedScheme } = parseWithStatus(baseURI, schemelessOptions);
|
|
20722
|
+
const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed, malformedPercentEncoding: relativeMalformedPercentEncoding, malformedSchemeSpecific: relativeMalformedSchemeSpecific, malformedHost: relativeMalformedHost, malformedScheme: relativeMalformedScheme } = parseWithStatus(relativeURI, schemelessOptions);
|
|
20723
|
+
if (baseMalformed || relativeMalformed || baseMalformedPercentEncoding || relativeMalformedPercentEncoding || baseMalformedSchemeSpecific || relativeMalformedSchemeSpecific || baseMalformedHost || relativeMalformedHost || baseMalformedScheme || relativeMalformedScheme) throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
|
|
20724
|
+
const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
|
|
20725
|
+
const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
|
|
20726
|
+
const resolvedHost = resolved.host;
|
|
20727
|
+
const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
|
|
20728
|
+
canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
|
|
20729
|
+
const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !/\P{ASCII}/u.test(resolvedHost);
|
|
20730
|
+
if (resolved.error && !encodedASCIIHost) throw new Error(resolved.error);
|
|
20344
20731
|
schemelessOptions.skipEscape = true;
|
|
20345
20732
|
return serialize(resolved, schemelessOptions);
|
|
20346
20733
|
}
|
|
@@ -20404,27 +20791,9 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20404
20791
|
* @returns {boolean}
|
|
20405
20792
|
*/
|
|
20406
20793
|
function equal(uriA, uriB, options) {
|
|
20407
|
-
|
|
20408
|
-
|
|
20409
|
-
|
|
20410
|
-
...options,
|
|
20411
|
-
skipEscape: true
|
|
20412
|
-
});
|
|
20413
|
-
} else if (typeof uriA === "object") uriA = serialize(normalizeComponentEncoding(uriA, true), {
|
|
20414
|
-
...options,
|
|
20415
|
-
skipEscape: true
|
|
20416
|
-
});
|
|
20417
|
-
if (typeof uriB === "string") {
|
|
20418
|
-
uriB = unescape(uriB);
|
|
20419
|
-
uriB = serialize(normalizeComponentEncoding(parse(uriB, options), true), {
|
|
20420
|
-
...options,
|
|
20421
|
-
skipEscape: true
|
|
20422
|
-
});
|
|
20423
|
-
} else if (typeof uriB === "object") uriB = serialize(normalizeComponentEncoding(uriB, true), {
|
|
20424
|
-
...options,
|
|
20425
|
-
skipEscape: true
|
|
20426
|
-
});
|
|
20427
|
-
return uriA.toLowerCase() === uriB.toLowerCase();
|
|
20794
|
+
const normalizedA = normalizeComparableURI(uriA, options);
|
|
20795
|
+
const normalizedB = normalizeComparableURI(uriB, options);
|
|
20796
|
+
return normalizedA !== void 0 && normalizedB !== void 0 && normalizedA === normalizedB;
|
|
20428
20797
|
}
|
|
20429
20798
|
/**
|
|
20430
20799
|
* @param {Readonly<import('./types/index').URIComponent>} cmpts
|
|
@@ -20450,13 +20819,17 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20450
20819
|
};
|
|
20451
20820
|
const options = Object.assign({}, opts);
|
|
20452
20821
|
const uriTokens = [];
|
|
20822
|
+
if (component.scheme) component.scheme = decodeValidScheme(component.scheme);
|
|
20453
20823
|
const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
|
|
20454
20824
|
if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
|
|
20455
|
-
|
|
20456
|
-
|
|
20457
|
-
|
|
20458
|
-
|
|
20459
|
-
if (options.reference !== "suffix" && component.scheme)
|
|
20825
|
+
const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
|
|
20826
|
+
const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
|
|
20827
|
+
if (component.path !== void 0) if (!options.skipEscape) component.path = serializePathEncoding(component.path, pathNoScheme);
|
|
20828
|
+
else component.path = normalizePercentEncoding(component.path);
|
|
20829
|
+
if (options.reference !== "suffix" && component.scheme) {
|
|
20830
|
+
component.scheme = decodeValidScheme(component.scheme);
|
|
20831
|
+
uriTokens.push(component.scheme, ":");
|
|
20832
|
+
}
|
|
20460
20833
|
const authority = recomposeAuthority(component);
|
|
20461
20834
|
if (authority !== void 0) {
|
|
20462
20835
|
if (options.reference !== "suffix") uriTokens.push("//");
|
|
@@ -20466,20 +20839,84 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20466
20839
|
if (component.path !== void 0) {
|
|
20467
20840
|
let s = component.path;
|
|
20468
20841
|
if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) s = removeDotSegments(s);
|
|
20842
|
+
if (pathNoScheme) s = serializePathEncoding(s, true);
|
|
20469
20843
|
if (authority === void 0 && s[0] === "/" && s[1] === "/") s = "/%2F" + s.slice(2);
|
|
20470
20844
|
uriTokens.push(s);
|
|
20471
20845
|
}
|
|
20472
|
-
if (component.query !== void 0) uriTokens.push("?", component.query);
|
|
20473
|
-
if (component.fragment !== void 0) uriTokens.push("#", component.fragment);
|
|
20846
|
+
if (component.query !== void 0) uriTokens.push("?", encodeQuery(component.query));
|
|
20847
|
+
if (component.fragment !== void 0) uriTokens.push("#", encodeFragment(component.fragment));
|
|
20474
20848
|
return uriTokens.join("");
|
|
20475
20849
|
}
|
|
20476
20850
|
const URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
|
|
20851
|
+
const AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
|
|
20852
|
+
const AUTHORITY_INTRODUCER_REGION = /^(?:[^#/:?]+:)?([/\\\t\n\r]*)/;
|
|
20853
|
+
/**
|
|
20854
|
+
* @param {import('./types/index').URIComponent} parsed
|
|
20855
|
+
* @param {RegExpMatchArray} matches
|
|
20856
|
+
* @returns {string|undefined}
|
|
20857
|
+
*/
|
|
20858
|
+
function getParseError(parsed, matches) {
|
|
20859
|
+
if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") return "URI path must start with \"/\" when authority is present.";
|
|
20860
|
+
if (typeof parsed.port === "number" && (parsed.port < 0 || parsed.port > 65535)) return "URI port is malformed.";
|
|
20861
|
+
}
|
|
20862
|
+
/**
|
|
20863
|
+
* Checks percent syntax without decoding the represented octets. RFC 3986
|
|
20864
|
+
* percent-encoding is byte-oriented, so sequences such as `%FF` are valid even
|
|
20865
|
+
* though they are not independently valid UTF-8.
|
|
20866
|
+
*
|
|
20867
|
+
* @param {string|undefined} component
|
|
20868
|
+
* @returns {boolean}
|
|
20869
|
+
*/
|
|
20870
|
+
function hasMalformedPercentEncoding(component) {
|
|
20871
|
+
if (component === void 0) return false;
|
|
20872
|
+
let percent = component.indexOf("%");
|
|
20873
|
+
while (percent !== -1) {
|
|
20874
|
+
if (percent + 2 >= component.length || !/^[\da-f]{2}$/iu.test(component.slice(percent + 1, percent + 3))) return true;
|
|
20875
|
+
percent = component.indexOf("%", percent + 3);
|
|
20876
|
+
}
|
|
20877
|
+
return false;
|
|
20878
|
+
}
|
|
20879
|
+
/**
|
|
20880
|
+
* Whether the host is a bracketed IP literal (RFC 3986 `IP-literal`).
|
|
20881
|
+
* An unterminated `[` is not a literal, so it must still be validated as a
|
|
20882
|
+
* reg-name instead of being waved through as an IP.
|
|
20883
|
+
*
|
|
20884
|
+
* @param {string} host
|
|
20885
|
+
* @returns {boolean}
|
|
20886
|
+
*/
|
|
20887
|
+
function isIPLiteral(host) {
|
|
20888
|
+
return host[0] === "[" && host[host.length - 1] === "]";
|
|
20889
|
+
}
|
|
20890
|
+
/**
|
|
20891
|
+
* @param {RegExpMatchArray} matches
|
|
20892
|
+
* @returns {boolean}
|
|
20893
|
+
*/
|
|
20894
|
+
function hasMalformedComponentPercentEncoding(matches) {
|
|
20895
|
+
const host = matches[4];
|
|
20896
|
+
return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
|
|
20897
|
+
}
|
|
20898
|
+
/**
|
|
20899
|
+
* @param {import('./types/index').URIComponent} parsed
|
|
20900
|
+
* @param {import('./types/index').Options} options
|
|
20901
|
+
* @param {{ domainHost?: boolean, unicodeSupport?: boolean }|undefined} schemeHandler
|
|
20902
|
+
* @param {boolean} isIP
|
|
20903
|
+
* @returns {boolean} whether host conversion failed
|
|
20904
|
+
*/
|
|
20905
|
+
function canonicalizeHost(parsed, options, schemeHandler, isIP) {
|
|
20906
|
+
if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) try {
|
|
20907
|
+
parsed.host = new URL("http://" + parsed.host).hostname;
|
|
20908
|
+
} catch (e) {
|
|
20909
|
+
parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
|
|
20910
|
+
return true;
|
|
20911
|
+
}
|
|
20912
|
+
return false;
|
|
20913
|
+
}
|
|
20477
20914
|
/**
|
|
20478
20915
|
* @param {string} uri
|
|
20479
20916
|
* @param {import('./types/index').Options} [opts]
|
|
20480
|
-
* @returns
|
|
20917
|
+
* @returns {{ parsed: import('./types/index').URIComponent, malformedAuthorityOrPort: boolean, malformedPercentEncoding: boolean, malformedSchemeSpecific: boolean, malformedHost: boolean, malformedScheme: boolean }}
|
|
20481
20918
|
*/
|
|
20482
|
-
function
|
|
20919
|
+
function parseWithStatus(uri, opts) {
|
|
20483
20920
|
const options = Object.assign({}, opts);
|
|
20484
20921
|
/** @type {import('./types/index').URIComponent} */
|
|
20485
20922
|
const parsed = {
|
|
@@ -20491,9 +20928,34 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20491
20928
|
query: void 0,
|
|
20492
20929
|
fragment: void 0
|
|
20493
20930
|
};
|
|
20931
|
+
let malformedAuthorityOrPort = false;
|
|
20932
|
+
let malformedPercentEncoding = false;
|
|
20933
|
+
let malformedSchemeSpecific = false;
|
|
20934
|
+
let malformedHost = false;
|
|
20935
|
+
let malformedIPLiteral = false;
|
|
20936
|
+
let malformedScheme = false;
|
|
20494
20937
|
let isIP = false;
|
|
20495
20938
|
if (options.reference === "suffix") if (options.scheme) uri = options.scheme + ":" + uri;
|
|
20496
20939
|
else uri = "//" + uri;
|
|
20940
|
+
const authorityMatch = uri.match(AUTHORITY_PREFIX);
|
|
20941
|
+
if (authorityMatch !== null && authorityMatch[1].indexOf("\\") !== -1) {
|
|
20942
|
+
parsed.error = "URI authority must not contain a literal backslash.";
|
|
20943
|
+
malformedAuthorityOrPort = true;
|
|
20944
|
+
}
|
|
20945
|
+
const introducerMatch = uri.match(AUTHORITY_INTRODUCER_REGION);
|
|
20946
|
+
if (introducerMatch !== null) {
|
|
20947
|
+
const region = introducerMatch[1];
|
|
20948
|
+
const normalizedRegion = region.replace(/[\t\n\r]/g, "");
|
|
20949
|
+
if (normalizedRegion.length >= 2) {
|
|
20950
|
+
if (normalizedRegion.slice(0, 2) !== "//") {
|
|
20951
|
+
parsed.error = parsed.error || "URI authority must not contain a literal backslash.";
|
|
20952
|
+
malformedAuthorityOrPort = true;
|
|
20953
|
+
} else if (region.length !== normalizedRegion.length) {
|
|
20954
|
+
parsed.error = parsed.error || "URI authority introducer must not contain whitespace.";
|
|
20955
|
+
malformedAuthorityOrPort = true;
|
|
20956
|
+
}
|
|
20957
|
+
}
|
|
20958
|
+
}
|
|
20497
20959
|
const matches = uri.match(URI_PARSE);
|
|
20498
20960
|
if (matches) {
|
|
20499
20961
|
parsed.scheme = matches[1];
|
|
@@ -20503,11 +20965,33 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20503
20965
|
parsed.path = matches[6] || "";
|
|
20504
20966
|
parsed.query = matches[7];
|
|
20505
20967
|
parsed.fragment = matches[8];
|
|
20968
|
+
if (parsed.scheme !== void 0) {
|
|
20969
|
+
const decodedScheme = unescape(parsed.scheme);
|
|
20970
|
+
if (VALID_SCHEME.test(decodedScheme)) parsed.scheme = decodedScheme.toLowerCase();
|
|
20971
|
+
else {
|
|
20972
|
+
parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
|
|
20973
|
+
malformedScheme = true;
|
|
20974
|
+
}
|
|
20975
|
+
}
|
|
20976
|
+
malformedPercentEncoding = hasMalformedComponentPercentEncoding(matches);
|
|
20977
|
+
if (malformedPercentEncoding) parsed.error = parsed.error || "URI contains malformed percent-encoding.";
|
|
20506
20978
|
if (isNaN(parsed.port)) parsed.port = matches[5];
|
|
20979
|
+
const parseError = getParseError(parsed, matches);
|
|
20980
|
+
if (parseError !== void 0) {
|
|
20981
|
+
parsed.error = parsed.error || parseError;
|
|
20982
|
+
malformedAuthorityOrPort = true;
|
|
20983
|
+
}
|
|
20507
20984
|
if (parsed.host) if (isIPv4(parsed.host) === false) {
|
|
20985
|
+
const bracketedIPLiteral = isIPLiteral(parsed.host);
|
|
20986
|
+
const hasIPLiteralBracket = parsed.host.indexOf("[") !== -1 || parsed.host.indexOf("]") !== -1;
|
|
20508
20987
|
const ipv6result = normalizeIPv6(parsed.host);
|
|
20509
|
-
|
|
20510
|
-
|
|
20988
|
+
isIP = ipv6result.isIPV6 || ipv6result.isIPVFuture === true;
|
|
20989
|
+
malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
|
|
20990
|
+
parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
|
|
20991
|
+
if (malformedIPLiteral) {
|
|
20992
|
+
parsed.error = parsed.error || "URI host is malformed.";
|
|
20993
|
+
malformedAuthorityOrPort = true;
|
|
20994
|
+
}
|
|
20511
20995
|
} else isIP = true;
|
|
20512
20996
|
if (parsed.scheme === void 0 && parsed.userinfo === void 0 && parsed.host === void 0 && parsed.port === void 0 && parsed.query === void 0 && !parsed.path) parsed.reference = "same-document";
|
|
20513
20997
|
else if (parsed.scheme === void 0) parsed.reference = "relative";
|
|
@@ -20515,53 +20999,107 @@ var require_fast_uri = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
20515
20999
|
else parsed.reference = "uri";
|
|
20516
21000
|
if (options.reference && options.reference !== "suffix" && options.reference !== parsed.reference) parsed.error = parsed.error || "URI is not a " + options.reference + " reference.";
|
|
20517
21001
|
const schemeHandler = getSchemeHandler(options.scheme || parsed.scheme);
|
|
20518
|
-
if (!
|
|
20519
|
-
|
|
20520
|
-
|
|
20521
|
-
|
|
20522
|
-
|
|
20523
|
-
}
|
|
21002
|
+
if (!malformedIPLiteral) malformedHost = canonicalizeHost(parsed, options, schemeHandler, isIP);
|
|
21003
|
+
if (uri.indexOf("%") !== -1 && parsed.host !== void 0 && !malformedIPLiteral) {
|
|
21004
|
+
let host = isIP ? parsed.host : normalizePercentEncoding(parsed.host, true);
|
|
21005
|
+
if (!isIP) host = normalizePercentEncoding(host.toLowerCase());
|
|
21006
|
+
parsed.host = reescapeHostDelimiters(host, isIP);
|
|
20524
21007
|
}
|
|
20525
21008
|
if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
|
|
20526
|
-
if (
|
|
20527
|
-
|
|
20528
|
-
|
|
20529
|
-
|
|
20530
|
-
|
|
20531
|
-
|
|
21009
|
+
if (parsed.path) parsed.path = normalizePathEncoding(parsed.path);
|
|
21010
|
+
if (parsed.query) parsed.query = normalizeQueryFragmentEncoding(parsed.query);
|
|
21011
|
+
if (parsed.fragment) parsed.fragment = normalizeQueryFragmentEncoding(parsed.fragment);
|
|
21012
|
+
}
|
|
21013
|
+
if (schemeHandler && schemeHandler.parse) {
|
|
21014
|
+
schemeHandler.parse(parsed, options);
|
|
21015
|
+
if (schemeHandler === SCHEMES.urn && parsed.nid === void 0) malformedSchemeSpecific = true;
|
|
20532
21016
|
}
|
|
20533
|
-
if (schemeHandler && schemeHandler.parse) schemeHandler.parse(parsed, options);
|
|
20534
21017
|
} else parsed.error = parsed.error || "URI can not be parsed.";
|
|
20535
|
-
return
|
|
21018
|
+
return {
|
|
21019
|
+
parsed,
|
|
21020
|
+
malformedAuthorityOrPort,
|
|
21021
|
+
malformedPercentEncoding,
|
|
21022
|
+
malformedSchemeSpecific,
|
|
21023
|
+
malformedHost,
|
|
21024
|
+
malformedScheme
|
|
21025
|
+
};
|
|
20536
21026
|
}
|
|
20537
|
-
|
|
20538
|
-
|
|
20539
|
-
|
|
20540
|
-
|
|
20541
|
-
|
|
20542
|
-
|
|
20543
|
-
|
|
20544
|
-
|
|
20545
|
-
|
|
20546
|
-
|
|
20547
|
-
|
|
20548
|
-
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
|
|
20552
|
-
|
|
20553
|
-
|
|
20554
|
-
|
|
20555
|
-
}
|
|
20556
|
-
|
|
20557
|
-
|
|
20558
|
-
|
|
20559
|
-
|
|
20560
|
-
|
|
20561
|
-
|
|
20562
|
-
|
|
20563
|
-
|
|
20564
|
-
|
|
21027
|
+
/**
|
|
21028
|
+
* @param {string} uri
|
|
21029
|
+
* @param {import('./types/index').Options} [opts]
|
|
21030
|
+
* @returns
|
|
21031
|
+
*/
|
|
21032
|
+
function parse(uri, opts) {
|
|
21033
|
+
return parseWithStatus(uri, opts).parsed;
|
|
21034
|
+
}
|
|
21035
|
+
/**
|
|
21036
|
+
* @param {string} uri
|
|
21037
|
+
* @param {import('./types/index').Options} [opts]
|
|
21038
|
+
* @returns {string}
|
|
21039
|
+
*/
|
|
21040
|
+
function normalizeString(uri, opts) {
|
|
21041
|
+
return normalizeStringWithStatus(uri, opts).normalized;
|
|
21042
|
+
}
|
|
21043
|
+
/**
|
|
21044
|
+
* @param {string} uri
|
|
21045
|
+
* @param {import('./types/index').Options} [opts]
|
|
21046
|
+
* @returns {{ normalized: string, malformedAuthorityOrPort: boolean, malformedPercentEncoding: boolean, malformedSchemeSpecific: boolean, malformedHost: boolean, malformedScheme: boolean }}
|
|
21047
|
+
*/
|
|
21048
|
+
function normalizeStringWithStatus(uri, opts) {
|
|
21049
|
+
const { parsed, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = parseWithStatus(uri, opts);
|
|
21050
|
+
return {
|
|
21051
|
+
normalized: malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? uri : serialize(parsed, opts),
|
|
21052
|
+
malformedAuthorityOrPort,
|
|
21053
|
+
malformedPercentEncoding,
|
|
21054
|
+
malformedSchemeSpecific,
|
|
21055
|
+
malformedHost,
|
|
21056
|
+
malformedScheme
|
|
21057
|
+
};
|
|
21058
|
+
}
|
|
21059
|
+
/**
|
|
21060
|
+
* @param {import ('./types/index').URIComponent|string} uri
|
|
21061
|
+
* @param {import('./types/index').Options} [opts]
|
|
21062
|
+
* @returns {string|undefined}
|
|
21063
|
+
*/
|
|
21064
|
+
function normalizeComparableURI(uri, opts) {
|
|
21065
|
+
if (typeof uri !== "string" && typeof uri !== "object") return;
|
|
21066
|
+
let value;
|
|
21067
|
+
try {
|
|
21068
|
+
value = typeof uri === "string" ? uri : serialize(uri, opts);
|
|
21069
|
+
} catch {
|
|
21070
|
+
return;
|
|
21071
|
+
}
|
|
21072
|
+
const { normalized, malformedAuthorityOrPort, malformedPercentEncoding, malformedSchemeSpecific, malformedHost, malformedScheme } = normalizeStringWithStatus(value, opts);
|
|
21073
|
+
return malformedAuthorityOrPort || malformedPercentEncoding || malformedSchemeSpecific || malformedHost || malformedScheme ? void 0 : normalized;
|
|
21074
|
+
}
|
|
21075
|
+
const fastUri = {
|
|
21076
|
+
SCHEMES,
|
|
21077
|
+
normalize,
|
|
21078
|
+
resolve,
|
|
21079
|
+
resolveComponent,
|
|
21080
|
+
equal,
|
|
21081
|
+
serialize,
|
|
21082
|
+
parse
|
|
21083
|
+
};
|
|
21084
|
+
module.exports = fastUri;
|
|
21085
|
+
module.exports.default = fastUri;
|
|
21086
|
+
module.exports.fastUri = fastUri;
|
|
21087
|
+
}));
|
|
21088
|
+
var require_uri = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
21089
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21090
|
+
const uri = require_fast_uri();
|
|
21091
|
+
uri.code = "require(\"ajv/dist/runtime/uri\").default";
|
|
21092
|
+
exports.default = uri;
|
|
21093
|
+
}));
|
|
21094
|
+
var require_core$3 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
21095
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21096
|
+
exports.CodeGen = exports.Name = exports.nil = exports.stringify = exports.str = exports._ = exports.KeywordCxt = void 0;
|
|
21097
|
+
var validate_1 = require_validate();
|
|
21098
|
+
Object.defineProperty(exports, "KeywordCxt", {
|
|
21099
|
+
enumerable: true,
|
|
21100
|
+
get: function() {
|
|
21101
|
+
return validate_1.KeywordCxt;
|
|
21102
|
+
}
|
|
20565
21103
|
});
|
|
20566
21104
|
var codegen_1 = require_codegen();
|
|
20567
21105
|
Object.defineProperty(exports, "_", {
|
|
@@ -24322,7 +24860,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
24322
24860
|
};
|
|
24323
24861
|
import_ajv.Ajv;
|
|
24324
24862
|
//#endregion
|
|
24325
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
24863
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/mcp-oHn3ureC.mjs
|
|
24326
24864
|
const COMPLETABLE_SYMBOL = Symbol.for("mcp.completable");
|
|
24327
24865
|
/**
|
|
24328
24866
|
* Checks if a schema is completable (has completion metadata).
|
|
@@ -24344,240 +24882,195 @@ function armSseKeepAlive(intervalMs, onTick) {
|
|
|
24344
24882
|
timer.unref?.();
|
|
24345
24883
|
return timer;
|
|
24346
24884
|
}
|
|
24885
|
+
let readClassification;
|
|
24347
24886
|
/**
|
|
24348
|
-
*
|
|
24887
|
+
* The per-request micro-transport: a real, connected `Transport` whose whole
|
|
24888
|
+
* lifetime is one HTTP exchange. See the module documentation for the
|
|
24889
|
+
* response shapes it produces.
|
|
24349
24890
|
*
|
|
24350
|
-
* `
|
|
24351
|
-
*
|
|
24352
|
-
* listeners never unsubscribe peers). A throwing listener does not stop
|
|
24353
|
-
* delivery to the others.
|
|
24891
|
+
* Connecting a `Server` binds the instance to the classified modern revision
|
|
24892
|
+
* when its `supportedProtocolVersions` lists it and the SDK implements it.
|
|
24354
24893
|
*/
|
|
24355
|
-
var
|
|
24356
|
-
|
|
24894
|
+
var PerRequestHTTPServerTransport = class {
|
|
24895
|
+
static {
|
|
24896
|
+
readClassification = (transport) => transport._classification;
|
|
24897
|
+
}
|
|
24898
|
+
onclose;
|
|
24899
|
+
onerror;
|
|
24900
|
+
onmessage;
|
|
24901
|
+
_classification;
|
|
24902
|
+
_responseMode;
|
|
24903
|
+
_started = false;
|
|
24904
|
+
_used = false;
|
|
24905
|
+
_closed = false;
|
|
24906
|
+
_terminalDelivered = false;
|
|
24357
24907
|
/**
|
|
24358
|
-
*
|
|
24359
|
-
*
|
|
24908
|
+
* `true` only while the inbound message is being delivered synchronously
|
|
24909
|
+
* to the connected protocol layer. The pre-handler gates (the era
|
|
24910
|
+
* registry gate, the edge→instance handoff check, the missing-handler
|
|
24911
|
+
* rejection) answer inside this window; request handlers always run
|
|
24912
|
+
* after it (the protocol layer defers them to a microtask). An error
|
|
24913
|
+
* sent inside the window is therefore ladder-originated, and an error
|
|
24914
|
+
* sent after it is handler-produced.
|
|
24360
24915
|
*/
|
|
24361
|
-
|
|
24362
|
-
|
|
24916
|
+
_dispatchWindowOpen = false;
|
|
24917
|
+
_requestId;
|
|
24918
|
+
_deferredResponse;
|
|
24919
|
+
_sse;
|
|
24920
|
+
_abortCleanup;
|
|
24921
|
+
_keepAliveMs;
|
|
24922
|
+
constructor(options) {
|
|
24923
|
+
this._classification = options.classification;
|
|
24924
|
+
this._responseMode = options.responseMode ?? "auto";
|
|
24925
|
+
this._keepAliveMs = options.keepAliveMs ?? 15e3;
|
|
24363
24926
|
}
|
|
24364
|
-
|
|
24365
|
-
|
|
24366
|
-
|
|
24367
|
-
} catch (error) {
|
|
24368
|
-
this.onerror?.(error instanceof Error ? error : new Error(String(error)));
|
|
24369
|
-
}
|
|
24927
|
+
async start() {
|
|
24928
|
+
if (this._started) throw new Error("PerRequestHTTPServerTransport is already started");
|
|
24929
|
+
this._started = true;
|
|
24370
24930
|
}
|
|
24371
|
-
|
|
24372
|
-
|
|
24373
|
-
|
|
24374
|
-
|
|
24375
|
-
|
|
24376
|
-
|
|
24377
|
-
|
|
24931
|
+
/**
|
|
24932
|
+
* Serves the single exchange: delivers the classified message to the
|
|
24933
|
+
* connected server instance and resolves with the HTTP response.
|
|
24934
|
+
*
|
|
24935
|
+
* Throws when called a second time (the transport is strictly
|
|
24936
|
+
* single-use), or before a server has been connected to the transport.
|
|
24937
|
+
* The returned promise rejects with a connection-closed error when the
|
|
24938
|
+
* transport is closed before a response was produced (for example because
|
|
24939
|
+
* the client disconnected).
|
|
24940
|
+
*/
|
|
24941
|
+
async handleMessage(message, extra) {
|
|
24942
|
+
if (this._used) throw new Error("PerRequestHTTPServerTransport serves exactly one exchange; construct a new transport per request");
|
|
24943
|
+
if (!this._started || this.onmessage === void 0) throw new Error("PerRequestHTTPServerTransport is not connected: connect a server to this transport before handling a message");
|
|
24944
|
+
if (this._closed) throw new Error("PerRequestHTTPServerTransport is closed");
|
|
24945
|
+
this._used = true;
|
|
24946
|
+
const signal = extra?.request?.signal;
|
|
24947
|
+
if (signal?.aborted) {
|
|
24948
|
+
await this.close();
|
|
24949
|
+
throw new SdkError(SdkErrorCode.ConnectionClosed, "The request was aborted before it could be handled");
|
|
24950
|
+
}
|
|
24951
|
+
const messageExtra = {
|
|
24952
|
+
classification: this._classification,
|
|
24953
|
+
...extra?.request !== void 0 && { request: extra.request },
|
|
24954
|
+
...extra?.authInfo !== void 0 && { authInfo: extra.authInfo }
|
|
24378
24955
|
};
|
|
24956
|
+
if (isJSONRPCRequest(message)) {
|
|
24957
|
+
this._requestId = message.id;
|
|
24958
|
+
let resolve;
|
|
24959
|
+
let reject;
|
|
24960
|
+
const promise = new Promise((promiseResolve, promiseReject) => {
|
|
24961
|
+
resolve = promiseResolve;
|
|
24962
|
+
reject = promiseReject;
|
|
24963
|
+
});
|
|
24964
|
+
this._deferredResponse = {
|
|
24965
|
+
promise,
|
|
24966
|
+
resolve,
|
|
24967
|
+
reject,
|
|
24968
|
+
settled: false
|
|
24969
|
+
};
|
|
24970
|
+
if (signal !== void 0) {
|
|
24971
|
+
const onAbort = () => void this.close();
|
|
24972
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
24973
|
+
this._abortCleanup = () => signal.removeEventListener("abort", onAbort);
|
|
24974
|
+
}
|
|
24975
|
+
this._dispatchWindowOpen = true;
|
|
24976
|
+
try {
|
|
24977
|
+
this.onmessage(message, messageExtra);
|
|
24978
|
+
} finally {
|
|
24979
|
+
this._dispatchWindowOpen = false;
|
|
24980
|
+
}
|
|
24981
|
+
if (this._responseMode === "sse" && !this._closed && !this._deferredResponse.settled) this.upgradeToSse();
|
|
24982
|
+
return promise;
|
|
24983
|
+
}
|
|
24984
|
+
this.onmessage(message, messageExtra);
|
|
24985
|
+
return new Response(null, { status: 202 });
|
|
24379
24986
|
}
|
|
24380
|
-
|
|
24381
|
-
|
|
24382
|
-
|
|
24987
|
+
async send(message, options) {
|
|
24988
|
+
if (this._closed) return;
|
|
24989
|
+
const isResponse = isJSONRPCResultResponse(message) || isJSONRPCErrorResponse(message);
|
|
24990
|
+
const relatedId = isResponse ? message.id : options?.relatedRequestId;
|
|
24991
|
+
if (this._requestId === void 0 || relatedId === void 0 || relatedId !== this._requestId) {
|
|
24992
|
+
if (isResponse) this.onerror?.(/* @__PURE__ */ new Error(`Received a response for an unknown request id: ${String(message.id)}`));
|
|
24993
|
+
return;
|
|
24994
|
+
}
|
|
24995
|
+
if (isResponse) {
|
|
24996
|
+
if (this._terminalDelivered) return;
|
|
24997
|
+
this._terminalDelivered = true;
|
|
24998
|
+
const errorCode = isJSONRPCErrorResponse(message) ? message.error.code : void 0;
|
|
24999
|
+
const ladderStatus = errorCode !== void 0 && (this._dispatchWindowOpen || errorCode === ProtocolErrorCode.MissingRequiredClientCapability) ? LADDER_ERROR_HTTP_STATUS[errorCode] : void 0;
|
|
25000
|
+
if (ladderStatus !== void 0 && this._sse === void 0) {
|
|
25001
|
+
this.settleResponse(Response.json(message, {
|
|
25002
|
+
status: ladderStatus,
|
|
25003
|
+
headers: { "Content-Type": "application/json" }
|
|
25004
|
+
}));
|
|
25005
|
+
queueMicrotask(() => void this.close());
|
|
25006
|
+
return;
|
|
25007
|
+
}
|
|
25008
|
+
if (this._sse !== void 0 || this._responseMode === "sse") {
|
|
25009
|
+
if (this._sse === void 0) this.upgradeToSse();
|
|
25010
|
+
this.writeMessageFrame(message);
|
|
25011
|
+
this.finalizeStream();
|
|
25012
|
+
return;
|
|
25013
|
+
}
|
|
25014
|
+
this.settleResponse(Response.json(message, {
|
|
25015
|
+
status: 200,
|
|
25016
|
+
headers: { "Content-Type": "application/json" }
|
|
25017
|
+
}));
|
|
25018
|
+
queueMicrotask(() => void this.close());
|
|
25019
|
+
return;
|
|
25020
|
+
}
|
|
25021
|
+
if (this._responseMode === "json") return;
|
|
25022
|
+
if (this._sse === void 0) this.upgradeToSse();
|
|
25023
|
+
this.writeMessageFrame(message);
|
|
24383
25024
|
}
|
|
24384
|
-
|
|
24385
|
-
|
|
24386
|
-
|
|
24387
|
-
|
|
24388
|
-
|
|
24389
|
-
|
|
24390
|
-
|
|
24391
|
-
|
|
24392
|
-
kind: "resource_updated",
|
|
24393
|
-
uri
|
|
24394
|
-
})
|
|
24395
|
-
};
|
|
24396
|
-
}
|
|
24397
|
-
/**
|
|
24398
|
-
* Whether a `subscriptions/listen` filter accepts a given change event.
|
|
24399
|
-
*
|
|
24400
|
-
* Pure: no I/O, no mutation. The filter governs ONLY the four
|
|
24401
|
-
* subscription-gated change types — non-gated notifications never reach the
|
|
24402
|
-
* bus and are not modeled here.
|
|
24403
|
-
*
|
|
24404
|
-
* `resource_updated` matches only when `resourceSubscriptions` is present and
|
|
24405
|
-
* contains the event's URI exactly (per the spec: "for these resource URIs").
|
|
24406
|
-
*/
|
|
24407
|
-
function listenFilterAccepts(filter, event) {
|
|
24408
|
-
switch (event.kind) {
|
|
24409
|
-
case "tools_list_changed": return filter.toolsListChanged === true;
|
|
24410
|
-
case "prompts_list_changed": return filter.promptsListChanged === true;
|
|
24411
|
-
case "resources_list_changed": return filter.resourcesListChanged === true;
|
|
24412
|
-
case "resource_updated": return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri);
|
|
25025
|
+
/**
|
|
25026
|
+
* Writes an SSE comment frame (a keep-alive heartbeat). Dropped when the
|
|
25027
|
+
* exchange is not currently streaming.
|
|
25028
|
+
*/
|
|
25029
|
+
writeCommentFrame(comment) {
|
|
25030
|
+
if (this._closed || this._sse === void 0 || this._sse.closed) return;
|
|
25031
|
+
const frame = comment.split("\n").map((line) => `: ${line}`).join("\n");
|
|
25032
|
+
this.writeFrame(`${frame}\n\n`);
|
|
24413
25033
|
}
|
|
24414
|
-
|
|
24415
|
-
|
|
24416
|
-
|
|
24417
|
-
|
|
24418
|
-
|
|
24419
|
-
|
|
24420
|
-
|
|
24421
|
-
|
|
24422
|
-
|
|
24423
|
-
|
|
24424
|
-
|
|
24425
|
-
* `capabilities.resources.subscribe` is advertised.
|
|
24426
|
-
*
|
|
24427
|
-
* `capabilities` is optional on this pure helper for test convenience only —
|
|
24428
|
-
* both wired routers REQUIRE capabilities at the call site (the HTTP router's
|
|
24429
|
-
* `serve()` takes a required parameter; `StdioListenRouter.serve()` throws
|
|
24430
|
-
* before `setServerCapabilities()` was called), so the fail-open
|
|
24431
|
-
* `undefined → honor everything` branch is never reachable on a wired entry.
|
|
24432
|
-
*/
|
|
24433
|
-
function honoredSubset(requested, capabilities) {
|
|
24434
|
-
const honored = {};
|
|
24435
|
-
const allow = (bit) => capabilities === void 0 || bit === true;
|
|
24436
|
-
if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true;
|
|
24437
|
-
if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true;
|
|
24438
|
-
if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true;
|
|
24439
|
-
if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions];
|
|
24440
|
-
return honored;
|
|
24441
|
-
}
|
|
24442
|
-
/** Map a {@linkcode ServerEvent} onto its wire notification `{method, params}`. */
|
|
24443
|
-
function serverEventToNotification(event) {
|
|
24444
|
-
switch (event.kind) {
|
|
24445
|
-
case "tools_list_changed": return { method: "notifications/tools/list_changed" };
|
|
24446
|
-
case "prompts_list_changed": return { method: "notifications/prompts/list_changed" };
|
|
24447
|
-
case "resources_list_changed": return { method: "notifications/resources/list_changed" };
|
|
24448
|
-
case "resource_updated": return {
|
|
24449
|
-
method: "notifications/resources/updated",
|
|
24450
|
-
params: { uri: event.uri }
|
|
24451
|
-
};
|
|
24452
|
-
}
|
|
24453
|
-
}
|
|
24454
|
-
/** Default capacity guard: refuse a new subscription when this many are already open. */
|
|
24455
|
-
const DEFAULT_MAX_SUBSCRIPTIONS = 1024;
|
|
24456
|
-
function jsonRpcError(id, code, message) {
|
|
24457
|
-
return Response.json({
|
|
24458
|
-
jsonrpc: "2.0",
|
|
24459
|
-
error: {
|
|
24460
|
-
code,
|
|
24461
|
-
message
|
|
24462
|
-
},
|
|
24463
|
-
id
|
|
24464
|
-
}, { status: 200 });
|
|
24465
|
-
}
|
|
24466
|
-
/** Stamp the subscription id onto a notification's `_meta`. Non-mutating. */
|
|
24467
|
-
function stampSubscriptionId(notification, subscriptionId) {
|
|
24468
|
-
return {
|
|
24469
|
-
method: notification.method,
|
|
24470
|
-
params: {
|
|
24471
|
-
...notification.params,
|
|
24472
|
-
_meta: {
|
|
24473
|
-
...notification.params?._meta,
|
|
24474
|
-
[SUBSCRIPTION_ID_META_KEY]: subscriptionId
|
|
24475
|
-
}
|
|
25034
|
+
async close() {
|
|
25035
|
+
if (this._closed) return;
|
|
25036
|
+
this._closed = true;
|
|
25037
|
+
this._abortCleanup?.();
|
|
25038
|
+
this._abortCleanup = void 0;
|
|
25039
|
+
if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
|
|
25040
|
+
if (this._sse !== void 0 && !this._sse.closed) {
|
|
25041
|
+
this._sse.closed = true;
|
|
25042
|
+
try {
|
|
25043
|
+
this._sse.controller.close();
|
|
25044
|
+
} catch {}
|
|
24476
25045
|
}
|
|
24477
|
-
|
|
24478
|
-
|
|
24479
|
-
|
|
24480
|
-
* Read the requested filter off a `subscriptions/listen` request body.
|
|
24481
|
-
* Returns the validated filter, or `undefined` when `params.notifications`
|
|
24482
|
-
* is absent or fails the schema (the caller answers `-32602` — the spec
|
|
24483
|
-
* marks `notifications` REQUIRED on the listen request).
|
|
24484
|
-
*/
|
|
24485
|
-
function parseListenFilter(message) {
|
|
24486
|
-
const outcome = codecForVersion(MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message);
|
|
24487
|
-
return outcome.ok ? outcome.value.params?.notifications : void 0;
|
|
24488
|
-
}
|
|
24489
|
-
function createListenRouter(options) {
|
|
24490
|
-
const { bus, onerror } = options;
|
|
24491
|
-
const maxSubscriptions = options.maxSubscriptions ?? 1024;
|
|
24492
|
-
const keepAliveMs = options.keepAliveMs ?? 15e3;
|
|
24493
|
-
const open = /* @__PURE__ */ new Set();
|
|
24494
|
-
function serve(message, signal, capabilities, serverInfo) {
|
|
24495
|
-
if (open.size >= maxSubscriptions) {
|
|
24496
|
-
onerror?.(/* @__PURE__ */ new Error(`subscriptions/listen refused: subscription limit reached (${maxSubscriptions})`));
|
|
24497
|
-
return jsonRpcError(message.id, -32603, "Subscription limit reached");
|
|
25046
|
+
if (this._deferredResponse !== void 0 && !this._deferredResponse.settled) {
|
|
25047
|
+
this._deferredResponse.settled = true;
|
|
25048
|
+
this._deferredResponse.reject(new SdkError(SdkErrorCode.ConnectionClosed, "Connection closed before a response was produced"));
|
|
24498
25049
|
}
|
|
24499
|
-
|
|
24500
|
-
|
|
24501
|
-
|
|
24502
|
-
|
|
24503
|
-
|
|
25050
|
+
this.onclose?.();
|
|
25051
|
+
}
|
|
25052
|
+
settleResponse(response) {
|
|
25053
|
+
if (this._deferredResponse === void 0 || this._deferredResponse.settled) return;
|
|
25054
|
+
this._deferredResponse.settled = true;
|
|
25055
|
+
this._deferredResponse.resolve(response);
|
|
25056
|
+
}
|
|
25057
|
+
upgradeToSse() {
|
|
24504
25058
|
let controller;
|
|
24505
|
-
let closed = false;
|
|
24506
|
-
let unsubscribe;
|
|
24507
|
-
let keepAliveTimer;
|
|
24508
|
-
let abortCleanup;
|
|
24509
|
-
const writeFrame = (frame) => {
|
|
24510
|
-
if (closed) return;
|
|
24511
|
-
try {
|
|
24512
|
-
controller.enqueue(encoder.encode(frame));
|
|
24513
|
-
} catch (error) {
|
|
24514
|
-
onerror?.(error instanceof Error ? error : new Error(String(error)));
|
|
24515
|
-
}
|
|
24516
|
-
};
|
|
24517
|
-
const writeNotification = (method, params) => {
|
|
24518
|
-
writeFrame(`event: message\ndata: ${JSON.stringify({
|
|
24519
|
-
jsonrpc: "2.0",
|
|
24520
|
-
method,
|
|
24521
|
-
params
|
|
24522
|
-
})}\n\n`);
|
|
24523
|
-
};
|
|
24524
|
-
const teardown = (graceful) => {
|
|
24525
|
-
if (closed) return;
|
|
24526
|
-
if (graceful) writeFrame(`event: message\ndata: ${JSON.stringify({
|
|
24527
|
-
jsonrpc: "2.0",
|
|
24528
|
-
id: subscriptionId,
|
|
24529
|
-
result: {
|
|
24530
|
-
resultType: "complete",
|
|
24531
|
-
_meta: {
|
|
24532
|
-
[SUBSCRIPTION_ID_META_KEY]: subscriptionId,
|
|
24533
|
-
[SERVER_INFO_META_KEY]: serverInfo
|
|
24534
|
-
}
|
|
24535
|
-
}
|
|
24536
|
-
})}\n\n`);
|
|
24537
|
-
closed = true;
|
|
24538
|
-
try {
|
|
24539
|
-
unsubscribe?.();
|
|
24540
|
-
} catch (error) {
|
|
24541
|
-
onerror?.(error instanceof Error ? error : new Error(String(error)));
|
|
24542
|
-
}
|
|
24543
|
-
if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
|
|
24544
|
-
abortCleanup?.();
|
|
24545
|
-
open.delete(teardown);
|
|
24546
|
-
try {
|
|
24547
|
-
controller.close();
|
|
24548
|
-
} catch {}
|
|
24549
|
-
};
|
|
24550
25059
|
const readable = new ReadableStream({
|
|
24551
|
-
start(streamController) {
|
|
25060
|
+
start: (streamController) => {
|
|
24552
25061
|
controller = streamController;
|
|
24553
|
-
const ack = stampSubscriptionId({
|
|
24554
|
-
method: "notifications/subscriptions/acknowledged",
|
|
24555
|
-
params: { notifications: honored }
|
|
24556
|
-
}, subscriptionId);
|
|
24557
|
-
writeNotification(ack.method, ack.params);
|
|
24558
|
-
if (Object.keys(honored).length === 0) {
|
|
24559
|
-
teardown(true);
|
|
24560
|
-
return;
|
|
24561
|
-
}
|
|
24562
|
-
unsubscribe = bus.subscribe((event) => {
|
|
24563
|
-
if (closed || !listenFilterAccepts(honored, event)) return;
|
|
24564
|
-
const note = stampSubscriptionId(serverEventToNotification(event), subscriptionId);
|
|
24565
|
-
writeNotification(note.method, note.params);
|
|
24566
|
-
});
|
|
24567
|
-
keepAliveTimer = armSseKeepAlive(keepAliveMs, () => writeFrame(": keepalive\n\n"));
|
|
24568
|
-
open.add(teardown);
|
|
24569
25062
|
},
|
|
24570
|
-
cancel() {
|
|
24571
|
-
|
|
25063
|
+
cancel: () => {
|
|
25064
|
+
this.close();
|
|
24572
25065
|
}
|
|
24573
25066
|
});
|
|
24574
|
-
|
|
24575
|
-
|
|
24576
|
-
|
|
24577
|
-
|
|
24578
|
-
|
|
24579
|
-
|
|
24580
|
-
|
|
25067
|
+
this._sse = {
|
|
25068
|
+
controller,
|
|
25069
|
+
encoder: new TextEncoder(),
|
|
25070
|
+
closed: false
|
|
25071
|
+
};
|
|
25072
|
+
this._sse.keepAliveTimer = armSseKeepAlive(this._keepAliveMs, () => this.writeCommentFrame("keepalive"));
|
|
25073
|
+
this.settleResponse(new Response(readable, {
|
|
24581
25074
|
status: 200,
|
|
24582
25075
|
headers: {
|
|
24583
25076
|
"Content-Type": "text/event-stream",
|
|
@@ -24585,167 +25078,33 @@ function createListenRouter(options) {
|
|
|
24585
25078
|
Connection: "keep-alive",
|
|
24586
25079
|
"X-Accel-Buffering": "no"
|
|
24587
25080
|
}
|
|
24588
|
-
});
|
|
25081
|
+
}));
|
|
24589
25082
|
}
|
|
24590
|
-
|
|
24591
|
-
|
|
24592
|
-
|
|
24593
|
-
|
|
24594
|
-
|
|
24595
|
-
|
|
24596
|
-
|
|
25083
|
+
finalizeStream() {
|
|
25084
|
+
if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
|
|
25085
|
+
if (this._sse !== void 0 && !this._sse.closed) {
|
|
25086
|
+
this._sse.closed = true;
|
|
25087
|
+
try {
|
|
25088
|
+
this._sse.controller.close();
|
|
25089
|
+
} catch {}
|
|
24597
25090
|
}
|
|
24598
|
-
|
|
24599
|
-
}
|
|
24600
|
-
const CHANGE_NOTIFICATION_METHODS = /* @__PURE__ */ new Set([
|
|
24601
|
-
"notifications/tools/list_changed",
|
|
24602
|
-
"notifications/prompts/list_changed",
|
|
24603
|
-
"notifications/resources/list_changed",
|
|
24604
|
-
"notifications/resources/updated"
|
|
24605
|
-
]);
|
|
24606
|
-
/**
|
|
24607
|
-
* Per-connection listen state for the stdio entry. One instance is held by
|
|
24608
|
-
* `serveStdio` for the connection lifetime; it routes inbound
|
|
24609
|
-
* `subscriptions/listen` / `notifications/cancelled` and rewrites outbound
|
|
24610
|
-
* change notifications onto the active subscriptions. No bus — the long-lived
|
|
24611
|
-
* pinned instance's existing `send*ListChanged()` calls feed straight into
|
|
24612
|
-
* `routeOutbound()`.
|
|
24613
|
-
*/
|
|
24614
|
-
var StdioListenRouter = class {
|
|
24615
|
-
/** Active subscriptions, keyed by the listen request's JSON-RPC id verbatim. */
|
|
24616
|
-
_subs = /* @__PURE__ */ new Map();
|
|
24617
|
-
/**
|
|
24618
|
-
* The serving instance's declared capabilities. Filled in by the entry
|
|
24619
|
-
* once the modern instance is constructed (the router is created before
|
|
24620
|
-
* the instance exists), so the acknowledged filter is narrowed against
|
|
24621
|
-
* what the server can actually deliver.
|
|
24622
|
-
*/
|
|
24623
|
-
_serverCapabilities;
|
|
24624
|
-
/**
|
|
24625
|
-
* The serving instance's identity, stamped onto the graceful-close
|
|
24626
|
-
* results' `_meta` (the spec's `SubscriptionsListenResultMetaObject` extends
|
|
24627
|
-
* `ResultMetaObject`). Handed over together with the capabilities.
|
|
24628
|
-
*/
|
|
24629
|
-
_serverInfo;
|
|
24630
|
-
constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) {
|
|
24631
|
-
this._maxSubscriptions = _maxSubscriptions;
|
|
24632
|
-
this._serverCapabilities = serverCapabilities;
|
|
24633
|
-
this._serverInfo = serverInfo;
|
|
25091
|
+
queueMicrotask(() => void this.close());
|
|
24634
25092
|
}
|
|
24635
|
-
|
|
24636
|
-
|
|
24637
|
-
* it has been constructed. Called by `serveStdio`'s connect path;
|
|
24638
|
-
* subsequent `serve()` calls narrow the honored filter against the
|
|
24639
|
-
* capabilities, and `teardownAll()` stamps the identity.
|
|
24640
|
-
*/
|
|
24641
|
-
setServerCapabilities(capabilities, serverInfo) {
|
|
24642
|
-
this._serverCapabilities = capabilities;
|
|
24643
|
-
if (serverInfo !== void 0) this._serverInfo = serverInfo;
|
|
25093
|
+
writeMessageFrame(message) {
|
|
25094
|
+
this.writeFrame(`event: message\ndata: ${JSON.stringify(message)}\n\n`);
|
|
24644
25095
|
}
|
|
24645
|
-
|
|
24646
|
-
|
|
24647
|
-
|
|
24648
|
-
|
|
24649
|
-
|
|
24650
|
-
|
|
24651
|
-
|
|
24652
|
-
* capacity / params rejection, the in-band JSON-RPC error response).
|
|
24653
|
-
*
|
|
24654
|
-
* @throws when called before {@linkcode setServerCapabilities} (or the
|
|
24655
|
-
* constructor) has supplied the serving instance's capabilities. Honoring a
|
|
24656
|
-
* filter without knowing the server's advertised capabilities would fail
|
|
24657
|
-
* open (deliver unadvertised types); the entry guarantees capabilities are
|
|
24658
|
-
* set before any listen request is routed here.
|
|
24659
|
-
*/
|
|
24660
|
-
serve(message) {
|
|
24661
|
-
if (this._serverCapabilities === void 0) throw new Error("StdioListenRouter.serve() called before setServerCapabilities(); refusing to honor a filter without capabilities");
|
|
24662
|
-
if (this._subs.size >= this._maxSubscriptions) return {
|
|
24663
|
-
jsonrpc: "2.0",
|
|
24664
|
-
id: message.id,
|
|
24665
|
-
error: {
|
|
24666
|
-
code: -32603,
|
|
24667
|
-
message: "Subscription limit reached"
|
|
24668
|
-
}
|
|
24669
|
-
};
|
|
24670
|
-
const filter = parseListenFilter(message);
|
|
24671
|
-
if (filter === void 0) return {
|
|
24672
|
-
jsonrpc: "2.0",
|
|
24673
|
-
id: message.id,
|
|
24674
|
-
error: {
|
|
24675
|
-
code: -32602,
|
|
24676
|
-
message: "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter"
|
|
24677
|
-
}
|
|
24678
|
-
};
|
|
24679
|
-
const honored = honoredSubset(filter, this._serverCapabilities);
|
|
24680
|
-
this._subs.set(message.id, honored);
|
|
24681
|
-
return stampSubscriptionId({
|
|
24682
|
-
method: "notifications/subscriptions/acknowledged",
|
|
24683
|
-
params: { notifications: honored }
|
|
24684
|
-
}, message.id);
|
|
24685
|
-
}
|
|
24686
|
-
/**
|
|
24687
|
-
* Tear down one subscription (inbound `notifications/cancelled`). Returns
|
|
24688
|
-
* `true` when a subscription was removed. After this call NOTHING further
|
|
24689
|
-
* is delivered for that subscription id (the post-cancel hardening).
|
|
24690
|
-
*/
|
|
24691
|
-
cancel(id) {
|
|
24692
|
-
return this._subs.delete(id);
|
|
24693
|
-
}
|
|
24694
|
-
/**
|
|
24695
|
-
* Route an outbound notification through the active subscriptions.
|
|
24696
|
-
*
|
|
24697
|
-
* - For a subscription-gated change notification, returns one stamped copy
|
|
24698
|
-
* per subscription that opted in to it (an empty array means it is
|
|
24699
|
-
* dropped — the modern era never delivers an un-requested change type).
|
|
24700
|
-
* - For any other outbound message, returns `'passthrough'` (the entry
|
|
24701
|
-
* forwards it as-is).
|
|
24702
|
-
*/
|
|
24703
|
-
routeOutbound(message) {
|
|
24704
|
-
if (!CHANGE_NOTIFICATION_METHODS.has(message.method)) return "passthrough";
|
|
24705
|
-
const uriParam = message.params?.["uri"];
|
|
24706
|
-
const uri = typeof uriParam === "string" ? uriParam : void 0;
|
|
24707
|
-
const event = notificationToServerEvent(message.method, uri);
|
|
24708
|
-
const out = [];
|
|
24709
|
-
for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({
|
|
24710
|
-
method: message.method,
|
|
24711
|
-
params: message.params ?? {}
|
|
24712
|
-
}, subscriptionId));
|
|
24713
|
-
return out;
|
|
24714
|
-
}
|
|
24715
|
-
/**
|
|
24716
|
-
* Server-side graceful teardown of every active subscription: returns the
|
|
24717
|
-
* empty `subscriptions/listen` JSON-RPC result for each subscription id —
|
|
24718
|
-
* the spec's graceful-close signal, `_meta` carrying the subscription id
|
|
24719
|
-
* and the serving instance's identity — for the entry to emit before
|
|
24720
|
-
* closing the wire. Clears the set so nothing further is delivered.
|
|
24721
|
-
*/
|
|
24722
|
-
teardownAll() {
|
|
24723
|
-
const out = [];
|
|
24724
|
-
for (const id of this._subs.keys()) out.push({
|
|
24725
|
-
jsonrpc: "2.0",
|
|
24726
|
-
id,
|
|
24727
|
-
result: {
|
|
24728
|
-
resultType: "complete",
|
|
24729
|
-
_meta: {
|
|
24730
|
-
[SUBSCRIPTION_ID_META_KEY]: id,
|
|
24731
|
-
...this._serverInfo !== void 0 && { ["io.modelcontextprotocol/serverInfo"]: this._serverInfo }
|
|
24732
|
-
}
|
|
24733
|
-
}
|
|
24734
|
-
});
|
|
24735
|
-
this._subs.clear();
|
|
24736
|
-
return out;
|
|
25096
|
+
writeFrame(frame) {
|
|
25097
|
+
if (this._sse === void 0 || this._sse.closed) return;
|
|
25098
|
+
try {
|
|
25099
|
+
this._sse.controller.enqueue(this._sse.encoder.encode(frame));
|
|
25100
|
+
} catch (error) {
|
|
25101
|
+
this.onerror?.(/* @__PURE__ */ new Error(`Failed to write to the response stream: ${error}`));
|
|
25102
|
+
}
|
|
24737
25103
|
}
|
|
24738
25104
|
};
|
|
24739
|
-
|
|
24740
|
-
|
|
24741
|
-
|
|
24742
|
-
case "notifications/prompts/list_changed": return { kind: "prompts_list_changed" };
|
|
24743
|
-
case "notifications/resources/list_changed": return { kind: "resources_list_changed" };
|
|
24744
|
-
default: return {
|
|
24745
|
-
kind: "resource_updated",
|
|
24746
|
-
uri: uri ?? ""
|
|
24747
|
-
};
|
|
24748
|
-
}
|
|
25105
|
+
/** Package-internal: the classification a per-request transport serves; `undefined` for any other transport. Not public API. */
|
|
25106
|
+
function perRequestClassificationOf(transport) {
|
|
25107
|
+
return transport instanceof PerRequestHTTPServerTransport ? readClassification(transport) : void 0;
|
|
24749
25108
|
}
|
|
24750
25109
|
function comparableResource(value) {
|
|
24751
25110
|
const text = String(value);
|
|
@@ -25129,6 +25488,7 @@ var Server = class extends Protocol {
|
|
|
25129
25488
|
_requestStateVerify;
|
|
25130
25489
|
_inputRequiredServing;
|
|
25131
25490
|
_legacyShim;
|
|
25491
|
+
_boundFromTransport = false;
|
|
25132
25492
|
/** Lazily-built legacy shim; the loop lives in legacyInputRequiredShim.ts behind a narrow host contract. */
|
|
25133
25493
|
_legacyInputRequiredShim() {
|
|
25134
25494
|
return this._legacyShim ??= new LegacyInputRequiredShim({
|
|
@@ -25168,6 +25528,15 @@ var Server = class extends Protocol {
|
|
|
25168
25528
|
/** Attaches to the given transport; rejects while this instance is connected to another one. */
|
|
25169
25529
|
async connect(transport) {
|
|
25170
25530
|
if (this.transport !== void 0) throw new SdkError(SdkErrorCode.AlreadyConnected, "Use a separate Server instance per connection: this instance is already connected to a transport. To connect it to a new transport, call close() first.");
|
|
25531
|
+
if (this._boundFromTransport) {
|
|
25532
|
+
this._boundFromTransport = false;
|
|
25533
|
+
this._negotiatedProtocolVersion = void 0;
|
|
25534
|
+
}
|
|
25535
|
+
const revision = perRequestClassificationOf(transport)?.revision;
|
|
25536
|
+
if (revision !== void 0 && !this._servedModernEra() && SUPPORTED_MODERN_PROTOCOL_VERSIONS.includes(revision) && modernProtocolVersions(this._supportedProtocolVersions).includes(revision)) {
|
|
25537
|
+
this._negotiatedProtocolVersion = revision;
|
|
25538
|
+
this._boundFromTransport = true;
|
|
25539
|
+
}
|
|
25171
25540
|
await super.connect(transport);
|
|
25172
25541
|
}
|
|
25173
25542
|
/**
|
|
@@ -25478,8 +25847,8 @@ var Server = class extends Protocol {
|
|
|
25478
25847
|
* @deprecated Read client identity from the per-request handler context instead: on
|
|
25479
25848
|
* 2026-07-28 (per-request envelope) requests `ctx.mcpReq.envelope` carries the client's
|
|
25480
25849
|
* declared capabilities, while on 2025-era connections this accessor keeps returning the
|
|
25481
|
-
* `initialize`-scoped value. The accessor remains functional
|
|
25482
|
-
* 2026-07-28 era
|
|
25850
|
+
* `initialize`-scoped value. The accessor remains functional where `createMcpHandler`
|
|
25851
|
+
* serves the 2026-07-28 era: it backfills it per request from the validated envelope.
|
|
25483
25852
|
*/
|
|
25484
25853
|
getClientCapabilities() {
|
|
25485
25854
|
return this._clientCapabilities;
|
|
@@ -25490,8 +25859,8 @@ var Server = class extends Protocol {
|
|
|
25490
25859
|
* @deprecated Read client identity from the per-request handler context instead: on
|
|
25491
25860
|
* 2026-07-28 (per-request envelope) requests `ctx.mcpReq.envelope` carries the client's
|
|
25492
25861
|
* name and version, while on 2025-era connections this accessor keeps returning the
|
|
25493
|
-
* `initialize`-scoped value. The accessor remains functional
|
|
25494
|
-
* 2026-07-28 era
|
|
25862
|
+
* `initialize`-scoped value. The accessor remains functional where `createMcpHandler`
|
|
25863
|
+
* serves the 2026-07-28 era: it backfills it per request from the validated envelope.
|
|
25495
25864
|
*/
|
|
25496
25865
|
getClientVersion() {
|
|
25497
25866
|
return this._clientVersion;
|
|
@@ -26084,8 +26453,14 @@ var McpServer = class {
|
|
|
26084
26453
|
if (updates.uri) this._registeredResources[updates.uri] = registeredResource;
|
|
26085
26454
|
}
|
|
26086
26455
|
if (updates.name !== void 0) registeredResource.name = updates.name;
|
|
26087
|
-
if (updates.title !== void 0) registeredResource.title = updates.title;
|
|
26088
26456
|
if (updates.metadata !== void 0) registeredResource.metadata = updates.metadata;
|
|
26457
|
+
if (updates.title !== void 0) {
|
|
26458
|
+
registeredResource.title = updates.title;
|
|
26459
|
+
registeredResource.metadata = {
|
|
26460
|
+
...registeredResource.metadata,
|
|
26461
|
+
title: updates.title
|
|
26462
|
+
};
|
|
26463
|
+
}
|
|
26089
26464
|
if (updates.callback !== void 0) registeredResource.readCallback = updates.callback;
|
|
26090
26465
|
if (updates.scopeChallenge !== void 0) registeredResource.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
|
|
26091
26466
|
if (updates.enabled !== void 0) registeredResource.enabled = updates.enabled;
|
|
@@ -26111,9 +26486,15 @@ var McpServer = class {
|
|
|
26111
26486
|
delete this._registeredResourceTemplates[name];
|
|
26112
26487
|
if (updates.name) this._registeredResourceTemplates[updates.name] = registeredResourceTemplate;
|
|
26113
26488
|
}
|
|
26114
|
-
if (updates.title !== void 0) registeredResourceTemplate.title = updates.title;
|
|
26115
26489
|
if (updates.template !== void 0) registeredResourceTemplate.resourceTemplate = updates.template;
|
|
26116
26490
|
if (updates.metadata !== void 0) registeredResourceTemplate.metadata = updates.metadata;
|
|
26491
|
+
if (updates.title !== void 0) {
|
|
26492
|
+
registeredResourceTemplate.title = updates.title;
|
|
26493
|
+
registeredResourceTemplate.metadata = {
|
|
26494
|
+
...registeredResourceTemplate.metadata,
|
|
26495
|
+
title: updates.title
|
|
26496
|
+
};
|
|
26497
|
+
}
|
|
26117
26498
|
if (updates.callback !== void 0) registeredResourceTemplate.readCallback = updates.callback;
|
|
26118
26499
|
if (updates.scopeChallenge !== void 0) registeredResourceTemplate.scopeChallenge = updates.scopeChallenge === null ? void 0 : updates.scopeChallenge;
|
|
26119
26500
|
if (updates.enabled !== void 0) registeredResourceTemplate.enabled = updates.enabled;
|
|
@@ -26417,189 +26798,253 @@ function unwrapOptionalSchema(schema) {
|
|
|
26417
26798
|
return schema.def?.innerType ?? schema;
|
|
26418
26799
|
}
|
|
26419
26800
|
//#endregion
|
|
26420
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
26801
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/listenRouter-Bartj63y.mjs
|
|
26421
26802
|
/**
|
|
26422
|
-
*
|
|
26423
|
-
*
|
|
26424
|
-
*
|
|
26803
|
+
* A `ServerEventBus` backed by an in-process listener set.
|
|
26804
|
+
*
|
|
26805
|
+
* `publish()` delivers synchronously to the live listener set (a listener
|
|
26806
|
+
* unsubscribing itself mid-dispatch is safe; the entry's listen-router
|
|
26807
|
+
* listeners never unsubscribe peers). A throwing listener does not stop
|
|
26808
|
+
* delivery to the others.
|
|
26425
26809
|
*/
|
|
26426
|
-
var
|
|
26427
|
-
|
|
26428
|
-
onerror;
|
|
26429
|
-
onmessage;
|
|
26430
|
-
_classification;
|
|
26431
|
-
_responseMode;
|
|
26432
|
-
_started = false;
|
|
26433
|
-
_used = false;
|
|
26434
|
-
_closed = false;
|
|
26435
|
-
_terminalDelivered = false;
|
|
26810
|
+
var InMemoryServerEventBus = class {
|
|
26811
|
+
_listeners = /* @__PURE__ */ new Set();
|
|
26436
26812
|
/**
|
|
26437
|
-
*
|
|
26438
|
-
*
|
|
26439
|
-
* registry gate, the edge→instance handoff check, the missing-handler
|
|
26440
|
-
* rejection) answer inside this window; request handlers always run
|
|
26441
|
-
* after it (the protocol layer defers them to a microtask). An error
|
|
26442
|
-
* sent inside the window is therefore ladder-originated, and an error
|
|
26443
|
-
* sent after it is handler-produced.
|
|
26813
|
+
* @param onerror - Optional callback for errors thrown by listeners
|
|
26814
|
+
* during dispatch.
|
|
26444
26815
|
*/
|
|
26445
|
-
|
|
26446
|
-
|
|
26447
|
-
_deferredResponse;
|
|
26448
|
-
_sse;
|
|
26449
|
-
_abortCleanup;
|
|
26450
|
-
_keepAliveMs;
|
|
26451
|
-
constructor(options) {
|
|
26452
|
-
this._classification = options.classification;
|
|
26453
|
-
this._responseMode = options.responseMode ?? "auto";
|
|
26454
|
-
this._keepAliveMs = options.keepAliveMs ?? 15e3;
|
|
26455
|
-
}
|
|
26456
|
-
async start() {
|
|
26457
|
-
if (this._started) throw new Error("PerRequestHTTPServerTransport is already started");
|
|
26458
|
-
this._started = true;
|
|
26816
|
+
constructor(onerror) {
|
|
26817
|
+
this.onerror = onerror;
|
|
26459
26818
|
}
|
|
26460
|
-
|
|
26461
|
-
|
|
26462
|
-
|
|
26463
|
-
|
|
26464
|
-
|
|
26465
|
-
* single-use), or before a server has been connected to the transport.
|
|
26466
|
-
* The returned promise rejects with a connection-closed error when the
|
|
26467
|
-
* transport is closed before a response was produced (for example because
|
|
26468
|
-
* the client disconnected).
|
|
26469
|
-
*/
|
|
26470
|
-
async handleMessage(message, extra) {
|
|
26471
|
-
if (this._used) throw new Error("PerRequestHTTPServerTransport serves exactly one exchange; construct a new transport per request");
|
|
26472
|
-
if (!this._started || this.onmessage === void 0) throw new Error("PerRequestHTTPServerTransport is not connected: connect a server to this transport before handling a message");
|
|
26473
|
-
if (this._closed) throw new Error("PerRequestHTTPServerTransport is closed");
|
|
26474
|
-
this._used = true;
|
|
26475
|
-
const signal = extra?.request?.signal;
|
|
26476
|
-
if (signal?.aborted) {
|
|
26477
|
-
await this.close();
|
|
26478
|
-
throw new SdkError(SdkErrorCode.ConnectionClosed, "The request was aborted before it could be handled");
|
|
26819
|
+
publish(event) {
|
|
26820
|
+
for (const listener of this._listeners) try {
|
|
26821
|
+
listener(event);
|
|
26822
|
+
} catch (error) {
|
|
26823
|
+
this.onerror?.(error instanceof Error ? error : new Error(String(error)));
|
|
26479
26824
|
}
|
|
26480
|
-
|
|
26481
|
-
|
|
26482
|
-
|
|
26483
|
-
|
|
26825
|
+
}
|
|
26826
|
+
subscribe(listener) {
|
|
26827
|
+
this._listeners.add(listener);
|
|
26828
|
+
let live = true;
|
|
26829
|
+
return () => {
|
|
26830
|
+
if (!live) return;
|
|
26831
|
+
live = false;
|
|
26832
|
+
this._listeners.delete(listener);
|
|
26484
26833
|
};
|
|
26485
|
-
|
|
26486
|
-
|
|
26487
|
-
|
|
26488
|
-
|
|
26489
|
-
|
|
26490
|
-
|
|
26491
|
-
|
|
26492
|
-
|
|
26493
|
-
|
|
26494
|
-
|
|
26495
|
-
|
|
26496
|
-
|
|
26497
|
-
|
|
26498
|
-
|
|
26499
|
-
|
|
26500
|
-
|
|
26501
|
-
|
|
26502
|
-
|
|
26834
|
+
}
|
|
26835
|
+
/** The number of currently registered listeners (test/introspection only — the routers track capacity via their own open-subscription set). */
|
|
26836
|
+
get listenerCount() {
|
|
26837
|
+
return this._listeners.size;
|
|
26838
|
+
}
|
|
26839
|
+
};
|
|
26840
|
+
/** Build a {@linkcode ServerNotifier} over a bus. */
|
|
26841
|
+
function createServerNotifier(bus) {
|
|
26842
|
+
return {
|
|
26843
|
+
toolsChanged: () => bus.publish({ kind: "tools_list_changed" }),
|
|
26844
|
+
promptsChanged: () => bus.publish({ kind: "prompts_list_changed" }),
|
|
26845
|
+
resourcesChanged: () => bus.publish({ kind: "resources_list_changed" }),
|
|
26846
|
+
resourceUpdated: (uri) => bus.publish({
|
|
26847
|
+
kind: "resource_updated",
|
|
26848
|
+
uri
|
|
26849
|
+
})
|
|
26850
|
+
};
|
|
26851
|
+
}
|
|
26852
|
+
/**
|
|
26853
|
+
* Whether a `subscriptions/listen` filter accepts a given change event.
|
|
26854
|
+
*
|
|
26855
|
+
* Pure: no I/O, no mutation. The filter governs ONLY the four
|
|
26856
|
+
* subscription-gated change types — non-gated notifications never reach the
|
|
26857
|
+
* bus and are not modeled here.
|
|
26858
|
+
*
|
|
26859
|
+
* `resource_updated` matches only when `resourceSubscriptions` is present and
|
|
26860
|
+
* contains the event's URI exactly (per the spec: "for these resource URIs").
|
|
26861
|
+
*/
|
|
26862
|
+
function listenFilterAccepts(filter, event) {
|
|
26863
|
+
switch (event.kind) {
|
|
26864
|
+
case "tools_list_changed": return filter.toolsListChanged === true;
|
|
26865
|
+
case "prompts_list_changed": return filter.promptsListChanged === true;
|
|
26866
|
+
case "resources_list_changed": return filter.resourcesListChanged === true;
|
|
26867
|
+
case "resource_updated": return filter.resourceSubscriptions !== void 0 && filter.resourceSubscriptions.includes(event.uri);
|
|
26868
|
+
}
|
|
26869
|
+
}
|
|
26870
|
+
/**
|
|
26871
|
+
* The honored subset of a requested filter: keeps only the fields the client
|
|
26872
|
+
* explicitly opted in to (drops `false` and absent fields), narrowed against
|
|
26873
|
+
* the server's declared capabilities when supplied. The serving entry sends
|
|
26874
|
+
* this back in `notifications/subscriptions/acknowledged` so the ack reflects
|
|
26875
|
+
* what the server can actually deliver.
|
|
26876
|
+
*
|
|
26877
|
+
* - `toolsListChanged` is honored only when `capabilities.tools.listChanged`
|
|
26878
|
+
* is advertised; likewise `promptsListChanged` / `resourcesListChanged`.
|
|
26879
|
+
* - `resourceSubscriptions` is honored only when
|
|
26880
|
+
* `capabilities.resources.subscribe` is advertised.
|
|
26881
|
+
*
|
|
26882
|
+
* `capabilities` is optional on this pure helper for test convenience only —
|
|
26883
|
+
* both wired routers REQUIRE capabilities at the call site (the HTTP router's
|
|
26884
|
+
* `serve()` takes a required parameter; `StdioListenRouter.serve()` throws
|
|
26885
|
+
* before `setServerCapabilities()` was called), so the fail-open
|
|
26886
|
+
* `undefined → honor everything` branch is never reachable on a wired entry.
|
|
26887
|
+
*/
|
|
26888
|
+
function honoredSubset(requested, capabilities) {
|
|
26889
|
+
const honored = {};
|
|
26890
|
+
const allow = (bit) => capabilities === void 0 || bit === true;
|
|
26891
|
+
if (requested.toolsListChanged === true && allow(capabilities?.tools?.listChanged)) honored.toolsListChanged = true;
|
|
26892
|
+
if (requested.promptsListChanged === true && allow(capabilities?.prompts?.listChanged)) honored.promptsListChanged = true;
|
|
26893
|
+
if (requested.resourcesListChanged === true && allow(capabilities?.resources?.listChanged)) honored.resourcesListChanged = true;
|
|
26894
|
+
if (requested.resourceSubscriptions !== void 0 && requested.resourceSubscriptions.length > 0 && allow(capabilities?.resources?.subscribe)) honored.resourceSubscriptions = [...requested.resourceSubscriptions];
|
|
26895
|
+
return honored;
|
|
26896
|
+
}
|
|
26897
|
+
/** Map a {@linkcode ServerEvent} onto its wire notification `{method, params}`. */
|
|
26898
|
+
function serverEventToNotification(event) {
|
|
26899
|
+
switch (event.kind) {
|
|
26900
|
+
case "tools_list_changed": return {
|
|
26901
|
+
method: "notifications/tools/list_changed",
|
|
26902
|
+
...event.params !== void 0 && { params: event.params }
|
|
26903
|
+
};
|
|
26904
|
+
case "prompts_list_changed": return {
|
|
26905
|
+
method: "notifications/prompts/list_changed",
|
|
26906
|
+
...event.params !== void 0 && { params: event.params }
|
|
26907
|
+
};
|
|
26908
|
+
case "resources_list_changed": return {
|
|
26909
|
+
method: "notifications/resources/list_changed",
|
|
26910
|
+
...event.params !== void 0 && { params: event.params }
|
|
26911
|
+
};
|
|
26912
|
+
case "resource_updated": return {
|
|
26913
|
+
method: "notifications/resources/updated",
|
|
26914
|
+
params: {
|
|
26915
|
+
...event.params,
|
|
26916
|
+
uri: event.uri
|
|
26503
26917
|
}
|
|
26504
|
-
|
|
26505
|
-
|
|
26506
|
-
|
|
26507
|
-
|
|
26508
|
-
|
|
26918
|
+
};
|
|
26919
|
+
}
|
|
26920
|
+
}
|
|
26921
|
+
/** Default capacity guard: refuse a new subscription when this many are already open. */
|
|
26922
|
+
const DEFAULT_MAX_SUBSCRIPTIONS = 1024;
|
|
26923
|
+
function jsonRpcError(id, code, message) {
|
|
26924
|
+
return Response.json({
|
|
26925
|
+
jsonrpc: "2.0",
|
|
26926
|
+
error: {
|
|
26927
|
+
code,
|
|
26928
|
+
message
|
|
26929
|
+
},
|
|
26930
|
+
id
|
|
26931
|
+
}, { status: 200 });
|
|
26932
|
+
}
|
|
26933
|
+
/** Stamp the subscription id onto a notification's `_meta`. Non-mutating. */
|
|
26934
|
+
function stampSubscriptionId(notification, subscriptionId) {
|
|
26935
|
+
return {
|
|
26936
|
+
method: notification.method,
|
|
26937
|
+
params: {
|
|
26938
|
+
...notification.params,
|
|
26939
|
+
_meta: {
|
|
26940
|
+
...notification.params?._meta,
|
|
26941
|
+
[SUBSCRIPTION_ID_META_KEY]: subscriptionId
|
|
26509
26942
|
}
|
|
26510
|
-
if (this._responseMode === "sse" && !this._closed && !this._deferredResponse.settled) this.upgradeToSse();
|
|
26511
|
-
return promise;
|
|
26512
26943
|
}
|
|
26513
|
-
|
|
26514
|
-
|
|
26515
|
-
|
|
26516
|
-
|
|
26517
|
-
|
|
26518
|
-
|
|
26519
|
-
|
|
26520
|
-
|
|
26521
|
-
|
|
26522
|
-
|
|
26944
|
+
};
|
|
26945
|
+
}
|
|
26946
|
+
/**
|
|
26947
|
+
* Read the requested filter off a `subscriptions/listen` request body.
|
|
26948
|
+
* Returns the validated filter, or `undefined` when `params.notifications`
|
|
26949
|
+
* is absent or fails the schema (the caller answers `-32602` — the spec
|
|
26950
|
+
* marks `notifications` REQUIRED on the listen request).
|
|
26951
|
+
*/
|
|
26952
|
+
function parseListenFilter(message) {
|
|
26953
|
+
const outcome = codecForVersion(MODERN_WIRE_REVISION).validateRequest("subscriptions/listen", message);
|
|
26954
|
+
return outcome.ok ? outcome.value.params?.notifications : void 0;
|
|
26955
|
+
}
|
|
26956
|
+
function createListenRouter(options) {
|
|
26957
|
+
const { bus, onerror } = options;
|
|
26958
|
+
const maxSubscriptions = options.maxSubscriptions ?? 1024;
|
|
26959
|
+
const keepAliveMs = options.keepAliveMs ?? 15e3;
|
|
26960
|
+
const open = /* @__PURE__ */ new Set();
|
|
26961
|
+
function serve(message, signal, capabilities, serverInfo) {
|
|
26962
|
+
if (open.size >= maxSubscriptions) {
|
|
26963
|
+
onerror?.(/* @__PURE__ */ new Error(`subscriptions/listen refused: subscription limit reached (${maxSubscriptions})`));
|
|
26964
|
+
return jsonRpcError(message.id, -32603, "Subscription limit reached");
|
|
26523
26965
|
}
|
|
26524
|
-
|
|
26525
|
-
|
|
26526
|
-
|
|
26527
|
-
|
|
26528
|
-
|
|
26529
|
-
|
|
26530
|
-
|
|
26531
|
-
|
|
26532
|
-
|
|
26533
|
-
|
|
26534
|
-
|
|
26535
|
-
|
|
26536
|
-
|
|
26537
|
-
|
|
26538
|
-
|
|
26539
|
-
|
|
26540
|
-
this.finalizeStream();
|
|
26541
|
-
return;
|
|
26966
|
+
const filter = parseListenFilter(message);
|
|
26967
|
+
if (filter === void 0) return jsonRpcError(message.id, -32602, "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter");
|
|
26968
|
+
const honored = honoredSubset(filter, capabilities);
|
|
26969
|
+
const subscriptionId = message.id;
|
|
26970
|
+
const encoder = new TextEncoder();
|
|
26971
|
+
let controller;
|
|
26972
|
+
let closed = false;
|
|
26973
|
+
let unsubscribe;
|
|
26974
|
+
let keepAliveTimer;
|
|
26975
|
+
let abortCleanup;
|
|
26976
|
+
const writeFrame = (frame) => {
|
|
26977
|
+
if (closed) return;
|
|
26978
|
+
try {
|
|
26979
|
+
controller.enqueue(encoder.encode(frame));
|
|
26980
|
+
} catch (error) {
|
|
26981
|
+
onerror?.(error instanceof Error ? error : new Error(String(error)));
|
|
26542
26982
|
}
|
|
26543
|
-
|
|
26544
|
-
|
|
26545
|
-
|
|
26546
|
-
|
|
26547
|
-
|
|
26548
|
-
|
|
26549
|
-
|
|
26550
|
-
|
|
26551
|
-
|
|
26552
|
-
|
|
26553
|
-
|
|
26554
|
-
|
|
26555
|
-
|
|
26556
|
-
|
|
26557
|
-
|
|
26558
|
-
|
|
26559
|
-
|
|
26560
|
-
|
|
26561
|
-
|
|
26562
|
-
|
|
26563
|
-
|
|
26564
|
-
|
|
26565
|
-
this._closed = true;
|
|
26566
|
-
this._abortCleanup?.();
|
|
26567
|
-
this._abortCleanup = void 0;
|
|
26568
|
-
if (this._sse?.keepAliveTimer !== void 0) clearInterval(this._sse.keepAliveTimer);
|
|
26569
|
-
if (this._sse !== void 0 && !this._sse.closed) {
|
|
26570
|
-
this._sse.closed = true;
|
|
26983
|
+
};
|
|
26984
|
+
const writeNotification = (method, params) => {
|
|
26985
|
+
writeFrame(`event: message\ndata: ${JSON.stringify({
|
|
26986
|
+
jsonrpc: "2.0",
|
|
26987
|
+
method,
|
|
26988
|
+
params
|
|
26989
|
+
})}\n\n`);
|
|
26990
|
+
};
|
|
26991
|
+
const teardown = (graceful) => {
|
|
26992
|
+
if (closed) return;
|
|
26993
|
+
if (graceful) writeFrame(`event: message\ndata: ${JSON.stringify({
|
|
26994
|
+
jsonrpc: "2.0",
|
|
26995
|
+
id: subscriptionId,
|
|
26996
|
+
result: {
|
|
26997
|
+
resultType: "complete",
|
|
26998
|
+
_meta: {
|
|
26999
|
+
[SUBSCRIPTION_ID_META_KEY]: subscriptionId,
|
|
27000
|
+
[SERVER_INFO_META_KEY]: serverInfo
|
|
27001
|
+
}
|
|
27002
|
+
}
|
|
27003
|
+
})}\n\n`);
|
|
27004
|
+
closed = true;
|
|
26571
27005
|
try {
|
|
26572
|
-
|
|
27006
|
+
unsubscribe?.();
|
|
27007
|
+
} catch (error) {
|
|
27008
|
+
onerror?.(error instanceof Error ? error : new Error(String(error)));
|
|
27009
|
+
}
|
|
27010
|
+
if (keepAliveTimer !== void 0) clearInterval(keepAliveTimer);
|
|
27011
|
+
abortCleanup?.();
|
|
27012
|
+
open.delete(teardown);
|
|
27013
|
+
try {
|
|
27014
|
+
controller.close();
|
|
26573
27015
|
} catch {}
|
|
26574
|
-
}
|
|
26575
|
-
if (this._deferredResponse !== void 0 && !this._deferredResponse.settled) {
|
|
26576
|
-
this._deferredResponse.settled = true;
|
|
26577
|
-
this._deferredResponse.reject(new SdkError(SdkErrorCode.ConnectionClosed, "Connection closed before a response was produced"));
|
|
26578
|
-
}
|
|
26579
|
-
this.onclose?.();
|
|
26580
|
-
}
|
|
26581
|
-
settleResponse(response) {
|
|
26582
|
-
if (this._deferredResponse === void 0 || this._deferredResponse.settled) return;
|
|
26583
|
-
this._deferredResponse.settled = true;
|
|
26584
|
-
this._deferredResponse.resolve(response);
|
|
26585
|
-
}
|
|
26586
|
-
upgradeToSse() {
|
|
26587
|
-
let controller;
|
|
27016
|
+
};
|
|
26588
27017
|
const readable = new ReadableStream({
|
|
26589
|
-
start
|
|
27018
|
+
start(streamController) {
|
|
26590
27019
|
controller = streamController;
|
|
27020
|
+
const ack = stampSubscriptionId({
|
|
27021
|
+
method: "notifications/subscriptions/acknowledged",
|
|
27022
|
+
params: { notifications: honored }
|
|
27023
|
+
}, subscriptionId);
|
|
27024
|
+
writeNotification(ack.method, ack.params);
|
|
27025
|
+
if (Object.keys(honored).length === 0) {
|
|
27026
|
+
teardown(true);
|
|
27027
|
+
return;
|
|
27028
|
+
}
|
|
27029
|
+
unsubscribe = bus.subscribe((event) => {
|
|
27030
|
+
if (closed || !listenFilterAccepts(honored, event)) return;
|
|
27031
|
+
const note = stampSubscriptionId(serverEventToNotification(event), subscriptionId);
|
|
27032
|
+
writeNotification(note.method, note.params);
|
|
27033
|
+
});
|
|
27034
|
+
keepAliveTimer = armSseKeepAlive(keepAliveMs, () => writeFrame(": keepalive\n\n"));
|
|
27035
|
+
open.add(teardown);
|
|
26591
27036
|
},
|
|
26592
|
-
cancel
|
|
26593
|
-
|
|
27037
|
+
cancel() {
|
|
27038
|
+
teardown(false);
|
|
26594
27039
|
}
|
|
26595
27040
|
});
|
|
26596
|
-
|
|
26597
|
-
|
|
26598
|
-
|
|
26599
|
-
|
|
26600
|
-
|
|
26601
|
-
|
|
26602
|
-
|
|
27041
|
+
if (signal !== void 0) if (signal.aborted) teardown(false);
|
|
27042
|
+
else {
|
|
27043
|
+
const onAbort = () => teardown(false);
|
|
27044
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
27045
|
+
abortCleanup = () => signal.removeEventListener("abort", onAbort);
|
|
27046
|
+
}
|
|
27047
|
+
return new Response(readable, {
|
|
26603
27048
|
status: 200,
|
|
26604
27049
|
headers: {
|
|
26605
27050
|
"Content-Type": "text/event-stream",
|
|
@@ -26607,30 +27052,170 @@ var PerRequestHTTPServerTransport = class {
|
|
|
26607
27052
|
Connection: "keep-alive",
|
|
26608
27053
|
"X-Accel-Buffering": "no"
|
|
26609
27054
|
}
|
|
26610
|
-
})
|
|
27055
|
+
});
|
|
26611
27056
|
}
|
|
26612
|
-
|
|
26613
|
-
|
|
26614
|
-
|
|
26615
|
-
|
|
26616
|
-
|
|
26617
|
-
|
|
26618
|
-
|
|
27057
|
+
return {
|
|
27058
|
+
serve,
|
|
27059
|
+
closeAll() {
|
|
27060
|
+
for (const teardown of open) teardown(true);
|
|
27061
|
+
},
|
|
27062
|
+
get openCount() {
|
|
27063
|
+
return open.size;
|
|
26619
27064
|
}
|
|
26620
|
-
|
|
27065
|
+
};
|
|
27066
|
+
}
|
|
27067
|
+
const CHANGE_NOTIFICATION_METHODS = /* @__PURE__ */ new Set([
|
|
27068
|
+
"notifications/tools/list_changed",
|
|
27069
|
+
"notifications/prompts/list_changed",
|
|
27070
|
+
"notifications/resources/list_changed",
|
|
27071
|
+
"notifications/resources/updated"
|
|
27072
|
+
]);
|
|
27073
|
+
/**
|
|
27074
|
+
* Per-connection listen state for the stdio entry. One instance is held by
|
|
27075
|
+
* `serveStdio` for the connection lifetime; it routes inbound
|
|
27076
|
+
* `subscriptions/listen` / `notifications/cancelled` and rewrites outbound
|
|
27077
|
+
* change notifications onto the active subscriptions. No bus — the long-lived
|
|
27078
|
+
* pinned instance's existing `send*ListChanged()` calls feed straight into
|
|
27079
|
+
* `routeOutbound()`.
|
|
27080
|
+
*/
|
|
27081
|
+
var StdioListenRouter = class {
|
|
27082
|
+
/** Active subscriptions, keyed by the listen request's JSON-RPC id verbatim. */
|
|
27083
|
+
_subs = /* @__PURE__ */ new Map();
|
|
27084
|
+
/**
|
|
27085
|
+
* The serving instance's declared capabilities. Filled in by the entry
|
|
27086
|
+
* once the modern instance is constructed (the router is created before
|
|
27087
|
+
* the instance exists), so the acknowledged filter is narrowed against
|
|
27088
|
+
* what the server can actually deliver.
|
|
27089
|
+
*/
|
|
27090
|
+
_serverCapabilities;
|
|
27091
|
+
/**
|
|
27092
|
+
* The serving instance's identity, stamped onto the graceful-close
|
|
27093
|
+
* results' `_meta` (the spec's `SubscriptionsListenResultMetaObject` extends
|
|
27094
|
+
* `ResultMetaObject`). Handed over together with the capabilities.
|
|
27095
|
+
*/
|
|
27096
|
+
_serverInfo;
|
|
27097
|
+
constructor(_maxSubscriptions = DEFAULT_MAX_SUBSCRIPTIONS, serverCapabilities, serverInfo) {
|
|
27098
|
+
this._maxSubscriptions = _maxSubscriptions;
|
|
27099
|
+
this._serverCapabilities = serverCapabilities;
|
|
27100
|
+
this._serverInfo = serverInfo;
|
|
26621
27101
|
}
|
|
26622
|
-
|
|
26623
|
-
|
|
27102
|
+
/**
|
|
27103
|
+
* Record the serving instance's declared capabilities and identity once
|
|
27104
|
+
* it has been constructed. Called by `serveStdio`'s connect path;
|
|
27105
|
+
* subsequent `serve()` calls narrow the honored filter against the
|
|
27106
|
+
* capabilities, and `teardownAll()` stamps the identity.
|
|
27107
|
+
*/
|
|
27108
|
+
setServerCapabilities(capabilities, serverInfo) {
|
|
27109
|
+
this._serverCapabilities = capabilities;
|
|
27110
|
+
if (serverInfo !== void 0) this._serverInfo = serverInfo;
|
|
26624
27111
|
}
|
|
26625
|
-
|
|
26626
|
-
|
|
26627
|
-
|
|
26628
|
-
|
|
26629
|
-
|
|
26630
|
-
|
|
26631
|
-
|
|
27112
|
+
/** Whether `id` is an active listen subscription on this connection. */
|
|
27113
|
+
has(id) {
|
|
27114
|
+
return this._subs.has(id);
|
|
27115
|
+
}
|
|
27116
|
+
/**
|
|
27117
|
+
* Serve one inbound `subscriptions/listen` request: registers the
|
|
27118
|
+
* subscription and returns the stamped acknowledged notification (or, on
|
|
27119
|
+
* capacity / params rejection, the in-band JSON-RPC error response).
|
|
27120
|
+
*
|
|
27121
|
+
* @throws when called before {@linkcode setServerCapabilities} (or the
|
|
27122
|
+
* constructor) has supplied the serving instance's capabilities. Honoring a
|
|
27123
|
+
* filter without knowing the server's advertised capabilities would fail
|
|
27124
|
+
* open (deliver unadvertised types); the entry guarantees capabilities are
|
|
27125
|
+
* set before any listen request is routed here.
|
|
27126
|
+
*/
|
|
27127
|
+
serve(message) {
|
|
27128
|
+
if (this._serverCapabilities === void 0) throw new Error("StdioListenRouter.serve() called before setServerCapabilities(); refusing to honor a filter without capabilities");
|
|
27129
|
+
if (this._subs.size >= this._maxSubscriptions) return {
|
|
27130
|
+
jsonrpc: "2.0",
|
|
27131
|
+
id: message.id,
|
|
27132
|
+
error: {
|
|
27133
|
+
code: -32603,
|
|
27134
|
+
message: "Subscription limit reached"
|
|
27135
|
+
}
|
|
27136
|
+
};
|
|
27137
|
+
const filter = parseListenFilter(message);
|
|
27138
|
+
if (filter === void 0) return {
|
|
27139
|
+
jsonrpc: "2.0",
|
|
27140
|
+
id: message.id,
|
|
27141
|
+
error: {
|
|
27142
|
+
code: -32602,
|
|
27143
|
+
message: "Invalid params: 'notifications' is required and must be a valid SubscriptionFilter"
|
|
27144
|
+
}
|
|
27145
|
+
};
|
|
27146
|
+
const honored = honoredSubset(filter, this._serverCapabilities);
|
|
27147
|
+
this._subs.set(message.id, honored);
|
|
27148
|
+
return stampSubscriptionId({
|
|
27149
|
+
method: "notifications/subscriptions/acknowledged",
|
|
27150
|
+
params: { notifications: honored }
|
|
27151
|
+
}, message.id);
|
|
27152
|
+
}
|
|
27153
|
+
/**
|
|
27154
|
+
* Tear down one subscription (inbound `notifications/cancelled`). Returns
|
|
27155
|
+
* `true` when a subscription was removed. After this call NOTHING further
|
|
27156
|
+
* is delivered for that subscription id (the post-cancel hardening).
|
|
27157
|
+
*/
|
|
27158
|
+
cancel(id) {
|
|
27159
|
+
return this._subs.delete(id);
|
|
27160
|
+
}
|
|
27161
|
+
/**
|
|
27162
|
+
* Route an outbound notification through the active subscriptions.
|
|
27163
|
+
*
|
|
27164
|
+
* - For a subscription-gated change notification, returns one stamped copy
|
|
27165
|
+
* per subscription that opted in to it (an empty array means it is
|
|
27166
|
+
* dropped — the modern era never delivers an un-requested change type).
|
|
27167
|
+
* - For any other outbound message, returns `'passthrough'` (the entry
|
|
27168
|
+
* forwards it as-is).
|
|
27169
|
+
*/
|
|
27170
|
+
routeOutbound(message) {
|
|
27171
|
+
if (!CHANGE_NOTIFICATION_METHODS.has(message.method)) return "passthrough";
|
|
27172
|
+
const uriParam = message.params?.["uri"];
|
|
27173
|
+
const uri = typeof uriParam === "string" ? uriParam : void 0;
|
|
27174
|
+
const event = notificationToServerEvent(message.method, uri);
|
|
27175
|
+
const out = [];
|
|
27176
|
+
for (const [subscriptionId, filter] of this._subs) if (listenFilterAccepts(filter, event)) out.push(stampSubscriptionId({
|
|
27177
|
+
method: message.method,
|
|
27178
|
+
params: message.params ?? {}
|
|
27179
|
+
}, subscriptionId));
|
|
27180
|
+
return out;
|
|
27181
|
+
}
|
|
27182
|
+
/**
|
|
27183
|
+
* Server-side graceful teardown of every active subscription: returns the
|
|
27184
|
+
* empty `subscriptions/listen` JSON-RPC result for each subscription id —
|
|
27185
|
+
* the spec's graceful-close signal, `_meta` carrying the subscription id
|
|
27186
|
+
* and the serving instance's identity — for the entry to emit before
|
|
27187
|
+
* closing the wire. Clears the set so nothing further is delivered.
|
|
27188
|
+
*/
|
|
27189
|
+
teardownAll() {
|
|
27190
|
+
const out = [];
|
|
27191
|
+
for (const id of this._subs.keys()) out.push({
|
|
27192
|
+
jsonrpc: "2.0",
|
|
27193
|
+
id,
|
|
27194
|
+
result: {
|
|
27195
|
+
resultType: "complete",
|
|
27196
|
+
_meta: {
|
|
27197
|
+
[SUBSCRIPTION_ID_META_KEY]: id,
|
|
27198
|
+
...this._serverInfo !== void 0 && { ["io.modelcontextprotocol/serverInfo"]: this._serverInfo }
|
|
27199
|
+
}
|
|
27200
|
+
}
|
|
27201
|
+
});
|
|
27202
|
+
this._subs.clear();
|
|
27203
|
+
return out;
|
|
26632
27204
|
}
|
|
26633
27205
|
};
|
|
27206
|
+
function notificationToServerEvent(method, uri) {
|
|
27207
|
+
switch (method) {
|
|
27208
|
+
case "notifications/tools/list_changed": return { kind: "tools_list_changed" };
|
|
27209
|
+
case "notifications/prompts/list_changed": return { kind: "prompts_list_changed" };
|
|
27210
|
+
case "notifications/resources/list_changed": return { kind: "resources_list_changed" };
|
|
27211
|
+
default: return {
|
|
27212
|
+
kind: "resource_updated",
|
|
27213
|
+
uri: uri ?? ""
|
|
27214
|
+
};
|
|
27215
|
+
}
|
|
27216
|
+
}
|
|
27217
|
+
//#endregion
|
|
27218
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/index.mjs
|
|
26634
27219
|
/**
|
|
26635
27220
|
* Serves one classified inbound message on the given server instance and
|
|
26636
27221
|
* returns the HTTP response for the exchange.
|
|
@@ -27430,7 +28015,10 @@ function jsonRpcErrorResponse(httpStatus, code, message, data, id = null) {
|
|
|
27430
28015
|
...data !== void 0 && { data }
|
|
27431
28016
|
},
|
|
27432
28017
|
id
|
|
27433
|
-
}, {
|
|
28018
|
+
}, {
|
|
28019
|
+
status: httpStatus,
|
|
28020
|
+
...httpStatus === 405 && { headers: { Allow: "POST" } }
|
|
28021
|
+
});
|
|
27434
28022
|
}
|
|
27435
28023
|
function rejectionResponse(rejection, id = null) {
|
|
27436
28024
|
return jsonRpcErrorResponse(rejection.httpStatus, rejection.code, rejection.message, rejection.data, id);
|
|
@@ -27793,7 +28381,7 @@ function createMcpHandler(factory, options = {}) {
|
|
|
27793
28381
|
const inputSchema = toolName === void 0 ? void 0 : product.toolInputSchemaJson(toolName);
|
|
27794
28382
|
if (inputSchema !== void 0) {
|
|
27795
28383
|
const scan = scanXMcpHeaderDeclarations(inputSchema);
|
|
27796
|
-
if (scan.
|
|
28384
|
+
if (scan.declarations !== void 0 && scan.declarations.length > 0) {
|
|
27797
28385
|
const rejection = validateMcpParamHeaders(scan.declarations, callParams?.arguments, request.headers);
|
|
27798
28386
|
if (rejection !== void 0) {
|
|
27799
28387
|
product.close().catch(reportError);
|
|
@@ -28419,7 +29007,7 @@ const memoisedUntilFailure = (load) => {
|
|
|
28419
29007
|
* processes never touch an article, and it is the heaviest code in the bundle.
|
|
28420
29008
|
* `tests/unit/module-graph.test.ts` keeps it off the static graph.
|
|
28421
29009
|
*/
|
|
28422
|
-
const loadArticleFormat = memoisedUntilFailure(() => import("./article-sections-
|
|
29010
|
+
const loadArticleFormat = memoisedUntilFailure(() => import("./article-sections-DA7_Jm2H.js"));
|
|
28423
29011
|
//#endregion
|
|
28424
29012
|
//#region src/utils/formatting.ts
|
|
28425
29013
|
const truncateIfNeeded = (text, advice = "Use pagination or filters to reduce results.") => {
|
|
@@ -33761,9 +34349,9 @@ const registerSingleProxies = (registration, tools) => {
|
|
|
33761
34349
|
* (`dev/reload.ts`) can keep this long-lived shell (and its transport/session)
|
|
33762
34350
|
* alive while swapping the toolset underneath it via `registerToolset`.
|
|
33763
34351
|
*/
|
|
33764
|
-
const createServerShell = (config, requestStateCodec = createRequestStateCodec({})) => {
|
|
34352
|
+
const createServerShell = (config, requestStateCodec = createRequestStateCodec({}), extraInstructions) => {
|
|
33765
34353
|
const pkg = readPackageInfo();
|
|
33766
|
-
const instructions = buildInstructions(config);
|
|
34354
|
+
const instructions = [buildInstructions(config), extraInstructions].filter((block) => block !== void 0).join("\n\n") || void 0;
|
|
33767
34355
|
return new McpServer({
|
|
33768
34356
|
name: pkg.name,
|
|
33769
34357
|
version: pkg.version
|
|
@@ -34081,8 +34669,8 @@ const toolEnv = (config) => ({
|
|
|
34081
34669
|
subdomain: config.subdomain,
|
|
34082
34670
|
brandIds: config.brandIds
|
|
34083
34671
|
});
|
|
34084
|
-
const createMcpServer = (config, getToken, logger = silentLogger, onUnauthorized, { caches = createServerCaches(config, getToken, onUnauthorized), requestStateCodec, slaRuntime = createSlaRuntime(config), listens, getBackgroundToken, alertPolling = "server", tools = createAllTools(toolEnv(config)) } = {}) => {
|
|
34085
|
-
const server = createServerShell(config, requestStateCodec);
|
|
34672
|
+
const createMcpServer = (config, getToken, logger = silentLogger, onUnauthorized, { caches = createServerCaches(config, getToken, onUnauthorized), requestStateCodec, slaRuntime = createSlaRuntime(config), listens, getBackgroundToken, alertPolling = "server", tools = createAllTools(toolEnv(config)), extraInstructions, decorate } = {}) => {
|
|
34673
|
+
const server = createServerShell(config, requestStateCodec, extraInstructions);
|
|
34086
34674
|
const sla = createSlaService(slaSettings(config), slaRuntime, caches.resolveUserId);
|
|
34087
34675
|
registerToolset(server, {
|
|
34088
34676
|
config,
|
|
@@ -34104,9 +34692,12 @@ const createMcpServer = (config, getToken, logger = silentLogger, onUnauthorized
|
|
|
34104
34692
|
installAlertSubscriptions(server, config, reader, logger, listens);
|
|
34105
34693
|
}
|
|
34106
34694
|
}
|
|
34695
|
+
decorate?.(server);
|
|
34107
34696
|
return server;
|
|
34108
34697
|
};
|
|
34109
|
-
const defaultServerFactory = ({ config, getToken, logger, onUnauthorized, caches, tools, requestStateCodec, slaRuntime, listens, getBackgroundToken, alertPolling }) => createMcpServer(config, getToken, logger, onUnauthorized, {
|
|
34698
|
+
const defaultServerFactory = ({ config, getToken, logger, onUnauthorized, caches, tools, requestStateCodec, slaRuntime, listens, getBackgroundToken, alertPolling, extraInstructions, decorate }) => createMcpServer(config, getToken, logger, onUnauthorized, {
|
|
34699
|
+
extraInstructions,
|
|
34700
|
+
decorate,
|
|
34110
34701
|
...caches ? { caches } : {},
|
|
34111
34702
|
...tools ? { tools } : {},
|
|
34112
34703
|
...slaRuntime ? { slaRuntime } : {},
|
|
@@ -34116,7 +34707,7 @@ const defaultServerFactory = ({ config, getToken, logger, onUnauthorized, caches
|
|
|
34116
34707
|
requestStateCodec
|
|
34117
34708
|
});
|
|
34118
34709
|
//#endregion
|
|
34119
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
34710
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.4.0/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
|
|
34120
34711
|
/**
|
|
34121
34712
|
* Marks a stdout `'error'` listener that a closed transport left attached purely to
|
|
34122
34713
|
* swallow late write failures (see {@link StdioServerTransport.close}). A fresh
|
|
@@ -35146,7 +35737,7 @@ const installShutdown = (options) => {
|
|
|
35146
35737
|
//#endregion
|
|
35147
35738
|
//#region src/index.ts
|
|
35148
35739
|
const buildStdioTokenStore = async (config, logger) => {
|
|
35149
|
-
const { createTokenStore } = await import("./token-store-
|
|
35740
|
+
const { createTokenStore } = await import("./token-store-EwRwZiJO.js");
|
|
35150
35741
|
return createTokenStore({
|
|
35151
35742
|
subdomain: config.subdomain,
|
|
35152
35743
|
oauthClientId: config.oauthClientId,
|
|
@@ -35196,7 +35787,7 @@ const main = async () => {
|
|
|
35196
35787
|
logger,
|
|
35197
35788
|
cleanup: async () => (await starting?.catch(() => void 0))?.close()
|
|
35198
35789
|
});
|
|
35199
|
-
const { startHttpTransport } = await import("./http-
|
|
35790
|
+
const { startHttpTransport } = await import("./http-DuRcQrOc.js");
|
|
35200
35791
|
starting = startHttpTransport(config, logger);
|
|
35201
35792
|
await starting;
|
|
35202
35793
|
};
|
|
@@ -35206,4 +35797,4 @@ main().catch((error) => {
|
|
|
35206
35797
|
process.exit(1);
|
|
35207
35798
|
});
|
|
35208
35799
|
//#endregion
|
|
35209
|
-
export {
|
|
35800
|
+
export { _enum as $, ResourceTemplate as A, stampErrorBrands as B, DEFAULT_CALLBACK_PORT as C, createMcpHandler as D, WebStandardStreamableHTTPServerTransport as E, ProtocolErrorCode as F, ResultSchema as G, PaginatedRequestParamsSchema as H, ResourceNotFoundError as I, toStrictStandardSchema as J, buildInstructions as K, assertValidCacheHint as L, OAuthError as M, OAuthErrorCode as N, isLegacyRequest as O, ProtocolError as P, errnoCode as Q, brandedHasInstance as R, deadlineSignal as S, DEFAULT_MAX_REQUEST_BODY_SIZE as T, PaginatedResultSchema as U, BaseRequestParamsSchema as V, ResourceSchema as W, STARTUP_DOCS as X, compareCodeUnits as Y, createStartupError as Z, createAllTools as _, toolEnv as a, object as at, zendeskGet as b, clearToken as c, union as ct, resolveTokenPath as d, array as et, saveToken as f, silentLogger as g, readPackageInfo as h, defaultServerFactory as i, number$1 as it, verifyBearerToken as j, McpServer as k, configDir as l, unknown as lt, createRequestStateCodec as m, listenedUris as n, literal as nt, watchGrantAlerts as o, record as ot, signInRequiredError as p, Namespace as q, createServerCaches as r, looseObject as rt, startSlaRuntime as s, string as st, createListenFeed as t, boolean as tt, loadToken as u, createTopologyProvider as v, getOAuthUrls as w, REQUEST_TIMEOUT_MS as x, ZendeskApiError as y, isModernProtocolVersion as z };
|