@fruggr/zendesk-mcp-server 3.8.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 CHANGED
@@ -5,7 +5,7 @@
5
5
  [![npm version](https://img.shields.io/npm/v/@fruggr/zendesk-mcp-server?logo=npm&color=cb3837)](https://www.npmjs.com/package/@fruggr/zendesk-mcp-server)
6
6
  [![License: MIT](https://img.shields.io/npm/l/@fruggr/zendesk-mcp-server?color=blue)](LICENSE)
7
7
  [![Node.js](https://img.shields.io/node/v/@fruggr/zendesk-mcp-server?logo=nodedotjs&logoColor=white&color=339933)](https://nodejs.org)
8
- [![Container base](https://img.shields.io/static/v1?label=container%20base&message=dhi.io%2Fnode%3A24.22.1-alpine3.24&logo=docker&logoColor=white&color=2496ED)](https://github.com/fruggr/zendesk-mcp-server/blob/main/docs/http-deployment.md#container)
8
+ [![Container base](https://img.shields.io/static/v1?label=container%20base&message=dhi.io%2Fnode%3A24.22.2-alpine3.24&logo=docker&logoColor=white&color=2496ED)](https://github.com/fruggr/zendesk-mcp-server/blob/main/docs/http-deployment.md#container)
9
9
 
10
10
  A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that
11
11
  puts Zendesk inside your AI assistant, for **both sides of the conversation**.
package/dist/index.js CHANGED
@@ -7980,21 +7980,42 @@ const portEnv = (name) => {
7980
7980
  return env.value === void 0 ? void 0 : parsePort(env.value, env.name);
7981
7981
  };
7982
7982
  /**
7983
- * Split a raw `--brand-ids` / `ZENDESK_BRAND_IDS` value into its entries.
7984
- * Comma-separated, entries trimmed; an empty entry (from `a,,b`, a leading/
7985
- * trailing comma, or a whitespace-only value) is a misconfiguration, not an
7986
- * ignored blank: it fails at startup naming the knob. Format validation only —
7987
- * whether an id/subdomain exists is decided lazily, on first use (no token is
7988
- * 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`.
7989
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
+ };
7990
7993
  const parseBrandIds = (raw) => {
7991
7994
  if (raw === void 0) return void 0;
7992
- const entries = raw.split(",").map((entry) => entry.trim());
7993
- 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);
7994
- 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());
7995
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);
7996
7997
  return [...new Set(normalized)];
7997
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
+ };
7998
8019
  const CLI_OPTIONS = {
7999
8020
  mode: { type: "string" },
8000
8021
  "brand-ids": { type: "string" },
@@ -8181,7 +8202,7 @@ const loadConfig = (argv = process.argv.slice(2)) => {
8181
8202
  const subdomain = cli.subdomain ?? requireNonEmptyEnv("ZENDESK_SUBDOMAIN") ?? "";
8182
8203
  const oauthClientId = requireNonEmptyEnv("ZENDESK_OAUTH_CLIENT_ID") ?? `${subdomain}_zendesk`;
8183
8204
  const mode = cli.tools?.length ? "all" : cli.mode ?? "namespace";
8184
- const namespaces = cli.namespaces ?? (cli.tools?.length ? [...Namespace.options] : void 0);
8205
+ const namespaces = resolveNamespaces(cli.namespaces) ?? (cli.tools?.length ? [...Namespace.options] : void 0);
8185
8206
  const callbackPort = cli.callbackPort ?? portEnv("OAUTH_CALLBACK_PORT");
8186
8207
  const brandIds = cli.brandIds ?? requireNonEmptyEnv("ZENDESK_BRAND_IDS");
8187
8208
  const hcResourceScheme = cli.hcResourceScheme ?? requireNonEmptyEnv("HC_RESOURCE_SCHEME");
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.6",
4
- "serialNumber": "urn:uuid:49731904-0250-5427-b41c-e6167f6080ec",
4
+ "serialNumber": "urn:uuid:4adc7c5a-c9ae-5a39-909b-d6f99b8b284c",
5
5
  "version": 1,
6
6
  "metadata": {
7
7
  "component": {
8
8
  "type": "application",
9
- "bom-ref": "pkg:npm/%40fruggr/zendesk-mcp-server@3.8.0",
9
+ "bom-ref": "pkg:npm/%40fruggr/zendesk-mcp-server@3.9.0",
10
10
  "name": "@fruggr/zendesk-mcp-server",
11
- "version": "3.8.0",
12
- "purl": "pkg:npm/%40fruggr/zendesk-mcp-server@3.8.0"
11
+ "version": "3.9.0",
12
+ "purl": "pkg:npm/%40fruggr/zendesk-mcp-server@3.9.0"
13
13
  }
14
14
  },
15
15
  "components": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fruggr/zendesk-mcp-server",
3
- "version": "3.8.0",
3
+ "version": "3.9.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",
@@ -18,7 +18,7 @@
18
18
  "typecheck": "node scripts/typecheck.mjs",
19
19
  "start": "node dist/index.js",
20
20
  "dev": "tsx watch src/index.ts",
21
- "dev:http": "tsx src/index.ts --transport http --host 127.0.0.1 --port 3000 --public-url http://localhost:3000 --mode all --namespace tickets --namespace help_center --namespace users --namespace requests",
21
+ "dev:http": "tsx src/index.ts --transport http --host 127.0.0.1 --port 3000 --public-url http://localhost:3000 --mode all --namespace all",
22
22
  "prepare": "npm run build && (lefthook install || true)",
23
23
  "prepublishOnly": "npm run build",
24
24
  "check": "biome check --error-on-warnings .",