@fruggr/zendesk-mcp-server 3.1.1 → 3.2.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/dist/THIRD-PARTY-NOTICES.md +2 -2
- package/dist/{http-CmtU-oNu.js → http-CUsGYeuV.js} +188 -80
- package/dist/index.js +19 -13
- package/dist/sbom.cdx.json +10 -9
- package/package.json +3 -3
|
@@ -30,7 +30,7 @@ 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.2.0
|
|
34
34
|
|
|
35
35
|
License: MIT
|
|
36
36
|
|
|
@@ -476,7 +476,7 @@ 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.2.0
|
|
480
480
|
|
|
481
481
|
License: MIT
|
|
482
482
|
|
|
@@ -504,7 +504,7 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
504
504
|
};
|
|
505
505
|
};
|
|
506
506
|
//#endregion
|
|
507
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+node@2.1.0_@modelcontextprotocol+server@2.
|
|
507
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+node@2.1.0_@modelcontextprotocol+server@2.2.0_hono@4.13.9/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.
|
|
@@ -2264,82 +2264,6 @@ function decodeJwt(jwt) {
|
|
|
2264
2264
|
return result;
|
|
2265
2265
|
}
|
|
2266
2266
|
//#endregion
|
|
2267
|
-
//#region src/auth/server/expiring-map.ts
|
|
2268
|
-
/**
|
|
2269
|
-
* An in-memory map whose entries lapse after their own TTL. Expired entries are
|
|
2270
|
-
* swept on every `set`, so the map stays bounded by what was set within the
|
|
2271
|
-
* longest TTL, with no timer to hold the process open.
|
|
2272
|
-
*/
|
|
2273
|
-
const createExpiringMap = () => {
|
|
2274
|
-
const entries = /* @__PURE__ */ new Map();
|
|
2275
|
-
const get = (key) => {
|
|
2276
|
-
const entry = entries.get(key);
|
|
2277
|
-
return entry && entry.expiresAt > Date.now() ? entry.value : void 0;
|
|
2278
|
-
};
|
|
2279
|
-
return {
|
|
2280
|
-
set: (key, value, ttlMs) => {
|
|
2281
|
-
const now = Date.now();
|
|
2282
|
-
for (const [k, entry] of entries) if (entry.expiresAt <= now) entries.delete(k);
|
|
2283
|
-
entries.set(key, {
|
|
2284
|
-
value,
|
|
2285
|
-
expiresAt: now + ttlMs
|
|
2286
|
-
});
|
|
2287
|
-
},
|
|
2288
|
-
get,
|
|
2289
|
-
/** Read and forget: a pending value is used at most once. */
|
|
2290
|
-
take: (key) => {
|
|
2291
|
-
const value = get(key);
|
|
2292
|
-
entries.delete(key);
|
|
2293
|
-
return value;
|
|
2294
|
-
},
|
|
2295
|
-
/** Live and not-yet-swept entries. */
|
|
2296
|
-
size: () => entries.size
|
|
2297
|
-
};
|
|
2298
|
-
};
|
|
2299
|
-
//#endregion
|
|
2300
|
-
//#region src/auth/server/consent.ts
|
|
2301
|
-
const hostOf = (uri) => {
|
|
2302
|
-
try {
|
|
2303
|
-
return new URL(uri).host;
|
|
2304
|
-
} catch {
|
|
2305
|
-
return uri;
|
|
2306
|
-
}
|
|
2307
|
-
};
|
|
2308
|
-
const SCOPE_LABELS = {
|
|
2309
|
-
read: "Read your Zendesk data",
|
|
2310
|
-
write: "Create and change Zendesk data on your behalf"
|
|
2311
|
-
};
|
|
2312
|
-
/**
|
|
2313
|
-
* The MCP consent screen, shown once per client that is not trusted (DCR,
|
|
2314
|
-
* unknown CIMD, loopback redirects). Names the client, the scopes and where the
|
|
2315
|
-
* code goes, per the spec's UI requirements. Every interpolated value is
|
|
2316
|
-
* escaped: the client name comes from a document anyone can publish.
|
|
2317
|
-
*/
|
|
2318
|
-
const renderConsentPage = (view) => {
|
|
2319
|
-
const name = escapeHtml(view.clientName ?? view.clientId);
|
|
2320
|
-
const scopes = view.scopes.map((scope) => `<li>${escapeHtml(SCOPE_LABELS[scope] ?? scope)}</li>`).join("");
|
|
2321
|
-
const action = `/interaction/${encodeURIComponent(view.uid)}`;
|
|
2322
|
-
return [
|
|
2323
|
-
"<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">",
|
|
2324
|
-
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
|
|
2325
|
-
"<title>Authorize access to Zendesk</title>",
|
|
2326
|
-
"<style>body{font-family:system-ui,sans-serif;max-width:32rem;margin:3rem auto;padding:0 1rem;line-height:1.5}",
|
|
2327
|
-
"code{word-break:break-all}button{font:inherit;padding:.5rem 1.25rem;margin-right:.5rem}</style>",
|
|
2328
|
-
"</head><body>",
|
|
2329
|
-
`<h1>Allow ${name} to use your Zendesk account?</h1>`,
|
|
2330
|
-
`<p><strong>${name}</strong> is asking to act as you on <strong>${escapeHtml(view.subdomain)}.zendesk.com</strong>:</p>`,
|
|
2331
|
-
`<ul>${scopes}</ul>`,
|
|
2332
|
-
`<p>After you allow it, you are sent back to <strong>${escapeHtml(hostOf(view.redirectUri))}</strong>`,
|
|
2333
|
-
` (<code>${escapeHtml(view.redirectUri)}</code>). Only continue if you started this connection yourself.</p>`,
|
|
2334
|
-
`<p>Client id: <code>${escapeHtml(view.clientId)}</code></p>`,
|
|
2335
|
-
`<form method="post" action="${action}/confirm" style="display:inline"><button type="submit">Allow</button></form>`,
|
|
2336
|
-
`<form method="post" action="${action}/abort" style="display:inline"><button type="submit">Deny</button></form>`,
|
|
2337
|
-
"</body></html>"
|
|
2338
|
-
].join("");
|
|
2339
|
-
};
|
|
2340
|
-
/** Plain error page for a failed sign-in. ASCII message, escaped. */
|
|
2341
|
-
const renderErrorPage = (title, detail) => `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Sign-in failed</title></head><body><h1>${escapeHtml(title)}</h1><p>${escapeHtml(detail)}</p></body></html>`;
|
|
2342
|
-
//#endregion
|
|
2343
2267
|
//#region src/auth/server/trusted-clients.ts
|
|
2344
2268
|
/**
|
|
2345
2269
|
* Which CIMD clients skip our consent screen, and the fetch shim applied to CIMD
|
|
@@ -2425,6 +2349,184 @@ const createCimdFetch = (baseFetch) => async (url, options) => {
|
|
|
2425
2349
|
});
|
|
2426
2350
|
};
|
|
2427
2351
|
//#endregion
|
|
2352
|
+
//#region src/auth/server/cimd-documents.ts
|
|
2353
|
+
/** How long a kept copy may stand in for its document, after it was kept. */
|
|
2354
|
+
const LAST_GOOD_TTL_S = 604800;
|
|
2355
|
+
const STALE_MAX_AGE_S = 60;
|
|
2356
|
+
const CIMD_FETCH_HINT = "A client document, or a URL it names, could not be fetched: the client cannot sign in or refresh unless a last good copy is served. See https://github.com/fruggr/zendesk-mcp-server/blob/main/docs/troubleshooting.md#http-the-log-shows-oauth_client_fetch_failed";
|
|
2357
|
+
const isTransientFailure = (status) => status === 403 || status === 408 || status === 429 || status >= 500;
|
|
2358
|
+
const messageOf = (err) => {
|
|
2359
|
+
if (!(err instanceof Error)) return String(err);
|
|
2360
|
+
return err.cause instanceof Error ? `${err.message}: ${err.cause.message}` : err.message;
|
|
2361
|
+
};
|
|
2362
|
+
const ownDocument = async (response, url) => {
|
|
2363
|
+
const parsed = await response.json().catch(() => void 0);
|
|
2364
|
+
return parsed?.client_id === url ? parsed : void 0;
|
|
2365
|
+
};
|
|
2366
|
+
/**
|
|
2367
|
+
* A copy is kept when a token is issued, from the client oidc-provider built
|
|
2368
|
+
* and validated: an unauthenticated caller can make the server fetch any URL,
|
|
2369
|
+
* but not write to the grant store, and a rejected document is never kept.
|
|
2370
|
+
*/
|
|
2371
|
+
const createCimdDocuments = (baseFetch, { lastGood, logger }) => {
|
|
2372
|
+
const rewrite = createCimdFetch(baseFetch);
|
|
2373
|
+
const stale = /* @__PURE__ */ new Set();
|
|
2374
|
+
const kept = (url) => lastGood.get(url).catch((err) => {
|
|
2375
|
+
logger.warn("oauth_cimd_last_good_read_failed", {
|
|
2376
|
+
url,
|
|
2377
|
+
error: messageOf(err)
|
|
2378
|
+
});
|
|
2379
|
+
});
|
|
2380
|
+
const report = (url, failure, copy) => {
|
|
2381
|
+
logger.warn("oauth_client_fetch_failed", {
|
|
2382
|
+
url,
|
|
2383
|
+
...failure,
|
|
2384
|
+
fallback: copy ? "last_good" : "none",
|
|
2385
|
+
...copy && { ageS: Math.floor((Date.now() - copy.fetchedAt) / 1e3) },
|
|
2386
|
+
hint: CIMD_FETCH_HINT
|
|
2387
|
+
});
|
|
2388
|
+
};
|
|
2389
|
+
const serve = (url, copy) => {
|
|
2390
|
+
stale.add(url);
|
|
2391
|
+
return Response.json(copy.document, { headers: { "cache-control": `max-age=${STALE_MAX_AGE_S}` } });
|
|
2392
|
+
};
|
|
2393
|
+
const fallBack = async (url, failure, failed) => {
|
|
2394
|
+
const copy = await kept(url);
|
|
2395
|
+
report(url, failure, copy);
|
|
2396
|
+
if (!copy) return void 0;
|
|
2397
|
+
await failed?.body?.cancel();
|
|
2398
|
+
return serve(url, copy);
|
|
2399
|
+
};
|
|
2400
|
+
const succeeded = async (url, response) => {
|
|
2401
|
+
if (await ownDocument(response.clone(), url) && response.status === 200) {
|
|
2402
|
+
stale.delete(url);
|
|
2403
|
+
return response;
|
|
2404
|
+
}
|
|
2405
|
+
const copy = await kept(url);
|
|
2406
|
+
if (!copy) return response;
|
|
2407
|
+
report(url, {
|
|
2408
|
+
status: response.status,
|
|
2409
|
+
error: "not a client document"
|
|
2410
|
+
}, copy);
|
|
2411
|
+
await response.body?.cancel();
|
|
2412
|
+
return serve(url, copy);
|
|
2413
|
+
};
|
|
2414
|
+
const fetch = async (input, init) => {
|
|
2415
|
+
const url = String(input);
|
|
2416
|
+
let response;
|
|
2417
|
+
try {
|
|
2418
|
+
response = await rewrite(input, init);
|
|
2419
|
+
} catch (err) {
|
|
2420
|
+
const copy = await fallBack(url, { error: messageOf(err) });
|
|
2421
|
+
if (copy) return copy;
|
|
2422
|
+
throw err;
|
|
2423
|
+
}
|
|
2424
|
+
if (response.ok) return succeeded(url, response);
|
|
2425
|
+
if (!isTransientFailure(response.status)) {
|
|
2426
|
+
logger.debug("oauth_client_fetch_failed", {
|
|
2427
|
+
url,
|
|
2428
|
+
status: response.status,
|
|
2429
|
+
fallback: "none"
|
|
2430
|
+
});
|
|
2431
|
+
return response;
|
|
2432
|
+
}
|
|
2433
|
+
return await fallBack(url, { status: response.status }, response) ?? response;
|
|
2434
|
+
};
|
|
2435
|
+
return {
|
|
2436
|
+
fetch,
|
|
2437
|
+
granted: async (client) => {
|
|
2438
|
+
if (client.clientIdMetadataDocument !== true || stale.has(client.clientId)) return;
|
|
2439
|
+
try {
|
|
2440
|
+
await lastGood.set(client.clientId, {
|
|
2441
|
+
document: client.metadata(),
|
|
2442
|
+
fetchedAt: Date.now()
|
|
2443
|
+
}, LAST_GOOD_TTL_S);
|
|
2444
|
+
} catch (err) {
|
|
2445
|
+
logger.warn("oauth_cimd_last_good_store_failed", {
|
|
2446
|
+
url: client.clientId,
|
|
2447
|
+
error: messageOf(err)
|
|
2448
|
+
});
|
|
2449
|
+
}
|
|
2450
|
+
}
|
|
2451
|
+
};
|
|
2452
|
+
};
|
|
2453
|
+
//#endregion
|
|
2454
|
+
//#region src/auth/server/expiring-map.ts
|
|
2455
|
+
/**
|
|
2456
|
+
* An in-memory map whose entries lapse after their own TTL. Expired entries are
|
|
2457
|
+
* swept on every `set`, so the map stays bounded by what was set within the
|
|
2458
|
+
* longest TTL, with no timer to hold the process open.
|
|
2459
|
+
*/
|
|
2460
|
+
const createExpiringMap = () => {
|
|
2461
|
+
const entries = /* @__PURE__ */ new Map();
|
|
2462
|
+
const get = (key) => {
|
|
2463
|
+
const entry = entries.get(key);
|
|
2464
|
+
return entry && entry.expiresAt > Date.now() ? entry.value : void 0;
|
|
2465
|
+
};
|
|
2466
|
+
return {
|
|
2467
|
+
set: (key, value, ttlMs) => {
|
|
2468
|
+
const now = Date.now();
|
|
2469
|
+
for (const [k, entry] of entries) if (entry.expiresAt <= now) entries.delete(k);
|
|
2470
|
+
entries.set(key, {
|
|
2471
|
+
value,
|
|
2472
|
+
expiresAt: now + ttlMs
|
|
2473
|
+
});
|
|
2474
|
+
},
|
|
2475
|
+
get,
|
|
2476
|
+
/** Read and forget: a pending value is used at most once. */
|
|
2477
|
+
take: (key) => {
|
|
2478
|
+
const value = get(key);
|
|
2479
|
+
entries.delete(key);
|
|
2480
|
+
return value;
|
|
2481
|
+
},
|
|
2482
|
+
/** Live and not-yet-swept entries. */
|
|
2483
|
+
size: () => entries.size
|
|
2484
|
+
};
|
|
2485
|
+
};
|
|
2486
|
+
//#endregion
|
|
2487
|
+
//#region src/auth/server/consent.ts
|
|
2488
|
+
const hostOf = (uri) => {
|
|
2489
|
+
try {
|
|
2490
|
+
return new URL(uri).host;
|
|
2491
|
+
} catch {
|
|
2492
|
+
return uri;
|
|
2493
|
+
}
|
|
2494
|
+
};
|
|
2495
|
+
const SCOPE_LABELS = {
|
|
2496
|
+
read: "Read your Zendesk data",
|
|
2497
|
+
write: "Create and change Zendesk data on your behalf"
|
|
2498
|
+
};
|
|
2499
|
+
/**
|
|
2500
|
+
* The MCP consent screen, shown once per client that is not trusted (DCR,
|
|
2501
|
+
* unknown CIMD, loopback redirects). Names the client, the scopes and where the
|
|
2502
|
+
* code goes, per the spec's UI requirements. Every interpolated value is
|
|
2503
|
+
* escaped: the client name comes from a document anyone can publish.
|
|
2504
|
+
*/
|
|
2505
|
+
const renderConsentPage = (view) => {
|
|
2506
|
+
const name = escapeHtml(view.clientName ?? view.clientId);
|
|
2507
|
+
const scopes = view.scopes.map((scope) => `<li>${escapeHtml(SCOPE_LABELS[scope] ?? scope)}</li>`).join("");
|
|
2508
|
+
const action = `/interaction/${encodeURIComponent(view.uid)}`;
|
|
2509
|
+
return [
|
|
2510
|
+
"<!doctype html><html lang=\"en\"><head><meta charset=\"utf-8\">",
|
|
2511
|
+
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
|
|
2512
|
+
"<title>Authorize access to Zendesk</title>",
|
|
2513
|
+
"<style>body{font-family:system-ui,sans-serif;max-width:32rem;margin:3rem auto;padding:0 1rem;line-height:1.5}",
|
|
2514
|
+
"code{word-break:break-all}button{font:inherit;padding:.5rem 1.25rem;margin-right:.5rem}</style>",
|
|
2515
|
+
"</head><body>",
|
|
2516
|
+
`<h1>Allow ${name} to use your Zendesk account?</h1>`,
|
|
2517
|
+
`<p><strong>${name}</strong> is asking to act as you on <strong>${escapeHtml(view.subdomain)}.zendesk.com</strong>:</p>`,
|
|
2518
|
+
`<ul>${scopes}</ul>`,
|
|
2519
|
+
`<p>After you allow it, you are sent back to <strong>${escapeHtml(hostOf(view.redirectUri))}</strong>`,
|
|
2520
|
+
` (<code>${escapeHtml(view.redirectUri)}</code>). Only continue if you started this connection yourself.</p>`,
|
|
2521
|
+
`<p>Client id: <code>${escapeHtml(view.clientId)}</code></p>`,
|
|
2522
|
+
`<form method="post" action="${action}/confirm" style="display:inline"><button type="submit">Allow</button></form>`,
|
|
2523
|
+
`<form method="post" action="${action}/abort" style="display:inline"><button type="submit">Deny</button></form>`,
|
|
2524
|
+
"</body></html>"
|
|
2525
|
+
].join("");
|
|
2526
|
+
};
|
|
2527
|
+
/** Plain error page for a failed sign-in. ASCII message, escaped. */
|
|
2528
|
+
const renderErrorPage = (title, detail) => `<!doctype html><html lang="en"><head><meta charset="utf-8"><title>Sign-in failed</title></head><body><h1>${escapeHtml(title)}</h1><p>${escapeHtml(detail)}</p></body></html>`;
|
|
2529
|
+
//#endregion
|
|
2428
2530
|
//#region src/auth/server/upstream.ts
|
|
2429
2531
|
/**
|
|
2430
2532
|
* Zendesk as the upstream identity provider, through the same public PKCE client
|
|
@@ -35898,13 +36000,12 @@ const buildProvider = (options) => {
|
|
|
35898
36000
|
const { ring, resource } = options;
|
|
35899
36001
|
const [current] = ring;
|
|
35900
36002
|
const scopes = options.allowWrite ? RESOURCE_SCOPES.join(" ") : "read";
|
|
35901
|
-
const baseFetch = options.fetch ?? ((url, init) => globalThis.fetch(url, init));
|
|
35902
36003
|
const provider = new lib_default(options.issuer, {
|
|
35903
36004
|
adapter: options.adapter,
|
|
35904
36005
|
jwks: { keys: ring.map((set) => set.signingJwk) },
|
|
35905
36006
|
cookies: { keys: ring.map((set) => set.cookieKey) },
|
|
35906
36007
|
clients: [],
|
|
35907
|
-
fetch:
|
|
36008
|
+
fetch: options.cimdDocuments.fetch,
|
|
35908
36009
|
scopes: options.allowWrite ? [...RESOURCE_SCOPES, "offline_access"] : ["read", "offline_access"],
|
|
35909
36010
|
clientDefaults: {
|
|
35910
36011
|
grant_types: ["authorization_code", "refresh_token"],
|
|
@@ -36109,6 +36210,10 @@ const createAuthorizationServer = (options) => {
|
|
|
36109
36210
|
hint: "Revoked in this process only. Fix the store before restarting: its next successful write persists the removal."
|
|
36110
36211
|
});
|
|
36111
36212
|
};
|
|
36213
|
+
const cimdDocuments = createCimdDocuments(options.fetch ?? ((url, init) => globalThis.fetch(url, init)), {
|
|
36214
|
+
lastGood: createSealedCollection(persistent, "CimdDocument", ring),
|
|
36215
|
+
logger
|
|
36216
|
+
});
|
|
36112
36217
|
const provider = buildProvider({
|
|
36113
36218
|
issuer,
|
|
36114
36219
|
resource,
|
|
@@ -36118,7 +36223,10 @@ const createAuthorizationServer = (options) => {
|
|
|
36118
36223
|
allowWrite: !config.readOnly,
|
|
36119
36224
|
isAllowedOrigin: options.isAllowedOrigin,
|
|
36120
36225
|
behindProxy: config.publicUrl?.startsWith("https:") === true,
|
|
36121
|
-
|
|
36226
|
+
cimdDocuments
|
|
36227
|
+
});
|
|
36228
|
+
provider.on("grant.success", (ctx) => {
|
|
36229
|
+
if (ctx.oidc.client) cimdDocuments.granted(ctx.oidc.client);
|
|
36122
36230
|
});
|
|
36123
36231
|
provider.on("server_error", (_ctx, err) => {
|
|
36124
36232
|
logger.error("oauth_server_error", { error: err.message });
|
package/dist/index.js
CHANGED
|
@@ -7832,7 +7832,7 @@ const loadConfig = (argv = process.argv.slice(2)) => {
|
|
|
7832
7832
|
});
|
|
7833
7833
|
};
|
|
7834
7834
|
//#endregion
|
|
7835
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
7835
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.2.0/node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
|
|
7836
7836
|
var __create = Object.create;
|
|
7837
7837
|
var __defProp = Object.defineProperty;
|
|
7838
7838
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
@@ -7864,7 +7864,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
7864
7864
|
enumerable: true
|
|
7865
7865
|
}) : target, mod));
|
|
7866
7866
|
//#endregion
|
|
7867
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
7867
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.2.0/node_modules/@modelcontextprotocol/server/dist/dialects-DoSzNhcb.mjs
|
|
7868
7868
|
/**
|
|
7869
7869
|
* Canonical `$schema` URIs per supported dialect (http + https variants, trailing-`#` stripped).
|
|
7870
7870
|
*/
|
|
@@ -9447,7 +9447,8 @@ const OAuthTokensSchema = object({
|
|
|
9447
9447
|
token_type: string$2(),
|
|
9448
9448
|
expires_in: number$1().optional(),
|
|
9449
9449
|
scope: string$2().optional(),
|
|
9450
|
-
refresh_token: string$2().optional()
|
|
9450
|
+
refresh_token: string$2().optional(),
|
|
9451
|
+
issuer: string$2().optional().catch(void 0)
|
|
9451
9452
|
}).strip();
|
|
9452
9453
|
/**
|
|
9453
9454
|
* RFC 8693 §2.2.1 Token Exchange response for ID-JAG tokens.
|
|
@@ -9504,7 +9505,8 @@ const OAuthClientInformationSchema = object({
|
|
|
9504
9505
|
client_id: string$2(),
|
|
9505
9506
|
client_secret: string$2().optional(),
|
|
9506
9507
|
client_id_issued_at: number$2().optional(),
|
|
9507
|
-
client_secret_expires_at: number$2().optional()
|
|
9508
|
+
client_secret_expires_at: number$2().optional(),
|
|
9509
|
+
issuer: string$2().optional().catch(void 0)
|
|
9508
9510
|
}).strip();
|
|
9509
9511
|
/**
|
|
9510
9512
|
* RFC 7591 OAuth 2.0 Dynamic Client Registration full response (client information plus metadata)
|
|
@@ -9525,7 +9527,7 @@ const OAuthTokenRevocationRequestSchema = object({
|
|
|
9525
9527
|
token_type_hint: string$2().optional()
|
|
9526
9528
|
}).strip();
|
|
9527
9529
|
//#endregion
|
|
9528
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
9530
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.2.0/node_modules/@modelcontextprotocol/server/dist/src-BHSMhZ_W.mjs
|
|
9529
9531
|
/**
|
|
9530
9532
|
* Cross-bundle `instanceof` support for the SDK error classes.
|
|
9531
9533
|
*
|
|
@@ -13486,6 +13488,8 @@ const rev2026Codec = {
|
|
|
13486
13488
|
const rawInputRequests = raw["inputRequests"];
|
|
13487
13489
|
const inputRequests = isPlainObject$4(rawInputRequests) ? rawInputRequests : {};
|
|
13488
13490
|
const requestState = raw["requestState"];
|
|
13491
|
+
const metaParse = raw["_meta"] === void 0 ? void 0 : buildSchemas2026().ResultMetaSchema.safeParse(raw["_meta"]);
|
|
13492
|
+
const meta = metaParse?.success ? metaParse.data : void 0;
|
|
13489
13493
|
if (Object.keys(inputRequests).length === 0 && typeof requestState !== "string") return {
|
|
13490
13494
|
kind: "invalid",
|
|
13491
13495
|
error: new SdkError(SdkErrorCode.InvalidResult, `Invalid result for ${method}: input_required carries neither inputRequests nor requestState (every input_required result must include at least one of the two)`, {
|
|
@@ -13496,7 +13500,8 @@ const rev2026Codec = {
|
|
|
13496
13500
|
return {
|
|
13497
13501
|
kind: "input_required",
|
|
13498
13502
|
inputRequests,
|
|
13499
|
-
...typeof requestState === "string" && { requestState }
|
|
13503
|
+
...typeof requestState === "string" && { requestState },
|
|
13504
|
+
...meta !== void 0 && { _meta: meta }
|
|
13500
13505
|
};
|
|
13501
13506
|
}
|
|
13502
13507
|
if (rawResultType !== "complete") return {
|
|
@@ -15230,7 +15235,7 @@ var Protocol = class {
|
|
|
15230
15235
|
* Emits a notification, which is a one-way message that does not expect a response.
|
|
15231
15236
|
*/
|
|
15232
15237
|
async notification(notification, options) {
|
|
15233
|
-
return this._notificationViaCodec(this._resolveOutboundCodec(notification.method), notification, options);
|
|
15238
|
+
return await this._notificationViaCodec(this._resolveOutboundCodec(notification.method), notification, options);
|
|
15234
15239
|
}
|
|
15235
15240
|
/**
|
|
15236
15241
|
* The notification funnel proper, keyed by the resolved era codec —
|
|
@@ -15399,7 +15404,8 @@ function manualInputRequiredValue(decoded) {
|
|
|
15399
15404
|
return {
|
|
15400
15405
|
resultType: "input_required",
|
|
15401
15406
|
inputRequests: decoded.inputRequests,
|
|
15402
|
-
...decoded.requestState !== void 0 && { requestState: decoded.requestState }
|
|
15407
|
+
...decoded.requestState !== void 0 && { requestState: decoded.requestState },
|
|
15408
|
+
...decoded._meta !== void 0 && { _meta: decoded._meta }
|
|
15403
15409
|
};
|
|
15404
15410
|
}
|
|
15405
15411
|
/*!
|
|
@@ -15889,7 +15895,7 @@ function normalizeRawShapeSchema(schema) {
|
|
|
15889
15895
|
return schema;
|
|
15890
15896
|
}
|
|
15891
15897
|
//#endregion
|
|
15892
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
15898
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.2.0/node_modules/@modelcontextprotocol/server/dist/ajvProvider-CEoC__sr.mjs
|
|
15893
15899
|
var require_code$1 = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
15894
15900
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15895
15901
|
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;
|
|
@@ -23024,7 +23030,7 @@ var AjvJsonSchemaValidator = class {
|
|
|
23024
23030
|
};
|
|
23025
23031
|
import_ajv.Ajv;
|
|
23026
23032
|
//#endregion
|
|
23027
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
23033
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.2.0/node_modules/@modelcontextprotocol/server/dist/mcp-DYuW2ZSs.mjs
|
|
23028
23034
|
const COMPLETABLE_SYMBOL = Symbol.for("mcp.completable");
|
|
23029
23035
|
/**
|
|
23030
23036
|
* Checks if a schema is completable (has completion metadata).
|
|
@@ -24595,7 +24601,7 @@ function unwrapOptionalSchema(schema) {
|
|
|
24595
24601
|
return schema.def?.innerType ?? schema;
|
|
24596
24602
|
}
|
|
24597
24603
|
//#endregion
|
|
24598
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
24604
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.2.0/node_modules/@modelcontextprotocol/server/dist/index.mjs
|
|
24599
24605
|
/** Default upper bound, in bytes, on a request body read by the HTTP entry points (4 MiB). */
|
|
24600
24606
|
const DEFAULT_MAX_REQUEST_BODY_SIZE = 4194304;
|
|
24601
24607
|
/** Upper bound on the number of messages accepted in one JSON-RPC batch array. */
|
|
@@ -106621,7 +106627,7 @@ const createMcpServer = (config, getToken, logger = silentLogger, onUnauthorized
|
|
|
106621
106627
|
return server;
|
|
106622
106628
|
};
|
|
106623
106629
|
//#endregion
|
|
106624
|
-
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.
|
|
106630
|
+
//#region node_modules/.pnpm/@modelcontextprotocol+server@2.2.0/node_modules/@modelcontextprotocol/server/dist/stdio.mjs
|
|
106625
106631
|
/**
|
|
106626
106632
|
* Marks a stdout `'error'` listener that a closed transport left attached purely to
|
|
106627
106633
|
* swallow late write failures (see {@link StdioServerTransport.close}). A fresh
|
|
@@ -107085,7 +107091,7 @@ const main = async () => {
|
|
|
107085
107091
|
return;
|
|
107086
107092
|
}
|
|
107087
107093
|
if (config.dev) logger.warn("dev_mode_ignored_http");
|
|
107088
|
-
const { startHttpTransport } = await import("./http-
|
|
107094
|
+
const { startHttpTransport } = await import("./http-CUsGYeuV.js");
|
|
107089
107095
|
const http = await startHttpTransport(config, logger);
|
|
107090
107096
|
installShutdown({
|
|
107091
107097
|
watchStdin: false,
|
package/dist/sbom.cdx.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"bomFormat": "CycloneDX",
|
|
3
3
|
"specVersion": "1.6",
|
|
4
|
+
"serialNumber": "urn:uuid:b370c80f-c327-5c78-b90b-e161da6f00fc",
|
|
4
5
|
"version": 1,
|
|
5
6
|
"metadata": {
|
|
6
7
|
"component": {
|
|
7
8
|
"type": "application",
|
|
8
|
-
"bom-ref": "pkg:npm/%40fruggr/zendesk-mcp-server@3.
|
|
9
|
+
"bom-ref": "pkg:npm/%40fruggr/zendesk-mcp-server@3.2.0",
|
|
9
10
|
"name": "@fruggr/zendesk-mcp-server",
|
|
10
|
-
"version": "3.
|
|
11
|
-
"purl": "pkg:npm/%40fruggr/zendesk-mcp-server@3.
|
|
11
|
+
"version": "3.2.0",
|
|
12
|
+
"purl": "pkg:npm/%40fruggr/zendesk-mcp-server@3.2.0"
|
|
12
13
|
}
|
|
13
14
|
},
|
|
14
15
|
"components": [
|
|
@@ -26,10 +27,10 @@
|
|
|
26
27
|
},
|
|
27
28
|
{
|
|
28
29
|
"type": "library",
|
|
29
|
-
"bom-ref": "pkg:npm/%40modelcontextprotocol/core@2.
|
|
30
|
+
"bom-ref": "pkg:npm/%40modelcontextprotocol/core@2.2.0",
|
|
30
31
|
"name": "@modelcontextprotocol/core",
|
|
31
|
-
"version": "2.
|
|
32
|
-
"purl": "pkg:npm/%40modelcontextprotocol/core@2.
|
|
32
|
+
"version": "2.2.0",
|
|
33
|
+
"purl": "pkg:npm/%40modelcontextprotocol/core@2.2.0",
|
|
33
34
|
"licenses": [
|
|
34
35
|
{
|
|
35
36
|
"expression": "MIT"
|
|
@@ -50,10 +51,10 @@
|
|
|
50
51
|
},
|
|
51
52
|
{
|
|
52
53
|
"type": "library",
|
|
53
|
-
"bom-ref": "pkg:npm/%40modelcontextprotocol/server@2.
|
|
54
|
+
"bom-ref": "pkg:npm/%40modelcontextprotocol/server@2.2.0",
|
|
54
55
|
"name": "@modelcontextprotocol/server",
|
|
55
|
-
"version": "2.
|
|
56
|
-
"purl": "pkg:npm/%40modelcontextprotocol/server@2.
|
|
56
|
+
"version": "2.2.0",
|
|
57
|
+
"purl": "pkg:npm/%40modelcontextprotocol/server@2.2.0",
|
|
57
58
|
"licenses": [
|
|
58
59
|
{
|
|
59
60
|
"expression": "MIT"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fruggr/zendesk-mcp-server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
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",
|
|
@@ -75,9 +75,9 @@
|
|
|
75
75
|
"packageManager": "pnpm@12.5.1+sha512.e3f305bc784a2bc89f5ad3b6138889470fae8d2af5f36b61216ec91c2c3d64089775f9de38aac331044ea40f245cb0d5666392dfdf65824e1907ef6a2c62de5f",
|
|
76
76
|
"devDependencies": {
|
|
77
77
|
"@biomejs/biome": "2.5.14",
|
|
78
|
-
"@modelcontextprotocol/client": "2.
|
|
78
|
+
"@modelcontextprotocol/client": "2.2.0",
|
|
79
79
|
"@modelcontextprotocol/node": "2.1.0",
|
|
80
|
-
"@modelcontextprotocol/server": "2.
|
|
80
|
+
"@modelcontextprotocol/server": "2.2.0",
|
|
81
81
|
"@semantic-release/changelog": "^7.0.0",
|
|
82
82
|
"@semantic-release/exec": "^7.1.0",
|
|
83
83
|
"@semantic-release/git": "^11.0.0",
|