@fruggr/zendesk-mcp-server 3.3.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/THIRD-PARTY-NOTICES.md +7 -7
- package/dist/{http-GIKJdf05.js → http-BYYYoQaK.js} +45 -17
- package/dist/index.js +251 -75
- package/dist/sbom.cdx.json +19 -19
- package/dist/{token-persistence-BeetFqPF.js → token-persistence-BUHh23BM.js} +1 -1
- package/dist/{token-store-Aq7gP39o.js → token-store-BLAkLLQO.js} +2 -2
- package/package.json +6 -6
|
@@ -30,9 +30,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
30
30
|
SOFTWARE.
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
## @modelcontextprotocol/core@2.
|
|
33
|
+
## @modelcontextprotocol/core@2.3.1
|
|
34
34
|
|
|
35
|
-
License:
|
|
35
|
+
License: Apache-2.0
|
|
36
36
|
|
|
37
37
|
```
|
|
38
38
|
The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
|
|
@@ -253,9 +253,9 @@ CC-BY-4.0. See https://creativecommons.org/licenses/by/4.0/legalcode for
|
|
|
253
253
|
the full license text.
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
-
## @modelcontextprotocol/node@2.1.
|
|
256
|
+
## @modelcontextprotocol/node@2.1.1
|
|
257
257
|
|
|
258
|
-
License:
|
|
258
|
+
License: Apache-2.0
|
|
259
259
|
|
|
260
260
|
```
|
|
261
261
|
The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
|
|
@@ -476,9 +476,9 @@ CC-BY-4.0. See https://creativecommons.org/licenses/by/4.0/legalcode for
|
|
|
476
476
|
the full license text.
|
|
477
477
|
```
|
|
478
478
|
|
|
479
|
-
## @modelcontextprotocol/server@2.
|
|
479
|
+
## @modelcontextprotocol/server@2.3.1
|
|
480
480
|
|
|
481
|
-
License:
|
|
481
|
+
License: Apache-2.0
|
|
482
482
|
|
|
483
483
|
```
|
|
484
484
|
The MCP project is undergoing a licensing transition from the MIT License to the Apache License, Version 2.0 ("Apache-2.0"). All new code and specification contributions to the project are licensed under Apache-2.0. Documentation contributions (excluding specifications) are licensed under CC-BY-4.0.
|
|
@@ -2629,7 +2629,7 @@ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
|
2629
2629
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
2630
2630
|
```
|
|
2631
2631
|
|
|
2632
|
-
## mdast-util-find-and-replace@3.0.
|
|
2632
|
+
## mdast-util-find-and-replace@3.0.3
|
|
2633
2633
|
|
|
2634
2634
|
License: MIT
|
|
2635
2635
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { _ as
|
|
3
|
-
import { d as escapeHtml, l as requestedScope, n as configDir, o as generateCodeChallenge, s as generateCodeVerifier, u as supportedScopes } from "./token-persistence-
|
|
2
|
+
import { _ as __commonJSMin, a as verifyBearerToken, b as __toESM, c as zendeskGet, f as getOAuthUrls, h as errnoCode, i as WebStandardStreamableHTTPServerTransport, l as REQUEST_TIMEOUT_MS, m as createStartupError, o as OAuthError, p as STARTUP_DOCS, r as silentLogger, s as OAuthErrorCode, t as createMcpServer, u as deadlineSignal, v as __exportAll, y as __require } from "./index.js";
|
|
3
|
+
import { d as escapeHtml, l as requestedScope, n as configDir, o as generateCodeChallenge, s as generateCodeVerifier, u as supportedScopes } from "./token-persistence-BUHh23BM.js";
|
|
4
4
|
import * as util$1 from "node:util";
|
|
5
5
|
import { format, inspect } from "node:util";
|
|
6
6
|
import * as crypto$2 from "node:crypto";
|
|
@@ -16,7 +16,7 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
16
16
|
import { accessSync, chmodSync, constants, mkdirSync, readFileSync, renameSync, statSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { Http2ServerRequest, constants as constants$1 } from "http2";
|
|
18
18
|
import crypto$1 from "crypto";
|
|
19
|
-
//#region node_modules/.pnpm/@hono+node-server@1.19.17_hono@4.13.
|
|
19
|
+
//#region node_modules/.pnpm/@hono+node-server@1.19.17_hono@4.13.13/node_modules/@hono/node-server/dist/index.mjs
|
|
20
20
|
var RequestError = class extends Error {
|
|
21
21
|
constructor(message, options) {
|
|
22
22
|
super(message, options);
|
|
@@ -504,7 +504,7 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
504
504
|
};
|
|
505
505
|
};
|
|
506
506
|
//#endregion
|
|
507
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+node@2.1.
|
|
507
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+node@2.1.1_@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/node/dist/index.mjs
|
|
508
508
|
/**
|
|
509
509
|
* Server transport for Streamable HTTP: this implements the MCP Streamable HTTP transport specification.
|
|
510
510
|
* It supports both SSE streaming and direct HTTP responses.
|
|
@@ -543,8 +543,12 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
543
543
|
*
|
|
544
544
|
* @example Using with a pre-parsed request body (e.g. Express)
|
|
545
545
|
* ```ts source="./streamableHttp.examples.ts#NodeStreamableHTTPServerTransport_express"
|
|
546
|
-
* app.post('/mcp', (req, res) => {
|
|
547
|
-
* transport
|
|
546
|
+
* app.post('/mcp', async (req, res) => {
|
|
547
|
+
* // Stateless example: create a server and a transport per request.
|
|
548
|
+
* const server = new McpServer({ name: 'my-server', version: '1.0.0' });
|
|
549
|
+
* const transport = new NodeStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
550
|
+
* await server.connect(transport);
|
|
551
|
+
* await transport.handleRequest(req, res, req.body);
|
|
548
552
|
* });
|
|
549
553
|
* ```
|
|
550
554
|
*/
|
|
@@ -36178,16 +36182,16 @@ const resolveMasterSecret = (input, logger = silentLogger) => {
|
|
|
36178
36182
|
//#endregion
|
|
36179
36183
|
//#region src/auth/server/authorization-server.ts
|
|
36180
36184
|
const decoder = new TextDecoder();
|
|
36181
|
-
const asVerified = (claims, issuer
|
|
36182
|
-
|
|
36183
|
-
if (!(claims.iss === issuer && audiences.includes(resource) && typeof claims.exp === "number" && claims.exp * 1e3 > Date.now() && typeof claims.zd === "string" && typeof claims.gid === "string")) return void 0;
|
|
36185
|
+
const asVerified = (claims, issuer) => {
|
|
36186
|
+
if (!(claims.iss === issuer && typeof claims.exp === "number" && typeof claims.zd === "string" && typeof claims.gid === "string")) return void 0;
|
|
36184
36187
|
return {
|
|
36185
36188
|
zendeskAccessToken: claims.zd,
|
|
36186
36189
|
grantId: claims.gid,
|
|
36187
36190
|
clientId: String(claims.client_id),
|
|
36188
36191
|
subject: String(claims.sub),
|
|
36189
36192
|
canWrite: typeof claims.scope === "string" && claims.scope.split(" ").includes("write"),
|
|
36190
|
-
expiresAt: claims.exp
|
|
36193
|
+
expiresAt: claims.exp,
|
|
36194
|
+
resource: typeof claims.aud === "string" ? claims.aud : void 0
|
|
36191
36195
|
};
|
|
36192
36196
|
};
|
|
36193
36197
|
const createAuthorizationServer = (options) => {
|
|
@@ -36252,7 +36256,7 @@ const createAuthorizationServer = (options) => {
|
|
|
36252
36256
|
const keySet = ring.find((set) => set.accessToken.kid === kid);
|
|
36253
36257
|
if (!keySet) return void 0;
|
|
36254
36258
|
const { plaintext } = await compactDecrypt(bearer, keySet.accessToken.key);
|
|
36255
|
-
return asVerified(JSON.parse(decoder.decode(plaintext)), issuer
|
|
36259
|
+
return asVerified(JSON.parse(decoder.decode(plaintext)), issuer);
|
|
36256
36260
|
};
|
|
36257
36261
|
return {
|
|
36258
36262
|
issuer,
|
|
@@ -36414,11 +36418,36 @@ const resolvePublicUrl = (config, logger = silentLogger) => {
|
|
|
36414
36418
|
return `http://${config.host}:${config.port}`;
|
|
36415
36419
|
};
|
|
36416
36420
|
const MISSING_BEARER_MESSAGE = "Missing or invalid access token. Sign in through this server: its OAuth authorization server is named in the protected resource metadata.";
|
|
36417
|
-
const
|
|
36421
|
+
const SPACES = / +/;
|
|
36422
|
+
/**
|
|
36423
|
+
* The access token on this request, or `undefined` when it must be refused.
|
|
36424
|
+
* The SDK parses the header and checks the audience against our `/mcp`
|
|
36425
|
+
* resource (`expectedResource`) and the expiry; decrypting and every other
|
|
36426
|
+
* claim stay with the authorization server.
|
|
36427
|
+
*/
|
|
36428
|
+
const authenticate = async (request, as) => {
|
|
36418
36429
|
const header = request.headers["authorization"];
|
|
36419
|
-
|
|
36420
|
-
|
|
36421
|
-
|
|
36430
|
+
const verifier = { verifyAccessToken: async (bearer) => {
|
|
36431
|
+
const token = await as.verifyAccessToken(bearer);
|
|
36432
|
+
if (!token) throw new OAuthError(OAuthErrorCode.InvalidToken, "Invalid access token");
|
|
36433
|
+
return {
|
|
36434
|
+
token: bearer,
|
|
36435
|
+
clientId: token.clientId,
|
|
36436
|
+
scopes: [],
|
|
36437
|
+
expiresAt: token.expiresAt,
|
|
36438
|
+
...token.resource && URL.canParse(token.resource) && { resource: new URL(token.resource) },
|
|
36439
|
+
extra: { verified: token }
|
|
36440
|
+
};
|
|
36441
|
+
} };
|
|
36442
|
+
try {
|
|
36443
|
+
const normalized = typeof header === "string" ? header.replace(SPACES, " ") : void 0;
|
|
36444
|
+
return (await verifyBearerToken(normalized, {
|
|
36445
|
+
verifier,
|
|
36446
|
+
expectedResource: new URL(as.resource)
|
|
36447
|
+
})).extra?.["verified"];
|
|
36448
|
+
} catch {
|
|
36449
|
+
return;
|
|
36450
|
+
}
|
|
36422
36451
|
};
|
|
36423
36452
|
const PROTECTED_RESOURCE_PATHS = ["/.well-known/oauth-protected-resource/mcp", "/.well-known/oauth-protected-resource"];
|
|
36424
36453
|
const sendJson = (res, status, body) => {
|
|
@@ -36572,8 +36601,7 @@ const startHttpTransport = async (config, logger = silentLogger, options = {}) =
|
|
|
36572
36601
|
await transport.handleRequest(req, res, body);
|
|
36573
36602
|
};
|
|
36574
36603
|
const handleMcpRequest = async (req, res, as) => {
|
|
36575
|
-
const
|
|
36576
|
-
const token = bearer ? await as.verifyAccessToken(bearer) : void 0;
|
|
36604
|
+
const token = await authenticate(req, as);
|
|
36577
36605
|
if (!token) {
|
|
36578
36606
|
sendUnauthorized(res, as.issuer);
|
|
36579
36607
|
return;
|
package/dist/index.js
CHANGED
|
@@ -7546,6 +7546,92 @@ const isStartupError = (err) => err instanceof Error && err.name === "StartupErr
|
|
|
7546
7546
|
/** The errno code of a failed filesystem call, for the message. */
|
|
7547
7547
|
const errnoCode = (err) => err?.code ?? "unknown error";
|
|
7548
7548
|
//#endregion
|
|
7549
|
+
//#region src/utils/validation.ts
|
|
7550
|
+
const formatPath = (path) => path.map(String).join(".");
|
|
7551
|
+
const formatIssue$1 = (issue) => issue.path.length > 0 ? `${formatPath(issue.path)}: ${issue.message}` : issue.message;
|
|
7552
|
+
/**
|
|
7553
|
+
* `path: message` per issue, joined by `; ` since zod messages carry commas.
|
|
7554
|
+
* Ours rather than the SDK's (not exported): one wording for every mode and for
|
|
7555
|
+
* startup config errors, stable across SDK bumps.
|
|
7556
|
+
*/
|
|
7557
|
+
const formatIssues = (issues) => issues.map(formatIssue$1).join("; ");
|
|
7558
|
+
const unwrap$1 = (node) => node._zod.def.innerType ? unwrap$1(node._zod.def.innerType) : node;
|
|
7559
|
+
/**
|
|
7560
|
+
* Keys declared by the object at `path`, or undefined when no plain object sits
|
|
7561
|
+
* there (a record, say, whose keys zod checks against an enum).
|
|
7562
|
+
*/
|
|
7563
|
+
const keysAt = (node, path) => {
|
|
7564
|
+
const { def } = unwrap$1(node)._zod;
|
|
7565
|
+
if (path.length === 0) return def.shape && Object.keys(def.shape);
|
|
7566
|
+
const [head, ...rest] = path;
|
|
7567
|
+
const child = typeof head === "number" ? def.element : def.shape?.[String(head)];
|
|
7568
|
+
return child && keysAt(child, rest);
|
|
7569
|
+
};
|
|
7570
|
+
const keyList = (keys) => [...keys].sort().join(", ") || "(none)";
|
|
7571
|
+
/** One sentence per object holding unknown keys, the top level first. */
|
|
7572
|
+
const unknownKeysMessage = (schema, issues, topLevelKeys) => [...issues].sort((a, b) => a.path.length - b.path.length).map(({ path, keys }) => {
|
|
7573
|
+
if (path.length === 0) return `Unknown parameter(s): ${keys.join(", ")}. Valid parameters: ${topLevelKeys}.`;
|
|
7574
|
+
const parent = formatPath(path);
|
|
7575
|
+
const unknown = `Unknown parameter(s): ${keys.map((key) => `${parent}.${key}`).join(", ")}.`;
|
|
7576
|
+
const valid = keysAt(schema, path);
|
|
7577
|
+
return valid ? `${unknown} Valid parameters for ${parent}: ${keyList(valid)}.` : unknown;
|
|
7578
|
+
}).join(" ");
|
|
7579
|
+
/**
|
|
7580
|
+
* Build a strict validator for a tool's input schema, computing the strict
|
|
7581
|
+
* schema and the valid-key list once at construction rather than per call.
|
|
7582
|
+
*
|
|
7583
|
+
* Zod objects default to `strip`, which silently drops unknown keys. That hid
|
|
7584
|
+
* #100: a caller passing `per_page` to list_tickets (whose parameter is
|
|
7585
|
+
* `page_size`) had the key dropped, so a large unpaginated page came back. The
|
|
7586
|
+
* validator rejects unknown keys and names both the offending ones and the
|
|
7587
|
+
* valid parameters, so a misremembered name fails loudly. Any other failure is
|
|
7588
|
+
* one `path: message` per issue (#206). When both occur only the unknown keys
|
|
7589
|
+
* are reported: a guessed name is the one error a caller cannot spot by
|
|
7590
|
+
* re-reading its own arguments.
|
|
7591
|
+
*/
|
|
7592
|
+
const createStrictValidator = (schema, strict = schema.strict()) => {
|
|
7593
|
+
const topLevelKeys = keyList(Object.keys(schema.shape));
|
|
7594
|
+
return (params) => {
|
|
7595
|
+
const result = strict.safeParse(params);
|
|
7596
|
+
if (result.success) return {
|
|
7597
|
+
success: true,
|
|
7598
|
+
data: result.data
|
|
7599
|
+
};
|
|
7600
|
+
const unknownKeyIssues = result.error.issues.filter((issue) => issue.code === "unrecognized_keys");
|
|
7601
|
+
return {
|
|
7602
|
+
success: false,
|
|
7603
|
+
message: unknownKeyIssues.length > 0 ? unknownKeysMessage(schema, unknownKeyIssues, topLevelKeys) : `Invalid parameter(s): ${formatIssues(result.error.issues)}`
|
|
7604
|
+
};
|
|
7605
|
+
};
|
|
7606
|
+
};
|
|
7607
|
+
/** The proxy dispatch path (namespace/single modes): throws the validator's message. */
|
|
7608
|
+
const createStrictParamsParser = (schema) => {
|
|
7609
|
+
const validate = createStrictValidator(schema);
|
|
7610
|
+
return (params) => {
|
|
7611
|
+
const result = validate(params);
|
|
7612
|
+
if (!result.success) throw new Error(result.message);
|
|
7613
|
+
return result.data;
|
|
7614
|
+
};
|
|
7615
|
+
};
|
|
7616
|
+
/**
|
|
7617
|
+
* The same validator as a Standard Schema, for `all` mode: the SDK calls this
|
|
7618
|
+
* `validate` and prints our pathless issue after its own prefix, so all three
|
|
7619
|
+
* modes word an error alike. The JSON Schema is zod's own, untouched.
|
|
7620
|
+
*/
|
|
7621
|
+
const toStrictStandardSchema = (schema) => {
|
|
7622
|
+
const strict = schema.strict();
|
|
7623
|
+
const validate = createStrictValidator(schema, strict);
|
|
7624
|
+
return { "~standard": {
|
|
7625
|
+
version: 1,
|
|
7626
|
+
vendor: "zendesk-mcp-server",
|
|
7627
|
+
validate: (value) => {
|
|
7628
|
+
const result = validate(value);
|
|
7629
|
+
return result.success ? { value: result.data } : { issues: [{ message: result.message }] };
|
|
7630
|
+
},
|
|
7631
|
+
jsonSchema: strict["~standard"].jsonSchema
|
|
7632
|
+
} };
|
|
7633
|
+
};
|
|
7634
|
+
//#endregion
|
|
7549
7635
|
//#region src/config.ts
|
|
7550
7636
|
const ToolMode = _enum([
|
|
7551
7637
|
"single",
|
|
@@ -7790,7 +7876,7 @@ const parseStrict = (args) => {
|
|
|
7790
7876
|
const validated = (input) => {
|
|
7791
7877
|
const result = ConfigSchema.safeParse(input);
|
|
7792
7878
|
if (result.success) return result.data;
|
|
7793
|
-
throw createStartupError(`${result.error.issues
|
|
7879
|
+
throw createStartupError(`${formatIssues(result.error.issues)}.`, STARTUP_DOCS.cliReference, result.error);
|
|
7794
7880
|
};
|
|
7795
7881
|
const parseCliArgs = (args) => {
|
|
7796
7882
|
const { values, positionals } = parseStrict(args);
|
|
@@ -8240,7 +8326,7 @@ const createBrandSubdomainResolver = (subdomain, getToken) => {
|
|
|
8240
8326
|
};
|
|
8241
8327
|
};
|
|
8242
8328
|
//#endregion
|
|
8243
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
8329
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
|
|
8244
8330
|
var __create = Object.create;
|
|
8245
8331
|
var __defProp = Object.defineProperty;
|
|
8246
8332
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -8272,7 +8358,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
8272
8358
|
enumerable: true
|
|
8273
8359
|
}) : target, mod));
|
|
8274
8360
|
//#endregion
|
|
8275
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
8361
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/dialects-DoSzNhcb.mjs
|
|
8276
8362
|
/**
|
|
8277
8363
|
* Canonical `$schema` URIs per supported dialect (http + https variants, trailing-`#` stripped).
|
|
8278
8364
|
*/
|
|
@@ -9935,7 +10021,7 @@ const OAuthTokenRevocationRequestSchema = object({
|
|
|
9935
10021
|
token_type_hint: string$2().optional()
|
|
9936
10022
|
}).strip();
|
|
9937
10023
|
//#endregion
|
|
9938
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
10024
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/src-Cqbh3MYc.mjs
|
|
9939
10025
|
/**
|
|
9940
10026
|
* Cross-bundle `instanceof` support for the SDK error classes.
|
|
9941
10027
|
*
|
|
@@ -12990,7 +13076,7 @@ function build() {
|
|
|
12990
13076
|
const subscriptionsListenParamsShape = { notifications: SubscriptionFilterSchema$1 };
|
|
12991
13077
|
const SubscriptionsListenRequestSchema$1 = wireRequest("subscriptions/listen", subscriptionsListenParamsShape);
|
|
12992
13078
|
/**
|
|
12993
|
-
* Anchor
|
|
13079
|
+
* Anchor SubscriptionsListenResultMetaObject — required subscriptionId stamp on
|
|
12994
13080
|
* the graceful-close result. Extends `ResultMetaObject` since spec PR
|
|
12995
13081
|
* #3002 (composed, so the serverInfo key and its leniency stay single-sourced).
|
|
12996
13082
|
*/
|
|
@@ -13263,7 +13349,8 @@ function build() {
|
|
|
13263
13349
|
ListResourceTemplatesResultResponseSchema: wireResultResponse(ListResourceTemplatesResultSchema$1),
|
|
13264
13350
|
ReadResourceResultResponseSchema: wireResultResponse(union([ReadResourceResultSchema$1, InputRequiredResultSchema])),
|
|
13265
13351
|
CompleteResultResponseSchema: wireResultResponse(CompleteResultSchema$1),
|
|
13266
|
-
DiscoverResultResponseSchema: wireResultResponse(DiscoverResultSchema$1)
|
|
13352
|
+
DiscoverResultResponseSchema: wireResultResponse(DiscoverResultSchema$1),
|
|
13353
|
+
SubscriptionsListenResultResponseSchema: wireResultResponse(SubscriptionsListenResultSchema$1)
|
|
13267
13354
|
};
|
|
13268
13355
|
}
|
|
13269
13356
|
let memo;
|
|
@@ -14007,6 +14094,10 @@ function isSpecRequestMethod(method) {
|
|
|
14007
14094
|
function isSpecNotificationMethod(method) {
|
|
14008
14095
|
return ALL_CODECS.some((codec) => codec.hasNotificationMethod(method));
|
|
14009
14096
|
}
|
|
14097
|
+
/** The names SEP-2663 re-defines for the Tasks extension on the era that removed them from core. */
|
|
14098
|
+
function isExtensionReusedRequestMethod(method) {
|
|
14099
|
+
return method === "tasks/get" || method === "tasks/cancel";
|
|
14100
|
+
}
|
|
14010
14101
|
const ALL_CODECS = [rev2025Codec, rev2026Codec];
|
|
14011
14102
|
var schemas_exports = /* @__PURE__ */ __exportAll({
|
|
14012
14103
|
AnnotationsSchema: () => AnnotationsSchema,
|
|
@@ -15039,6 +15130,8 @@ var Protocol = class {
|
|
|
15039
15130
|
_transport;
|
|
15040
15131
|
_requestMessageId = 0;
|
|
15041
15132
|
_requestHandlers = /* @__PURE__ */ new Map();
|
|
15133
|
+
/** Methods registered with an explicit schema; the era gate in `_onrequest` reads it for the Tasks extension names. */
|
|
15134
|
+
_customSchemaRequestMethods = /* @__PURE__ */ new Set();
|
|
15042
15135
|
_requestHandlerAbortControllers = /* @__PURE__ */ new Map();
|
|
15043
15136
|
_notificationHandlers = /* @__PURE__ */ new Map();
|
|
15044
15137
|
_responseHandlers = /* @__PURE__ */ new Map();
|
|
@@ -15316,7 +15409,7 @@ var Protocol = class {
|
|
|
15316
15409
|
return;
|
|
15317
15410
|
}
|
|
15318
15411
|
}
|
|
15319
|
-
if (isSpecRequestMethod(request.method) && !codec.hasRequestMethod(request.method)) {
|
|
15412
|
+
if (isSpecRequestMethod(request.method) && !codec.hasRequestMethod(request.method) && !(isExtensionReusedRequestMethod(request.method) && this._customSchemaRequestMethods.has(request.method))) {
|
|
15320
15413
|
sendErrorResponse(ProtocolErrorCode.MethodNotFound, "Method not found");
|
|
15321
15414
|
return;
|
|
15322
15415
|
}
|
|
@@ -15449,8 +15542,11 @@ var Protocol = class {
|
|
|
15449
15542
|
}
|
|
15450
15543
|
request(request, schemaOrOptions, maybeOptions) {
|
|
15451
15544
|
const codec = this._resolveOutboundCodec(request.method);
|
|
15545
|
+
if (isStandardSchema(schemaOrOptions)) {
|
|
15546
|
+
if (!isExtensionReusedRequestMethod(request.method)) this._assertOutboundRequestInEra(codec, request.method);
|
|
15547
|
+
return this._requestWithSchemaViaCodec(codec, request, schemaOrOptions, maybeOptions);
|
|
15548
|
+
}
|
|
15452
15549
|
this._assertOutboundRequestInEra(codec, request.method);
|
|
15453
|
-
if (isStandardSchema(schemaOrOptions)) return this._requestWithSchemaViaCodec(codec, request, schemaOrOptions, maybeOptions);
|
|
15454
15550
|
const validate = codecResultValidator(codec, request.method);
|
|
15455
15551
|
if (validate === void 0) throw new TypeError(`'${request.method}' is not a spec method; pass a result schema as the second argument to request().`);
|
|
15456
15552
|
return this._requestWithSchemaViaCodec(codec, request, validate, schemaOrOptions);
|
|
@@ -15694,6 +15790,8 @@ var Protocol = class {
|
|
|
15694
15790
|
return maybeHandler(parsed.data, ctx);
|
|
15695
15791
|
};
|
|
15696
15792
|
else throw new TypeError("setRequestHandler: handler is required");
|
|
15793
|
+
if (typeof schemasOrHandler === "function") this._customSchemaRequestMethods.delete(method);
|
|
15794
|
+
else this._customSchemaRequestMethods.add(method);
|
|
15697
15795
|
this._requestHandlers.set(method, this._wrapHandler(method, stored));
|
|
15698
15796
|
}
|
|
15699
15797
|
/**
|
|
@@ -15722,6 +15820,7 @@ var Protocol = class {
|
|
|
15722
15820
|
*/
|
|
15723
15821
|
removeRequestHandler(method) {
|
|
15724
15822
|
this._requestHandlers.delete(method);
|
|
15823
|
+
this._customSchemaRequestMethods.delete(method);
|
|
15725
15824
|
}
|
|
15726
15825
|
/**
|
|
15727
15826
|
* Asserts that a request handler has not already been set for the given method, in preparation for a new one being automatically installed.
|
|
@@ -16303,7 +16402,7 @@ function normalizeRawShapeSchema(schema) {
|
|
|
16303
16402
|
return schema;
|
|
16304
16403
|
}
|
|
16305
16404
|
//#endregion
|
|
16306
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
16405
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/ajvProvider-CEoC__sr.mjs
|
|
16307
16406
|
var require_code$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
16308
16407
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16309
16408
|
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;
|
|
@@ -23438,7 +23537,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
23438
23537
|
};
|
|
23439
23538
|
import_ajv.Ajv;
|
|
23440
23539
|
//#endregion
|
|
23441
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
23540
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/mcp-DIH4cS6P.mjs
|
|
23442
23541
|
const COMPLETABLE_SYMBOL = Symbol.for("mcp.completable");
|
|
23443
23542
|
/**
|
|
23444
23543
|
* Checks if a schema is completable (has completion metadata).
|
|
@@ -23460,6 +23559,15 @@ function armSseKeepAlive(intervalMs, onTick) {
|
|
|
23460
23559
|
timer.unref?.();
|
|
23461
23560
|
return timer;
|
|
23462
23561
|
}
|
|
23562
|
+
function comparableResource(value) {
|
|
23563
|
+
const text = String(value);
|
|
23564
|
+
const hash = text.indexOf("#");
|
|
23565
|
+
return (hash === -1 ? text : text.slice(0, hash)).replace(/\/$/, "");
|
|
23566
|
+
}
|
|
23567
|
+
function sameResource(reported, expected) {
|
|
23568
|
+
if (!reported) return false;
|
|
23569
|
+
return comparableResource(reported) === comparableResource(expected);
|
|
23570
|
+
}
|
|
23463
23571
|
function headerQuotedValue(value) {
|
|
23464
23572
|
return value.replaceAll(/[\\"]/g, String.raw`\$&`).replaceAll(/[^\u0020-\u007E]/g, " ");
|
|
23465
23573
|
}
|
|
@@ -23479,6 +23587,38 @@ function buildWwwAuthenticateHeader(errorCode, description, requiredScopes, reso
|
|
|
23479
23587
|
return header;
|
|
23480
23588
|
}
|
|
23481
23589
|
/**
|
|
23590
|
+
* Validate a raw `Authorization` header value as a Bearer token and return
|
|
23591
|
+
* the verified {@link AuthInfo}.
|
|
23592
|
+
*
|
|
23593
|
+
* The runtime-neutral core of Bearer authentication: it parses the header,
|
|
23594
|
+
* runs the verifier, compares the token's resource with `expectedResource`,
|
|
23595
|
+
* enforces `requiredScopes`, and rejects tokens without an
|
|
23596
|
+
* expiration or past it. On any failure it throws an {@link OAuthError} —
|
|
23597
|
+
* pass that to {@link bearerAuthChallengeResponse} for the matching HTTP
|
|
23598
|
+
* answer, or use {@link requireBearerAuth} to get both steps as one call.
|
|
23599
|
+
*
|
|
23600
|
+
* Framework adapters build on this: `requireBearerAuth` from
|
|
23601
|
+
* `@modelcontextprotocol/express` feeds it `req.headers.authorization`.
|
|
23602
|
+
*/
|
|
23603
|
+
async function verifyBearerToken(authorizationHeader, options) {
|
|
23604
|
+
const { verifier, requiredScopes = [], expectedResource } = options;
|
|
23605
|
+
if (!authorizationHeader) throw new OAuthError(OAuthErrorCode.InvalidToken, "Missing Authorization header");
|
|
23606
|
+
const [type, token] = authorizationHeader.split(" ");
|
|
23607
|
+
if (type?.toLowerCase() !== "bearer" || !token) throw new OAuthError(OAuthErrorCode.InvalidToken, "Invalid Authorization header format, expected 'Bearer TOKEN'");
|
|
23608
|
+
const authInfo = await verifier.verifyAccessToken(token);
|
|
23609
|
+
if (expectedResource !== void 0 && !sameResource(authInfo.resource, expectedResource)) throw new OAuthError(OAuthErrorCode.InvalidToken, "Token was not issued for this resource");
|
|
23610
|
+
if (requiredScopes.length > 0) {
|
|
23611
|
+
if (!requiredScopes.every((scope) => authInfo.scopes.includes(scope))) throw new OAuthError(OAuthErrorCode.InsufficientScope, "Insufficient scope");
|
|
23612
|
+
}
|
|
23613
|
+
if (typeof authInfo.expiresAt !== "number" || Number.isNaN(authInfo.expiresAt)) throw new OAuthError(OAuthErrorCode.InvalidToken, "Token has no expiration time");
|
|
23614
|
+
else if (authInfo.expiresAt < Date.now() / 1e3) throw new OAuthError(OAuthErrorCode.InvalidToken, "Token has expired");
|
|
23615
|
+
if (options.resourceMetadataUrl !== void 0 && authInfo.resourceMetadataUrl === void 0) return {
|
|
23616
|
+
...authInfo,
|
|
23617
|
+
resourceMetadataUrl: options.resourceMetadataUrl
|
|
23618
|
+
};
|
|
23619
|
+
return authInfo;
|
|
23620
|
+
}
|
|
23621
|
+
/**
|
|
23482
23622
|
* Build the HTTP answer for a Bearer authentication failure.
|
|
23483
23623
|
*
|
|
23484
23624
|
* Maps an {@link OAuthError} to its status — `401` for `invalid_token` and
|
|
@@ -23791,6 +23931,11 @@ var Server = class extends Protocol {
|
|
|
23791
23931
|
if (modernProtocolVersions(this._supportedProtocolVersions).length > 0) this.setRequestHandler("server/discover", () => this._ondiscover());
|
|
23792
23932
|
if (this._capabilities.logging) this._registerLoggingHandler();
|
|
23793
23933
|
}
|
|
23934
|
+
/** Attaches to the given transport; rejects while this instance is connected to another one. */
|
|
23935
|
+
async connect(transport) {
|
|
23936
|
+
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.");
|
|
23937
|
+
await super.connect(transport);
|
|
23938
|
+
}
|
|
23794
23939
|
/**
|
|
23795
23940
|
* Registers the built-in `logging/setLevel` request handler.
|
|
23796
23941
|
*
|
|
@@ -24336,6 +24481,30 @@ var Server = class extends Protocol {
|
|
|
24336
24481
|
function discoverAdvertisedCapabilities(capabilities) {
|
|
24337
24482
|
return { ...capabilities };
|
|
24338
24483
|
}
|
|
24484
|
+
function toolInputElementCount(value, max) {
|
|
24485
|
+
let count = 0;
|
|
24486
|
+
const stack = [value];
|
|
24487
|
+
while (stack.length > 0) {
|
|
24488
|
+
const node = stack.pop();
|
|
24489
|
+
if (node === null || typeof node !== "object") continue;
|
|
24490
|
+
if (Array.isArray(node)) for (const child of node) {
|
|
24491
|
+
if (++count > max) return count;
|
|
24492
|
+
if (child !== null && typeof child === "object") stack.push(child);
|
|
24493
|
+
}
|
|
24494
|
+
else for (const key in node) {
|
|
24495
|
+
if (!Object.prototype.hasOwnProperty.call(node, key)) continue;
|
|
24496
|
+
if (++count > max) return count;
|
|
24497
|
+
const child = node[key];
|
|
24498
|
+
if (child !== null && typeof child === "object") stack.push(child);
|
|
24499
|
+
}
|
|
24500
|
+
}
|
|
24501
|
+
return count;
|
|
24502
|
+
}
|
|
24503
|
+
function resolveMaxToolInputElements(value) {
|
|
24504
|
+
if (value === void 0 || value === Infinity) return void 0;
|
|
24505
|
+
if (typeof value !== "number" || Number.isNaN(value) || value < 1) throw new RangeError(`maxToolInputElements must be a number of at least 1, or Infinity, got ${String(value)}`);
|
|
24506
|
+
return value;
|
|
24507
|
+
}
|
|
24339
24508
|
/**
|
|
24340
24509
|
* High-level MCP server that provides a simpler API for working with resources, tools, and prompts.
|
|
24341
24510
|
* For advanced usage (like sending notifications or setting custom request handlers), use the underlying
|
|
@@ -24354,16 +24523,12 @@ var McpServer = class {
|
|
|
24354
24523
|
* The underlying {@linkcode Server} instance, useful for advanced operations like sending notifications.
|
|
24355
24524
|
*/
|
|
24356
24525
|
server;
|
|
24526
|
+
_maxToolInputElements;
|
|
24357
24527
|
_registeredResources = {};
|
|
24358
24528
|
_registeredResourceTemplates = {};
|
|
24359
24529
|
_registeredTools = {};
|
|
24360
24530
|
_registeredPrompts = {};
|
|
24361
|
-
/**
|
|
24362
|
-
* Per-tool JSON-converted `inputSchema`, memoized so the SEP-2243
|
|
24363
|
-
* registration-time scan and the pre-dispatch validation step share one
|
|
24364
|
-
* conversion instead of paying it twice per request under the
|
|
24365
|
-
* per-request-factory `createMcpHandler` model.
|
|
24366
|
-
*/
|
|
24531
|
+
/** Per-tool JSON-converted `inputSchema`, filled on first use by `toolInputSchemaJson()`. */
|
|
24367
24532
|
_toolInputSchemaJson = {};
|
|
24368
24533
|
/**
|
|
24369
24534
|
* The JSON-serialized `inputSchema` of a registered tool, or `undefined`
|
|
@@ -24388,6 +24553,7 @@ var McpServer = class {
|
|
|
24388
24553
|
}
|
|
24389
24554
|
constructor(serverInfo, options) {
|
|
24390
24555
|
this.server = new Server(serverInfo, options);
|
|
24556
|
+
this._maxToolInputElements = resolveMaxToolInputElements(options?.maxToolInputElements);
|
|
24391
24557
|
if (options?.capabilities?.tools) this.setToolRequestHandlers();
|
|
24392
24558
|
if (options?.capabilities?.resources) this.setResourceRequestHandlers();
|
|
24393
24559
|
if (options?.capabilities?.prompts) this.setPromptRequestHandlers();
|
|
@@ -24459,7 +24625,7 @@ var McpServer = class {
|
|
|
24459
24625
|
name,
|
|
24460
24626
|
title: tool.title,
|
|
24461
24627
|
description: tool.description,
|
|
24462
|
-
inputSchema: tool.inputSchema ?
|
|
24628
|
+
inputSchema: tool.inputSchema ? convertListedInputSchema(name, tool.inputSchema) : EMPTY_OBJECT_JSON_SCHEMA,
|
|
24463
24629
|
annotations: tool.annotations,
|
|
24464
24630
|
icons: tool.icons,
|
|
24465
24631
|
execution: tool.execution,
|
|
@@ -24504,6 +24670,7 @@ var McpServer = class {
|
|
|
24504
24670
|
* Validates tool input arguments against the tool's input schema.
|
|
24505
24671
|
*/
|
|
24506
24672
|
async validateToolInput(tool, args, toolName) {
|
|
24673
|
+
if (this._maxToolInputElements !== void 0 && toolInputElementCount(args, this._maxToolInputElements) > this._maxToolInputElements) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for tool ${toolName}: arguments contain more than the maximum of ${this._maxToolInputElements} elements`);
|
|
24507
24674
|
if (!tool.inputSchema) return;
|
|
24508
24675
|
const parseResult = await validateStandardSchema(tool.inputSchema, args ?? {});
|
|
24509
24676
|
if (!parseResult.success) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Input validation error: Invalid arguments for tool ${toolName}: ${parseResult.error}`);
|
|
@@ -24777,19 +24944,19 @@ var McpServer = class {
|
|
|
24777
24944
|
}
|
|
24778
24945
|
_createRegisteredTool(name, title, description, inputSchema, outputSchema, annotations, icons, execution, scopeChallenge, _meta, handler) {
|
|
24779
24946
|
validateAndWarnToolName(name);
|
|
24780
|
-
if (inputSchema !== void 0) try {
|
|
24781
|
-
const json = standardSchemaToJsonSchema(inputSchema, "input");
|
|
24782
|
-
this._toolInputSchemaJson[name] = json;
|
|
24783
|
-
const scan = scanXMcpHeaderDeclarations(json);
|
|
24784
|
-
if (!scan.valid) console.warn(`[mcp-sdk] tool '${name}' carries an invalid x-mcp-header declaration and will be excluded by conforming Streamable HTTP clients: ${scan.reason}`);
|
|
24785
|
-
} catch {}
|
|
24786
24947
|
let currentHandler = handler;
|
|
24948
|
+
let outputSchemaJson;
|
|
24787
24949
|
const registeredTool = {
|
|
24788
24950
|
title,
|
|
24789
24951
|
description,
|
|
24790
24952
|
inputSchema,
|
|
24791
24953
|
outputSchema,
|
|
24792
|
-
outputSchemaJson
|
|
24954
|
+
get outputSchemaJson() {
|
|
24955
|
+
return outputSchemaJson ??= convertOutputSchemaJson(registeredTool.outputSchema);
|
|
24956
|
+
},
|
|
24957
|
+
set outputSchemaJson(value) {
|
|
24958
|
+
outputSchemaJson = value;
|
|
24959
|
+
},
|
|
24793
24960
|
annotations,
|
|
24794
24961
|
icons,
|
|
24795
24962
|
execution,
|
|
@@ -24950,6 +25117,13 @@ const EMPTY_OBJECT_JSON_SCHEMA = {
|
|
|
24950
25117
|
type: "object",
|
|
24951
25118
|
properties: {}
|
|
24952
25119
|
};
|
|
25120
|
+
/** Converts a tool's `inputSchema` for `tools/list` and warns on an invalid SEP-2243 `x-mcp-header` declaration. */
|
|
25121
|
+
function convertListedInputSchema(name, inputSchema) {
|
|
25122
|
+
const json = standardSchemaToJsonSchema(inputSchema, "input");
|
|
25123
|
+
const scan = scanXMcpHeaderDeclarations(json);
|
|
25124
|
+
if (!scan.valid) console.warn(`[mcp-sdk] tool '${name}' carries an invalid x-mcp-header declaration and will be excluded by conforming Streamable HTTP clients: ${scan.reason}`);
|
|
25125
|
+
return json;
|
|
25126
|
+
}
|
|
24953
25127
|
/**
|
|
24954
25128
|
* Convert a registered `outputSchema` to JSON Schema, memoised on {@link RegisteredTool.outputSchemaJson}
|
|
24955
25129
|
* so `tools/call` passes the SAME advertised schema to the wire codec's `projectCallToolResult` that
|
|
@@ -24972,7 +25146,7 @@ function createPromptHandler(name, argsSchema, callback) {
|
|
|
24972
25146
|
if (argsSchema) {
|
|
24973
25147
|
const typedCallback = callback;
|
|
24974
25148
|
return async (args, ctx) => {
|
|
24975
|
-
const parseResult = await validateStandardSchema(argsSchema, args);
|
|
25149
|
+
const parseResult = await validateStandardSchema(argsSchema, args ?? {});
|
|
24976
25150
|
if (!parseResult.success) throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Invalid arguments for prompt ${name}: ${parseResult.error}`);
|
|
24977
25151
|
return typedCallback(parseResult.data, ctx);
|
|
24978
25152
|
};
|
|
@@ -25009,7 +25183,7 @@ function unwrapOptionalSchema(schema) {
|
|
|
25009
25183
|
return schema.def?.innerType ?? schema;
|
|
25010
25184
|
}
|
|
25011
25185
|
//#endregion
|
|
25012
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
25186
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/index.mjs
|
|
25013
25187
|
/** Default upper bound, in bytes, on a request body read by the HTTP entry points (4 MiB). */
|
|
25014
25188
|
const DEFAULT_MAX_REQUEST_BODY_SIZE = 4194304;
|
|
25015
25189
|
/** Upper bound on the number of messages accepted in one JSON-RPC batch array. */
|
|
@@ -25098,6 +25272,10 @@ async function readRequestBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_SIZE
|
|
|
25098
25272
|
* @example Hono.js
|
|
25099
25273
|
* ```ts source="./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_hono"
|
|
25100
25274
|
* app.all('/mcp', async c => {
|
|
25275
|
+
* // Stateless example: create a server and a transport per request.
|
|
25276
|
+
* const server = new McpServer({ name: 'my-server', version: '1.0.0' });
|
|
25277
|
+
* const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
25278
|
+
* await server.connect(transport);
|
|
25101
25279
|
* return transport.handleRequest(c.req.raw);
|
|
25102
25280
|
* });
|
|
25103
25281
|
* ```
|
|
@@ -25106,6 +25284,10 @@ async function readRequestBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_SIZE
|
|
|
25106
25284
|
* ```ts source="./streamableHttp.examples.ts#WebStandardStreamableHTTPServerTransport_workers"
|
|
25107
25285
|
* const worker = {
|
|
25108
25286
|
* async fetch(request: Request): Promise<Response> {
|
|
25287
|
+
* // Stateless example: create a server and a transport per request.
|
|
25288
|
+
* const server = new McpServer({ name: 'my-server', version: '1.0.0' });
|
|
25289
|
+
* const transport = new WebStandardStreamableHTTPServerTransport({ sessionIdGenerator: undefined });
|
|
25290
|
+
* await server.connect(transport);
|
|
25109
25291
|
* return transport.handleRequest(request);
|
|
25110
25292
|
* }
|
|
25111
25293
|
* };
|
|
@@ -25114,6 +25296,7 @@ async function readRequestBody(request, maxBytes = DEFAULT_MAX_REQUEST_BODY_SIZE
|
|
|
25114
25296
|
var WebStandardStreamableHTTPServerTransport = class {
|
|
25115
25297
|
sessionIdGenerator;
|
|
25116
25298
|
_started = false;
|
|
25299
|
+
_hasHandledRequest = false;
|
|
25117
25300
|
_closed = false;
|
|
25118
25301
|
_streamMapping = /* @__PURE__ */ new Map();
|
|
25119
25302
|
_requestToStreamMapping = /* @__PURE__ */ new Map();
|
|
@@ -25235,6 +25418,8 @@ var WebStandardStreamableHTTPServerTransport = class {
|
|
|
25235
25418
|
*/
|
|
25236
25419
|
async handleRequest(req, options) {
|
|
25237
25420
|
if (this._closed) return this.createJsonErrorResponse(404, -32001, "Session not found");
|
|
25421
|
+
if (!this.sessionIdGenerator && this._hasHandledRequest) throw new Error("Stateless transport cannot be reused across requests. Create a new transport per request.");
|
|
25422
|
+
this._hasHandledRequest = true;
|
|
25238
25423
|
const validationError = this.validateRequestHeaders(req);
|
|
25239
25424
|
if (validationError) return validationError;
|
|
25240
25425
|
switch (req.method) {
|
|
@@ -83080,7 +83265,7 @@ function escapeStringRegexp(string) {
|
|
|
83080
83265
|
return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d");
|
|
83081
83266
|
}
|
|
83082
83267
|
//#endregion
|
|
83083
|
-
//#region node_modules/.pnpm/mdast-util-find-and-replace@3.0.
|
|
83268
|
+
//#region node_modules/.pnpm/mdast-util-find-and-replace@3.0.3/node_modules/mdast-util-find-and-replace/lib/index.js
|
|
83084
83269
|
/**
|
|
83085
83270
|
* @import {Nodes, Parents, PhrasingContent, Root, Text} from 'mdast'
|
|
83086
83271
|
* @import {BuildVisitor, Test, VisitorResult} from 'unist-util-visit-parents'
|
|
@@ -83157,7 +83342,11 @@ function findAndReplace(tree, list, options) {
|
|
|
83157
83342
|
const pairs = toPairs(list);
|
|
83158
83343
|
let pairIndex = -1;
|
|
83159
83344
|
while (++pairIndex < pairs.length) visitParents(tree, "text", visitor);
|
|
83160
|
-
/**
|
|
83345
|
+
/**
|
|
83346
|
+
* Visit a text node, and handle it if it is not in an ignored parent.
|
|
83347
|
+
*
|
|
83348
|
+
* @type {BuildVisitor<Root, 'text'>}
|
|
83349
|
+
*/
|
|
83161
83350
|
function visitor(node, parents) {
|
|
83162
83351
|
let index = -1;
|
|
83163
83352
|
/** @type {Parents | undefined} */
|
|
@@ -83175,11 +83364,11 @@ function findAndReplace(tree, list, options) {
|
|
|
83175
83364
|
* Handle a text node which is not in an ignored parent.
|
|
83176
83365
|
*
|
|
83177
83366
|
* @param {Text} node
|
|
83178
|
-
* Text node.
|
|
83367
|
+
* Text node to search in.
|
|
83179
83368
|
* @param {Array<Parents>} parents
|
|
83180
|
-
*
|
|
83369
|
+
* Ancestors of `node`.
|
|
83181
83370
|
* @returns {VisitorResult}
|
|
83182
|
-
*
|
|
83371
|
+
* Where to continue visiting.
|
|
83183
83372
|
*/
|
|
83184
83373
|
function handler(node, parents) {
|
|
83185
83374
|
const parent = parents[parents.length - 1];
|
|
@@ -83207,12 +83396,12 @@ function findAndReplace(tree, list, options) {
|
|
|
83207
83396
|
} : void 0;
|
|
83208
83397
|
if (value === false) find.lastIndex = position + 1;
|
|
83209
83398
|
else {
|
|
83210
|
-
if (start !== position)
|
|
83399
|
+
if (start !== position) add({
|
|
83211
83400
|
type: "text",
|
|
83212
83401
|
value: node.value.slice(start, position)
|
|
83213
83402
|
});
|
|
83214
|
-
if (Array.isArray(value))
|
|
83215
|
-
else if (value)
|
|
83403
|
+
if (Array.isArray(value)) for (const child of value) add(child);
|
|
83404
|
+
else if (value) add(value);
|
|
83216
83405
|
start = position + match[0].length;
|
|
83217
83406
|
change = true;
|
|
83218
83407
|
}
|
|
@@ -83220,13 +83409,26 @@ function findAndReplace(tree, list, options) {
|
|
|
83220
83409
|
match = find.exec(node.value);
|
|
83221
83410
|
}
|
|
83222
83411
|
if (change) {
|
|
83223
|
-
if (start < node.value.length)
|
|
83412
|
+
if (start < node.value.length) add({
|
|
83224
83413
|
type: "text",
|
|
83225
83414
|
value: node.value.slice(start)
|
|
83226
83415
|
});
|
|
83227
83416
|
parent.children.splice(index, 1, ...nodes);
|
|
83228
83417
|
} else nodes = [node];
|
|
83229
83418
|
return index + nodes.length;
|
|
83419
|
+
/**
|
|
83420
|
+
* Add a node.
|
|
83421
|
+
*
|
|
83422
|
+
* @param {PhrasingContent} child
|
|
83423
|
+
* Node to add.
|
|
83424
|
+
* @returns {undefined}
|
|
83425
|
+
* Nothing.
|
|
83426
|
+
*/
|
|
83427
|
+
function add(child) {
|
|
83428
|
+
const previous = nodes[nodes.length - 1];
|
|
83429
|
+
if (previous && previous.type === "text" && child.type === "text") previous.value += child.value;
|
|
83430
|
+
else nodes.push(child);
|
|
83431
|
+
}
|
|
83230
83432
|
}
|
|
83231
83433
|
}
|
|
83232
83434
|
/**
|
|
@@ -83238,9 +83440,9 @@ function findAndReplace(tree, list, options) {
|
|
|
83238
83440
|
* Clean pairs.
|
|
83239
83441
|
*/
|
|
83240
83442
|
function toPairs(tupleOrList) {
|
|
83443
|
+
if (!Array.isArray(tupleOrList)) throw new TypeError("Expected find and replace tuple or list of tuples");
|
|
83241
83444
|
/** @type {Pairs} */
|
|
83242
83445
|
const result = [];
|
|
83243
|
-
if (!Array.isArray(tupleOrList)) throw new TypeError("Expected find and replace tuple or list of tuples");
|
|
83244
83446
|
/** @type {FindAndReplaceList} */
|
|
83245
83447
|
const list = !tupleOrList[0] || Array.isArray(tupleOrList[0]) ? tupleOrList : [tupleOrList];
|
|
83246
83448
|
let index = -1;
|
|
@@ -83254,9 +83456,9 @@ function toPairs(tupleOrList) {
|
|
|
83254
83456
|
* Turn a find into an expression.
|
|
83255
83457
|
*
|
|
83256
83458
|
* @param {Find} find
|
|
83257
|
-
*
|
|
83459
|
+
* Pattern to find.
|
|
83258
83460
|
* @returns {RegExp}
|
|
83259
|
-
*
|
|
83461
|
+
* Global expression.
|
|
83260
83462
|
*/
|
|
83261
83463
|
function toExpression(find) {
|
|
83262
83464
|
return typeof find === "string" ? new RegExp(escapeStringRegexp(find), "g") : find;
|
|
@@ -83265,9 +83467,9 @@ function toExpression(find) {
|
|
|
83265
83467
|
* Turn a replace into a function.
|
|
83266
83468
|
*
|
|
83267
83469
|
* @param {Replace} replace
|
|
83268
|
-
*
|
|
83470
|
+
* Thing to replace with.
|
|
83269
83471
|
* @returns {ReplaceFunction}
|
|
83270
|
-
* Function.
|
|
83472
|
+
* Function that returns that thing.
|
|
83271
83473
|
*/
|
|
83272
83474
|
function toFunction(replace) {
|
|
83273
83475
|
return typeof replace === "function" ? replace : function() {
|
|
@@ -105892,7 +106094,7 @@ const attachmentSchema = object({
|
|
|
105892
106094
|
error: (issue) => `Attachment too large: ${issue.input.length} base64 characters, limit ${MAX_BASE64_INPUT_CHARS}. Downscale the file, split the upload, or link to it instead of uploading.`
|
|
105893
106095
|
}).base64().describe(`File content encoded as base64. At most ${MAX_BASE64_INPUT_CHARS} characters (about ${MAX_BASE64_INPUT_MB} MB of file), and the attachments of one call must stay under that total; the HTTP transport additionally caps request bodies at 4 MB.`),
|
|
105894
106096
|
content_type: string$2().min(1).default("application/octet-stream").describe("MIME type, e.g. \"text/plain\", \"image/png\", \"application/pdf\".")
|
|
105895
|
-
});
|
|
106097
|
+
}).strict();
|
|
105896
106098
|
/**
|
|
105897
106099
|
* The optional `attachments` array parameter, capped as a whole.
|
|
105898
106100
|
*
|
|
@@ -106222,7 +106424,7 @@ const createRequestTools = (ctx) => {
|
|
|
106222
106424
|
custom_fields: array(object({
|
|
106223
106425
|
id: number$2().int(),
|
|
106224
106426
|
value: unknown$3()
|
|
106225
|
-
})).optional().describe("Answers to the form's own questions, as { id, value } pairs. Take both the ids and the accepted values from get_request_form; an id this form does not carry, or a value a dropdown does not offer, is refused here because Zendesk would drop it without an error. Option values are the tag strings, never numbers."),
|
|
106427
|
+
}).strict()).optional().describe("Answers to the form's own questions, as { id, value } pairs. Take both the ids and the accepted values from get_request_form; an id this form does not carry, or a value a dropdown does not offer, is refused here because Zendesk would drop it without an error. Option values are the tag strings, never numbers."),
|
|
106226
106428
|
attachments: attachmentsParam("Files to attach to the request, such as a screenshot or a log, with their content base64-encoded.")
|
|
106227
106429
|
}),
|
|
106228
106430
|
annotations: {
|
|
@@ -107012,7 +107214,7 @@ const createTicketTools = (ctx) => {
|
|
|
107012
107214
|
custom_fields: array(object({
|
|
107013
107215
|
id: number$2().int(),
|
|
107014
107216
|
value: unknown$3()
|
|
107015
|
-
})).optional().describe("Custom field values as { id, value } pairs (field ids come from your Zendesk admin settings). Call list_ticket_fields first to discover the numeric field ids and, for dropdown/multiselect fields, the exact option values Zendesk accepts.")
|
|
107217
|
+
}).strict()).optional().describe("Custom field values as { id, value } pairs (field ids come from your Zendesk admin settings). Call list_ticket_fields first to discover the numeric field ids and, for dropdown/multiselect fields, the exact option values Zendesk accepts.")
|
|
107016
107218
|
}),
|
|
107017
107219
|
annotations: {
|
|
107018
107220
|
readOnlyHint: false,
|
|
@@ -107069,7 +107271,7 @@ const createTicketTools = (ctx) => {
|
|
|
107069
107271
|
custom_fields: array(object({
|
|
107070
107272
|
id: number$2().int(),
|
|
107071
107273
|
value: unknown$3()
|
|
107072
|
-
})).optional().describe("Custom field values as { id, value } pairs (field ids come from your Zendesk admin settings). Call list_ticket_fields first to discover the numeric field ids and, for dropdown/multiselect fields, the exact option values Zendesk accepts."),
|
|
107274
|
+
}).strict()).optional().describe("Custom field values as { id, value } pairs (field ids come from your Zendesk admin settings). Call list_ticket_fields first to discover the numeric field ids and, for dropdown/multiselect fields, the exact option values Zendesk accepts."),
|
|
107073
107275
|
followers: object({
|
|
107074
107276
|
add: subscriberIdList("User ids to start following the ticket. Omit to only remove."),
|
|
107075
107277
|
remove: subscriberIdList("User ids to stop following the ticket. Omit to only add.")
|
|
@@ -107733,32 +107935,6 @@ const readPackageInfo = () => {
|
|
|
107733
107935
|
return cached;
|
|
107734
107936
|
};
|
|
107735
107937
|
//#endregion
|
|
107736
|
-
//#region src/utils/validation.ts
|
|
107737
|
-
/**
|
|
107738
|
-
* Build a strict params parser for a tool's input schema, computing the strict
|
|
107739
|
-
* schema and the valid-key list once at construction rather than per call.
|
|
107740
|
-
*
|
|
107741
|
-
* Zod objects default to `strip`, which silently drops unknown keys. That hid
|
|
107742
|
-
* #100: a caller passing `per_page` to list_tickets (whose parameter is
|
|
107743
|
-
* `page_size`) had the key dropped, so a large unpaginated page came back. The
|
|
107744
|
-
* parser rejects unknown keys and names both the offending ones and the valid
|
|
107745
|
-
* parameters, so a misremembered name fails loudly.
|
|
107746
|
-
*
|
|
107747
|
-
* Used on the proxy dispatch path (namespace/single modes); in `all` mode the
|
|
107748
|
-
* SDK validates against the strict schema we register.
|
|
107749
|
-
*/
|
|
107750
|
-
const createStrictParamsParser = (schema) => {
|
|
107751
|
-
const strict = schema.strict();
|
|
107752
|
-
const validKeys = Object.keys(schema.shape).sort().join(", ");
|
|
107753
|
-
return (params) => {
|
|
107754
|
-
const result = strict.safeParse(params);
|
|
107755
|
-
if (result.success) return result.data;
|
|
107756
|
-
const unknownKeys = result.error.issues.flatMap((issue) => issue.code === "unrecognized_keys" ? issue.keys : []);
|
|
107757
|
-
if (unknownKeys.length > 0) throw new Error(`Unknown parameter(s): ${unknownKeys.join(", ")}. Valid parameters: ${validKeys || "(none)"}.`);
|
|
107758
|
-
throw result.error;
|
|
107759
|
-
};
|
|
107760
|
-
};
|
|
107761
|
-
//#endregion
|
|
107762
107938
|
//#region src/server.ts
|
|
107763
107939
|
/**
|
|
107764
107940
|
* Invoke a tool handler, notifying `onUnauthorized` when Zendesk rejects the
|
|
@@ -107892,7 +108068,7 @@ const registerToolset = (server, { config, getToken, resolveBrandSubdomain, onUn
|
|
|
107892
108068
|
for (const tool of filteredTools) registered.push(server.registerTool(tool.name, {
|
|
107893
108069
|
title: tool.title,
|
|
107894
108070
|
description: tool.description,
|
|
107895
|
-
inputSchema: tool.inputSchema
|
|
108071
|
+
inputSchema: toStrictStandardSchema(tool.inputSchema),
|
|
107896
108072
|
annotations: tool.annotations
|
|
107897
108073
|
}, async (params) => runHandler(tool, params, onUnauthorized)));
|
|
107898
108074
|
break;
|
|
@@ -107996,7 +108172,7 @@ const createMcpServer = (config, getToken, logger = silentLogger, onUnauthorized
|
|
|
107996
108172
|
return server;
|
|
107997
108173
|
};
|
|
107998
108174
|
//#endregion
|
|
107999
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
108175
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.3.1/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
|
|
108000
108176
|
/**
|
|
108001
108177
|
* Marks a stdout `'error'` listener that a closed transport left attached purely to
|
|
108002
108178
|
* swallow late write failures (see {@link StdioServerTransport.close}). A fresh
|
|
@@ -108424,7 +108600,7 @@ const installShutdown = (options) => {
|
|
|
108424
108600
|
//#endregion
|
|
108425
108601
|
//#region src/index.ts
|
|
108426
108602
|
const buildStdioTokenStore = async (config, logger) => {
|
|
108427
|
-
const { createTokenStore } = await import("./token-store-
|
|
108603
|
+
const { createTokenStore } = await import("./token-store-BLAkLLQO.js");
|
|
108428
108604
|
return createTokenStore({
|
|
108429
108605
|
subdomain: config.subdomain,
|
|
108430
108606
|
oauthClientId: config.oauthClientId,
|
|
@@ -108465,7 +108641,7 @@ const main = async () => {
|
|
|
108465
108641
|
return;
|
|
108466
108642
|
}
|
|
108467
108643
|
if (config.dev) logger.warn("dev_mode_ignored_http");
|
|
108468
|
-
const { startHttpTransport } = await import("./http-
|
|
108644
|
+
const { startHttpTransport } = await import("./http-BYYYoQaK.js");
|
|
108469
108645
|
const http = await startHttpTransport(config, logger);
|
|
108470
108646
|
installShutdown({
|
|
108471
108647
|
watchStdin: false,
|
|
@@ -108479,4 +108655,4 @@ main().catch((error) => {
|
|
|
108479
108655
|
process.exit(1);
|
|
108480
108656
|
});
|
|
108481
108657
|
//#endregion
|
|
108482
|
-
export {
|
|
108658
|
+
export { __commonJSMin$1 as _, verifyBearerToken as a, __toESM$1 as b, zendeskGet as c, DEFAULT_CALLBACK_PORT as d, getOAuthUrls as f, readEnv as g, errnoCode as h, WebStandardStreamableHTTPServerTransport as i, REQUEST_TIMEOUT_MS as l, createStartupError as m, readPackageInfo as n, OAuthError as o, STARTUP_DOCS as p, silentLogger as r, OAuthErrorCode as s, createMcpServer as t, deadlineSignal as u, __exportAll$1 as v, __require as y };
|
package/dist/sbom.cdx.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.6",
|
|
4
|
-
"serialNumber": "urn:uuid:
|
|
4
|
+
"serialNumber": "urn:uuid:e7c0861b-27d8-53fc-9aa5-7312e5af7ead",
|
|
5
5
|
"version": 1,
|
|
6
6
|
"metadata": {
|
|
7
7
|
"component": {
|
|
8
8
|
"type": "application",
|
|
9
|
-
"bom-ref": "pkg:npm/%40fruggr/zendesk-mcp-server@3.3.
|
|
9
|
+
"bom-ref": "pkg:npm/%40fruggr/zendesk-mcp-server@3.3.1",
|
|
10
10
|
"name": "@fruggr/zendesk-mcp-server",
|
|
11
|
-
"version": "3.3.
|
|
12
|
-
"purl": "pkg:npm/%40fruggr/zendesk-mcp-server@3.3.
|
|
11
|
+
"version": "3.3.1",
|
|
12
|
+
"purl": "pkg:npm/%40fruggr/zendesk-mcp-server@3.3.1"
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"components": [
|
|
@@ -27,37 +27,37 @@
|
|
|
27
27
|
},
|
|
28
28
|
{
|
|
29
29
|
"type": "library",
|
|
30
|
-
"bom-ref": "pkg:npm/%40modelcontextprotocol/core@2.
|
|
30
|
+
"bom-ref": "pkg:npm/%40modelcontextprotocol/core@2.3.1",
|
|
31
31
|
"name": "@modelcontextprotocol/core",
|
|
32
|
-
"version": "2.
|
|
33
|
-
"purl": "pkg:npm/%40modelcontextprotocol/core@2.
|
|
32
|
+
"version": "2.3.1",
|
|
33
|
+
"purl": "pkg:npm/%40modelcontextprotocol/core@2.3.1",
|
|
34
34
|
"licenses": [
|
|
35
35
|
{
|
|
36
|
-
"expression": "
|
|
36
|
+
"expression": "Apache-2.0"
|
|
37
37
|
}
|
|
38
38
|
]
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
41
|
"type": "library",
|
|
42
|
-
"bom-ref": "pkg:npm/%40modelcontextprotocol/node@2.1.
|
|
42
|
+
"bom-ref": "pkg:npm/%40modelcontextprotocol/node@2.1.1",
|
|
43
43
|
"name": "@modelcontextprotocol/node",
|
|
44
|
-
"version": "2.1.
|
|
45
|
-
"purl": "pkg:npm/%40modelcontextprotocol/node@2.1.
|
|
44
|
+
"version": "2.1.1",
|
|
45
|
+
"purl": "pkg:npm/%40modelcontextprotocol/node@2.1.1",
|
|
46
46
|
"licenses": [
|
|
47
47
|
{
|
|
48
|
-
"expression": "
|
|
48
|
+
"expression": "Apache-2.0"
|
|
49
49
|
}
|
|
50
50
|
]
|
|
51
51
|
},
|
|
52
52
|
{
|
|
53
53
|
"type": "library",
|
|
54
|
-
"bom-ref": "pkg:npm/%40modelcontextprotocol/server@2.
|
|
54
|
+
"bom-ref": "pkg:npm/%40modelcontextprotocol/server@2.3.1",
|
|
55
55
|
"name": "@modelcontextprotocol/server",
|
|
56
|
-
"version": "2.
|
|
57
|
-
"purl": "pkg:npm/%40modelcontextprotocol/server@2.
|
|
56
|
+
"version": "2.3.1",
|
|
57
|
+
"purl": "pkg:npm/%40modelcontextprotocol/server@2.3.1",
|
|
58
58
|
"licenses": [
|
|
59
59
|
{
|
|
60
|
-
"expression": "
|
|
60
|
+
"expression": "Apache-2.0"
|
|
61
61
|
}
|
|
62
62
|
]
|
|
63
63
|
},
|
|
@@ -999,10 +999,10 @@
|
|
|
999
999
|
},
|
|
1000
1000
|
{
|
|
1001
1001
|
"type": "library",
|
|
1002
|
-
"bom-ref": "pkg:npm/mdast-util-find-and-replace@3.0.
|
|
1002
|
+
"bom-ref": "pkg:npm/mdast-util-find-and-replace@3.0.3",
|
|
1003
1003
|
"name": "mdast-util-find-and-replace",
|
|
1004
|
-
"version": "3.0.
|
|
1005
|
-
"purl": "pkg:npm/mdast-util-find-and-replace@3.0.
|
|
1004
|
+
"version": "3.0.3",
|
|
1005
|
+
"purl": "pkg:npm/mdast-util-find-and-replace@3.0.3",
|
|
1006
1006
|
"licenses": [
|
|
1007
1007
|
{
|
|
1008
1008
|
"expression": "MIT"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { g as readEnv, n as readPackageInfo, r as silentLogger } from "./index.js";
|
|
3
3
|
import { createHash, randomBytes } from "node:crypto";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { chmodSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import { a as saveToken, c as grantCovers, d as escapeHtml, i as resolveTokenPath, l as requestedScope, o as generateCodeChallenge, r as loadToken, s as generateCodeVerifier, t as clearToken } from "./token-persistence-
|
|
2
|
+
import { f as getOAuthUrls, r as silentLogger } from "./index.js";
|
|
3
|
+
import { a as saveToken, c as grantCovers, d as escapeHtml, i as resolveTokenPath, l as requestedScope, o as generateCodeChallenge, r as loadToken, s as generateCodeVerifier, t as clearToken } from "./token-persistence-BUHh23BM.js";
|
|
4
4
|
import { promisify } from "node:util";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fruggr/zendesk-mcp-server",
|
|
3
|
-
"version": "3.3.
|
|
3
|
+
"version": "3.3.1",
|
|
4
4
|
"mcpName": "io.github.fruggr/zendesk-mcp-server",
|
|
5
5
|
"description": "Deep Zendesk MCP server for your AI assistant: search, draft, update and translate Help Center articles and manage Support tickets end to end — comments, triage and image attachments.",
|
|
6
6
|
"type": "module",
|
|
@@ -72,12 +72,12 @@
|
|
|
72
72
|
"engines": {
|
|
73
73
|
"node": ">=22"
|
|
74
74
|
},
|
|
75
|
-
"packageManager": "pnpm@12.
|
|
75
|
+
"packageManager": "pnpm@12.11.1+sha512.5b0e3288239a7ea4155d2094f547066e122a1376b3cd785a680c9112e116913e64aaaecf20dd83cc34030fa67013f5c5511f9cf430dd8384188b4c60b8a2ad1e",
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@biomejs/biome": "2.5.14",
|
|
78
|
-
"@modelcontextprotocol/client": "2.
|
|
79
|
-
"@modelcontextprotocol/node": "2.1.
|
|
80
|
-
"@modelcontextprotocol/server": "2.
|
|
78
|
+
"@modelcontextprotocol/client": "2.3.1",
|
|
79
|
+
"@modelcontextprotocol/node": "2.1.1",
|
|
80
|
+
"@modelcontextprotocol/server": "2.3.1",
|
|
81
81
|
"@semantic-release/changelog": "^7.0.0",
|
|
82
82
|
"@semantic-release/exec": "^7.1.0",
|
|
83
83
|
"@semantic-release/git": "^11.0.0",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"hast-util-to-mdast": "10.1.2",
|
|
99
99
|
"jose": "6.2.12",
|
|
100
100
|
"lefthook": "^2.1.10",
|
|
101
|
-
"msw": "^
|
|
101
|
+
"msw": "^3.0.0",
|
|
102
102
|
"oidc-provider": "~9.12.2",
|
|
103
103
|
"open": "11.0.4",
|
|
104
104
|
"rehype-parse": "9.0.1",
|