@fruggr/zendesk-mcp-server 1.0.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,7 +9,7 @@ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that co
9
9
  Most Zendesk integrations use a shared admin API key, giving every user full access to every ticket. This server takes a different approach:
10
10
 
11
11
  - **Per-user authentication** — Each user authenticates with their own Zendesk credentials via OAuth 2.1 PKCE. No shared admin key, no elevated privileges. The LLM sees exactly what the user is allowed to see.
12
- - **Context-friendly tool modes** — Expose 36 individual tools, 3 namespace proxies, or a single unified tool. Choose the mode that fits your LLM's context budget.
12
+ - **Context-friendly tool modes** — Expose 37 individual tools, 3 namespace proxies, or a single unified tool. Choose the mode that fits your LLM's context budget.
13
13
  - **Section-based article editing** — For large Help Center articles, read and rewrite one section at a time (parsed by h1/h2/h3 headings) instead of shuffling the full HTML body through the LLM. Reduces tokens by 10–100× on targeted edits.
14
14
  - **Read-only mode** — Restrict the server to read operations only, ideal for assistants that should never modify data.
15
15
  - **Zero runtime dependencies beyond the MCP SDK** — Built on `@modelcontextprotocol/sdk` and `zod`. No Express, no heavyweight frameworks.
@@ -22,7 +22,7 @@ The server registers tools in one of three modes, controlled by `--mode`:
22
22
 
23
23
  | Mode | Tools exposed | Best for |
24
24
  |------|--------------|----------|
25
- | **`all`** | 36 individual tools (`get_ticket`, `search_articles`, ...) | Clients with good tool selection, full granularity |
25
+ | **`all`** | 37 individual tools (`get_ticket`, `search_articles`, ...) | Clients with good tool selection, full granularity |
26
26
  | **`namespace`** (default) | 3 proxy tools (`zendesk_tickets`, `zendesk_help_center`, `zendesk_users`) | Balanced context usage, grouped operations |
27
27
  | **`single`** | 1 proxy tool (`zendesk`) | Minimal context footprint, single entry point |
28
28
 
@@ -47,11 +47,12 @@ zendesk-mcp-server acme --namespace tickets
47
47
  ## Available tools
48
48
 
49
49
  <details>
50
- <summary><strong>Tickets</strong> (9 tools)</summary>
50
+ <summary><strong>Tickets</strong> (10 tools)</summary>
51
51
 
52
52
  | Tool | Description | Mode |
53
53
  |------|-------------|------|
54
54
  | `get_ticket` | Retrieve a ticket by ID with optional comments | read |
55
+ | `get_ticket_attachments` | Download ticket attachments (images as base64, others as references) | read |
55
56
  | `search_tickets` | Search tickets using Zendesk query syntax | read |
56
57
  | `list_tickets` | List tickets with cursor-based pagination | read |
57
58
  | `get_linked_incidents` | Get incidents linked to a problem ticket | read |
@@ -259,7 +260,7 @@ Options:
259
260
  **Examples:**
260
261
 
261
262
  ```bash
262
- # Single tool mode — minimal context, all 36 operations in one tool
263
+ # Single tool mode — minimal context, all 37 operations in one tool
263
264
  zendesk-mcp-server acme --mode single
264
265
 
265
266
  # Read-only tickets only
@@ -324,17 +325,18 @@ Versions follow [SemVer](https://semver.org/) and are calculated **automatically
324
325
 
325
326
  ## Contributing
326
327
 
327
- Pull requests are welcome! Whether you write code by hand or with the help of AI, contributions are appreciated.
328
+ Pull requests are welcome including AI-assisted ones, as long as the human author has read and validated every line.
328
329
 
329
- If you'd like to contribute:
330
+ The full guide is in [`CONTRIBUTING.md`](CONTRIBUTING.md). The short version:
330
331
 
331
- 1. Fork the repository
332
- 2. Create a feature branch
333
- 3. Write tests (we practice TDD)
334
- 4. Use [Conventional Commits](https://www.conventionalcommits.org/) in your commit messages they directly drive the next version bump
335
- 5. Submit a pull request
332
+ 1. Fork and create a feature branch from `main`.
333
+ 2. Practice TDD: write the failing test first, then implement.
334
+ 3. Use [Conventional Commits](https://www.conventionalcommits.org/) they drive the next version bump via semantic-release.
335
+ 4. Make `pnpm check`, `pnpm typecheck`, and `pnpm test` pass locally.
336
+ 5. Run a Claude Code review on your diff before pushing.
337
+ 6. Open a PR.
336
338
 
337
- Please ensure `pnpm check` and `pnpm test` pass before submitting.
339
+ Every PR is reviewed automatically by [CodeRabbit](https://www.coderabbit.ai) in CI, on top of the author-side AI review. The project is maintained in part with [Claude Code](https://www.anthropic.com/claude-code) assistance; that workflow is documented in [`CONTRIBUTING.md`](CONTRIBUTING.md).
338
340
 
339
341
  ## License
340
342
 
package/dist/index.js CHANGED
@@ -16,6 +16,9 @@ var CHARACTER_LIMIT = 25e3;
16
16
  var DEFAULT_PAGE_SIZE = 100;
17
17
  var MAX_PAGE_SIZE = 100;
18
18
  var TOKEN_CACHE_TTL_MS = 5 * 60 * 1e3;
19
+ var MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;
20
+ var MAX_EMBEDDED_IMAGE_COUNT = 10;
21
+ var MAX_COMMENT_PAGES = Number(process.env["ZENDESK_MAX_COMMENT_PAGES"] ?? 10);
19
22
  var LARGE_ARTICLE_BODY_CHARS = 3e3;
20
23
  var LARGE_ARTICLE_SECTION_COUNT = 4;
21
24
  var getBaseUrl = (subdomain) => `https://${subdomain}.zendesk.com/api/v2`;
@@ -273,6 +276,7 @@ var ZendeskApiError = class _ZendeskApiError extends Error {
273
276
  }
274
277
  }
275
278
  };
279
+ var buildAuthHeader = (token) => token.startsWith("Basic ") ? token : `Bearer ${token}`;
276
280
  var buildUrl = (base, path, params) => {
277
281
  const url = new URL(`${base}${path}`);
278
282
  if (params) {
@@ -284,9 +288,8 @@ var buildUrl = (base, path, params) => {
284
288
  };
285
289
  var executeRequest = async (url, token, options = {}) => {
286
290
  const { method = "GET", body } = options;
287
- const authorization = token.startsWith("Basic ") ? token : `Bearer ${token}`;
288
291
  const headers = {
289
- Authorization: authorization,
292
+ Authorization: buildAuthHeader(token),
290
293
  Accept: "application/json"
291
294
  };
292
295
  if (body) {
@@ -330,12 +333,26 @@ var helpCenterPut = (subdomain, token, path, body) => {
330
333
  const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);
331
334
  return executeRequest(url, token, { method: "PUT", body });
332
335
  };
336
+ var fetchZendeskBinary = async (subdomain, token, contentUrl) => {
337
+ const expectedHost = `${subdomain}.zendesk.com`;
338
+ const headers = {};
339
+ if (new URL(contentUrl).hostname === expectedHost) {
340
+ headers["Authorization"] = buildAuthHeader(token);
341
+ }
342
+ const response = await fetch(contentUrl, { headers });
343
+ if (!response.ok) {
344
+ const body = await response.text();
345
+ throw new ZendeskApiError(response.status, response.statusText, body);
346
+ }
347
+ const contentType = response.headers.get("content-type") ?? "application/octet-stream";
348
+ const arrayBuffer = await response.arrayBuffer();
349
+ return { data: Buffer.from(arrayBuffer), contentType };
350
+ };
333
351
  var helpCenterUpload = async (subdomain, token, path, formData) => {
334
352
  const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);
335
- const authorization = token.startsWith("Basic ") ? token : `Bearer ${token}`;
336
353
  const response = await fetch(url, {
337
354
  method: "POST",
338
- headers: { Authorization: authorization },
355
+ headers: { Authorization: buildAuthHeader(token) },
339
356
  body: formData
340
357
  });
341
358
  if (!response.ok) {
@@ -471,12 +488,18 @@ var formatTicket = (ticket) => [
471
488
  ticket.description ? `
472
489
  ${ticket.description}` : ""
473
490
  ].filter(Boolean).join("\n");
474
- var formatComment = (comment) => [
475
- `### ${comment.public ? "Public comment" : "Internal note"} by ${comment.author_id}`,
476
- `*${comment.created_at}*`,
477
- "",
478
- comment.body
479
- ].join("\n");
491
+ var formatComment = (comment) => {
492
+ const lines = [
493
+ `### ${comment.public ? "Public comment" : "Internal note"} by ${comment.author_id}`,
494
+ `*${comment.created_at}*`
495
+ ];
496
+ if (comment.attachments?.length) {
497
+ const summary = comment.attachments.map((a) => `#${a.id} (${a.content_type})`).join(", ");
498
+ lines.push(`Attachments: ${summary}`);
499
+ }
500
+ lines.push("", comment.body);
501
+ return lines.join("\n");
502
+ };
480
503
  var formatUser = (user) => [
481
504
  `## ${user.name} (${user.id})`,
482
505
  `- **Email**: ${user.email}`,
@@ -1456,6 +1479,57 @@ var createSearchTools = (ctx) => {
1456
1479
 
1457
1480
  // src/tools/tickets.ts
1458
1481
  import * as z4 from "zod/v4";
1482
+ var formatReference = (attachment) => `**${attachment.file_name}** (id ${attachment.id}, ${attachment.content_type}, ${attachment.size} bytes) \u2014 ${attachment.content_url}`;
1483
+ var buildEmbeddedImageBlocks = async (subdomain, token, attachment, reference) => {
1484
+ const { data, contentType } = await fetchZendeskBinary(subdomain, token, attachment.content_url);
1485
+ return [
1486
+ { type: "image", data: data.toString("base64"), mimeType: contentType },
1487
+ { type: "text", text: reference }
1488
+ ];
1489
+ };
1490
+ var fetchAllTicketComments = async (subdomain, token, ticketId) => {
1491
+ const all = [];
1492
+ let cursor;
1493
+ let pages = 0;
1494
+ while (pages < MAX_COMMENT_PAGES) {
1495
+ const response = await zendeskGet(subdomain, token, `/tickets/${ticketId}/comments`, buildCursorParams(MAX_PAGE_SIZE, cursor));
1496
+ all.push(...response.comments);
1497
+ pages += 1;
1498
+ if (!response.meta?.has_more || !response.meta?.after_cursor) break;
1499
+ cursor = response.meta.after_cursor;
1500
+ }
1501
+ return all;
1502
+ };
1503
+ var collectAttachmentBlocks = async (subdomain, token, attachments) => {
1504
+ const blocks = [];
1505
+ let embeddedCount = 0;
1506
+ for (const attachment of attachments) {
1507
+ const reference = formatReference(attachment);
1508
+ const isImage = attachment.content_type.startsWith("image/");
1509
+ if (!isImage) {
1510
+ blocks.push({ type: "text", text: reference });
1511
+ continue;
1512
+ }
1513
+ let skipReason = null;
1514
+ if (attachment.size > MAX_ATTACHMENT_BYTES) {
1515
+ skipReason = "skipped: exceeds 5 MB per-image limit";
1516
+ } else if (embeddedCount >= MAX_EMBEDDED_IMAGE_COUNT) {
1517
+ skipReason = `skipped: max ${MAX_EMBEDDED_IMAGE_COUNT} embedded images reached`;
1518
+ }
1519
+ if (skipReason) {
1520
+ blocks.push({ type: "text", text: `${reference} \u2014 ${skipReason}` });
1521
+ continue;
1522
+ }
1523
+ try {
1524
+ blocks.push(...await buildEmbeddedImageBlocks(subdomain, token, attachment, reference));
1525
+ embeddedCount += 1;
1526
+ } catch (error) {
1527
+ const reason = error instanceof ZendeskApiError ? `download failed: ${error.status} ${error.statusText}` : "download failed";
1528
+ blocks.push({ type: "text", text: `${reference} \u2014 ${reason}` });
1529
+ }
1530
+ }
1531
+ return blocks;
1532
+ };
1459
1533
  var createTicketTools = (ctx) => {
1460
1534
  const { subdomain, getToken } = ctx;
1461
1535
  return [
@@ -1500,6 +1574,63 @@ ${comments.map(formatComment).join("\n\n")}`;
1500
1574
  return { content: [{ type: "text", text: truncateIfNeeded(text) }] };
1501
1575
  }
1502
1576
  },
1577
+ {
1578
+ name: "get_ticket_attachments",
1579
+ namespace: "tickets",
1580
+ readOnly: true,
1581
+ title: "Get Zendesk Ticket Attachments",
1582
+ description: "Retrieve ticket attachments. Images are embedded inline; other files are listed as text references.",
1583
+ inputSchema: z4.object({
1584
+ ticket_id: z4.number().int().describe("Ticket ID"),
1585
+ attachment_ids: z4.array(z4.number().int()).optional().describe(
1586
+ "Attachment IDs to fetch directly (e.g. extracted from a previous get_ticket(include_comments=true) call). When provided, skips the comments fetch entirely. When omitted, all attachments of the ticket are returned."
1587
+ )
1588
+ }),
1589
+ annotations: {
1590
+ readOnlyHint: true,
1591
+ destructiveHint: false,
1592
+ idempotentHint: true,
1593
+ openWorldHint: true
1594
+ },
1595
+ handler: async (params) => {
1596
+ const { ticket_id, attachment_ids } = params;
1597
+ const token = await getToken();
1598
+ let attachments;
1599
+ if (attachment_ids && attachment_ids.length > 0) {
1600
+ attachments = [];
1601
+ for (const id of attachment_ids) {
1602
+ try {
1603
+ const { attachment } = await zendeskGet(
1604
+ subdomain,
1605
+ token,
1606
+ `/attachments/${id}`
1607
+ );
1608
+ attachments.push(attachment);
1609
+ } catch (error) {
1610
+ if (!(error instanceof ZendeskApiError) || error.status !== 404) throw error;
1611
+ }
1612
+ }
1613
+ } else {
1614
+ const comments = await fetchAllTicketComments(subdomain, token, ticket_id);
1615
+ attachments = comments.flatMap((c) => c.attachments ?? []);
1616
+ }
1617
+ if (attachments.length === 0) {
1618
+ return {
1619
+ content: [{ type: "text", text: `No attachments found on ticket #${ticket_id}.` }]
1620
+ };
1621
+ }
1622
+ const blocks = await collectAttachmentBlocks(subdomain, token, attachments);
1623
+ return {
1624
+ content: [
1625
+ {
1626
+ type: "text",
1627
+ text: `# Attachments for ticket #${ticket_id} (${attachments.length} total)`
1628
+ },
1629
+ ...blocks
1630
+ ]
1631
+ };
1632
+ }
1633
+ },
1503
1634
  {
1504
1635
  name: "search_tickets",
1505
1636
  namespace: "tickets",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/api-token.ts","../src/auth/browser-oauth.ts","../src/constants.ts","../src/auth/token-store.ts","../src/config.ts","../src/server.ts","../src/routing/registry.ts","../src/tools/help-center.ts","../src/client/zendesk-api.ts","../src/utils/article-sections.ts","../src/utils/formatting.ts","../src/utils/pagination.ts","../src/tools/search.ts","../src/tools/tickets.ts","../src/tools/users.ts","../src/tools/index.ts","../src/transports/stdio.ts","../src/index.ts"],"sourcesContent":["/**\n * API token authentication for stdio transport.\n * Uses Basic auth: base64(email/token:api_token)\n */\nexport const buildBasicAuthHeader = (email: string, apiToken: string): string => {\n const credentials = `${email}/token:${apiToken}`;\n return `Basic ${Buffer.from(credentials).toString('base64')}`;\n};\n","import { createHash, randomBytes } from 'node:crypto';\nimport { createServer, type Server } from 'node:http';\nimport open from 'open';\nimport { getOAuthUrls } from '../constants';\n\nconst DEFAULT_CALLBACK_PORT = 3000;\n\ninterface BrowserOAuthConfig {\n subdomain: string;\n oauthClientId: string;\n callbackPort?: number | undefined;\n}\n\ninterface TokenResult {\n access_token: string;\n refresh_token?: string;\n token_type: string;\n scope: string;\n}\n\nconst generateCodeVerifier = (): string => randomBytes(32).toString('base64url');\n\nconst generateCodeChallenge = (verifier: string): string =>\n createHash('sha256').update(verifier).digest('base64url');\n\n/**\n * Performs OAuth 2.1 PKCE flow by opening the user's browser.\n * Starts a temporary HTTP server to receive the callback.\n * Returns the access token on success.\n */\nexport const authenticateViaBrowser = (config: BrowserOAuthConfig): Promise<TokenResult> => {\n const { subdomain, oauthClientId } = config;\n const { authorizeUrl, tokenUrl } = getOAuthUrls(subdomain);\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n\n return new Promise((resolve, reject) => {\n let callbackServer: Server;\n\n callbackServer = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://localhost`);\n\n if (url.pathname !== '/callback') {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n if (error) {\n const desc = url.searchParams.get('error_description') ?? error;\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(`<html><body><h1>Authentication failed</h1><p>${desc}</p></body></html>`);\n callbackServer.close();\n reject(new Error(`OAuth error: ${desc}`));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Missing authorization code</h1></body></html>');\n callbackServer.close();\n reject(new Error('Missing authorization code in callback'));\n return;\n }\n\n // Exchange code for token\n try {\n const callbackPort = (callbackServer.address() as { port: number }).port;\n const tokenBody = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n client_id: oauthClientId,\n redirect_uri: `http://localhost:${callbackPort}/callback`,\n code_verifier: codeVerifier,\n });\n\n const tokenResponse = await fetch(tokenUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: tokenBody.toString(),\n });\n\n if (!tokenResponse.ok) {\n const errorBody = await tokenResponse.text();\n throw new Error(`Token exchange failed (${tokenResponse.status}): ${errorBody}`);\n }\n\n const tokenData = (await tokenResponse.json()) as TokenResult;\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<html><body><h1>Authentication successful!</h1>' +\n '<p>You can close this tab and return to Claude Code.</p>' +\n '<script>window.close()</script></body></html>',\n );\n\n callbackServer.close();\n resolve(tokenData);\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'text/html' });\n res.end(\n `<html><body><h1>Token exchange failed</h1><p>${err instanceof Error ? err.message : String(err)}</p></body></html>`,\n );\n callbackServer.close();\n reject(err);\n }\n });\n\n // Start on fixed port (must match redirect_uri registered in Zendesk OAuth client)\n callbackServer.listen(config.callbackPort ?? DEFAULT_CALLBACK_PORT, () => {\n const port = (callbackServer.address() as { port: number }).port;\n const redirectUri = `http://localhost:${port}/callback`;\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: oauthClientId,\n redirect_uri: redirectUri,\n scope: 'read write',\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n const authUrl = `${authorizeUrl}?${params.toString()}`;\n console.error(`Opening browser for Zendesk authentication...`);\n console.error(`If the browser doesn't open, visit: ${authUrl}`);\n\n open(authUrl).catch(() => {\n // Browser open failed — the URL is already logged\n });\n });\n\n // Timeout after 5 minutes\n setTimeout(\n () => {\n callbackServer.close();\n reject(new Error('OAuth authentication timed out (5 min). Please try again.'));\n },\n 5 * 60 * 1000,\n ).unref();\n });\n};\n","export const CHARACTER_LIMIT = 25_000;\nexport const DEFAULT_PAGE_SIZE = 100;\nexport const MAX_PAGE_SIZE = 100;\nexport const TOKEN_CACHE_TTL_MS = 5 * 60 * 1000;\n\n// Thresholds used to nudge callers toward section-scoped article tools\n// (get_article_outline / get_article_section / update_article_section)\n// instead of fetching/rewriting the full body.\nexport const LARGE_ARTICLE_BODY_CHARS = 3_000;\nexport const LARGE_ARTICLE_SECTION_COUNT = 4;\n\nexport const getBaseUrl = (subdomain: string): string => `https://${subdomain}.zendesk.com/api/v2`;\n\nexport const getHelpCenterBaseUrl = (subdomain: string): string =>\n `https://${subdomain}.zendesk.com/api/v2/help_center`;\n\nexport const getOAuthUrls = (subdomain: string) => ({\n authorizeUrl: `https://${subdomain}.zendesk.com/oauth/authorizations/new`,\n tokenUrl: `https://${subdomain}.zendesk.com/oauth/tokens`,\n});\n","import { authenticateViaBrowser } from './browser-oauth';\n\ninterface StoredToken {\n accessToken: string;\n refreshToken?: string | undefined;\n}\n\nexport const createTokenStore = (config: { subdomain: string; oauthClientId: string }) => {\n let token: StoredToken | undefined;\n let authPromise: Promise<StoredToken> | undefined;\n\n const setToken = (accessToken: string, refreshToken?: string | undefined) => {\n token = { accessToken, refreshToken };\n };\n\n const ensureToken = async (): Promise<StoredToken> => {\n if (token) return token;\n\n if (!authPromise) {\n authPromise = authenticateViaBrowser({\n subdomain: config.subdomain,\n oauthClientId: config.oauthClientId,\n })\n .then((result) => {\n const stored: StoredToken = {\n accessToken: result.access_token,\n refreshToken: result.refresh_token,\n };\n token = stored;\n authPromise = undefined;\n return stored;\n })\n .catch((err) => {\n authPromise = undefined;\n throw err;\n });\n }\n\n return authPromise;\n };\n\n const getToken = async (): Promise<string> => {\n const stored = await ensureToken();\n return stored.accessToken;\n };\n\n return { getToken, setToken };\n};\n","import * as z from 'zod/v4';\n\nexport const ToolMode = z.enum(['single', 'namespace', 'all']);\nexport type ToolMode = z.infer<typeof ToolMode>;\n\nexport const LogLevel = z.enum(['debug', 'info', 'warn', 'error']);\nexport type LogLevel = z.infer<typeof LogLevel>;\n\nexport const Namespace = z.enum(['tickets', 'help_center', 'users']);\nexport type Namespace = z.infer<typeof Namespace>;\n\nexport const ConfigSchema = z.object({\n subdomain: z.string().min(1, 'ZENDESK_SUBDOMAIN is required'),\n oauthClientId: z.string().min(1),\n zendeskEmail: z.string().optional(),\n zendeskApiToken: z.string().optional(),\n logLevel: LogLevel,\n mode: ToolMode,\n readOnly: z.boolean(),\n namespaces: z.array(Namespace).optional(),\n tools: z.array(z.string()).optional(),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\ninterface CliResult {\n subdomain?: string;\n mode?: string;\n readOnly?: boolean;\n namespaces?: string[];\n tools?: string[];\n logLevel?: string;\n}\n\nconst parseCliArgs = (args: string[]): CliResult => {\n const result: CliResult = {};\n let positionalIndex = 0;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n const next = args[i + 1];\n\n if (arg === '--mode' && next) {\n result.mode = next;\n i++;\n } else if (arg === '--read-only') {\n result.readOnly = true;\n } else if (arg === '--namespace' && next) {\n result.namespaces = result.namespaces ?? [];\n result.namespaces.push(next);\n i++;\n } else if (arg === '--tool' && next) {\n result.tools = result.tools ?? [];\n result.tools.push(next);\n i++;\n } else if (arg === '--log-level' && next) {\n result.logLevel = next;\n i++;\n } else if (!arg.startsWith('-') && positionalIndex === 0) {\n result.subdomain = arg;\n positionalIndex++;\n }\n }\n\n return result;\n};\n\nexport const loadConfig = (argv: string[] = process.argv.slice(2)): Config => {\n const cli = parseCliArgs(argv);\n\n const subdomain = cli.subdomain ?? process.env['ZENDESK_SUBDOMAIN'] ?? '';\n const oauthClientId =\n process.env['ZENDESK_OAUTH_CLIENT_ID'] ?? (subdomain ? `${subdomain}_zendesk` : '');\n\n const mode = cli.tools?.length ? 'all' : (cli.mode ?? 'namespace');\n\n return ConfigSchema.parse({\n subdomain,\n oauthClientId,\n zendeskEmail: process.env['ZENDESK_EMAIL'],\n zendeskApiToken: process.env['ZENDESK_API_TOKEN'],\n logLevel: cli.logLevel ?? process.env['LOG_LEVEL'] ?? 'info',\n mode,\n readOnly: cli.readOnly ?? false,\n namespaces: cli.namespaces,\n tools: cli.tools,\n });\n};\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport * as z from 'zod/v4';\nimport type { Config } from './config';\nimport { filterTools, groupByNamespace } from './routing/registry';\nimport { createAllTools, type ToolDefinition } from './tools/index';\n\nconst NAMESPACE_LABELS: Record<string, { toolName: string; title: string }> = {\n tickets: { toolName: 'zendesk_tickets', title: 'Zendesk Tickets' },\n help_center: { toolName: 'zendesk_help_center', title: 'Zendesk Help Center' },\n users: { toolName: 'zendesk_users', title: 'Zendesk Users' },\n};\n\n// Keep proxy descriptions compact: a proxy tool concatenates one line per\n// sub-operation, so only the first sentence of each tool description is\n// included. Clients still receive the full schema via the wrapped tool.\nexport const summarizeDescription = (description: string): string => {\n const idx = description.indexOf('. ');\n if (idx === -1) return description;\n return description.slice(0, idx + 1);\n};\n\nexport const buildOperationList = (\n tools: ReadonlyArray<Pick<ToolDefinition, 'name' | 'description' | 'readOnly'>>,\n): string =>\n tools\n .map(\n (t) =>\n `- **${t.name}**: ${summarizeDescription(t.description)}${t.readOnly ? '' : ' (write)'}`,\n )\n .join('\\n');\n\nconst registerProxyTool = (\n server: McpServer,\n toolName: string,\n title: string,\n tools: ToolDefinition[],\n handlerMap: Map<string, ToolDefinition>,\n): void => {\n const operationNames = tools.map((t) => t.name);\n const operationList = buildOperationList(tools);\n\n server.registerTool(\n toolName,\n {\n title,\n description: `${title}. Specify the operation and its parameters.\\n\\nAvailable operations:\\n${operationList}`,\n inputSchema: z.object({\n operation: z.string().describe(`One of: ${operationNames.join(', ')}`),\n params: z.record(z.string(), z.unknown()).default({}).describe('Operation parameters'),\n }),\n },\n async ({ operation, params }) => {\n const def = handlerMap.get(operation);\n if (!def) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Unknown operation \"${operation}\". Available: ${operationNames.join(', ')}`,\n },\n ],\n };\n }\n // Validate params through the tool's own schema\n const validated = def.inputSchema.parse(params);\n return def.handler(validated);\n },\n );\n};\n\nexport const createMcpServer = (\n config: Config,\n getToken: () => string | Promise<string>,\n): McpServer => {\n const server = new McpServer({\n name: '@digital4better/zendesk-mcp-server',\n version: '0.1.0',\n });\n\n const allTools = createAllTools({ subdomain: config.subdomain, getToken });\n\n // Apply filters (--read-only, --namespace, --tool)\n const filteredTools = filterTools(allTools, {\n readOnly: config.readOnly,\n namespaces: config.namespaces,\n tools: config.tools,\n });\n\n // Build handler map for proxy dispatch\n const handlerMap = new Map<string, ToolDefinition>();\n for (const tool of filteredTools) {\n handlerMap.set(tool.name, tool);\n }\n\n switch (config.mode) {\n case 'all': {\n // Register each tool individually\n for (const tool of filteredTools) {\n server.registerTool(\n tool.name,\n {\n title: tool.title,\n description: tool.description,\n inputSchema: tool.inputSchema,\n annotations: tool.annotations,\n },\n async (params) => tool.handler(params as Record<string, unknown>),\n );\n }\n break;\n }\n case 'namespace': {\n const grouped = groupByNamespace(filteredTools);\n for (const [namespace, tools] of grouped) {\n const label = NAMESPACE_LABELS[namespace];\n if (label) {\n registerProxyTool(server, label.toolName, label.title, tools, handlerMap);\n }\n }\n break;\n }\n case 'single': {\n registerProxyTool(server, 'zendesk', 'Zendesk', filteredTools, handlerMap);\n break;\n }\n }\n\n console.error(`Registered ${filteredTools.length} tools in ${config.mode} mode`);\n return server;\n};\n","import type { Namespace } from '../config';\nimport type { ToolDefinition } from '../tools/definitions';\n\nexport interface FilterOptions {\n readOnly: boolean;\n namespaces?: Namespace[] | undefined;\n tools?: string[] | undefined;\n}\n\nexport const filterTools = (allTools: ToolDefinition[], options: FilterOptions): ToolDefinition[] =>\n allTools.filter((tool) => {\n if (options.readOnly && !tool.readOnly) return false;\n if (options.namespaces?.length && !options.namespaces.includes(tool.namespace)) return false;\n if (options.tools?.length && !options.tools.includes(tool.name)) return false;\n return true;\n });\n\nexport const groupByNamespace = (tools: ToolDefinition[]): Map<string, ToolDefinition[]> => {\n const grouped = new Map<string, ToolDefinition[]>();\n for (const tool of tools) {\n const existing = grouped.get(tool.namespace) ?? [];\n existing.push(tool);\n grouped.set(tool.namespace, existing);\n }\n return grouped;\n};\n","import * as z from 'zod/v4';\nimport {\n helpCenterGet,\n helpCenterPost,\n helpCenterPut,\n helpCenterUpload,\n zendeskGet,\n zendeskPost,\n} from '../client/zendesk-api';\nimport {\n DEFAULT_PAGE_SIZE,\n LARGE_ARTICLE_BODY_CHARS,\n LARGE_ARTICLE_SECTION_COUNT,\n MAX_PAGE_SIZE,\n} from '../constants';\nimport type {\n ZendeskArticle,\n ZendeskArticleAttachment,\n ZendeskCategory,\n ZendeskContentTag,\n ZendeskLabel,\n ZendeskListResponse,\n ZendeskPermissionGroup,\n ZendeskSection,\n ZendeskTranslation,\n ZendeskUserSegment,\n} from '../types';\nimport {\n htmlToMarkdown,\n markdownToHtml,\n parseSections,\n replaceSectionContent,\n} from '../utils/article-sections';\nimport {\n formatArticle,\n formatArticleSummary,\n formatAttachment,\n formatCategory,\n formatContentTag,\n formatLabel,\n formatList,\n formatPermissionGroup,\n formatSection,\n formatTranslation,\n formatTranslationSummary,\n formatUserSegment,\n truncateIfNeeded,\n} from '../utils/formatting';\nimport {\n buildCursorParams,\n buildOffsetParams,\n extractPaginationMeta,\n extractSearchPaginationMeta,\n} from '../utils/pagination';\nimport type { ToolContext, ToolDefinition } from './definitions';\n\nconst largeArticleHint = (body: string, sectionCount: number): string | null => {\n if (body.length < LARGE_ARTICLE_BODY_CHARS && sectionCount < LARGE_ARTICLE_SECTION_COUNT) {\n return null;\n }\n return [\n `> ⚠ Large article (${body.length} chars, ${sectionCount} sections).`,\n '> For targeted edits, prefer get_article_outline + get_article_section +',\n '> update_article_section to avoid re-sending the full body on each write.',\n '',\n ].join('\\n');\n};\n\nexport const createHelpCenterTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'search_articles',\n namespace: 'help_center',\n readOnly: true,\n title: 'Search Help Center Articles',\n description:\n 'Full-text search across Help Center articles (metadata only, no body). Use get_article for full content. Supports locale filtering. Returns total count.',\n inputSchema: z.object({\n query: z.string().min(1).describe('Search query'),\n locale: z.string().optional().describe('Filter by locale (e.g., \"en-us\", \"fr\")'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page'),\n page: z.number().int().min(1).default(1).describe('Page number'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, locale, per_page, page } = params as {\n query: string;\n locale?: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const p: Record<string, string> = { query, ...buildOffsetParams(per_page, page) };\n if (locale) p['locale'] = locale;\n const response = await helpCenterGet<ZendeskListResponse<ZendeskArticle>>(\n subdomain,\n token,\n '/articles/search',\n p,\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.results ?? [],\n formatArticleSummary,\n extractSearchPaginationMeta(response, per_page, page),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'get_article',\n namespace: 'help_center',\n readOnly: true,\n title: 'Get Help Center Article',\n description:\n 'Retrieve an article by ID with full body content. For large articles, prefer get_article_outline + get_article_section to save tokens. Optionally specify locale for a translated version. Returns body (HTML), metadata, source_locale, and list of available translations.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z.string().optional().describe('Locale for translated version'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale } = params as { article_id: number; locale?: string };\n const token = await getToken();\n const path = locale ? `/${locale}/articles/${article_id}` : `/articles/${article_id}`;\n const { article } = await helpCenterGet<{ article: ZendeskArticle }>(\n subdomain,\n token,\n path,\n );\n const { translations } = await helpCenterGet<{ translations: ZendeskTranslation[] }>(\n subdomain,\n token,\n `/articles/${article_id}/translations`,\n );\n const hint = largeArticleHint(article.body, parseSections(article.body).length);\n const text =\n (hint ?? '') +\n formatArticle(article) +\n `\\n\\n**Available translations**: ${translations.map((t) => t.locale).join(', ')}`;\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'list_categories',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Help Center Categories',\n description: 'List all Help Center categories. Optionally filter by locale.',\n inputSchema: z.object({\n locale: z.string().optional(),\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { locale, page_size, cursor } = params as {\n locale?: string;\n page_size: number;\n cursor?: string;\n };\n const token = await getToken();\n const path = locale ? `/${locale}/categories` : '/categories';\n const response = await helpCenterGet<ZendeskListResponse<ZendeskCategory>>(\n subdomain,\n token,\n path,\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.categories ?? [],\n formatCategory,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'list_sections',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Help Center Sections',\n description: 'List sections, optionally filtered by category ID and locale.',\n inputSchema: z.object({\n category_id: z.number().int().optional(),\n locale: z.string().optional(),\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { category_id, locale, page_size, cursor } = params as {\n category_id?: number;\n locale?: string;\n page_size: number;\n cursor?: string;\n };\n const token = await getToken();\n const path =\n category_id && locale\n ? `/${locale}/categories/${category_id}/sections`\n : category_id\n ? `/categories/${category_id}/sections`\n : locale\n ? `/${locale}/sections`\n : '/sections';\n const response = await helpCenterGet<ZendeskListResponse<ZendeskSection>>(\n subdomain,\n token,\n path,\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.sections ?? [],\n formatSection,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'list_articles',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Help Center Articles',\n description:\n 'List articles (metadata only, no body). Use get_article for full content. Optionally filter by section ID and locale. Supports sort_by (\"title\", \"created_at\", \"updated_at\") and include_translations: true to show available translation locales per article. Note: include_translations must be re-sent on each paginated request.',\n inputSchema: z.object({\n section_id: z.number().int().optional(),\n locale: z.string().optional(),\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n sort_by: z\n .enum(['created_at', 'updated_at', 'position', 'title'])\n .default('position')\n .describe('Sort field'),\n sort_order: z.enum(['asc', 'desc']).default('asc').describe('Sort direction'),\n include_translations: z\n .boolean()\n .default(false)\n .describe(\n 'Include available translation locales per article (causes 1 extra API call per article)',\n ),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { section_id, locale, page_size, cursor, sort_by, sort_order, include_translations } =\n params as {\n section_id?: number;\n locale?: string;\n page_size: number;\n cursor?: string;\n sort_by: string;\n sort_order: string;\n include_translations: boolean;\n };\n const token = await getToken();\n const path =\n section_id && locale\n ? `/${locale}/sections/${section_id}/articles`\n : section_id\n ? `/sections/${section_id}/articles`\n : locale\n ? `/${locale}/articles`\n : '/articles';\n const response = await helpCenterGet<ZendeskListResponse<ZendeskArticle>>(\n subdomain,\n token,\n path,\n { ...buildCursorParams(page_size, cursor), sort_by, sort_order },\n );\n const articles = response.articles ?? [];\n if (!include_translations) {\n return {\n content: [\n {\n type: 'text',\n text: formatList(articles, formatArticleSummary, extractPaginationMeta(response)),\n },\n ],\n };\n }\n const formatted = await Promise.all(\n articles.map(async (article) => {\n const { translations } = await helpCenterGet<{ translations: ZendeskTranslation[] }>(\n subdomain,\n token,\n `/articles/${article.id}/translations`,\n );\n const locales = translations.map((t) => t.locale).join(', ');\n return `${formatArticleSummary(article)}\\n- **Translations**: ${locales}`;\n }),\n );\n const meta = extractPaginationMeta(response);\n const header = meta.count\n ? `Results: ${meta.count}${meta.has_more ? ` | More available (cursor: ${meta.after_cursor})` : ''}`\n : '';\n const text = [header, ...formatted].filter(Boolean).join('\\n\\n');\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'list_article_translations',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Article Translations',\n description:\n 'List all available translations for an article (metadata only, no body: locale, title, draft, updated_at). Use get_article with locale for full translated content.',\n inputSchema: z.object({ article_id: z.number().int().describe('Article ID') }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id } = params as { article_id: number };\n const token = await getToken();\n const { translations } = await helpCenterGet<{ translations: ZendeskTranslation[] }>(\n subdomain,\n token,\n `/articles/${article_id}/translations`,\n );\n return {\n content: [{ type: 'text', text: formatList(translations, formatTranslationSummary) }],\n };\n },\n },\n {\n name: 'create_article_translation',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Article Translation',\n description: 'Create a translation for an existing article in a specific locale.',\n inputSchema: z.object({\n article_id: z.number().int(),\n locale: z.string().describe('Target locale (e.g., \"fr\", \"de\")'),\n title: z.string().min(1),\n body: z.string().min(1).describe('Translated body (HTML)'),\n draft: z.boolean().default(false),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, title, body, draft } = params as {\n article_id: number;\n locale: string;\n title: string;\n body: string;\n draft: boolean;\n };\n const token = await getToken();\n const { translation } = await helpCenterPost<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations`,\n { translation: { locale, title, body, draft } },\n );\n return {\n content: [\n {\n type: 'text',\n text: `Translation created for article #${article_id} in \"${locale}\".\\n\\n${formatTranslation(translation)}`,\n },\n ],\n };\n },\n },\n {\n name: 'update_article_translation',\n namespace: 'help_center',\n readOnly: false,\n title: 'Update Article Translation',\n description:\n \"Update article content (title, body) in a specific locale. For targeted edits on one or a few sections, prefer update_article_section — this tool replaces the FULL body and re-sends the entire article on each write. Use the article's source_locale (from get_article) for the default language, or another locale for translations.\",\n inputSchema: z.object({\n article_id: z.number().int(),\n locale: z.string(),\n title: z.string().optional(),\n body: z.string().optional(),\n draft: z.boolean().optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, ...updates } = params as {\n article_id: number;\n locale: string;\n } & Record<string, unknown>;\n const token = await getToken();\n const { translation } = await helpCenterPut<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n { translation: updates },\n );\n return {\n content: [\n {\n type: 'text',\n text: `Translation updated for article #${article_id} in \"${locale}\".\\n\\n${formatTranslation(translation)}`,\n },\n ],\n };\n },\n },\n {\n name: 'list_permission_groups',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Permission Groups',\n description:\n 'List all Guide permission groups. Use this to find the permission_group_id required when creating articles.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await zendeskGet<{\n permission_groups: ZendeskPermissionGroup[];\n count: number;\n }>(subdomain, token, '/guide/permission_groups');\n return {\n content: [\n {\n type: 'text',\n text: formatList(response.permission_groups ?? [], formatPermissionGroup),\n },\n ],\n };\n },\n },\n {\n name: 'create_article',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Help Center Article',\n description:\n \"Create a new article in a section. The locale becomes the article's source_locale. Requires a permission_group_id (use list_permission_groups to find available IDs). To add content in other locales afterwards, use create_article_translation.\",\n inputSchema: z.object({\n section_id: z.number().int(),\n title: z.string().min(1),\n body: z.string().min(1).describe('Article body (HTML)'),\n permission_group_id: z\n .number()\n .int()\n .describe('Permission group ID (use list_permission_groups to find it)'),\n user_segment_id: z\n .number()\n .int()\n .optional()\n .describe(\n 'User segment ID for visibility (use list_user_segments to find it). Defaults to everyone.',\n ),\n author_id: z\n .number()\n .int()\n .optional()\n .describe('Author user ID. Defaults to the authenticated user.'),\n content_tag_ids: z\n .array(z.string())\n .optional()\n .describe('Content tag IDs (use list_content_tags to find them)'),\n locale: z.string().optional(),\n draft: z.boolean().default(true),\n promoted: z.boolean().default(false),\n label_names: z\n .array(z.string())\n .optional()\n .describe('Label names for search ranking (use list_labels to see existing labels)'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { section_id, ...articleData } = params as { section_id: number } & Record<\n string,\n unknown\n >;\n const token = await getToken();\n const { article } = await helpCenterPost<{ article: ZendeskArticle }>(\n subdomain,\n token,\n `/sections/${section_id}/articles`,\n { article: articleData },\n );\n return {\n content: [\n { type: 'text', text: `Article #${article.id} created.\\n\\n${formatArticle(article)}` },\n ],\n };\n },\n },\n {\n name: 'update_article',\n namespace: 'help_center',\n readOnly: false,\n title: 'Update Help Center Article',\n description:\n 'Update article metadata only (draft, promoted, labels, tags, visibility, section, etc.). Does NOT update content (title, body) — use update_article_translation for that.',\n inputSchema: z.object({\n article_id: z.number().int(),\n draft: z.boolean().optional(),\n promoted: z.boolean().optional(),\n label_names: z.array(z.string()).optional().describe('Label names for search ranking'),\n content_tag_ids: z.array(z.string()).optional().describe('Content tag IDs'),\n user_segment_id: z.number().int().optional().describe('User segment ID for visibility'),\n author_id: z.number().int().optional().describe('Author user ID'),\n permission_group_id: z.number().int().optional().describe('Permission group ID'),\n section_id: z.number().int().optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, ...updates } = params as { article_id: number } & Record<\n string,\n unknown\n >;\n const token = await getToken();\n const { article } = await helpCenterPut<{ article: ZendeskArticle }>(\n subdomain,\n token,\n `/articles/${article_id}`,\n { article: updates },\n );\n return {\n content: [\n { type: 'text', text: `Article #${article.id} updated.\\n\\n${formatArticle(article)}` },\n ],\n };\n },\n },\n {\n name: 'list_content_tags',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Content Tags',\n description:\n 'List all Guide content tags. Content tags are visible to end users and help them find related articles.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await zendeskGet<{ records: ZendeskContentTag[]; count: number }>(\n subdomain,\n token,\n '/guide/content_tags',\n );\n return {\n content: [{ type: 'text', text: formatList(response.records ?? [], formatContentTag) }],\n };\n },\n },\n {\n name: 'create_content_tag',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Content Tag',\n description: 'Create a new content tag for Guide articles.',\n inputSchema: z.object({\n name: z.string().min(1).describe('Content tag name'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { name } = params as { name: string };\n const token = await getToken();\n const { record } = await zendeskPost<{ record: ZendeskContentTag }>(\n subdomain,\n token,\n '/guide/content_tags',\n { record: { name } },\n );\n return {\n content: [{ type: 'text', text: `Content tag created.\\n\\n${formatContentTag(record)}` }],\n };\n },\n },\n {\n name: 'list_labels',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Article Labels',\n description:\n 'List all article labels. Labels improve Help Center search ranking and are not visible to end users.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await helpCenterGet<{ labels: ZendeskLabel[]; count: number }>(\n subdomain,\n token,\n '/articles/labels',\n );\n return {\n content: [{ type: 'text', text: formatList(response.labels ?? [], formatLabel) }],\n };\n },\n },\n {\n name: 'list_user_segments',\n namespace: 'help_center',\n readOnly: true,\n title: 'List User Segments',\n description:\n 'List all user segments. User segments control article visibility (who can view). Use the ID when creating or updating articles.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await helpCenterGet<{\n user_segments: ZendeskUserSegment[];\n count: number;\n }>(subdomain, token, '/user_segments');\n return {\n content: [\n { type: 'text', text: formatList(response.user_segments ?? [], formatUserSegment) },\n ],\n };\n },\n },\n {\n name: 'list_article_attachments',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Article Attachments',\n description: 'List all attachments for an article.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id } = params as { article_id: number };\n const token = await getToken();\n const response = await helpCenterGet<{\n article_attachments: ZendeskArticleAttachment[];\n count: number;\n }>(subdomain, token, `/articles/${article_id}/attachments`);\n return {\n content: [\n {\n type: 'text',\n text: formatList(response.article_attachments ?? [], formatAttachment),\n },\n ],\n };\n },\n },\n {\n name: 'get_article_outline',\n namespace: 'help_center',\n readOnly: true,\n title: 'Get Article Outline',\n description:\n 'Return a compact outline of an article (list of sections delimited by h1/h2/h3, with word counts) for the given locale (defaults to source_locale). Includes available translations with their outdated status. Use get_article_section to fetch a specific section.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z\n .string()\n .optional()\n .describe('Locale of the body to outline (defaults to article source_locale)'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale } = params as { article_id: number; locale?: string };\n const token = await getToken();\n const { article } = await helpCenterGet<{ article: ZendeskArticle }>(\n subdomain,\n token,\n `/articles/${article_id}`,\n );\n const effectiveLocale = locale ?? article.source_locale;\n const { translation } = await helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${effectiveLocale}`,\n );\n const { translations } = await helpCenterGet<{\n translations: Array<ZendeskTranslation & { outdated?: boolean }>;\n }>(subdomain, token, `/articles/${article_id}/translations`);\n const sections = parseSections(translation.body);\n\n const outlineLines = sections.length\n ? sections\n .map(\n (s) =>\n `- [${s.index}] ${s.headingTag ? `${s.headingTag}: ` : ''}${s.heading} (${s.wordCount} words)`,\n )\n .join('\\n')\n : '_(no sections detected)_';\n const translationsList = translations\n .map((t) => `- ${t.locale}${t.outdated ? ' (outdated)' : ''}`)\n .join('\\n');\n\n const text = [\n `# Outline — Article #${article_id} (${effectiveLocale})`,\n `**Title**: ${translation.title}`,\n '',\n '## Sections',\n outlineLines,\n '',\n '## Available translations',\n translationsList,\n ].join('\\n');\n return { content: [{ type: 'text', text }] };\n },\n },\n {\n name: 'get_article_section',\n namespace: 'help_center',\n readOnly: true,\n title: 'Get Article Section',\n description:\n 'Retrieve the content of a single section of an article in a given locale. Use get_article_outline first to discover section indexes. Default format=\"html\" for round-trip safety. Pass format=\"markdown\" only for human review — the Markdown representation is lossy on some structures (<pre> with <br>, tables with multi-<p> cells are kept as raw HTML to limit the damage, but do not round-trip markdown content back through update_article_section).',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z.string().describe('Locale of the body (e.g., \"en-us\", \"fr\")'),\n section_index: z\n .number()\n .int()\n .min(0)\n .describe('0-based index of the section (see get_article_outline)'),\n format: z\n .enum(['html', 'markdown'])\n .default('html')\n .describe(\n 'Output format. \"html\" (default) is round-trip safe. \"markdown\" is lossy on some HTML structures — use only for human review, not before update_article_section.',\n ),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, section_index, format } = params as {\n article_id: number;\n locale: string;\n section_index: number;\n format: 'html' | 'markdown';\n };\n const token = await getToken();\n const { translation } = await helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n );\n const sections = parseSections(translation.body);\n const section = sections[section_index];\n if (!section) {\n throw new Error(\n `Section index ${section_index} not found. Article has ${sections.length} section(s) (0-${Math.max(0, sections.length - 1)}).`,\n );\n }\n const content = format === 'markdown' ? htmlToMarkdown(section.html) : section.html;\n const headerLine = section.headingTag\n ? `## [${section.index}] ${section.headingTag}: ${section.heading}`\n : `## [${section.index}] ${section.heading}`;\n const text = [\n headerLine,\n `_Locale: ${locale} | Words: ${section.wordCount} | Format: ${format}_`,\n '',\n content,\n ].join('\\n');\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'update_article_section',\n namespace: 'help_center',\n readOnly: false,\n title: 'Update Article Section',\n description:\n 'Replace the content of a single section of an article in a given locale, keeping the rest of the body intact. The server fetches the current body, replaces the targeted section, and PUTs the full reconstructed body via the Translations API. Default format=\"html\" for fidelity. Use format=\"markdown\" only when you control the input and know it does not rely on structures that round-trip poorly (code blocks with line breaks, tables with multi-paragraph cells). The section heading is preserved and is NOT part of the replaced content.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z.string().describe('Locale of the translation to update'),\n section_index: z\n .number()\n .int()\n .min(0)\n .describe('0-based index of the section to replace (see get_article_outline)'),\n content: z\n .string()\n .describe(\n 'New content for the section (heading excluded). HTML by default, Markdown if format=\"markdown\".',\n ),\n format: z\n .enum(['html', 'markdown'])\n .default('html')\n .describe(\n 'Input format. \"html\" (default) is the safe path. \"markdown\" is converted to HTML server-side but may introduce artifacts on complex content.',\n ),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, section_index, content, format } = params as {\n article_id: number;\n locale: string;\n section_index: number;\n content: string;\n format: 'html' | 'markdown';\n };\n const token = await getToken();\n const { translation } = await helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n );\n const newSectionHtml = format === 'markdown' ? markdownToHtml(content) : content;\n const newBody = replaceSectionContent(translation.body, section_index, newSectionHtml);\n const { translation: updated } = await helpCenterPut<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n { translation: { body: newBody } },\n );\n const updatedSections = parseSections(updated.body);\n const updatedSection = updatedSections[section_index];\n const newWordCount = updatedSection?.wordCount ?? 0;\n const headingLabel = updatedSection?.heading ?? '(intro)';\n const text = [\n `Section [${section_index}] \"${headingLabel}\" updated for article #${article_id} (${locale}).`,\n `New word count: ${newWordCount}.`,\n ].join('\\n');\n return { content: [{ type: 'text', text }] };\n },\n },\n {\n name: 'compare_translations',\n namespace: 'help_center',\n readOnly: true,\n title: 'Compare Article Translations',\n description:\n 'Compare section structure between two locales of the same article, matched by index. Returns a compact table (one row per section) with status: \"ok\" (both present, source/target word count ratio within 25%), \"different\" (word count ratio diverges by more than 25% — size signal only, NOT a semantic divergence: two locales may legitimately differ in verbosity) or \"missing\" (section absent in target). Useful to spot structurally stale or missing sections; do not interpret \"different\" as an edit regression on its own.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n source_locale: z.string().describe('Source (reference) locale'),\n target_locale: z.string().describe('Target locale to compare against source'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, source_locale, target_locale } = params as {\n article_id: number;\n source_locale: string;\n target_locale: string;\n };\n const token = await getToken();\n const [sourceRes, targetRes] = await Promise.all([\n helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${source_locale}`,\n ),\n helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${target_locale}`,\n ),\n ]);\n const sourceSections = parseSections(sourceRes.translation.body);\n const targetSections = parseSections(targetRes.translation.body);\n const maxLen = Math.max(sourceSections.length, targetSections.length);\n\n const rows: string[] = [];\n rows.push(`| Idx | Heading | Status | Source words | Target words |`);\n rows.push(`| --- | --- | --- | --- | --- |`);\n for (let i = 0; i < maxLen; i += 1) {\n const src = sourceSections[i];\n const tgt = targetSections[i];\n const heading = src?.heading ?? tgt?.heading ?? '';\n const sourceWords = src?.wordCount ?? 0;\n const targetWords = tgt?.wordCount ?? 0;\n let status: 'ok' | 'missing' | 'different';\n if (!tgt) status = 'missing';\n else if (!src) status = 'different';\n else {\n const denom = Math.max(sourceWords, 1);\n const diffRatio = Math.abs(sourceWords - targetWords) / denom;\n status = diffRatio > 0.25 ? 'different' : 'ok';\n }\n rows.push(`| ${i} | ${heading} | ${status} | ${sourceWords} | ${targetWords} |`);\n }\n\n const text = [\n `# Translation diff — Article #${article_id} (${source_locale} → ${target_locale})`,\n '',\n ...rows,\n ].join('\\n');\n return { content: [{ type: 'text', text }] };\n },\n },\n {\n name: 'create_article_attachment',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Article Attachment',\n description:\n 'Upload an attachment to an article. Provide file content as base64-encoded string.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n file_name: z.string().min(1).describe('File name (e.g., \"screenshot.png\")'),\n file_base64: z.string().min(1).describe('File content encoded as base64'),\n content_type: z\n .string()\n .default('application/octet-stream')\n .describe('MIME type (e.g., \"image/png\", \"application/pdf\")'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, file_name, file_base64, content_type } = params as {\n article_id: number;\n file_name: string;\n file_base64: string;\n content_type: string;\n };\n const token = await getToken();\n const buffer = Buffer.from(file_base64, 'base64');\n const blob = new Blob([buffer], { type: content_type });\n const formData = new FormData();\n formData.append('file', blob, file_name);\n const { article_attachment } = await helpCenterUpload<{\n article_attachment: ZendeskArticleAttachment;\n }>(subdomain, token, `/articles/${article_id}/attachments`, formData);\n return {\n content: [\n {\n type: 'text',\n text: `Attachment created for article #${article_id}.\\n\\n${formatAttachment(article_attachment)}`,\n },\n ],\n };\n },\n },\n ];\n};\n","import { getBaseUrl, getHelpCenterBaseUrl } from '../constants.js';\n\nexport class ZendeskApiError extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly body: string,\n ) {\n super(ZendeskApiError.buildMessage(status, statusText, body));\n this.name = 'ZendeskApiError';\n }\n\n private static buildMessage(status: number, statusText: string, body: string): string {\n switch (status) {\n case 401:\n return 'Authentication failed. Your Zendesk token may be expired or invalid. Re-authenticate to get a new token.';\n case 403:\n return 'Permission denied. Your Zendesk account does not have access to this resource.';\n case 404:\n return `Resource not found. Please verify the ID is correct. (${statusText})`;\n case 422:\n return `Validation error: ${body}`;\n case 429:\n return 'Rate limit exceeded. Please wait before making more requests.';\n default:\n return `Zendesk API error ${status}: ${statusText}. ${body}`;\n }\n }\n}\n\nexport interface ZendeskRequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n body?: unknown;\n params?: Record<string, string>;\n}\n\nconst buildUrl = (base: string, path: string, params?: Record<string, string>): string => {\n const url = new URL(`${base}${path}`);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n }\n return url.toString();\n};\n\nconst executeRequest = async <T>(\n url: string,\n token: string,\n options: ZendeskRequestOptions = {},\n): Promise<T> => {\n const { method = 'GET', body } = options;\n\n // token is either a Bearer OAuth token or a \"Basic xxx\" string (stdio API token mode)\n const authorization = token.startsWith('Basic ') ? token : `Bearer ${token}`;\n const headers: Record<string, string> = {\n Authorization: authorization,\n Accept: 'application/json',\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n }\n\n const init: RequestInit = { method, headers };\n if (body) {\n init.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, init);\n\n if (!response.ok) {\n const responseBody = await response.text();\n throw new ZendeskApiError(response.status, response.statusText, responseBody);\n }\n\n if (response.status === 204) {\n return {} as T;\n }\n\n return response.json() as Promise<T>;\n};\n\nexport const zendeskGet = <T>(\n subdomain: string,\n token: string,\n path: string,\n params?: Record<string, string>,\n): Promise<T> => {\n const url = buildUrl(getBaseUrl(subdomain), path, params);\n return executeRequest<T>(url, token);\n};\n\nexport const zendeskPost = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'POST', body });\n};\n\nexport const zendeskPut = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'PUT', body });\n};\n\nexport const helpCenterGet = <T>(\n subdomain: string,\n token: string,\n path: string,\n params?: Record<string, string>,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path, params);\n return executeRequest<T>(url, token);\n};\n\nexport const helpCenterPost = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'POST', body });\n};\n\nexport const helpCenterPut = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'PUT', body });\n};\n\nexport const helpCenterUpload = async <T>(\n subdomain: string,\n token: string,\n path: string,\n formData: FormData,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);\n const authorization = token.startsWith('Basic ') ? token : `Bearer ${token}`;\n const response = await fetch(url, {\n method: 'POST',\n headers: { Authorization: authorization },\n body: formData,\n });\n\n if (!response.ok) {\n const responseBody = await response.text();\n throw new ZendeskApiError(response.status, response.statusText, responseBody);\n }\n\n return response.json() as Promise<T>;\n};\n","import * as cheerio from 'cheerio';\nimport type { Element } from 'hast';\nimport { toHtml } from 'hast-util-to-html';\nimport type { Handle } from 'hast-util-to-mdast';\nimport rehypeParse from 'rehype-parse';\nimport rehypeRaw from 'rehype-raw';\nimport rehypeRemark from 'rehype-remark';\nimport rehypeStringify from 'rehype-stringify';\nimport remarkGfm from 'remark-gfm';\nimport remarkParse from 'remark-parse';\nimport remarkRehype from 'remark-rehype';\nimport remarkStringify from 'remark-stringify';\nimport { unified } from 'unified';\n\nexport interface Section {\n index: number;\n heading: string;\n headingTag: string;\n level: number;\n html: string;\n wordCount: number;\n}\n\nconst HEADING_LEVELS = new Set(['h1', 'h2', 'h3']);\n\nconst countWords = (text: string): number => {\n const trimmed = text.trim();\n if (!trimmed) return 0;\n return trimmed.split(/\\s+/).length;\n};\n\nconst textOf = (html: string): string => {\n if (!html) return '';\n const $ = cheerio.load(`<div>${html}</div>`, null, false);\n return $('div').first().text();\n};\n\nexport const parseSections = (html: string): Section[] => {\n if (!html || !html.trim()) return [];\n\n const $ = cheerio.load(html, null, false);\n const children = $.root().contents().toArray();\n\n const introParts: string[] = [];\n const sections: Array<{\n heading: string;\n headingTag: string;\n level: number;\n contentParts: string[];\n }> = [];\n let current: (typeof sections)[number] | null = null;\n\n for (const node of children) {\n const tagName = node.type === 'tag' ? node.name.toLowerCase() : '';\n\n if (HEADING_LEVELS.has(tagName)) {\n const level = Number.parseInt(tagName.slice(1), 10);\n current = {\n heading: $(node).text().trim(),\n headingTag: tagName,\n level,\n contentParts: [],\n };\n sections.push(current);\n continue;\n }\n\n const outer = $.html(node);\n if (current) {\n current.contentParts.push(outer);\n } else {\n introParts.push(outer);\n }\n }\n\n const result: Section[] = [];\n\n if (introParts.length > 0) {\n const introHtml = introParts.join('');\n result.push({\n index: 0,\n heading: 'intro',\n headingTag: '',\n level: 0,\n html: introHtml,\n wordCount: countWords(textOf(introHtml)),\n });\n }\n\n for (const s of sections) {\n const sectionHtml = s.contentParts.join('');\n result.push({\n index: result.length,\n heading: s.heading,\n headingTag: s.headingTag,\n level: s.level,\n html: sectionHtml,\n wordCount: countWords(textOf(sectionHtml)),\n });\n }\n\n return result;\n};\n\nexport const replaceSectionContent = (\n html: string,\n sectionIndex: number,\n newHtml: string,\n): string => {\n const sections = parseSections(html);\n if (sectionIndex < 0 || sectionIndex >= sections.length) {\n throw new Error(\n `Section index ${sectionIndex} out of range (valid: 0-${Math.max(0, sections.length - 1)})`,\n );\n }\n\n return sections\n .map((section, idx) => {\n const content = idx === sectionIndex ? newHtml : section.html;\n if (section.level === 0) return content;\n return `<${section.headingTag}>${section.heading}</${section.headingTag}>${content}`;\n })\n .join('');\n};\n\n// Keep structural HTML that markdown flattens lossily: <pre> with inline <br>\n// collapses to a single line, and <table> cells with multiple <p> break GFM\n// pipe tables. Leaving them as raw HTML is safer for round-trip.\nconst keepAsHtml: Handle = (_state, node) => ({\n type: 'html',\n value: toHtml(node as Element),\n});\n\nconst htmlToMdProcessor = unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeRemark, { handlers: { table: keepAsHtml, pre: keepAsHtml } })\n .use(remarkGfm)\n .use(remarkStringify, { bullet: '-', emphasis: '_', fences: true });\n\nconst mdToHtmlProcessor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, { allowDangerousHtml: true })\n .use(rehypeRaw)\n .use(rehypeStringify);\n\nexport const htmlToMarkdown = (html: string): string => {\n if (!html) return '';\n return String(htmlToMdProcessor.processSync(html));\n};\n\nexport const markdownToHtml = (markdown: string): string => {\n if (!markdown) return '';\n return String(mdToHtmlProcessor.processSync(markdown));\n};\n","import { CHARACTER_LIMIT } from '../constants.js';\nimport type {\n PaginationMeta,\n ZendeskArticle,\n ZendeskArticleAttachment,\n ZendeskCategory,\n ZendeskComment,\n ZendeskContentTag,\n ZendeskLabel,\n ZendeskOrganization,\n ZendeskPermissionGroup,\n ZendeskSection,\n ZendeskTicket,\n ZendeskTranslation,\n ZendeskUser,\n ZendeskUserSegment,\n} from '../types.js';\n\nexport const truncateIfNeeded = (text: string): string => {\n if (text.length <= CHARACTER_LIMIT) return text;\n return `${text.slice(0, CHARACTER_LIMIT)}\\n\\n--- Response truncated (${text.length} chars, limit ${CHARACTER_LIMIT}). Use pagination or filters to reduce results. ---`;\n};\n\nconst formatPagination = (meta: PaginationMeta): string => {\n const parts = [`Results: ${meta.count}`];\n if (meta.has_more) {\n parts.push(`More available (cursor: ${meta.after_cursor})`);\n }\n return parts.join(' | ');\n};\n\nexport const formatTicket = (ticket: ZendeskTicket): string =>\n [\n `## Ticket #${ticket.id}: ${ticket.subject}`,\n `- **Status**: ${ticket.status} | **Priority**: ${ticket.priority ?? 'none'} | **Type**: ${ticket.type ?? 'none'}`,\n `- **Requester**: ${ticket.requester_id} | **Assignee**: ${ticket.assignee_id ?? 'unassigned'}`,\n `- **Tags**: ${ticket.tags.length > 0 ? ticket.tags.join(', ') : 'none'}`,\n `- **Created**: ${ticket.created_at} | **Updated**: ${ticket.updated_at}`,\n ticket.description ? `\\n${ticket.description}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatComment = (comment: ZendeskComment): string =>\n [\n `### ${comment.public ? 'Public comment' : 'Internal note'} by ${comment.author_id}`,\n `*${comment.created_at}*`,\n '',\n comment.body,\n ].join('\\n');\n\nexport const formatUser = (user: ZendeskUser): string =>\n [\n `## ${user.name} (${user.id})`,\n `- **Email**: ${user.email}`,\n `- **Role**: ${user.role}`,\n user.role_type != null ? `- **Role type**: ${user.role_type}` : '',\n `- **Active**: ${user.active}`,\n user.organization_id ? `- **Organization**: ${user.organization_id}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatOrganization = (org: ZendeskOrganization): string =>\n [\n `## ${org.name} (${org.id})`,\n org.details ? `- **Details**: ${org.details}` : '',\n org.domain_names.length > 0 ? `- **Domains**: ${org.domain_names.join(', ')}` : '',\n org.tags.length > 0 ? `- **Tags**: ${org.tags.join(', ')}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatArticleSummary = (article: ZendeskArticle): string =>\n [\n `## ${article.title} (${article.id})`,\n `- **Locale**: ${article.locale} | **Source locale**: ${article.source_locale}`,\n `- **Section**: ${article.section_id} | **Draft**: ${article.draft}`,\n article.label_names.length > 0 ? `- **Labels**: ${article.label_names.join(', ')}` : '',\n `- **Created**: ${article.created_at} | **Updated**: ${article.updated_at}`,\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatArticle = (article: ZendeskArticle): string =>\n [formatArticleSummary(article), '', article.body].join('\\n');\n\nexport const formatTranslationSummary = (translation: ZendeskTranslation): string =>\n [\n `## Translation: ${translation.locale} (${translation.id})`,\n `- **Title**: ${translation.title}`,\n `- **Draft**: ${translation.draft}`,\n `- **Updated**: ${translation.updated_at}`,\n ].join('\\n');\n\nexport const formatTranslation = (translation: ZendeskTranslation): string =>\n [formatTranslationSummary(translation), '', translation.body].join('\\n');\n\nexport const formatCategory = (category: ZendeskCategory): string =>\n `- **${category.name}** (${category.id}) — ${category.description || 'No description'}`;\n\nexport const formatSection = (section: ZendeskSection): string =>\n `- **${section.name}** (${section.id}) — Category: ${section.category_id} — ${section.description || 'No description'}`;\n\nexport const formatPermissionGroup = (group: ZendeskPermissionGroup): string =>\n `- **${group.name}** (${group.id})${group.built_in ? ' — Built-in' : ''}`;\n\nexport const formatContentTag = (tag: ZendeskContentTag): string => `- **${tag.name}** (${tag.id})`;\n\nexport const formatLabel = (label: ZendeskLabel): string => `- **${label.name}** (${label.id})`;\n\nexport const formatUserSegment = (segment: ZendeskUserSegment): string =>\n `- **${segment.name}** (${segment.id}) — ${segment.user_type}${segment.built_in ? ' — Built-in' : ''}`;\n\nexport const formatAttachment = (attachment: ZendeskArticleAttachment): string =>\n `- **${attachment.file_name}** (${attachment.id}) — ${attachment.content_type} — ${attachment.size} bytes`;\n\nexport const formatList = <T>(\n items: T[],\n formatter: (item: T) => string,\n meta?: PaginationMeta,\n): string => {\n const header = meta ? formatPagination(meta) : '';\n const body = items.map(formatter).join('\\n\\n');\n const text = [header, body].filter(Boolean).join('\\n\\n');\n return truncateIfNeeded(text);\n};\n","import type { PaginationMeta, ZendeskListResponse } from '../types';\n\n// Cursor-based pagination (for list endpoints: /tickets, /organizations, etc.)\nexport const buildCursorParams = (pageSize: number, cursor?: string): Record<string, string> => {\n const params: Record<string, string> = {\n 'page[size]': String(pageSize),\n };\n if (cursor) {\n params['page[after]'] = cursor;\n }\n return params;\n};\n\n// Offset-based pagination (for search endpoints: /search, /help_center/articles/search)\nexport const buildOffsetParams = (perPage: number, page?: number): Record<string, string> => {\n const params: Record<string, string> = {\n per_page: String(perPage),\n };\n if (page && page > 1) {\n params['page'] = String(page);\n }\n return params;\n};\n\nexport const extractPaginationMeta = <T>(response: ZendeskListResponse<T>): PaginationMeta => ({\n has_more: response.meta?.has_more ?? response.next_page != null,\n after_cursor: response.meta?.after_cursor ?? null,\n count: response.count ?? 0,\n});\n\n// For search responses — offset-based, count is always present\nexport const extractSearchPaginationMeta = <T>(\n response: ZendeskListResponse<T>,\n perPage: number,\n page: number,\n): PaginationMeta => {\n const count = response.count ?? 0;\n const has_more = count > page * perPage;\n return {\n has_more,\n after_cursor: has_more ? String(page + 1) : null,\n count,\n };\n};\n","import * as z from 'zod/v4';\nimport { zendeskGet } from '../client/zendesk-api';\nimport { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../constants';\nimport type { ZendeskListResponse } from '../types';\nimport { truncateIfNeeded } from '../utils/formatting';\nimport { buildOffsetParams, extractSearchPaginationMeta } from '../utils/pagination';\nimport type { ToolContext, ToolDefinition } from './definitions';\n\nconst formatSearchResult = (result: Record<string, unknown>): string => {\n const lines: string[] = [`## [${result['result_type']}] #${result['id']}`];\n if (result['subject']) lines.push(`**Subject**: ${result['subject']}`);\n if (result['name']) lines.push(`**Name**: ${result['name']}`);\n if (result['title']) lines.push(`**Title**: ${result['title']}`);\n if (result['email']) lines.push(`**Email**: ${result['email']}`);\n if (result['status']) lines.push(`**Status**: ${result['status']}`);\n if (result['description']) {\n const desc = String(result['description']);\n lines.push(desc.length > 200 ? `${desc.slice(0, 200)}...` : desc);\n }\n return lines.join('\\n');\n};\n\nexport const createSearchTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'search',\n namespace: 'tickets',\n readOnly: true,\n title: 'Zendesk Unified Search',\n description:\n 'Search across tickets, users, and organizations. Supports filters like \"type:ticket status:open\", \"type:user role:agent\". Returns total count and paginated results (100 per page). Organization results include name and ID only — use get_organization for full details (tags, domains, details).',\n inputSchema: z.object({\n query: z.string().min(1).describe('Zendesk search query'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page (max 100)'),\n page: z.number().int().min(1).default(1).describe('Page number (1-based)'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, per_page, page } = params as {\n query: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<Record<string, unknown>>>(\n subdomain,\n token,\n '/search',\n {\n query,\n ...buildOffsetParams(per_page, page),\n },\n );\n const results = response.results ?? [];\n const meta = extractSearchPaginationMeta(response, per_page, page);\n const header = `Total: ${meta.count} | Page ${page} (${results.length} results)${meta.has_more ? ` | Next page: ${meta.after_cursor}` : ''}`;\n const body = results.map(formatSearchResult).join('\\n\\n');\n return {\n content: [\n { type: 'text', text: truncateIfNeeded([header, body].filter(Boolean).join('\\n\\n')) },\n ],\n };\n },\n },\n ];\n};\n","import * as z from 'zod/v4';\nimport { zendeskGet, zendeskPost, zendeskPut } from '../client/zendesk-api';\nimport { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../constants';\nimport type { ZendeskComment, ZendeskListResponse, ZendeskTicket } from '../types';\nimport { formatComment, formatList, formatTicket, truncateIfNeeded } from '../utils/formatting';\nimport {\n buildCursorParams,\n buildOffsetParams,\n extractPaginationMeta,\n extractSearchPaginationMeta,\n} from '../utils/pagination';\nimport type { ToolContext, ToolDefinition } from './definitions';\n\nexport const createTicketTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'get_ticket',\n namespace: 'tickets',\n readOnly: true,\n title: 'Get Zendesk Ticket',\n description:\n 'Retrieve a Zendesk ticket by ID, including its comments if requested. Returns ticket details (subject, status, priority, assignee, tags, description) and optionally all comments/internal notes.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n include_comments: z.boolean().default(false).describe('Include ticket comments'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, include_comments } = params as {\n ticket_id: number;\n include_comments: boolean;\n };\n const token = await getToken();\n const { ticket } = await zendeskGet<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n );\n let text = formatTicket(ticket);\n if (include_comments) {\n const { comments } = await zendeskGet<{ comments: ZendeskComment[] }>(\n subdomain,\n token,\n `/tickets/${ticket_id}/comments`,\n );\n text += `\\n\\n---\\n# Comments\\n\\n${comments.map(formatComment).join('\\n\\n')}`;\n }\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'search_tickets',\n namespace: 'tickets',\n readOnly: true,\n title: 'Search Zendesk Tickets',\n description:\n 'Search tickets using Zendesk query syntax (e.g., \"status:open assignee:me\", \"priority:urgent type:incident\"). Returns total count.',\n inputSchema: z.object({\n query: z.string().min(1).describe('Zendesk search query string'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page'),\n page: z.number().int().min(1).default(1).describe('Page number'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, per_page, page } = params as {\n query: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskTicket>>(\n subdomain,\n token,\n '/search',\n {\n query: `type:ticket ${query}`,\n ...buildOffsetParams(per_page, page),\n },\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.results ?? [],\n formatTicket,\n extractSearchPaginationMeta(response, per_page, page),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'create_ticket',\n namespace: 'tickets',\n readOnly: false,\n title: 'Create Zendesk Ticket',\n description:\n 'Create a new Zendesk support ticket with subject, description, and optional priority/type/assignee/tags.',\n inputSchema: z.object({\n subject: z.string().min(1).describe('Ticket subject'),\n description: z.string().min(1).describe('Ticket description'),\n priority: z.enum(['urgent', 'high', 'normal', 'low']).optional(),\n type: z.enum(['problem', 'incident', 'question', 'task']).optional(),\n assignee_id: z.number().int().optional(),\n group_id: z.number().int().optional(),\n tags: z.array(z.string()).optional(),\n custom_fields: z.array(z.object({ id: z.number().int(), value: z.unknown() })).optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { subject, description, ...rest } = params as Record<string, unknown>;\n const token = await getToken();\n const { ticket } = await zendeskPost<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n '/tickets',\n {\n ticket: { subject, comment: { body: description }, ...rest },\n },\n );\n return {\n content: [\n { type: 'text', text: `Ticket #${ticket.id} created.\\n\\n${formatTicket(ticket)}` },\n ],\n };\n },\n },\n {\n name: 'update_ticket',\n namespace: 'tickets',\n readOnly: false,\n title: 'Update Zendesk Ticket',\n description:\n 'Update an existing ticket (status, priority, type, assignee, group, subject, tags, custom fields).',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n status: z.enum(['new', 'open', 'pending', 'hold', 'solved', 'closed']).optional(),\n priority: z.enum(['urgent', 'high', 'normal', 'low']).optional(),\n type: z.enum(['problem', 'incident', 'question', 'task']).optional(),\n assignee_id: z.number().int().optional(),\n group_id: z.number().int().optional(),\n subject: z.string().optional(),\n tags: z.array(z.string()).optional(),\n custom_fields: z.array(z.object({ id: z.number().int(), value: z.unknown() })).optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, ...updates } = params as { ticket_id: number } & Record<string, unknown>;\n const token = await getToken();\n const { ticket } = await zendeskPut<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n { ticket: updates },\n );\n return {\n content: [\n { type: 'text', text: `Ticket #${ticket.id} updated.\\n\\n${formatTicket(ticket)}` },\n ],\n };\n },\n },\n {\n name: 'add_private_note',\n namespace: 'tickets',\n readOnly: false,\n title: 'Add Private Note',\n description: 'Add an internal note (not visible to requester) to a ticket.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n body: z.string().min(1).describe('Note content'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, body } = params as { ticket_id: number; body: string };\n const token = await getToken();\n await zendeskPut(subdomain, token, `/tickets/${ticket_id}`, {\n ticket: { comment: { body, public: false } },\n });\n return { content: [{ type: 'text', text: `Private note added to ticket #${ticket_id}.` }] };\n },\n },\n {\n name: 'add_public_comment',\n namespace: 'tickets',\n readOnly: false,\n title: 'Add Public Comment',\n description: 'Add a public comment (visible to requester) to a ticket.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n body: z.string().min(1).describe('Comment content'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, body } = params as { ticket_id: number; body: string };\n const token = await getToken();\n await zendeskPut(subdomain, token, `/tickets/${ticket_id}`, {\n ticket: { comment: { body, public: true } },\n });\n return {\n content: [{ type: 'text', text: `Public comment added to ticket #${ticket_id}.` }],\n };\n },\n },\n {\n name: 'list_tickets',\n namespace: 'tickets',\n readOnly: true,\n title: 'List Zendesk Tickets',\n description: 'List tickets with cursor-based pagination, sorted by most recently updated.',\n inputSchema: z.object({\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional().describe('Pagination cursor'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { page_size, cursor } = params as { page_size: number; cursor?: string };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskTicket>>(\n subdomain,\n token,\n '/tickets',\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.tickets ?? [],\n formatTicket,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'get_linked_incidents',\n namespace: 'tickets',\n readOnly: true,\n title: 'Get Linked Incidents',\n description: 'Get all incident tickets linked to a problem ticket.',\n inputSchema: z.object({\n problem_id: z.number().int().describe('Problem ticket ID'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { problem_id } = params as { problem_id: number };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskTicket>>(\n subdomain,\n token,\n `/tickets/${problem_id}/incidents`,\n );\n const incidents = response.tickets ?? [];\n const text =\n incidents.length > 0\n ? `# Incidents linked to problem #${problem_id}\\n\\n${incidents.map(formatTicket).join('\\n\\n')}`\n : `No incidents linked to problem #${problem_id}.`;\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'manage_tags',\n namespace: 'tickets',\n readOnly: false,\n title: 'Manage Ticket Tags',\n description: 'Add or remove tags on a ticket.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n add: z.array(z.string()).optional().describe('Tags to add'),\n remove: z.array(z.string()).optional().describe('Tags to remove'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, add, remove } = params as {\n ticket_id: number;\n add?: string[];\n remove?: string[];\n };\n const token = await getToken();\n const { ticket } = await zendeskGet<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n );\n const tags = new Set(ticket.tags);\n add?.forEach((t) => {\n tags.add(t);\n });\n remove?.forEach((t) => {\n tags.delete(t);\n });\n const { ticket: updated } = await zendeskPut<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n { ticket: { tags: [...tags] } },\n );\n return {\n content: [\n {\n type: 'text',\n text: `Tags updated on ticket #${ticket_id}. Current: ${updated.tags.join(', ') || 'none'}`,\n },\n ],\n };\n },\n },\n ];\n};\n","import * as z from 'zod/v4';\nimport { zendeskGet } from '../client/zendesk-api';\nimport { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../constants';\nimport type { ZendeskListResponse, ZendeskOrganization, ZendeskUser } from '../types';\nimport { formatList, formatOrganization, formatUser } from '../utils/formatting';\nimport {\n buildCursorParams,\n buildOffsetParams,\n extractPaginationMeta,\n extractSearchPaginationMeta,\n} from '../utils/pagination';\nimport type { ToolContext, ToolDefinition } from './definitions';\n\nexport const createUserTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'get_current_user',\n namespace: 'users',\n readOnly: true,\n title: 'Get Current Zendesk User',\n description:\n 'Get the currently authenticated Zendesk user. Useful to verify identity and permissions.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const { user } = await zendeskGet<{ user: ZendeskUser }>(subdomain, token, '/users/me');\n return { content: [{ type: 'text', text: formatUser(user) }] };\n },\n },\n {\n name: 'search_users',\n namespace: 'users',\n readOnly: true,\n title: 'Search Zendesk Users',\n description:\n 'Search for users by name, email, or other criteria using Zendesk search query syntax. Returns total count.',\n inputSchema: z.object({\n query: z.string().min(1).describe('Search query'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page'),\n page: z.number().int().min(1).default(1).describe('Page number'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, per_page, page } = params as {\n query: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskUser>>(\n subdomain,\n token,\n '/search',\n {\n query: `type:user ${query}`,\n ...buildOffsetParams(per_page, page),\n },\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.results ?? [],\n formatUser,\n extractSearchPaginationMeta(response, per_page, page),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'get_user',\n namespace: 'users',\n readOnly: true,\n title: 'Get Zendesk User',\n description: 'Retrieve a user by ID.',\n inputSchema: z.object({ user_id: z.number().int().describe('User ID') }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { user_id } = params as { user_id: number };\n const token = await getToken();\n const { user } = await zendeskGet<{ user: ZendeskUser }>(\n subdomain,\n token,\n `/users/${user_id}`,\n );\n return { content: [{ type: 'text', text: formatUser(user) }] };\n },\n },\n {\n name: 'get_organization',\n namespace: 'users',\n readOnly: true,\n title: 'Get Zendesk Organization',\n description: 'Retrieve an organization by ID.',\n inputSchema: z.object({ organization_id: z.number().int().describe('Organization ID') }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { organization_id } = params as { organization_id: number };\n const token = await getToken();\n const { organization } = await zendeskGet<{ organization: ZendeskOrganization }>(\n subdomain,\n token,\n `/organizations/${organization_id}`,\n );\n return { content: [{ type: 'text', text: formatOrganization(organization) }] };\n },\n },\n {\n name: 'list_organizations',\n namespace: 'users',\n readOnly: true,\n title: 'List Zendesk Organizations',\n description: 'List all organizations with pagination.',\n inputSchema: z.object({\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { page_size, cursor } = params as { page_size: number; cursor?: string };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskOrganization>>(\n subdomain,\n token,\n '/organizations',\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.organizations ?? [],\n formatOrganization,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n ];\n};\n","import type { ToolContext, ToolDefinition } from './definitions';\nimport { createHelpCenterTools } from './help-center';\nimport { createSearchTools } from './search';\nimport { createTicketTools } from './tickets';\nimport { createUserTools } from './users';\n\nexport type { ToolContext, ToolDefinition } from './definitions';\n\nexport const createAllTools = (ctx: ToolContext): ToolDefinition[] => [\n ...createTicketTools(ctx),\n ...createSearchTools(ctx),\n ...createHelpCenterTools(ctx),\n ...createUserTools(ctx),\n];\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nexport const startStdioTransport = async (server: McpServer): Promise<void> => {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Zendesk MCP server running via stdio');\n};\n","import { buildBasicAuthHeader } from './auth/api-token';\nimport { createTokenStore } from './auth/token-store';\nimport { loadConfig } from './config';\nimport { createMcpServer } from './server';\nimport { startStdioTransport } from './transports/stdio';\n\nconst main = async (): Promise<void> => {\n const config = loadConfig();\n\n if (config.zendeskEmail && config.zendeskApiToken) {\n // API token mode — static Basic auth\n const staticToken = buildBasicAuthHeader(config.zendeskEmail, config.zendeskApiToken);\n const getToken = () => staticToken;\n const server = createMcpServer(config, getToken);\n await startStdioTransport(server);\n } else {\n // OAuth mode — browser-based auth on first tool call\n const tokenStore = createTokenStore({\n subdomain: config.subdomain,\n oauthClientId: config.oauthClientId,\n });\n const server = createMcpServer(config, tokenStore.getToken);\n await startStdioTransport(server);\n }\n};\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n"],"mappings":";;;AAIO,IAAM,uBAAuB,CAAC,OAAe,aAA6B;AAC/E,QAAM,cAAc,GAAG,KAAK,UAAU,QAAQ;AAC9C,SAAO,SAAS,OAAO,KAAK,WAAW,EAAE,SAAS,QAAQ,CAAC;AAC7D;;;ACPA,SAAS,YAAY,mBAAmB;AACxC,SAAS,oBAAiC;AAC1C,OAAO,UAAU;;;ACFV,IAAM,kBAAkB;AACxB,IAAM,oBAAoB;AAC1B,IAAM,gBAAgB;AACtB,IAAM,qBAAqB,IAAI,KAAK;AAKpC,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AAEpC,IAAM,aAAa,CAAC,cAA8B,WAAW,SAAS;AAEtE,IAAM,uBAAuB,CAAC,cACnC,WAAW,SAAS;AAEf,IAAM,eAAe,CAAC,eAAuB;AAAA,EAClD,cAAc,WAAW,SAAS;AAAA,EAClC,UAAU,WAAW,SAAS;AAChC;;;ADdA,IAAM,wBAAwB;AAe9B,IAAM,uBAAuB,MAAc,YAAY,EAAE,EAAE,SAAS,WAAW;AAE/E,IAAM,wBAAwB,CAAC,aAC7B,WAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,WAAW;AAOnD,IAAM,yBAAyB,CAAC,WAAqD;AAC1F,QAAM,EAAE,WAAW,cAAc,IAAI;AACrC,QAAM,EAAE,cAAc,SAAS,IAAI,aAAa,SAAS;AACzD,QAAM,eAAe,qBAAqB;AAC1C,QAAM,gBAAgB,sBAAsB,YAAY;AAExD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI;AAEJ,qBAAiB,aAAa,OAAO,KAAK,QAAQ;AAChD,YAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,kBAAkB;AAEtD,UAAI,IAAI,aAAa,aAAa;AAChC,YAAI,UAAU,GAAG;AACjB,YAAI,IAAI,WAAW;AACnB;AAAA,MACF;AAEA,YAAM,OAAO,IAAI,aAAa,IAAI,MAAM;AACxC,YAAM,QAAQ,IAAI,aAAa,IAAI,OAAO;AAE1C,UAAI,OAAO;AACT,cAAM,OAAO,IAAI,aAAa,IAAI,mBAAmB,KAAK;AAC1D,YAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,YAAI,IAAI,gDAAgD,IAAI,oBAAoB;AAChF,uBAAe,MAAM;AACrB,eAAO,IAAI,MAAM,gBAAgB,IAAI,EAAE,CAAC;AACxC;AAAA,MACF;AAEA,UAAI,CAAC,MAAM;AACT,YAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,YAAI,IAAI,+DAA+D;AACvE,uBAAe,MAAM;AACrB,eAAO,IAAI,MAAM,wCAAwC,CAAC;AAC1D;AAAA,MACF;AAGA,UAAI;AACF,cAAM,eAAgB,eAAe,QAAQ,EAAuB;AACpE,cAAM,YAAY,IAAI,gBAAgB;AAAA,UACpC,YAAY;AAAA,UACZ;AAAA,UACA,WAAW;AAAA,UACX,cAAc,oBAAoB,YAAY;AAAA,UAC9C,eAAe;AAAA,QACjB,CAAC;AAED,cAAM,gBAAgB,MAAM,MAAM,UAAU;AAAA,UAC1C,QAAQ;AAAA,UACR,SAAS,EAAE,gBAAgB,oCAAoC;AAAA,UAC/D,MAAM,UAAU,SAAS;AAAA,QAC3B,CAAC;AAED,YAAI,CAAC,cAAc,IAAI;AACrB,gBAAM,YAAY,MAAM,cAAc,KAAK;AAC3C,gBAAM,IAAI,MAAM,0BAA0B,cAAc,MAAM,MAAM,SAAS,EAAE;AAAA,QACjF;AAEA,cAAM,YAAa,MAAM,cAAc,KAAK;AAE5C,YAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,YAAI;AAAA,UACF;AAAA,QAGF;AAEA,uBAAe,MAAM;AACrB,gBAAQ,SAAS;AAAA,MACnB,SAAS,KAAK;AACZ,YAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,YAAI;AAAA,UACF,gDAAgD,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,QAClG;AACA,uBAAe,MAAM;AACrB,eAAO,GAAG;AAAA,MACZ;AAAA,IACF,CAAC;AAGD,mBAAe,OAAO,OAAO,gBAAgB,uBAAuB,MAAM;AACxE,YAAM,OAAQ,eAAe,QAAQ,EAAuB;AAC5D,YAAM,cAAc,oBAAoB,IAAI;AAE5C,YAAM,SAAS,IAAI,gBAAgB;AAAA,QACjC,eAAe;AAAA,QACf,WAAW;AAAA,QACX,cAAc;AAAA,QACd,OAAO;AAAA,QACP,gBAAgB;AAAA,QAChB,uBAAuB;AAAA,MACzB,CAAC;AAED,YAAM,UAAU,GAAG,YAAY,IAAI,OAAO,SAAS,CAAC;AACpD,cAAQ,MAAM,+CAA+C;AAC7D,cAAQ,MAAM,uCAAuC,OAAO,EAAE;AAE9D,WAAK,OAAO,EAAE,MAAM,MAAM;AAAA,MAE1B,CAAC;AAAA,IACH,CAAC;AAGD;AAAA,MACE,MAAM;AACJ,uBAAe,MAAM;AACrB,eAAO,IAAI,MAAM,2DAA2D,CAAC;AAAA,MAC/E;AAAA,MACA,IAAI,KAAK;AAAA,IACX,EAAE,MAAM;AAAA,EACV,CAAC;AACH;;;AExIO,IAAM,mBAAmB,CAAC,WAAyD;AACxF,MAAI;AACJ,MAAI;AAEJ,QAAM,WAAW,CAAC,aAAqB,iBAAsC;AAC3E,YAAQ,EAAE,aAAa,aAAa;AAAA,EACtC;AAEA,QAAM,cAAc,YAAkC;AACpD,QAAI,MAAO,QAAO;AAElB,QAAI,CAAC,aAAa;AAChB,oBAAc,uBAAuB;AAAA,QACnC,WAAW,OAAO;AAAA,QAClB,eAAe,OAAO;AAAA,MACxB,CAAC,EACE,KAAK,CAAC,WAAW;AAChB,cAAM,SAAsB;AAAA,UAC1B,aAAa,OAAO;AAAA,UACpB,cAAc,OAAO;AAAA,QACvB;AACA,gBAAQ;AACR,sBAAc;AACd,eAAO;AAAA,MACT,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,sBAAc;AACd,cAAM;AAAA,MACR,CAAC;AAAA,IACL;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,WAAW,YAA6B;AAC5C,UAAM,SAAS,MAAM,YAAY;AACjC,WAAO,OAAO;AAAA,EAChB;AAEA,SAAO,EAAE,UAAU,SAAS;AAC9B;;;AC/CA,YAAY,OAAO;AAEZ,IAAM,WAAa,OAAK,CAAC,UAAU,aAAa,KAAK,CAAC;AAGtD,IAAM,WAAa,OAAK,CAAC,SAAS,QAAQ,QAAQ,OAAO,CAAC;AAG1D,IAAM,YAAc,OAAK,CAAC,WAAW,eAAe,OAAO,CAAC;AAG5D,IAAM,eAAiB,SAAO;AAAA,EACnC,WAAa,SAAO,EAAE,IAAI,GAAG,+BAA+B;AAAA,EAC5D,eAAiB,SAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,cAAgB,SAAO,EAAE,SAAS;AAAA,EAClC,iBAAmB,SAAO,EAAE,SAAS;AAAA,EACrC,UAAU;AAAA,EACV,MAAM;AAAA,EACN,UAAY,UAAQ;AAAA,EACpB,YAAc,QAAM,SAAS,EAAE,SAAS;AAAA,EACxC,OAAS,QAAQ,SAAO,CAAC,EAAE,SAAS;AACtC,CAAC;AAaD,IAAM,eAAe,CAAC,SAA8B;AAClD,QAAM,SAAoB,CAAC;AAC3B,MAAI,kBAAkB;AAEtB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,QAAQ,OAAW;AACvB,UAAM,OAAO,KAAK,IAAI,CAAC;AAEvB,QAAI,QAAQ,YAAY,MAAM;AAC5B,aAAO,OAAO;AACd;AAAA,IACF,WAAW,QAAQ,eAAe;AAChC,aAAO,WAAW;AAAA,IACpB,WAAW,QAAQ,iBAAiB,MAAM;AACxC,aAAO,aAAa,OAAO,cAAc,CAAC;AAC1C,aAAO,WAAW,KAAK,IAAI;AAC3B;AAAA,IACF,WAAW,QAAQ,YAAY,MAAM;AACnC,aAAO,QAAQ,OAAO,SAAS,CAAC;AAChC,aAAO,MAAM,KAAK,IAAI;AACtB;AAAA,IACF,WAAW,QAAQ,iBAAiB,MAAM;AACxC,aAAO,WAAW;AAClB;AAAA,IACF,WAAW,CAAC,IAAI,WAAW,GAAG,KAAK,oBAAoB,GAAG;AACxD,aAAO,YAAY;AACnB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,IAAM,aAAa,CAAC,OAAiB,QAAQ,KAAK,MAAM,CAAC,MAAc;AAC5E,QAAM,MAAM,aAAa,IAAI;AAE7B,QAAM,YAAY,IAAI,aAAa,QAAQ,IAAI,mBAAmB,KAAK;AACvE,QAAM,gBACJ,QAAQ,IAAI,yBAAyB,MAAM,YAAY,GAAG,SAAS,aAAa;AAElF,QAAM,OAAO,IAAI,OAAO,SAAS,QAAS,IAAI,QAAQ;AAEtD,SAAO,aAAa,MAAM;AAAA,IACxB;AAAA,IACA;AAAA,IACA,cAAc,QAAQ,IAAI,eAAe;AAAA,IACzC,iBAAiB,QAAQ,IAAI,mBAAmB;AAAA,IAChD,UAAU,IAAI,YAAY,QAAQ,IAAI,WAAW,KAAK;AAAA,IACtD;AAAA,IACA,UAAU,IAAI,YAAY;AAAA,IAC1B,YAAY,IAAI;AAAA,IAChB,OAAO,IAAI;AAAA,EACb,CAAC;AACH;;;ACxFA,SAAS,iBAAiB;AAC1B,YAAYA,QAAO;;;ACQZ,IAAM,cAAc,CAAC,UAA4B,YACtD,SAAS,OAAO,CAAC,SAAS;AACxB,MAAI,QAAQ,YAAY,CAAC,KAAK,SAAU,QAAO;AAC/C,MAAI,QAAQ,YAAY,UAAU,CAAC,QAAQ,WAAW,SAAS,KAAK,SAAS,EAAG,QAAO;AACvF,MAAI,QAAQ,OAAO,UAAU,CAAC,QAAQ,MAAM,SAAS,KAAK,IAAI,EAAG,QAAO;AACxE,SAAO;AACT,CAAC;AAEI,IAAM,mBAAmB,CAAC,UAA2D;AAC1F,QAAM,UAAU,oBAAI,IAA8B;AAClD,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,QAAQ,IAAI,KAAK,SAAS,KAAK,CAAC;AACjD,aAAS,KAAK,IAAI;AAClB,YAAQ,IAAI,KAAK,WAAW,QAAQ;AAAA,EACtC;AACA,SAAO;AACT;;;ACzBA,YAAYC,QAAO;;;ACEZ,IAAM,kBAAN,MAAM,yBAAwB,MAAM;AAAA,EACzC,YACkB,QACA,YACA,MAChB;AACA,UAAM,iBAAgB,aAAa,QAAQ,YAAY,IAAI,CAAC;AAJ5C;AACA;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AAAA,EANkB;AAAA,EACA;AAAA,EACA;AAAA,EAMlB,OAAe,aAAa,QAAgB,YAAoB,MAAsB;AACpF,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO,yDAAyD,UAAU;AAAA,MAC5E,KAAK;AACH,eAAO,qBAAqB,IAAI;AAAA,MAClC,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO,qBAAqB,MAAM,KAAK,UAAU,KAAK,IAAI;AAAA,IAC9D;AAAA,EACF;AACF;AAQA,IAAM,WAAW,CAAC,MAAc,MAAc,WAA4C;AACxF,QAAM,MAAM,IAAI,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE;AACpC,MAAI,QAAQ;AACV,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,UAAI,aAAa,IAAI,KAAK,KAAK;AAAA,IACjC;AAAA,EACF;AACA,SAAO,IAAI,SAAS;AACtB;AAEA,IAAM,iBAAiB,OACrB,KACA,OACA,UAAiC,CAAC,MACnB;AACf,QAAM,EAAE,SAAS,OAAO,KAAK,IAAI;AAGjC,QAAM,gBAAgB,MAAM,WAAW,QAAQ,IAAI,QAAQ,UAAU,KAAK;AAC1E,QAAM,UAAkC;AAAA,IACtC,eAAe;AAAA,IACf,QAAQ;AAAA,EACV;AAEA,MAAI,MAAM;AACR,YAAQ,cAAc,IAAI;AAAA,EAC5B;AAEA,QAAM,OAAoB,EAAE,QAAQ,QAAQ;AAC5C,MAAI,MAAM;AACR,SAAK,OAAO,KAAK,UAAU,IAAI;AAAA,EACjC;AAEA,QAAM,WAAW,MAAM,MAAM,KAAK,IAAI;AAEtC,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,eAAe,MAAM,SAAS,KAAK;AACzC,UAAM,IAAI,gBAAgB,SAAS,QAAQ,SAAS,YAAY,YAAY;AAAA,EAC9E;AAEA,MAAI,SAAS,WAAW,KAAK;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,SAAS,KAAK;AACvB;AAEO,IAAM,aAAa,CACxB,WACA,OACA,MACA,WACe;AACf,QAAM,MAAM,SAAS,WAAW,SAAS,GAAG,MAAM,MAAM;AACxD,SAAO,eAAkB,KAAK,KAAK;AACrC;AAEO,IAAM,cAAc,CACzB,WACA,OACA,MACA,SACe;AACf,QAAM,MAAM,SAAS,WAAW,SAAS,GAAG,IAAI;AAChD,SAAO,eAAkB,KAAK,OAAO,EAAE,QAAQ,QAAQ,KAAK,CAAC;AAC/D;AAEO,IAAM,aAAa,CACxB,WACA,OACA,MACA,SACe;AACf,QAAM,MAAM,SAAS,WAAW,SAAS,GAAG,IAAI;AAChD,SAAO,eAAkB,KAAK,OAAO,EAAE,QAAQ,OAAO,KAAK,CAAC;AAC9D;AAEO,IAAM,gBAAgB,CAC3B,WACA,OACA,MACA,WACe;AACf,QAAM,MAAM,SAAS,qBAAqB,SAAS,GAAG,MAAM,MAAM;AAClE,SAAO,eAAkB,KAAK,KAAK;AACrC;AAEO,IAAM,iBAAiB,CAC5B,WACA,OACA,MACA,SACe;AACf,QAAM,MAAM,SAAS,qBAAqB,SAAS,GAAG,IAAI;AAC1D,SAAO,eAAkB,KAAK,OAAO,EAAE,QAAQ,QAAQ,KAAK,CAAC;AAC/D;AAEO,IAAM,gBAAgB,CAC3B,WACA,OACA,MACA,SACe;AACf,QAAM,MAAM,SAAS,qBAAqB,SAAS,GAAG,IAAI;AAC1D,SAAO,eAAkB,KAAK,OAAO,EAAE,QAAQ,OAAO,KAAK,CAAC;AAC9D;AAEO,IAAM,mBAAmB,OAC9B,WACA,OACA,MACA,aACe;AACf,QAAM,MAAM,SAAS,qBAAqB,SAAS,GAAG,IAAI;AAC1D,QAAM,gBAAgB,MAAM,WAAW,QAAQ,IAAI,QAAQ,UAAU,KAAK;AAC1E,QAAM,WAAW,MAAM,MAAM,KAAK;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,cAAc;AAAA,IACxC,MAAM;AAAA,EACR,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,eAAe,MAAM,SAAS,KAAK;AACzC,UAAM,IAAI,gBAAgB,SAAS,QAAQ,SAAS,YAAY,YAAY;AAAA,EAC9E;AAEA,SAAO,SAAS,KAAK;AACvB;;;ACnKA,YAAY,aAAa;AAEzB,SAAS,cAAc;AAEvB,OAAO,iBAAiB;AACxB,OAAO,eAAe;AACtB,OAAO,kBAAkB;AACzB,OAAO,qBAAqB;AAC5B,OAAO,eAAe;AACtB,OAAO,iBAAiB;AACxB,OAAO,kBAAkB;AACzB,OAAO,qBAAqB;AAC5B,SAAS,eAAe;AAWxB,IAAM,iBAAiB,oBAAI,IAAI,CAAC,MAAM,MAAM,IAAI,CAAC;AAEjD,IAAM,aAAa,CAAC,SAAyB;AAC3C,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,QAAQ,MAAM,KAAK,EAAE;AAC9B;AAEA,IAAM,SAAS,CAAC,SAAyB;AACvC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,IAAY,aAAK,QAAQ,IAAI,UAAU,MAAM,KAAK;AACxD,SAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK;AAC/B;AAEO,IAAM,gBAAgB,CAAC,SAA4B;AACxD,MAAI,CAAC,QAAQ,CAAC,KAAK,KAAK,EAAG,QAAO,CAAC;AAEnC,QAAM,IAAY,aAAK,MAAM,MAAM,KAAK;AACxC,QAAM,WAAW,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ;AAE7C,QAAM,aAAuB,CAAC;AAC9B,QAAM,WAKD,CAAC;AACN,MAAI,UAA4C;AAEhD,aAAW,QAAQ,UAAU;AAC3B,UAAM,UAAU,KAAK,SAAS,QAAQ,KAAK,KAAK,YAAY,IAAI;AAEhE,QAAI,eAAe,IAAI,OAAO,GAAG;AAC/B,YAAM,QAAQ,OAAO,SAAS,QAAQ,MAAM,CAAC,GAAG,EAAE;AAClD,gBAAU;AAAA,QACR,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK;AAAA,QAC7B,YAAY;AAAA,QACZ;AAAA,QACA,cAAc,CAAC;AAAA,MACjB;AACA,eAAS,KAAK,OAAO;AACrB;AAAA,IACF;AAEA,UAAM,QAAQ,EAAE,KAAK,IAAI;AACzB,QAAI,SAAS;AACX,cAAQ,aAAa,KAAK,KAAK;AAAA,IACjC,OAAO;AACL,iBAAW,KAAK,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,SAAoB,CAAC;AAE3B,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,YAAY,WAAW,KAAK,EAAE;AACpC,WAAO,KAAK;AAAA,MACV,OAAO;AAAA,MACP,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,MAAM;AAAA,MACN,WAAW,WAAW,OAAO,SAAS,CAAC;AAAA,IACzC,CAAC;AAAA,EACH;AAEA,aAAW,KAAK,UAAU;AACxB,UAAM,cAAc,EAAE,aAAa,KAAK,EAAE;AAC1C,WAAO,KAAK;AAAA,MACV,OAAO,OAAO;AAAA,MACd,SAAS,EAAE;AAAA,MACX,YAAY,EAAE;AAAA,MACd,OAAO,EAAE;AAAA,MACT,MAAM;AAAA,MACN,WAAW,WAAW,OAAO,WAAW,CAAC;AAAA,IAC3C,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEO,IAAM,wBAAwB,CACnC,MACA,cACA,YACW;AACX,QAAM,WAAW,cAAc,IAAI;AACnC,MAAI,eAAe,KAAK,gBAAgB,SAAS,QAAQ;AACvD,UAAM,IAAI;AAAA,MACR,iBAAiB,YAAY,2BAA2B,KAAK,IAAI,GAAG,SAAS,SAAS,CAAC,CAAC;AAAA,IAC1F;AAAA,EACF;AAEA,SAAO,SACJ,IAAI,CAAC,SAAS,QAAQ;AACrB,UAAM,UAAU,QAAQ,eAAe,UAAU,QAAQ;AACzD,QAAI,QAAQ,UAAU,EAAG,QAAO;AAChC,WAAO,IAAI,QAAQ,UAAU,IAAI,QAAQ,OAAO,KAAK,QAAQ,UAAU,IAAI,OAAO;AAAA,EACpF,CAAC,EACA,KAAK,EAAE;AACZ;AAKA,IAAM,aAAqB,CAAC,QAAQ,UAAU;AAAA,EAC5C,MAAM;AAAA,EACN,OAAO,OAAO,IAAe;AAC/B;AAEA,IAAM,oBAAoB,QAAQ,EAC/B,IAAI,aAAa,EAAE,UAAU,KAAK,CAAC,EACnC,IAAI,cAAc,EAAE,UAAU,EAAE,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC,EACtE,IAAI,SAAS,EACb,IAAI,iBAAiB,EAAE,QAAQ,KAAK,UAAU,KAAK,QAAQ,KAAK,CAAC;AAEpE,IAAM,oBAAoB,QAAQ,EAC/B,IAAI,WAAW,EACf,IAAI,SAAS,EACb,IAAI,cAAc,EAAE,oBAAoB,KAAK,CAAC,EAC9C,IAAI,SAAS,EACb,IAAI,eAAe;AAEf,IAAM,iBAAiB,CAAC,SAAyB;AACtD,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,OAAO,kBAAkB,YAAY,IAAI,CAAC;AACnD;AAEO,IAAM,iBAAiB,CAAC,aAA6B;AAC1D,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,OAAO,kBAAkB,YAAY,QAAQ,CAAC;AACvD;;;ACxIO,IAAM,mBAAmB,CAAC,SAAyB;AACxD,MAAI,KAAK,UAAU,gBAAiB,QAAO;AAC3C,SAAO,GAAG,KAAK,MAAM,GAAG,eAAe,CAAC;AAAA;AAAA,0BAA+B,KAAK,MAAM,iBAAiB,eAAe;AACpH;AAEA,IAAM,mBAAmB,CAAC,SAAiC;AACzD,QAAM,QAAQ,CAAC,YAAY,KAAK,KAAK,EAAE;AACvC,MAAI,KAAK,UAAU;AACjB,UAAM,KAAK,2BAA2B,KAAK,YAAY,GAAG;AAAA,EAC5D;AACA,SAAO,MAAM,KAAK,KAAK;AACzB;AAEO,IAAM,eAAe,CAAC,WAC3B;AAAA,EACE,cAAc,OAAO,EAAE,KAAK,OAAO,OAAO;AAAA,EAC1C,iBAAiB,OAAO,MAAM,oBAAoB,OAAO,YAAY,MAAM,gBAAgB,OAAO,QAAQ,MAAM;AAAA,EAChH,oBAAoB,OAAO,YAAY,oBAAoB,OAAO,eAAe,YAAY;AAAA,EAC7F,eAAe,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,IAAI,IAAI,MAAM;AAAA,EACvE,kBAAkB,OAAO,UAAU,mBAAmB,OAAO,UAAU;AAAA,EACvE,OAAO,cAAc;AAAA,EAAK,OAAO,WAAW,KAAK;AACnD,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAEP,IAAM,gBAAgB,CAAC,YAC5B;AAAA,EACE,OAAO,QAAQ,SAAS,mBAAmB,eAAe,OAAO,QAAQ,SAAS;AAAA,EAClF,IAAI,QAAQ,UAAU;AAAA,EACtB;AAAA,EACA,QAAQ;AACV,EAAE,KAAK,IAAI;AAEN,IAAM,aAAa,CAAC,SACzB;AAAA,EACE,MAAM,KAAK,IAAI,KAAK,KAAK,EAAE;AAAA,EAC3B,gBAAgB,KAAK,KAAK;AAAA,EAC1B,eAAe,KAAK,IAAI;AAAA,EACxB,KAAK,aAAa,OAAO,oBAAoB,KAAK,SAAS,KAAK;AAAA,EAChE,iBAAiB,KAAK,MAAM;AAAA,EAC5B,KAAK,kBAAkB,uBAAuB,KAAK,eAAe,KAAK;AACzE,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAEP,IAAM,qBAAqB,CAAC,QACjC;AAAA,EACE,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE;AAAA,EACzB,IAAI,UAAU,kBAAkB,IAAI,OAAO,KAAK;AAAA,EAChD,IAAI,aAAa,SAAS,IAAI,kBAAkB,IAAI,aAAa,KAAK,IAAI,CAAC,KAAK;AAAA,EAChF,IAAI,KAAK,SAAS,IAAI,eAAe,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK;AAC/D,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAEP,IAAM,uBAAuB,CAAC,YACnC;AAAA,EACE,MAAM,QAAQ,KAAK,KAAK,QAAQ,EAAE;AAAA,EAClC,iBAAiB,QAAQ,MAAM,yBAAyB,QAAQ,aAAa;AAAA,EAC7E,kBAAkB,QAAQ,UAAU,iBAAiB,QAAQ,KAAK;AAAA,EAClE,QAAQ,YAAY,SAAS,IAAI,iBAAiB,QAAQ,YAAY,KAAK,IAAI,CAAC,KAAK;AAAA,EACrF,kBAAkB,QAAQ,UAAU,mBAAmB,QAAQ,UAAU;AAC3E,EACG,OAAO,OAAO,EACd,KAAK,IAAI;AAEP,IAAM,gBAAgB,CAAC,YAC5B,CAAC,qBAAqB,OAAO,GAAG,IAAI,QAAQ,IAAI,EAAE,KAAK,IAAI;AAEtD,IAAM,2BAA2B,CAAC,gBACvC;AAAA,EACE,mBAAmB,YAAY,MAAM,KAAK,YAAY,EAAE;AAAA,EACxD,gBAAgB,YAAY,KAAK;AAAA,EACjC,gBAAgB,YAAY,KAAK;AAAA,EACjC,kBAAkB,YAAY,UAAU;AAC1C,EAAE,KAAK,IAAI;AAEN,IAAM,oBAAoB,CAAC,gBAChC,CAAC,yBAAyB,WAAW,GAAG,IAAI,YAAY,IAAI,EAAE,KAAK,IAAI;AAElE,IAAM,iBAAiB,CAAC,aAC7B,OAAO,SAAS,IAAI,OAAO,SAAS,EAAE,YAAO,SAAS,eAAe,gBAAgB;AAEhF,IAAM,gBAAgB,CAAC,YAC5B,OAAO,QAAQ,IAAI,OAAO,QAAQ,EAAE,sBAAiB,QAAQ,WAAW,WAAM,QAAQ,eAAe,gBAAgB;AAEhH,IAAM,wBAAwB,CAAC,UACpC,OAAO,MAAM,IAAI,OAAO,MAAM,EAAE,IAAI,MAAM,WAAW,qBAAgB,EAAE;AAElE,IAAM,mBAAmB,CAAC,QAAmC,OAAO,IAAI,IAAI,OAAO,IAAI,EAAE;AAEzF,IAAM,cAAc,CAAC,UAAgC,OAAO,MAAM,IAAI,OAAO,MAAM,EAAE;AAErF,IAAM,oBAAoB,CAAC,YAChC,OAAO,QAAQ,IAAI,OAAO,QAAQ,EAAE,YAAO,QAAQ,SAAS,GAAG,QAAQ,WAAW,qBAAgB,EAAE;AAE/F,IAAM,mBAAmB,CAAC,eAC/B,OAAO,WAAW,SAAS,OAAO,WAAW,EAAE,YAAO,WAAW,YAAY,WAAM,WAAW,IAAI;AAE7F,IAAM,aAAa,CACxB,OACA,WACA,SACW;AACX,QAAM,SAAS,OAAO,iBAAiB,IAAI,IAAI;AAC/C,QAAM,OAAO,MAAM,IAAI,SAAS,EAAE,KAAK,MAAM;AAC7C,QAAM,OAAO,CAAC,QAAQ,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,MAAM;AACvD,SAAO,iBAAiB,IAAI;AAC9B;;;AC3HO,IAAM,oBAAoB,CAAC,UAAkB,WAA4C;AAC9F,QAAM,SAAiC;AAAA,IACrC,cAAc,OAAO,QAAQ;AAAA,EAC/B;AACA,MAAI,QAAQ;AACV,WAAO,aAAa,IAAI;AAAA,EAC1B;AACA,SAAO;AACT;AAGO,IAAM,oBAAoB,CAAC,SAAiB,SAA0C;AAC3F,QAAM,SAAiC;AAAA,IACrC,UAAU,OAAO,OAAO;AAAA,EAC1B;AACA,MAAI,QAAQ,OAAO,GAAG;AACpB,WAAO,MAAM,IAAI,OAAO,IAAI;AAAA,EAC9B;AACA,SAAO;AACT;AAEO,IAAM,wBAAwB,CAAI,cAAsD;AAAA,EAC7F,UAAU,SAAS,MAAM,YAAY,SAAS,aAAa;AAAA,EAC3D,cAAc,SAAS,MAAM,gBAAgB;AAAA,EAC7C,OAAO,SAAS,SAAS;AAC3B;AAGO,IAAM,8BAA8B,CACzC,UACA,SACA,SACmB;AACnB,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,WAAW,QAAQ,OAAO;AAChC,SAAO;AAAA,IACL;AAAA,IACA,cAAc,WAAW,OAAO,OAAO,CAAC,IAAI;AAAA,IAC5C;AAAA,EACF;AACF;;;AJaA,IAAM,mBAAmB,CAAC,MAAc,iBAAwC;AAC9E,MAAI,KAAK,SAAS,4BAA4B,eAAe,6BAA6B;AACxF,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,2BAAsB,KAAK,MAAM,WAAW,YAAY;AAAA,IACxD;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAEO,IAAM,wBAAwB,CAAC,QAAuC;AAC3E,QAAM,EAAE,WAAW,SAAS,IAAI;AAEhC,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,OAAS,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,cAAc;AAAA,QAChD,QAAU,UAAO,EAAE,SAAS,EAAE,SAAS,wCAAwC;AAAA,QAC/E,UACG,UAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,aAAa,EACjB,QAAQ,iBAAiB,EACzB,SAAS,kBAAkB;AAAA,QAC9B,MAAQ,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,aAAa;AAAA,MACjE,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,OAAO,QAAQ,UAAU,KAAK,IAAI;AAM1C,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,IAA4B,EAAE,OAAO,GAAG,kBAAkB,UAAU,IAAI,EAAE;AAChF,YAAI,OAAQ,GAAE,QAAQ,IAAI;AAC1B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,SAAS,WAAW,CAAC;AAAA,gBACrB;AAAA,gBACA,4BAA4B,UAAU,UAAU,IAAI;AAAA,cACtD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY;AAAA,QAClD,QAAU,UAAO,EAAE,SAAS,EAAE,SAAS,+BAA+B;AAAA,MACxE,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,OAAO,IAAI;AAC/B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,OAAO,SAAS,IAAI,MAAM,aAAa,UAAU,KAAK,aAAa,UAAU;AACnF,cAAM,EAAE,QAAQ,IAAI,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,cAAM,EAAE,aAAa,IAAI,MAAM;AAAA,UAC7B;AAAA,UACA;AAAA,UACA,aAAa,UAAU;AAAA,QACzB;AACA,cAAM,OAAO,iBAAiB,QAAQ,MAAM,cAAc,QAAQ,IAAI,EAAE,MAAM;AAC9E,cAAM,QACH,QAAQ,MACT,cAAc,OAAO,IACrB;AAAA;AAAA,8BAAmC,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;AACjF,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,EAAE,CAAC,EAAE;AAAA,MACrE;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,QAAU,UAAO,EAAE,SAAS;AAAA,QAC5B,WAAa,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,EAAE,QAAQ,iBAAiB;AAAA,QAC/E,QAAU,UAAO,EAAE,SAAS;AAAA,MAC9B,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,QAAQ,WAAW,OAAO,IAAI;AAKtC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,OAAO,SAAS,IAAI,MAAM,gBAAgB;AAChD,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA,kBAAkB,WAAW,MAAM;AAAA,QACrC;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,SAAS,cAAc,CAAC;AAAA,gBACxB;AAAA,gBACA,sBAAsB,QAAQ;AAAA,cAChC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,aAAe,UAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QACvC,QAAU,UAAO,EAAE,SAAS;AAAA,QAC5B,WAAa,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,EAAE,QAAQ,iBAAiB;AAAA,QAC/E,QAAU,UAAO,EAAE,SAAS;AAAA,MAC9B,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,aAAa,QAAQ,WAAW,OAAO,IAAI;AAMnD,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,OACJ,eAAe,SACX,IAAI,MAAM,eAAe,WAAW,cACpC,cACE,eAAe,WAAW,cAC1B,SACE,IAAI,MAAM,cACV;AACV,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA,kBAAkB,WAAW,MAAM;AAAA,QACrC;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,SAAS,YAAY,CAAC;AAAA,gBACtB;AAAA,gBACA,sBAAsB,QAAQ;AAAA,cAChC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QACtC,QAAU,UAAO,EAAE,SAAS;AAAA,QAC5B,WAAa,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,EAAE,QAAQ,iBAAiB;AAAA,QAC/E,QAAU,UAAO,EAAE,SAAS;AAAA,QAC5B,SACG,QAAK,CAAC,cAAc,cAAc,YAAY,OAAO,CAAC,EACtD,QAAQ,UAAU,EAClB,SAAS,YAAY;AAAA,QACxB,YAAc,QAAK,CAAC,OAAO,MAAM,CAAC,EAAE,QAAQ,KAAK,EAAE,SAAS,gBAAgB;AAAA,QAC5E,sBACG,WAAQ,EACR,QAAQ,KAAK,EACb;AAAA,UACC;AAAA,QACF;AAAA,MACJ,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,QAAQ,WAAW,QAAQ,SAAS,YAAY,qBAAqB,IACvF;AASF,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,OACJ,cAAc,SACV,IAAI,MAAM,aAAa,UAAU,cACjC,aACE,aAAa,UAAU,cACvB,SACE,IAAI,MAAM,cACV;AACV,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA,EAAE,GAAG,kBAAkB,WAAW,MAAM,GAAG,SAAS,WAAW;AAAA,QACjE;AACA,cAAM,WAAW,SAAS,YAAY,CAAC;AACvC,YAAI,CAAC,sBAAsB;AACzB,iBAAO;AAAA,YACL,SAAS;AAAA,cACP;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM,WAAW,UAAU,sBAAsB,sBAAsB,QAAQ,CAAC;AAAA,cAClF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA,cAAM,YAAY,MAAM,QAAQ;AAAA,UAC9B,SAAS,IAAI,OAAO,YAAY;AAC9B,kBAAM,EAAE,aAAa,IAAI,MAAM;AAAA,cAC7B;AAAA,cACA;AAAA,cACA,aAAa,QAAQ,EAAE;AAAA,YACzB;AACA,kBAAM,UAAU,aAAa,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI;AAC3D,mBAAO,GAAG,qBAAqB,OAAO,CAAC;AAAA,sBAAyB,OAAO;AAAA,UACzE,CAAC;AAAA,QACH;AACA,cAAM,OAAO,sBAAsB,QAAQ;AAC3C,cAAM,SAAS,KAAK,QAChB,YAAY,KAAK,KAAK,GAAG,KAAK,WAAW,8BAA8B,KAAK,YAAY,MAAM,EAAE,KAChG;AACJ,cAAM,OAAO,CAAC,QAAQ,GAAG,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,MAAM;AAC/D,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,EAAE,CAAC,EAAE;AAAA,MACrE;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO,EAAE,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY,EAAE,CAAC;AAAA,MAC7E,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,IAAI;AACvB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,aAAa,IAAI,MAAM;AAAA,UAC7B;AAAA,UACA;AAAA,UACA,aAAa,UAAU;AAAA,QACzB;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,cAAc,wBAAwB,EAAE,CAAC;AAAA,QACtF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI;AAAA,QAC3B,QAAU,UAAO,EAAE,SAAS,kCAAkC;AAAA,QAC9D,OAAS,UAAO,EAAE,IAAI,CAAC;AAAA,QACvB,MAAQ,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,wBAAwB;AAAA,QACzD,OAAS,WAAQ,EAAE,QAAQ,KAAK;AAAA,MAClC,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,QAAQ,OAAO,MAAM,MAAM,IAAI;AAOnD,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,YAAY,IAAI,MAAM;AAAA,UAC5B;AAAA,UACA;AAAA,UACA,aAAa,UAAU;AAAA,UACvB,EAAE,aAAa,EAAE,QAAQ,OAAO,MAAM,MAAM,EAAE;AAAA,QAChD;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,oCAAoC,UAAU,QAAQ,MAAM;AAAA;AAAA,EAAS,kBAAkB,WAAW,CAAC;AAAA,YAC3G;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI;AAAA,QAC3B,QAAU,UAAO;AAAA,QACjB,OAAS,UAAO,EAAE,SAAS;AAAA,QAC3B,MAAQ,UAAO,EAAE,SAAS;AAAA,QAC1B,OAAS,WAAQ,EAAE,SAAS;AAAA,MAC9B,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,QAAQ,GAAG,QAAQ,IAAI;AAI3C,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,YAAY,IAAI,MAAM;AAAA,UAC5B;AAAA,UACA;AAAA,UACA,aAAa,UAAU,iBAAiB,MAAM;AAAA,UAC9C,EAAE,aAAa,QAAQ;AAAA,QACzB;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,oCAAoC,UAAU,QAAQ,MAAM;AAAA;AAAA,EAAS,kBAAkB,WAAW,CAAC;AAAA,YAC3G;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO,CAAC,CAAC;AAAA,MACxB,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,YAAY;AACnB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM,WAGpB,WAAW,OAAO,0BAA0B;AAC/C,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,WAAW,SAAS,qBAAqB,CAAC,GAAG,qBAAqB;AAAA,YAC1E;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI;AAAA,QAC3B,OAAS,UAAO,EAAE,IAAI,CAAC;AAAA,QACvB,MAAQ,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,qBAAqB;AAAA,QACtD,qBACG,UAAO,EACP,IAAI,EACJ,SAAS,6DAA6D;AAAA,QACzE,iBACG,UAAO,EACP,IAAI,EACJ,SAAS,EACT;AAAA,UACC;AAAA,QACF;AAAA,QACF,WACG,UAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,qDAAqD;AAAA,QACjE,iBACG,SAAQ,UAAO,CAAC,EAChB,SAAS,EACT,SAAS,sDAAsD;AAAA,QAClE,QAAU,UAAO,EAAE,SAAS;AAAA,QAC5B,OAAS,WAAQ,EAAE,QAAQ,IAAI;AAAA,QAC/B,UAAY,WAAQ,EAAE,QAAQ,KAAK;AAAA,QACnC,aACG,SAAQ,UAAO,CAAC,EAChB,SAAS,EACT,SAAS,yEAAyE;AAAA,MACvF,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,GAAG,YAAY,IAAI;AAIvC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,QAAQ,IAAI,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,UACA,aAAa,UAAU;AAAA,UACvB,EAAE,SAAS,YAAY;AAAA,QACzB;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,YAAY,QAAQ,EAAE;AAAA;AAAA,EAAgB,cAAc,OAAO,CAAC,GAAG;AAAA,UACvF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI;AAAA,QAC3B,OAAS,WAAQ,EAAE,SAAS;AAAA,QAC5B,UAAY,WAAQ,EAAE,SAAS;AAAA,QAC/B,aAAe,SAAQ,UAAO,CAAC,EAAE,SAAS,EAAE,SAAS,gCAAgC;AAAA,QACrF,iBAAmB,SAAQ,UAAO,CAAC,EAAE,SAAS,EAAE,SAAS,iBAAiB;AAAA,QAC1E,iBAAmB,UAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,gCAAgC;AAAA,QACtF,WAAa,UAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,gBAAgB;AAAA,QAChE,qBAAuB,UAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,qBAAqB;AAAA,QAC/E,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS;AAAA,MACxC,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,GAAG,QAAQ,IAAI;AAInC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,QAAQ,IAAI,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,UACA,aAAa,UAAU;AAAA,UACvB,EAAE,SAAS,QAAQ;AAAA,QACrB;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,YAAY,QAAQ,EAAE;AAAA;AAAA,EAAgB,cAAc,OAAO,CAAC,GAAG;AAAA,UACvF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO,CAAC,CAAC;AAAA,MACxB,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,YAAY;AACnB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,SAAS,WAAW,CAAC,GAAG,gBAAgB,EAAE,CAAC;AAAA,QACxF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,MAAQ,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,kBAAkB;AAAA,MACrD,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,KAAK,IAAI;AACjB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,QAAAC,QAAO,IAAI,MAAM;AAAA,UACvB;AAAA,UACA;AAAA,UACA;AAAA,UACA,EAAE,QAAQ,EAAE,KAAK,EAAE;AAAA,QACrB;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM;AAAA;AAAA,EAA2B,iBAAiBA,OAAM,CAAC,GAAG,CAAC;AAAA,QACzF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO,CAAC,CAAC;AAAA,MACxB,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,YAAY;AACnB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,SAAS,UAAU,CAAC,GAAG,WAAW,EAAE,CAAC;AAAA,QAClF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO,CAAC,CAAC;AAAA,MACxB,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,YAAY;AACnB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM,cAGpB,WAAW,OAAO,gBAAgB;AACrC,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,WAAW,SAAS,iBAAiB,CAAC,GAAG,iBAAiB,EAAE;AAAA,UACpF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY;AAAA,MACpD,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,IAAI;AACvB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM,cAGpB,WAAW,OAAO,aAAa,UAAU,cAAc;AAC1D,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,WAAW,SAAS,uBAAuB,CAAC,GAAG,gBAAgB;AAAA,YACvE;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY;AAAA,QAClD,QACG,UAAO,EACP,SAAS,EACT,SAAS,mEAAmE;AAAA,MACjF,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,OAAO,IAAI;AAC/B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,QAAQ,IAAI,MAAM;AAAA,UACxB;AAAA,UACA;AAAA,UACA,aAAa,UAAU;AAAA,QACzB;AACA,cAAM,kBAAkB,UAAU,QAAQ;AAC1C,cAAM,EAAE,YAAY,IAAI,MAAM;AAAA,UAC5B;AAAA,UACA;AAAA,UACA,aAAa,UAAU,iBAAiB,eAAe;AAAA,QACzD;AACA,cAAM,EAAE,aAAa,IAAI,MAAM,cAE5B,WAAW,OAAO,aAAa,UAAU,eAAe;AAC3D,cAAM,WAAW,cAAc,YAAY,IAAI;AAE/C,cAAM,eAAe,SAAS,SAC1B,SACG;AAAA,UACC,CAAC,MACC,MAAM,EAAE,KAAK,KAAK,EAAE,aAAa,GAAG,EAAE,UAAU,OAAO,EAAE,GAAG,EAAE,OAAO,KAAK,EAAE,SAAS;AAAA,QACzF,EACC,KAAK,IAAI,IACZ;AACJ,cAAM,mBAAmB,aACtB,IAAI,CAAC,MAAM,KAAK,EAAE,MAAM,GAAG,EAAE,WAAW,gBAAgB,EAAE,EAAE,EAC5D,KAAK,IAAI;AAEZ,cAAM,OAAO;AAAA,UACX,6BAAwB,UAAU,KAAK,eAAe;AAAA,UACtD,cAAc,YAAY,KAAK;AAAA,UAC/B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AACX,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE;AAAA,MAC7C;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY;AAAA,QAClD,QAAU,UAAO,EAAE,SAAS,0CAA0C;AAAA,QACtE,eACG,UAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,SAAS,wDAAwD;AAAA,QACpE,QACG,QAAK,CAAC,QAAQ,UAAU,CAAC,EACzB,QAAQ,MAAM,EACd;AAAA,UACC;AAAA,QACF;AAAA,MACJ,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,QAAQ,eAAe,OAAO,IAAI;AAMtD,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,YAAY,IAAI,MAAM;AAAA,UAC5B;AAAA,UACA;AAAA,UACA,aAAa,UAAU,iBAAiB,MAAM;AAAA,QAChD;AACA,cAAM,WAAW,cAAc,YAAY,IAAI;AAC/C,cAAM,UAAU,SAAS,aAAa;AACtC,YAAI,CAAC,SAAS;AACZ,gBAAM,IAAI;AAAA,YACR,iBAAiB,aAAa,2BAA2B,SAAS,MAAM,kBAAkB,KAAK,IAAI,GAAG,SAAS,SAAS,CAAC,CAAC;AAAA,UAC5H;AAAA,QACF;AACA,cAAM,UAAU,WAAW,aAAa,eAAe,QAAQ,IAAI,IAAI,QAAQ;AAC/E,cAAM,aAAa,QAAQ,aACvB,OAAO,QAAQ,KAAK,KAAK,QAAQ,UAAU,KAAK,QAAQ,OAAO,KAC/D,OAAO,QAAQ,KAAK,KAAK,QAAQ,OAAO;AAC5C,cAAM,OAAO;AAAA,UACX;AAAA,UACA,YAAY,MAAM,aAAa,QAAQ,SAAS,cAAc,MAAM;AAAA,UACpE;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AACX,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,EAAE,CAAC,EAAE;AAAA,MACrE;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY;AAAA,QAClD,QAAU,UAAO,EAAE,SAAS,qCAAqC;AAAA,QACjE,eACG,UAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,SAAS,mEAAmE;AAAA,QAC/E,SACG,UAAO,EACP;AAAA,UACC;AAAA,QACF;AAAA,QACF,QACG,QAAK,CAAC,QAAQ,UAAU,CAAC,EACzB,QAAQ,MAAM,EACd;AAAA,UACC;AAAA,QACF;AAAA,MACJ,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,QAAQ,eAAe,SAAS,OAAO,IAAI;AAO/D,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,YAAY,IAAI,MAAM;AAAA,UAC5B;AAAA,UACA;AAAA,UACA,aAAa,UAAU,iBAAiB,MAAM;AAAA,QAChD;AACA,cAAM,iBAAiB,WAAW,aAAa,eAAe,OAAO,IAAI;AACzE,cAAM,UAAU,sBAAsB,YAAY,MAAM,eAAe,cAAc;AACrF,cAAM,EAAE,aAAa,QAAQ,IAAI,MAAM;AAAA,UACrC;AAAA,UACA;AAAA,UACA,aAAa,UAAU,iBAAiB,MAAM;AAAA,UAC9C,EAAE,aAAa,EAAE,MAAM,QAAQ,EAAE;AAAA,QACnC;AACA,cAAM,kBAAkB,cAAc,QAAQ,IAAI;AAClD,cAAM,iBAAiB,gBAAgB,aAAa;AACpD,cAAM,eAAe,gBAAgB,aAAa;AAClD,cAAM,eAAe,gBAAgB,WAAW;AAChD,cAAM,OAAO;AAAA,UACX,YAAY,aAAa,MAAM,YAAY,0BAA0B,UAAU,KAAK,MAAM;AAAA,UAC1F,mBAAmB,YAAY;AAAA,QACjC,EAAE,KAAK,IAAI;AACX,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE;AAAA,MAC7C;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY;AAAA,QAClD,eAAiB,UAAO,EAAE,SAAS,2BAA2B;AAAA,QAC9D,eAAiB,UAAO,EAAE,SAAS,yCAAyC;AAAA,MAC9E,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,eAAe,cAAc,IAAI;AAKrD,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,CAAC,WAAW,SAAS,IAAI,MAAM,QAAQ,IAAI;AAAA,UAC/C;AAAA,YACE;AAAA,YACA;AAAA,YACA,aAAa,UAAU,iBAAiB,aAAa;AAAA,UACvD;AAAA,UACA;AAAA,YACE;AAAA,YACA;AAAA,YACA,aAAa,UAAU,iBAAiB,aAAa;AAAA,UACvD;AAAA,QACF,CAAC;AACD,cAAM,iBAAiB,cAAc,UAAU,YAAY,IAAI;AAC/D,cAAM,iBAAiB,cAAc,UAAU,YAAY,IAAI;AAC/D,cAAM,SAAS,KAAK,IAAI,eAAe,QAAQ,eAAe,MAAM;AAEpE,cAAM,OAAiB,CAAC;AACxB,aAAK,KAAK,0DAA0D;AACpE,aAAK,KAAK,iCAAiC;AAC3C,iBAAS,IAAI,GAAG,IAAI,QAAQ,KAAK,GAAG;AAClC,gBAAM,MAAM,eAAe,CAAC;AAC5B,gBAAM,MAAM,eAAe,CAAC;AAC5B,gBAAM,UAAU,KAAK,WAAW,KAAK,WAAW;AAChD,gBAAM,cAAc,KAAK,aAAa;AACtC,gBAAM,cAAc,KAAK,aAAa;AACtC,cAAI;AACJ,cAAI,CAAC,IAAK,UAAS;AAAA,mBACV,CAAC,IAAK,UAAS;AAAA,eACnB;AACH,kBAAM,QAAQ,KAAK,IAAI,aAAa,CAAC;AACrC,kBAAM,YAAY,KAAK,IAAI,cAAc,WAAW,IAAI;AACxD,qBAAS,YAAY,OAAO,cAAc;AAAA,UAC5C;AACA,eAAK,KAAK,KAAK,CAAC,MAAM,OAAO,MAAM,MAAM,MAAM,WAAW,MAAM,WAAW,IAAI;AAAA,QACjF;AAEA,cAAM,OAAO;AAAA,UACX,sCAAiC,UAAU,KAAK,aAAa,WAAM,aAAa;AAAA,UAChF;AAAA,UACA,GAAG;AAAA,QACL,EAAE,KAAK,IAAI;AACX,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE;AAAA,MAC7C;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,YAAY;AAAA,QAClD,WAAa,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oCAAoC;AAAA,QAC1E,aAAe,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gCAAgC;AAAA,QACxE,cACG,UAAO,EACP,QAAQ,0BAA0B,EAClC,SAAS,kDAAkD;AAAA,MAChE,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,YAAY,WAAW,aAAa,aAAa,IAAI;AAM7D,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,SAAS,OAAO,KAAK,aAAa,QAAQ;AAChD,cAAM,OAAO,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,MAAM,aAAa,CAAC;AACtD,cAAM,WAAW,IAAI,SAAS;AAC9B,iBAAS,OAAO,QAAQ,MAAM,SAAS;AACvC,cAAM,EAAE,mBAAmB,IAAI,MAAM,iBAElC,WAAW,OAAO,aAAa,UAAU,gBAAgB,QAAQ;AACpE,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,mCAAmC,UAAU;AAAA;AAAA,EAAQ,iBAAiB,kBAAkB,CAAC;AAAA,YACjG;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AKzhCA,YAAYC,QAAO;AAQnB,IAAM,qBAAqB,CAAC,WAA4C;AACtE,QAAM,QAAkB,CAAC,OAAO,OAAO,aAAa,CAAC,MAAM,OAAO,IAAI,CAAC,EAAE;AACzE,MAAI,OAAO,SAAS,EAAG,OAAM,KAAK,gBAAgB,OAAO,SAAS,CAAC,EAAE;AACrE,MAAI,OAAO,MAAM,EAAG,OAAM,KAAK,aAAa,OAAO,MAAM,CAAC,EAAE;AAC5D,MAAI,OAAO,OAAO,EAAG,OAAM,KAAK,cAAc,OAAO,OAAO,CAAC,EAAE;AAC/D,MAAI,OAAO,OAAO,EAAG,OAAM,KAAK,cAAc,OAAO,OAAO,CAAC,EAAE;AAC/D,MAAI,OAAO,QAAQ,EAAG,OAAM,KAAK,eAAe,OAAO,QAAQ,CAAC,EAAE;AAClE,MAAI,OAAO,aAAa,GAAG;AACzB,UAAM,OAAO,OAAO,OAAO,aAAa,CAAC;AACzC,UAAM,KAAK,KAAK,SAAS,MAAM,GAAG,KAAK,MAAM,GAAG,GAAG,CAAC,QAAQ,IAAI;AAAA,EAClE;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,IAAM,oBAAoB,CAAC,QAAuC;AACvE,QAAM,EAAE,WAAW,SAAS,IAAI;AAEhC,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,OAAS,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,sBAAsB;AAAA,QACxD,UACG,UAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,aAAa,EACjB,QAAQ,iBAAiB,EACzB,SAAS,4BAA4B;AAAA,QACxC,MAAQ,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,uBAAuB;AAAA,MAC3E,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,OAAO,UAAU,KAAK,IAAI;AAKlC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,YACE;AAAA,YACA,GAAG,kBAAkB,UAAU,IAAI;AAAA,UACrC;AAAA,QACF;AACA,cAAM,UAAU,SAAS,WAAW,CAAC;AACrC,cAAM,OAAO,4BAA4B,UAAU,UAAU,IAAI;AACjE,cAAM,SAAS,UAAU,KAAK,KAAK,WAAW,IAAI,KAAK,QAAQ,MAAM,YAAY,KAAK,WAAW,iBAAiB,KAAK,YAAY,KAAK,EAAE;AAC1I,cAAM,OAAO,QAAQ,IAAI,kBAAkB,EAAE,KAAK,MAAM;AACxD,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,iBAAiB,CAAC,QAAQ,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,MAAM,CAAC,EAAE;AAAA,UACtF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC9EA,YAAYC,QAAO;AAaZ,IAAM,oBAAoB,CAAC,QAAuC;AACvE,QAAM,EAAE,WAAW,SAAS,IAAI;AAEhC,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,IAAI,EAAE,SAAS,WAAW;AAAA,QAChD,kBAAoB,WAAQ,EAAE,QAAQ,KAAK,EAAE,SAAS,yBAAyB;AAAA,MACjF,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,iBAAiB,IAAI;AAIxC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,OAAO,IAAI,MAAM;AAAA,UACvB;AAAA,UACA;AAAA,UACA,YAAY,SAAS;AAAA,QACvB;AACA,YAAI,OAAO,aAAa,MAAM;AAC9B,YAAI,kBAAkB;AACpB,gBAAM,EAAE,SAAS,IAAI,MAAM;AAAA,YACzB;AAAA,YACA;AAAA,YACA,YAAY,SAAS;AAAA,UACvB;AACA,kBAAQ;AAAA;AAAA;AAAA;AAAA;AAAA,EAA0B,SAAS,IAAI,aAAa,EAAE,KAAK,MAAM,CAAC;AAAA,QAC5E;AACA,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,EAAE,CAAC,EAAE;AAAA,MACrE;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,OAAS,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,6BAA6B;AAAA,QAC/D,UACG,UAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,aAAa,EACjB,QAAQ,iBAAiB,EACzB,SAAS,kBAAkB;AAAA,QAC9B,MAAQ,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,aAAa;AAAA,MACjE,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,OAAO,UAAU,KAAK,IAAI;AAKlC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,YACE,OAAO,eAAe,KAAK;AAAA,YAC3B,GAAG,kBAAkB,UAAU,IAAI;AAAA,UACrC;AAAA,QACF;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,SAAS,WAAW,CAAC;AAAA,gBACrB;AAAA,gBACA,4BAA4B,UAAU,UAAU,IAAI;AAAA,cACtD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,SAAW,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,gBAAgB;AAAA,QACpD,aAAe,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,oBAAoB;AAAA,QAC5D,UAAY,QAAK,CAAC,UAAU,QAAQ,UAAU,KAAK,CAAC,EAAE,SAAS;AAAA,QAC/D,MAAQ,QAAK,CAAC,WAAW,YAAY,YAAY,MAAM,CAAC,EAAE,SAAS;AAAA,QACnE,aAAe,UAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QACvC,UAAY,UAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QACpC,MAAQ,SAAQ,UAAO,CAAC,EAAE,SAAS;AAAA,QACnC,eAAiB,SAAQ,UAAO,EAAE,IAAM,UAAO,EAAE,IAAI,GAAG,OAAS,WAAQ,EAAE,CAAC,CAAC,EAAE,SAAS;AAAA,MAC1F,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,SAAS,aAAa,GAAG,KAAK,IAAI;AAC1C,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,OAAO,IAAI,MAAM;AAAA,UACvB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,YACE,QAAQ,EAAE,SAAS,SAAS,EAAE,MAAM,YAAY,GAAG,GAAG,KAAK;AAAA,UAC7D;AAAA,QACF;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,WAAW,OAAO,EAAE;AAAA;AAAA,EAAgB,aAAa,MAAM,CAAC,GAAG;AAAA,UACnF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,IAAI,EAAE,SAAS,WAAW;AAAA,QAChD,QAAU,QAAK,CAAC,OAAO,QAAQ,WAAW,QAAQ,UAAU,QAAQ,CAAC,EAAE,SAAS;AAAA,QAChF,UAAY,QAAK,CAAC,UAAU,QAAQ,UAAU,KAAK,CAAC,EAAE,SAAS;AAAA,QAC/D,MAAQ,QAAK,CAAC,WAAW,YAAY,YAAY,MAAM,CAAC,EAAE,SAAS;AAAA,QACnE,aAAe,UAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QACvC,UAAY,UAAO,EAAE,IAAI,EAAE,SAAS;AAAA,QACpC,SAAW,UAAO,EAAE,SAAS;AAAA,QAC7B,MAAQ,SAAQ,UAAO,CAAC,EAAE,SAAS;AAAA,QACnC,eAAiB,SAAQ,UAAO,EAAE,IAAM,UAAO,EAAE,IAAI,GAAG,OAAS,WAAQ,EAAE,CAAC,CAAC,EAAE,SAAS;AAAA,MAC1F,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,GAAG,QAAQ,IAAI;AAClC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,OAAO,IAAI,MAAM;AAAA,UACvB;AAAA,UACA;AAAA,UACA,YAAY,SAAS;AAAA,UACrB,EAAE,QAAQ,QAAQ;AAAA,QACpB;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP,EAAE,MAAM,QAAQ,MAAM,WAAW,OAAO,EAAE;AAAA;AAAA,EAAgB,aAAa,MAAM,CAAC,GAAG;AAAA,UACnF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,IAAI,EAAE,SAAS,WAAW;AAAA,QAChD,MAAQ,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,cAAc;AAAA,MACjD,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,KAAK,IAAI;AAC5B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,WAAW,OAAO,YAAY,SAAS,IAAI;AAAA,UAC1D,QAAQ,EAAE,SAAS,EAAE,MAAM,QAAQ,MAAM,EAAE;AAAA,QAC7C,CAAC;AACD,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iCAAiC,SAAS,IAAI,CAAC,EAAE;AAAA,MAC5F;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,IAAI,EAAE,SAAS,WAAW;AAAA,QAChD,MAAQ,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,iBAAiB;AAAA,MACpD,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,KAAK,IAAI;AAC5B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,WAAW,OAAO,YAAY,SAAS,IAAI;AAAA,UAC1D,QAAQ,EAAE,SAAS,EAAE,MAAM,QAAQ,KAAK,EAAE;AAAA,QAC5C,CAAC;AACD,eAAO;AAAA,UACL,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,mCAAmC,SAAS,IAAI,CAAC;AAAA,QACnF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,EAAE,QAAQ,iBAAiB;AAAA,QAC/E,QAAU,UAAO,EAAE,SAAS,EAAE,SAAS,mBAAmB;AAAA,MAC5D,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,OAAO,IAAI;AAC9B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA,kBAAkB,WAAW,MAAM;AAAA,QACrC;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,SAAS,WAAW,CAAC;AAAA,gBACrB;AAAA,gBACA,sBAAsB,QAAQ;AAAA,cAChC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,YAAc,UAAO,EAAE,IAAI,EAAE,SAAS,mBAAmB;AAAA,MAC3D,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,IAAI;AACvB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA,YAAY,UAAU;AAAA,QACxB;AACA,cAAM,YAAY,SAAS,WAAW,CAAC;AACvC,cAAM,OACJ,UAAU,SAAS,IACf,kCAAkC,UAAU;AAAA;AAAA,EAAO,UAAU,IAAI,YAAY,EAAE,KAAK,MAAM,CAAC,KAC3F,mCAAmC,UAAU;AACnD,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,iBAAiB,IAAI,EAAE,CAAC,EAAE;AAAA,MACrE;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,IAAI,EAAE,SAAS,WAAW;AAAA,QAChD,KAAO,SAAQ,UAAO,CAAC,EAAE,SAAS,EAAE,SAAS,aAAa;AAAA,QAC1D,QAAU,SAAQ,UAAO,CAAC,EAAE,SAAS,EAAE,SAAS,gBAAgB;AAAA,MAClE,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,KAAK,OAAO,IAAI;AAKnC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,OAAO,IAAI,MAAM;AAAA,UACvB;AAAA,UACA;AAAA,UACA,YAAY,SAAS;AAAA,QACvB;AACA,cAAM,OAAO,IAAI,IAAI,OAAO,IAAI;AAChC,aAAK,QAAQ,CAAC,MAAM;AAClB,eAAK,IAAI,CAAC;AAAA,QACZ,CAAC;AACD,gBAAQ,QAAQ,CAAC,MAAM;AACrB,eAAK,OAAO,CAAC;AAAA,QACf,CAAC;AACD,cAAM,EAAE,QAAQ,QAAQ,IAAI,MAAM;AAAA,UAChC;AAAA,UACA;AAAA,UACA,YAAY,SAAS;AAAA,UACrB,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,IAAI,EAAE,EAAE;AAAA,QAChC;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,2BAA2B,SAAS,cAAc,QAAQ,KAAK,KAAK,IAAI,KAAK,MAAM;AAAA,YAC3F;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC/WA,YAAYC,QAAO;AAaZ,IAAM,kBAAkB,CAAC,QAAuC;AACrE,QAAM,EAAE,WAAW,SAAS,IAAI;AAEhC,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO,CAAC,CAAC;AAAA,MACxB,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,YAAY;AACnB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,KAAK,IAAI,MAAM,WAAkC,WAAW,OAAO,WAAW;AACtF,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,IAAI,EAAE,CAAC,EAAE;AAAA,MAC/D;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aACE;AAAA,MACF,aAAe,UAAO;AAAA,QACpB,OAAS,UAAO,EAAE,IAAI,CAAC,EAAE,SAAS,cAAc;AAAA,QAChD,UACG,UAAO,EACP,IAAI,EACJ,IAAI,CAAC,EACL,IAAI,aAAa,EACjB,QAAQ,iBAAiB,EACzB,SAAS,kBAAkB;AAAA,QAC9B,MAAQ,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,SAAS,aAAa;AAAA,MACjE,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,OAAO,UAAU,KAAK,IAAI;AAKlC,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,YACE,OAAO,aAAa,KAAK;AAAA,YACzB,GAAG,kBAAkB,UAAU,IAAI;AAAA,UACrC;AAAA,QACF;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,SAAS,WAAW,CAAC;AAAA,gBACrB;AAAA,gBACA,4BAA4B,UAAU,UAAU,IAAI;AAAA,cACtD;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO,EAAE,SAAW,UAAO,EAAE,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;AAAA,MACvE,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,QAAQ,IAAI;AACpB,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,KAAK,IAAI,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA,UAAU,OAAO;AAAA,QACnB;AACA,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,WAAW,IAAI,EAAE,CAAC,EAAE;AAAA,MAC/D;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO,EAAE,iBAAmB,UAAO,EAAE,IAAI,EAAE,SAAS,iBAAiB,EAAE,CAAC;AAAA,MACvF,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,gBAAgB,IAAI;AAC5B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,EAAE,aAAa,IAAI,MAAM;AAAA,UAC7B;AAAA,UACA;AAAA,UACA,kBAAkB,eAAe;AAAA,QACnC;AACA,eAAO,EAAE,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,mBAAmB,YAAY,EAAE,CAAC,EAAE;AAAA,MAC/E;AAAA,IACF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,MACX,UAAU;AAAA,MACV,OAAO;AAAA,MACP,aAAa;AAAA,MACb,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,aAAa,EAAE,QAAQ,iBAAiB;AAAA,QAC/E,QAAU,UAAO,EAAE,SAAS;AAAA,MAC9B,CAAC;AAAA,MACD,aAAa;AAAA,QACX,cAAc;AAAA,QACd,iBAAiB;AAAA,QACjB,gBAAgB;AAAA,QAChB,eAAe;AAAA,MACjB;AAAA,MACA,SAAS,OAAO,WAAW;AACzB,cAAM,EAAE,WAAW,OAAO,IAAI;AAC9B,cAAM,QAAQ,MAAM,SAAS;AAC7B,cAAM,WAAW,MAAM;AAAA,UACrB;AAAA,UACA;AAAA,UACA;AAAA,UACA,kBAAkB,WAAW,MAAM;AAAA,QACrC;AACA,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM;AAAA,gBACJ,SAAS,iBAAiB,CAAC;AAAA,gBAC3B;AAAA,gBACA,sBAAsB,QAAQ;AAAA,cAChC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;AC3KO,IAAM,iBAAiB,CAAC,QAAuC;AAAA,EACpE,GAAG,kBAAkB,GAAG;AAAA,EACxB,GAAG,kBAAkB,GAAG;AAAA,EACxB,GAAG,sBAAsB,GAAG;AAAA,EAC5B,GAAG,gBAAgB,GAAG;AACxB;;;AVPA,IAAM,mBAAwE;AAAA,EAC5E,SAAS,EAAE,UAAU,mBAAmB,OAAO,kBAAkB;AAAA,EACjE,aAAa,EAAE,UAAU,uBAAuB,OAAO,sBAAsB;AAAA,EAC7E,OAAO,EAAE,UAAU,iBAAiB,OAAO,gBAAgB;AAC7D;AAKO,IAAM,uBAAuB,CAAC,gBAAgC;AACnE,QAAM,MAAM,YAAY,QAAQ,IAAI;AACpC,MAAI,QAAQ,GAAI,QAAO;AACvB,SAAO,YAAY,MAAM,GAAG,MAAM,CAAC;AACrC;AAEO,IAAM,qBAAqB,CAChC,UAEA,MACG;AAAA,EACC,CAAC,MACC,OAAO,EAAE,IAAI,OAAO,qBAAqB,EAAE,WAAW,CAAC,GAAG,EAAE,WAAW,KAAK,UAAU;AAC1F,EACC,KAAK,IAAI;AAEd,IAAM,oBAAoB,CACxB,QACA,UACA,OACA,OACA,eACS;AACT,QAAM,iBAAiB,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAC9C,QAAM,gBAAgB,mBAAmB,KAAK;AAE9C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE;AAAA,MACA,aAAa,GAAG,KAAK;AAAA;AAAA;AAAA,EAAyE,aAAa;AAAA,MAC3G,aAAe,UAAO;AAAA,QACpB,WAAa,UAAO,EAAE,SAAS,WAAW,eAAe,KAAK,IAAI,CAAC,EAAE;AAAA,QACrE,QAAU,UAAS,UAAO,GAAK,WAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC,EAAE,SAAS,sBAAsB;AAAA,MACvF,CAAC;AAAA,IACH;AAAA,IACA,OAAO,EAAE,WAAW,OAAO,MAAM;AAC/B,YAAM,MAAM,WAAW,IAAI,SAAS;AACpC,UAAI,CAAC,KAAK;AACR,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MAAM,sBAAsB,SAAS,iBAAiB,eAAe,KAAK,IAAI,CAAC;AAAA,YACjF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEA,YAAM,YAAY,IAAI,YAAY,MAAM,MAAM;AAC9C,aAAO,IAAI,QAAQ,SAAS;AAAA,IAC9B;AAAA,EACF;AACF;AAEO,IAAM,kBAAkB,CAC7B,QACA,aACc;AACd,QAAM,SAAS,IAAI,UAAU;AAAA,IAC3B,MAAM;AAAA,IACN,SAAS;AAAA,EACX,CAAC;AAED,QAAM,WAAW,eAAe,EAAE,WAAW,OAAO,WAAW,SAAS,CAAC;AAGzE,QAAM,gBAAgB,YAAY,UAAU;AAAA,IAC1C,UAAU,OAAO;AAAA,IACjB,YAAY,OAAO;AAAA,IACnB,OAAO,OAAO;AAAA,EAChB,CAAC;AAGD,QAAM,aAAa,oBAAI,IAA4B;AACnD,aAAW,QAAQ,eAAe;AAChC,eAAW,IAAI,KAAK,MAAM,IAAI;AAAA,EAChC;AAEA,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,OAAO;AAEV,iBAAW,QAAQ,eAAe;AAChC,eAAO;AAAA,UACL,KAAK;AAAA,UACL;AAAA,YACE,OAAO,KAAK;AAAA,YACZ,aAAa,KAAK;AAAA,YAClB,aAAa,KAAK;AAAA,YAClB,aAAa,KAAK;AAAA,UACpB;AAAA,UACA,OAAO,WAAW,KAAK,QAAQ,MAAiC;AAAA,QAClE;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA,KAAK,aAAa;AAChB,YAAM,UAAU,iBAAiB,aAAa;AAC9C,iBAAW,CAAC,WAAW,KAAK,KAAK,SAAS;AACxC,cAAM,QAAQ,iBAAiB,SAAS;AACxC,YAAI,OAAO;AACT,4BAAkB,QAAQ,MAAM,UAAU,MAAM,OAAO,OAAO,UAAU;AAAA,QAC1E;AAAA,MACF;AACA;AAAA,IACF;AAAA,IACA,KAAK,UAAU;AACb,wBAAkB,QAAQ,WAAW,WAAW,eAAe,UAAU;AACzE;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,MAAM,cAAc,cAAc,MAAM,aAAa,OAAO,IAAI,OAAO;AAC/E,SAAO;AACT;;;AWhIA,SAAS,4BAA4B;AAE9B,IAAM,sBAAsB,OAAO,WAAqC;AAC7E,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAC9B,UAAQ,MAAM,sCAAsC;AACtD;;;ACDA,IAAM,OAAO,YAA2B;AACtC,QAAM,SAAS,WAAW;AAE1B,MAAI,OAAO,gBAAgB,OAAO,iBAAiB;AAEjD,UAAM,cAAc,qBAAqB,OAAO,cAAc,OAAO,eAAe;AACpF,UAAM,WAAW,MAAM;AACvB,UAAM,SAAS,gBAAgB,QAAQ,QAAQ;AAC/C,UAAM,oBAAoB,MAAM;AAAA,EAClC,OAAO;AAEL,UAAM,aAAa,iBAAiB;AAAA,MAClC,WAAW,OAAO;AAAA,MAClB,eAAe,OAAO;AAAA,IACxB,CAAC;AACD,UAAM,SAAS,gBAAgB,QAAQ,WAAW,QAAQ;AAC1D,UAAM,oBAAoB,MAAM;AAAA,EAClC;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,UAAU;AACtB,UAAQ,MAAM,gBAAgB,KAAK;AACnC,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["z","z","record","z","z","z"]}
1
+ {"version":3,"sources":["../src/auth/api-token.ts","../src/auth/browser-oauth.ts","../src/constants.ts","../src/auth/token-store.ts","../src/config.ts","../src/server.ts","../src/routing/registry.ts","../src/tools/help-center.ts","../src/client/zendesk-api.ts","../src/utils/article-sections.ts","../src/utils/formatting.ts","../src/utils/pagination.ts","../src/tools/search.ts","../src/tools/tickets.ts","../src/tools/users.ts","../src/tools/index.ts","../src/transports/stdio.ts","../src/index.ts"],"sourcesContent":["/**\n * API token authentication for stdio transport.\n * Uses Basic auth: base64(email/token:api_token)\n */\nexport const buildBasicAuthHeader = (email: string, apiToken: string): string => {\n const credentials = `${email}/token:${apiToken}`;\n return `Basic ${Buffer.from(credentials).toString('base64')}`;\n};\n","import { createHash, randomBytes } from 'node:crypto';\nimport { createServer, type Server } from 'node:http';\nimport open from 'open';\nimport { getOAuthUrls } from '../constants';\n\nconst DEFAULT_CALLBACK_PORT = 3000;\n\ninterface BrowserOAuthConfig {\n subdomain: string;\n oauthClientId: string;\n callbackPort?: number | undefined;\n}\n\ninterface TokenResult {\n access_token: string;\n refresh_token?: string;\n token_type: string;\n scope: string;\n}\n\nconst generateCodeVerifier = (): string => randomBytes(32).toString('base64url');\n\nconst generateCodeChallenge = (verifier: string): string =>\n createHash('sha256').update(verifier).digest('base64url');\n\n/**\n * Performs OAuth 2.1 PKCE flow by opening the user's browser.\n * Starts a temporary HTTP server to receive the callback.\n * Returns the access token on success.\n */\nexport const authenticateViaBrowser = (config: BrowserOAuthConfig): Promise<TokenResult> => {\n const { subdomain, oauthClientId } = config;\n const { authorizeUrl, tokenUrl } = getOAuthUrls(subdomain);\n const codeVerifier = generateCodeVerifier();\n const codeChallenge = generateCodeChallenge(codeVerifier);\n\n return new Promise((resolve, reject) => {\n let callbackServer: Server;\n\n callbackServer = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', `http://localhost`);\n\n if (url.pathname !== '/callback') {\n res.writeHead(404);\n res.end('Not found');\n return;\n }\n\n const code = url.searchParams.get('code');\n const error = url.searchParams.get('error');\n\n if (error) {\n const desc = url.searchParams.get('error_description') ?? error;\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end(`<html><body><h1>Authentication failed</h1><p>${desc}</p></body></html>`);\n callbackServer.close();\n reject(new Error(`OAuth error: ${desc}`));\n return;\n }\n\n if (!code) {\n res.writeHead(400, { 'Content-Type': 'text/html' });\n res.end('<html><body><h1>Missing authorization code</h1></body></html>');\n callbackServer.close();\n reject(new Error('Missing authorization code in callback'));\n return;\n }\n\n // Exchange code for token\n try {\n const callbackPort = (callbackServer.address() as { port: number }).port;\n const tokenBody = new URLSearchParams({\n grant_type: 'authorization_code',\n code,\n client_id: oauthClientId,\n redirect_uri: `http://localhost:${callbackPort}/callback`,\n code_verifier: codeVerifier,\n });\n\n const tokenResponse = await fetch(tokenUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n body: tokenBody.toString(),\n });\n\n if (!tokenResponse.ok) {\n const errorBody = await tokenResponse.text();\n throw new Error(`Token exchange failed (${tokenResponse.status}): ${errorBody}`);\n }\n\n const tokenData = (await tokenResponse.json()) as TokenResult;\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(\n '<html><body><h1>Authentication successful!</h1>' +\n '<p>You can close this tab and return to Claude Code.</p>' +\n '<script>window.close()</script></body></html>',\n );\n\n callbackServer.close();\n resolve(tokenData);\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'text/html' });\n res.end(\n `<html><body><h1>Token exchange failed</h1><p>${err instanceof Error ? err.message : String(err)}</p></body></html>`,\n );\n callbackServer.close();\n reject(err);\n }\n });\n\n // Start on fixed port (must match redirect_uri registered in Zendesk OAuth client)\n callbackServer.listen(config.callbackPort ?? DEFAULT_CALLBACK_PORT, () => {\n const port = (callbackServer.address() as { port: number }).port;\n const redirectUri = `http://localhost:${port}/callback`;\n\n const params = new URLSearchParams({\n response_type: 'code',\n client_id: oauthClientId,\n redirect_uri: redirectUri,\n scope: 'read write',\n code_challenge: codeChallenge,\n code_challenge_method: 'S256',\n });\n\n const authUrl = `${authorizeUrl}?${params.toString()}`;\n console.error(`Opening browser for Zendesk authentication...`);\n console.error(`If the browser doesn't open, visit: ${authUrl}`);\n\n open(authUrl).catch(() => {\n // Browser open failed — the URL is already logged\n });\n });\n\n // Timeout after 5 minutes\n setTimeout(\n () => {\n callbackServer.close();\n reject(new Error('OAuth authentication timed out (5 min). Please try again.'));\n },\n 5 * 60 * 1000,\n ).unref();\n });\n};\n","export const CHARACTER_LIMIT = 25_000;\nexport const DEFAULT_PAGE_SIZE = 100;\nexport const MAX_PAGE_SIZE = 100;\nexport const TOKEN_CACHE_TTL_MS = 5 * 60 * 1000;\n\n// Per-attachment cap for inline image content. Images larger than this are\n// returned as text references instead of base64 image content blocks.\n// Aligned with the Anthropic vision API per-image limit.\nexport const MAX_ATTACHMENT_BYTES = 5 * 1024 * 1024;\n\n// Maximum number of images embedded as base64 in a single tool call.\n// Remaining images are returned as text references.\nexport const MAX_EMBEDDED_IMAGE_COUNT = 10;\n\n// Hard cap on comment pages fetched when collecting ticket attachments.\n// Overridable via ZENDESK_MAX_COMMENT_PAGES for tickets with many comments.\nexport const MAX_COMMENT_PAGES = Number(process.env['ZENDESK_MAX_COMMENT_PAGES'] ?? 10);\n\n// Thresholds used to nudge callers toward section-scoped article tools\n// (get_article_outline / get_article_section / update_article_section)\n// instead of fetching/rewriting the full body.\nexport const LARGE_ARTICLE_BODY_CHARS = 3_000;\nexport const LARGE_ARTICLE_SECTION_COUNT = 4;\n\nexport const getBaseUrl = (subdomain: string): string => `https://${subdomain}.zendesk.com/api/v2`;\n\nexport const getHelpCenterBaseUrl = (subdomain: string): string =>\n `https://${subdomain}.zendesk.com/api/v2/help_center`;\n\nexport const getOAuthUrls = (subdomain: string) => ({\n authorizeUrl: `https://${subdomain}.zendesk.com/oauth/authorizations/new`,\n tokenUrl: `https://${subdomain}.zendesk.com/oauth/tokens`,\n});\n","import { authenticateViaBrowser } from './browser-oauth';\n\ninterface StoredToken {\n accessToken: string;\n refreshToken?: string | undefined;\n}\n\nexport const createTokenStore = (config: { subdomain: string; oauthClientId: string }) => {\n let token: StoredToken | undefined;\n let authPromise: Promise<StoredToken> | undefined;\n\n const setToken = (accessToken: string, refreshToken?: string | undefined) => {\n token = { accessToken, refreshToken };\n };\n\n const ensureToken = async (): Promise<StoredToken> => {\n if (token) return token;\n\n if (!authPromise) {\n authPromise = authenticateViaBrowser({\n subdomain: config.subdomain,\n oauthClientId: config.oauthClientId,\n })\n .then((result) => {\n const stored: StoredToken = {\n accessToken: result.access_token,\n refreshToken: result.refresh_token,\n };\n token = stored;\n authPromise = undefined;\n return stored;\n })\n .catch((err) => {\n authPromise = undefined;\n throw err;\n });\n }\n\n return authPromise;\n };\n\n const getToken = async (): Promise<string> => {\n const stored = await ensureToken();\n return stored.accessToken;\n };\n\n return { getToken, setToken };\n};\n","import * as z from 'zod/v4';\n\nexport const ToolMode = z.enum(['single', 'namespace', 'all']);\nexport type ToolMode = z.infer<typeof ToolMode>;\n\nexport const LogLevel = z.enum(['debug', 'info', 'warn', 'error']);\nexport type LogLevel = z.infer<typeof LogLevel>;\n\nexport const Namespace = z.enum(['tickets', 'help_center', 'users']);\nexport type Namespace = z.infer<typeof Namespace>;\n\nexport const ConfigSchema = z.object({\n subdomain: z.string().min(1, 'ZENDESK_SUBDOMAIN is required'),\n oauthClientId: z.string().min(1),\n zendeskEmail: z.string().optional(),\n zendeskApiToken: z.string().optional(),\n logLevel: LogLevel,\n mode: ToolMode,\n readOnly: z.boolean(),\n namespaces: z.array(Namespace).optional(),\n tools: z.array(z.string()).optional(),\n});\n\nexport type Config = z.infer<typeof ConfigSchema>;\n\ninterface CliResult {\n subdomain?: string;\n mode?: string;\n readOnly?: boolean;\n namespaces?: string[];\n tools?: string[];\n logLevel?: string;\n}\n\nconst parseCliArgs = (args: string[]): CliResult => {\n const result: CliResult = {};\n let positionalIndex = 0;\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i];\n if (arg === undefined) continue;\n const next = args[i + 1];\n\n if (arg === '--mode' && next) {\n result.mode = next;\n i++;\n } else if (arg === '--read-only') {\n result.readOnly = true;\n } else if (arg === '--namespace' && next) {\n result.namespaces = result.namespaces ?? [];\n result.namespaces.push(next);\n i++;\n } else if (arg === '--tool' && next) {\n result.tools = result.tools ?? [];\n result.tools.push(next);\n i++;\n } else if (arg === '--log-level' && next) {\n result.logLevel = next;\n i++;\n } else if (!arg.startsWith('-') && positionalIndex === 0) {\n result.subdomain = arg;\n positionalIndex++;\n }\n }\n\n return result;\n};\n\nexport const loadConfig = (argv: string[] = process.argv.slice(2)): Config => {\n const cli = parseCliArgs(argv);\n\n const subdomain = cli.subdomain ?? process.env['ZENDESK_SUBDOMAIN'] ?? '';\n const oauthClientId =\n process.env['ZENDESK_OAUTH_CLIENT_ID'] ?? (subdomain ? `${subdomain}_zendesk` : '');\n\n const mode = cli.tools?.length ? 'all' : (cli.mode ?? 'namespace');\n\n return ConfigSchema.parse({\n subdomain,\n oauthClientId,\n zendeskEmail: process.env['ZENDESK_EMAIL'],\n zendeskApiToken: process.env['ZENDESK_API_TOKEN'],\n logLevel: cli.logLevel ?? process.env['LOG_LEVEL'] ?? 'info',\n mode,\n readOnly: cli.readOnly ?? false,\n namespaces: cli.namespaces,\n tools: cli.tools,\n });\n};\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport * as z from 'zod/v4';\nimport type { Config } from './config';\nimport { filterTools, groupByNamespace } from './routing/registry';\nimport { createAllTools, type ToolDefinition } from './tools/index';\n\nconst NAMESPACE_LABELS: Record<string, { toolName: string; title: string }> = {\n tickets: { toolName: 'zendesk_tickets', title: 'Zendesk Tickets' },\n help_center: { toolName: 'zendesk_help_center', title: 'Zendesk Help Center' },\n users: { toolName: 'zendesk_users', title: 'Zendesk Users' },\n};\n\n// Keep proxy descriptions compact: a proxy tool concatenates one line per\n// sub-operation, so only the first sentence of each tool description is\n// included. Clients still receive the full schema via the wrapped tool.\nexport const summarizeDescription = (description: string): string => {\n const idx = description.indexOf('. ');\n if (idx === -1) return description;\n return description.slice(0, idx + 1);\n};\n\nexport const buildOperationList = (\n tools: ReadonlyArray<Pick<ToolDefinition, 'name' | 'description' | 'readOnly'>>,\n): string =>\n tools\n .map(\n (t) =>\n `- **${t.name}**: ${summarizeDescription(t.description)}${t.readOnly ? '' : ' (write)'}`,\n )\n .join('\\n');\n\nconst registerProxyTool = (\n server: McpServer,\n toolName: string,\n title: string,\n tools: ToolDefinition[],\n handlerMap: Map<string, ToolDefinition>,\n): void => {\n const operationNames = tools.map((t) => t.name);\n const operationList = buildOperationList(tools);\n\n server.registerTool(\n toolName,\n {\n title,\n description: `${title}. Specify the operation and its parameters.\\n\\nAvailable operations:\\n${operationList}`,\n inputSchema: z.object({\n operation: z.string().describe(`One of: ${operationNames.join(', ')}`),\n params: z.record(z.string(), z.unknown()).default({}).describe('Operation parameters'),\n }),\n },\n async ({ operation, params }) => {\n const def = handlerMap.get(operation);\n if (!def) {\n return {\n content: [\n {\n type: 'text' as const,\n text: `Unknown operation \"${operation}\". Available: ${operationNames.join(', ')}`,\n },\n ],\n };\n }\n // Validate params through the tool's own schema\n const validated = def.inputSchema.parse(params);\n return def.handler(validated);\n },\n );\n};\n\nexport const createMcpServer = (\n config: Config,\n getToken: () => string | Promise<string>,\n): McpServer => {\n const server = new McpServer({\n name: '@digital4better/zendesk-mcp-server',\n version: '0.1.0',\n });\n\n const allTools = createAllTools({ subdomain: config.subdomain, getToken });\n\n // Apply filters (--read-only, --namespace, --tool)\n const filteredTools = filterTools(allTools, {\n readOnly: config.readOnly,\n namespaces: config.namespaces,\n tools: config.tools,\n });\n\n // Build handler map for proxy dispatch\n const handlerMap = new Map<string, ToolDefinition>();\n for (const tool of filteredTools) {\n handlerMap.set(tool.name, tool);\n }\n\n switch (config.mode) {\n case 'all': {\n // Register each tool individually\n for (const tool of filteredTools) {\n server.registerTool(\n tool.name,\n {\n title: tool.title,\n description: tool.description,\n inputSchema: tool.inputSchema,\n annotations: tool.annotations,\n },\n async (params) => tool.handler(params as Record<string, unknown>),\n );\n }\n break;\n }\n case 'namespace': {\n const grouped = groupByNamespace(filteredTools);\n for (const [namespace, tools] of grouped) {\n const label = NAMESPACE_LABELS[namespace];\n if (label) {\n registerProxyTool(server, label.toolName, label.title, tools, handlerMap);\n }\n }\n break;\n }\n case 'single': {\n registerProxyTool(server, 'zendesk', 'Zendesk', filteredTools, handlerMap);\n break;\n }\n }\n\n console.error(`Registered ${filteredTools.length} tools in ${config.mode} mode`);\n return server;\n};\n","import type { Namespace } from '../config';\nimport type { ToolDefinition } from '../tools/definitions';\n\nexport interface FilterOptions {\n readOnly: boolean;\n namespaces?: Namespace[] | undefined;\n tools?: string[] | undefined;\n}\n\nexport const filterTools = (allTools: ToolDefinition[], options: FilterOptions): ToolDefinition[] =>\n allTools.filter((tool) => {\n if (options.readOnly && !tool.readOnly) return false;\n if (options.namespaces?.length && !options.namespaces.includes(tool.namespace)) return false;\n if (options.tools?.length && !options.tools.includes(tool.name)) return false;\n return true;\n });\n\nexport const groupByNamespace = (tools: ToolDefinition[]): Map<string, ToolDefinition[]> => {\n const grouped = new Map<string, ToolDefinition[]>();\n for (const tool of tools) {\n const existing = grouped.get(tool.namespace) ?? [];\n existing.push(tool);\n grouped.set(tool.namespace, existing);\n }\n return grouped;\n};\n","import * as z from 'zod/v4';\nimport {\n helpCenterGet,\n helpCenterPost,\n helpCenterPut,\n helpCenterUpload,\n zendeskGet,\n zendeskPost,\n} from '../client/zendesk-api';\nimport {\n DEFAULT_PAGE_SIZE,\n LARGE_ARTICLE_BODY_CHARS,\n LARGE_ARTICLE_SECTION_COUNT,\n MAX_PAGE_SIZE,\n} from '../constants';\nimport type {\n ZendeskArticle,\n ZendeskArticleAttachment,\n ZendeskCategory,\n ZendeskContentTag,\n ZendeskLabel,\n ZendeskListResponse,\n ZendeskPermissionGroup,\n ZendeskSection,\n ZendeskTranslation,\n ZendeskUserSegment,\n} from '../types';\nimport {\n htmlToMarkdown,\n markdownToHtml,\n parseSections,\n replaceSectionContent,\n} from '../utils/article-sections';\nimport {\n formatArticle,\n formatArticleSummary,\n formatAttachment,\n formatCategory,\n formatContentTag,\n formatLabel,\n formatList,\n formatPermissionGroup,\n formatSection,\n formatTranslation,\n formatTranslationSummary,\n formatUserSegment,\n truncateIfNeeded,\n} from '../utils/formatting';\nimport {\n buildCursorParams,\n buildOffsetParams,\n extractPaginationMeta,\n extractSearchPaginationMeta,\n} from '../utils/pagination';\nimport type { ToolContext, ToolDefinition } from './definitions';\n\nconst largeArticleHint = (body: string, sectionCount: number): string | null => {\n if (body.length < LARGE_ARTICLE_BODY_CHARS && sectionCount < LARGE_ARTICLE_SECTION_COUNT) {\n return null;\n }\n return [\n `> ⚠ Large article (${body.length} chars, ${sectionCount} sections).`,\n '> For targeted edits, prefer get_article_outline + get_article_section +',\n '> update_article_section to avoid re-sending the full body on each write.',\n '',\n ].join('\\n');\n};\n\nexport const createHelpCenterTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'search_articles',\n namespace: 'help_center',\n readOnly: true,\n title: 'Search Help Center Articles',\n description:\n 'Full-text search across Help Center articles (metadata only, no body). Use get_article for full content. Supports locale filtering. Returns total count.',\n inputSchema: z.object({\n query: z.string().min(1).describe('Search query'),\n locale: z.string().optional().describe('Filter by locale (e.g., \"en-us\", \"fr\")'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page'),\n page: z.number().int().min(1).default(1).describe('Page number'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, locale, per_page, page } = params as {\n query: string;\n locale?: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const p: Record<string, string> = { query, ...buildOffsetParams(per_page, page) };\n if (locale) p['locale'] = locale;\n const response = await helpCenterGet<ZendeskListResponse<ZendeskArticle>>(\n subdomain,\n token,\n '/articles/search',\n p,\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.results ?? [],\n formatArticleSummary,\n extractSearchPaginationMeta(response, per_page, page),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'get_article',\n namespace: 'help_center',\n readOnly: true,\n title: 'Get Help Center Article',\n description:\n 'Retrieve an article by ID with full body content. For large articles, prefer get_article_outline + get_article_section to save tokens. Optionally specify locale for a translated version. Returns body (HTML), metadata, source_locale, and list of available translations.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z.string().optional().describe('Locale for translated version'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale } = params as { article_id: number; locale?: string };\n const token = await getToken();\n const path = locale ? `/${locale}/articles/${article_id}` : `/articles/${article_id}`;\n const { article } = await helpCenterGet<{ article: ZendeskArticle }>(\n subdomain,\n token,\n path,\n );\n const { translations } = await helpCenterGet<{ translations: ZendeskTranslation[] }>(\n subdomain,\n token,\n `/articles/${article_id}/translations`,\n );\n const hint = largeArticleHint(article.body, parseSections(article.body).length);\n const text =\n (hint ?? '') +\n formatArticle(article) +\n `\\n\\n**Available translations**: ${translations.map((t) => t.locale).join(', ')}`;\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'list_categories',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Help Center Categories',\n description: 'List all Help Center categories. Optionally filter by locale.',\n inputSchema: z.object({\n locale: z.string().optional(),\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { locale, page_size, cursor } = params as {\n locale?: string;\n page_size: number;\n cursor?: string;\n };\n const token = await getToken();\n const path = locale ? `/${locale}/categories` : '/categories';\n const response = await helpCenterGet<ZendeskListResponse<ZendeskCategory>>(\n subdomain,\n token,\n path,\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.categories ?? [],\n formatCategory,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'list_sections',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Help Center Sections',\n description: 'List sections, optionally filtered by category ID and locale.',\n inputSchema: z.object({\n category_id: z.number().int().optional(),\n locale: z.string().optional(),\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { category_id, locale, page_size, cursor } = params as {\n category_id?: number;\n locale?: string;\n page_size: number;\n cursor?: string;\n };\n const token = await getToken();\n const path =\n category_id && locale\n ? `/${locale}/categories/${category_id}/sections`\n : category_id\n ? `/categories/${category_id}/sections`\n : locale\n ? `/${locale}/sections`\n : '/sections';\n const response = await helpCenterGet<ZendeskListResponse<ZendeskSection>>(\n subdomain,\n token,\n path,\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.sections ?? [],\n formatSection,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'list_articles',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Help Center Articles',\n description:\n 'List articles (metadata only, no body). Use get_article for full content. Optionally filter by section ID and locale. Supports sort_by (\"title\", \"created_at\", \"updated_at\") and include_translations: true to show available translation locales per article. Note: include_translations must be re-sent on each paginated request.',\n inputSchema: z.object({\n section_id: z.number().int().optional(),\n locale: z.string().optional(),\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n sort_by: z\n .enum(['created_at', 'updated_at', 'position', 'title'])\n .default('position')\n .describe('Sort field'),\n sort_order: z.enum(['asc', 'desc']).default('asc').describe('Sort direction'),\n include_translations: z\n .boolean()\n .default(false)\n .describe(\n 'Include available translation locales per article (causes 1 extra API call per article)',\n ),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { section_id, locale, page_size, cursor, sort_by, sort_order, include_translations } =\n params as {\n section_id?: number;\n locale?: string;\n page_size: number;\n cursor?: string;\n sort_by: string;\n sort_order: string;\n include_translations: boolean;\n };\n const token = await getToken();\n const path =\n section_id && locale\n ? `/${locale}/sections/${section_id}/articles`\n : section_id\n ? `/sections/${section_id}/articles`\n : locale\n ? `/${locale}/articles`\n : '/articles';\n const response = await helpCenterGet<ZendeskListResponse<ZendeskArticle>>(\n subdomain,\n token,\n path,\n { ...buildCursorParams(page_size, cursor), sort_by, sort_order },\n );\n const articles = response.articles ?? [];\n if (!include_translations) {\n return {\n content: [\n {\n type: 'text',\n text: formatList(articles, formatArticleSummary, extractPaginationMeta(response)),\n },\n ],\n };\n }\n const formatted = await Promise.all(\n articles.map(async (article) => {\n const { translations } = await helpCenterGet<{ translations: ZendeskTranslation[] }>(\n subdomain,\n token,\n `/articles/${article.id}/translations`,\n );\n const locales = translations.map((t) => t.locale).join(', ');\n return `${formatArticleSummary(article)}\\n- **Translations**: ${locales}`;\n }),\n );\n const meta = extractPaginationMeta(response);\n const header = meta.count\n ? `Results: ${meta.count}${meta.has_more ? ` | More available (cursor: ${meta.after_cursor})` : ''}`\n : '';\n const text = [header, ...formatted].filter(Boolean).join('\\n\\n');\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'list_article_translations',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Article Translations',\n description:\n 'List all available translations for an article (metadata only, no body: locale, title, draft, updated_at). Use get_article with locale for full translated content.',\n inputSchema: z.object({ article_id: z.number().int().describe('Article ID') }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id } = params as { article_id: number };\n const token = await getToken();\n const { translations } = await helpCenterGet<{ translations: ZendeskTranslation[] }>(\n subdomain,\n token,\n `/articles/${article_id}/translations`,\n );\n return {\n content: [{ type: 'text', text: formatList(translations, formatTranslationSummary) }],\n };\n },\n },\n {\n name: 'create_article_translation',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Article Translation',\n description: 'Create a translation for an existing article in a specific locale.',\n inputSchema: z.object({\n article_id: z.number().int(),\n locale: z.string().describe('Target locale (e.g., \"fr\", \"de\")'),\n title: z.string().min(1),\n body: z.string().min(1).describe('Translated body (HTML)'),\n draft: z.boolean().default(false),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, title, body, draft } = params as {\n article_id: number;\n locale: string;\n title: string;\n body: string;\n draft: boolean;\n };\n const token = await getToken();\n const { translation } = await helpCenterPost<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations`,\n { translation: { locale, title, body, draft } },\n );\n return {\n content: [\n {\n type: 'text',\n text: `Translation created for article #${article_id} in \"${locale}\".\\n\\n${formatTranslation(translation)}`,\n },\n ],\n };\n },\n },\n {\n name: 'update_article_translation',\n namespace: 'help_center',\n readOnly: false,\n title: 'Update Article Translation',\n description:\n \"Update article content (title, body) in a specific locale. For targeted edits on one or a few sections, prefer update_article_section — this tool replaces the FULL body and re-sends the entire article on each write. Use the article's source_locale (from get_article) for the default language, or another locale for translations.\",\n inputSchema: z.object({\n article_id: z.number().int(),\n locale: z.string(),\n title: z.string().optional(),\n body: z.string().optional(),\n draft: z.boolean().optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, ...updates } = params as {\n article_id: number;\n locale: string;\n } & Record<string, unknown>;\n const token = await getToken();\n const { translation } = await helpCenterPut<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n { translation: updates },\n );\n return {\n content: [\n {\n type: 'text',\n text: `Translation updated for article #${article_id} in \"${locale}\".\\n\\n${formatTranslation(translation)}`,\n },\n ],\n };\n },\n },\n {\n name: 'list_permission_groups',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Permission Groups',\n description:\n 'List all Guide permission groups. Use this to find the permission_group_id required when creating articles.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await zendeskGet<{\n permission_groups: ZendeskPermissionGroup[];\n count: number;\n }>(subdomain, token, '/guide/permission_groups');\n return {\n content: [\n {\n type: 'text',\n text: formatList(response.permission_groups ?? [], formatPermissionGroup),\n },\n ],\n };\n },\n },\n {\n name: 'create_article',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Help Center Article',\n description:\n \"Create a new article in a section. The locale becomes the article's source_locale. Requires a permission_group_id (use list_permission_groups to find available IDs). To add content in other locales afterwards, use create_article_translation.\",\n inputSchema: z.object({\n section_id: z.number().int(),\n title: z.string().min(1),\n body: z.string().min(1).describe('Article body (HTML)'),\n permission_group_id: z\n .number()\n .int()\n .describe('Permission group ID (use list_permission_groups to find it)'),\n user_segment_id: z\n .number()\n .int()\n .optional()\n .describe(\n 'User segment ID for visibility (use list_user_segments to find it). Defaults to everyone.',\n ),\n author_id: z\n .number()\n .int()\n .optional()\n .describe('Author user ID. Defaults to the authenticated user.'),\n content_tag_ids: z\n .array(z.string())\n .optional()\n .describe('Content tag IDs (use list_content_tags to find them)'),\n locale: z.string().optional(),\n draft: z.boolean().default(true),\n promoted: z.boolean().default(false),\n label_names: z\n .array(z.string())\n .optional()\n .describe('Label names for search ranking (use list_labels to see existing labels)'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { section_id, ...articleData } = params as { section_id: number } & Record<\n string,\n unknown\n >;\n const token = await getToken();\n const { article } = await helpCenterPost<{ article: ZendeskArticle }>(\n subdomain,\n token,\n `/sections/${section_id}/articles`,\n { article: articleData },\n );\n return {\n content: [\n { type: 'text', text: `Article #${article.id} created.\\n\\n${formatArticle(article)}` },\n ],\n };\n },\n },\n {\n name: 'update_article',\n namespace: 'help_center',\n readOnly: false,\n title: 'Update Help Center Article',\n description:\n 'Update article metadata only (draft, promoted, labels, tags, visibility, section, etc.). Does NOT update content (title, body) — use update_article_translation for that.',\n inputSchema: z.object({\n article_id: z.number().int(),\n draft: z.boolean().optional(),\n promoted: z.boolean().optional(),\n label_names: z.array(z.string()).optional().describe('Label names for search ranking'),\n content_tag_ids: z.array(z.string()).optional().describe('Content tag IDs'),\n user_segment_id: z.number().int().optional().describe('User segment ID for visibility'),\n author_id: z.number().int().optional().describe('Author user ID'),\n permission_group_id: z.number().int().optional().describe('Permission group ID'),\n section_id: z.number().int().optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, ...updates } = params as { article_id: number } & Record<\n string,\n unknown\n >;\n const token = await getToken();\n const { article } = await helpCenterPut<{ article: ZendeskArticle }>(\n subdomain,\n token,\n `/articles/${article_id}`,\n { article: updates },\n );\n return {\n content: [\n { type: 'text', text: `Article #${article.id} updated.\\n\\n${formatArticle(article)}` },\n ],\n };\n },\n },\n {\n name: 'list_content_tags',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Content Tags',\n description:\n 'List all Guide content tags. Content tags are visible to end users and help them find related articles.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await zendeskGet<{ records: ZendeskContentTag[]; count: number }>(\n subdomain,\n token,\n '/guide/content_tags',\n );\n return {\n content: [{ type: 'text', text: formatList(response.records ?? [], formatContentTag) }],\n };\n },\n },\n {\n name: 'create_content_tag',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Content Tag',\n description: 'Create a new content tag for Guide articles.',\n inputSchema: z.object({\n name: z.string().min(1).describe('Content tag name'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { name } = params as { name: string };\n const token = await getToken();\n const { record } = await zendeskPost<{ record: ZendeskContentTag }>(\n subdomain,\n token,\n '/guide/content_tags',\n { record: { name } },\n );\n return {\n content: [{ type: 'text', text: `Content tag created.\\n\\n${formatContentTag(record)}` }],\n };\n },\n },\n {\n name: 'list_labels',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Article Labels',\n description:\n 'List all article labels. Labels improve Help Center search ranking and are not visible to end users.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await helpCenterGet<{ labels: ZendeskLabel[]; count: number }>(\n subdomain,\n token,\n '/articles/labels',\n );\n return {\n content: [{ type: 'text', text: formatList(response.labels ?? [], formatLabel) }],\n };\n },\n },\n {\n name: 'list_user_segments',\n namespace: 'help_center',\n readOnly: true,\n title: 'List User Segments',\n description:\n 'List all user segments. User segments control article visibility (who can view). Use the ID when creating or updating articles.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const response = await helpCenterGet<{\n user_segments: ZendeskUserSegment[];\n count: number;\n }>(subdomain, token, '/user_segments');\n return {\n content: [\n { type: 'text', text: formatList(response.user_segments ?? [], formatUserSegment) },\n ],\n };\n },\n },\n {\n name: 'list_article_attachments',\n namespace: 'help_center',\n readOnly: true,\n title: 'List Article Attachments',\n description: 'List all attachments for an article.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id } = params as { article_id: number };\n const token = await getToken();\n const response = await helpCenterGet<{\n article_attachments: ZendeskArticleAttachment[];\n count: number;\n }>(subdomain, token, `/articles/${article_id}/attachments`);\n return {\n content: [\n {\n type: 'text',\n text: formatList(response.article_attachments ?? [], formatAttachment),\n },\n ],\n };\n },\n },\n {\n name: 'get_article_outline',\n namespace: 'help_center',\n readOnly: true,\n title: 'Get Article Outline',\n description:\n 'Return a compact outline of an article (list of sections delimited by h1/h2/h3, with word counts) for the given locale (defaults to source_locale). Includes available translations with their outdated status. Use get_article_section to fetch a specific section.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z\n .string()\n .optional()\n .describe('Locale of the body to outline (defaults to article source_locale)'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale } = params as { article_id: number; locale?: string };\n const token = await getToken();\n const { article } = await helpCenterGet<{ article: ZendeskArticle }>(\n subdomain,\n token,\n `/articles/${article_id}`,\n );\n const effectiveLocale = locale ?? article.source_locale;\n const { translation } = await helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${effectiveLocale}`,\n );\n const { translations } = await helpCenterGet<{\n translations: Array<ZendeskTranslation & { outdated?: boolean }>;\n }>(subdomain, token, `/articles/${article_id}/translations`);\n const sections = parseSections(translation.body);\n\n const outlineLines = sections.length\n ? sections\n .map(\n (s) =>\n `- [${s.index}] ${s.headingTag ? `${s.headingTag}: ` : ''}${s.heading} (${s.wordCount} words)`,\n )\n .join('\\n')\n : '_(no sections detected)_';\n const translationsList = translations\n .map((t) => `- ${t.locale}${t.outdated ? ' (outdated)' : ''}`)\n .join('\\n');\n\n const text = [\n `# Outline — Article #${article_id} (${effectiveLocale})`,\n `**Title**: ${translation.title}`,\n '',\n '## Sections',\n outlineLines,\n '',\n '## Available translations',\n translationsList,\n ].join('\\n');\n return { content: [{ type: 'text', text }] };\n },\n },\n {\n name: 'get_article_section',\n namespace: 'help_center',\n readOnly: true,\n title: 'Get Article Section',\n description:\n 'Retrieve the content of a single section of an article in a given locale. Use get_article_outline first to discover section indexes. Default format=\"html\" for round-trip safety. Pass format=\"markdown\" only for human review — the Markdown representation is lossy on some structures (<pre> with <br>, tables with multi-<p> cells are kept as raw HTML to limit the damage, but do not round-trip markdown content back through update_article_section).',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z.string().describe('Locale of the body (e.g., \"en-us\", \"fr\")'),\n section_index: z\n .number()\n .int()\n .min(0)\n .describe('0-based index of the section (see get_article_outline)'),\n format: z\n .enum(['html', 'markdown'])\n .default('html')\n .describe(\n 'Output format. \"html\" (default) is round-trip safe. \"markdown\" is lossy on some HTML structures — use only for human review, not before update_article_section.',\n ),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, section_index, format } = params as {\n article_id: number;\n locale: string;\n section_index: number;\n format: 'html' | 'markdown';\n };\n const token = await getToken();\n const { translation } = await helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n );\n const sections = parseSections(translation.body);\n const section = sections[section_index];\n if (!section) {\n throw new Error(\n `Section index ${section_index} not found. Article has ${sections.length} section(s) (0-${Math.max(0, sections.length - 1)}).`,\n );\n }\n const content = format === 'markdown' ? htmlToMarkdown(section.html) : section.html;\n const headerLine = section.headingTag\n ? `## [${section.index}] ${section.headingTag}: ${section.heading}`\n : `## [${section.index}] ${section.heading}`;\n const text = [\n headerLine,\n `_Locale: ${locale} | Words: ${section.wordCount} | Format: ${format}_`,\n '',\n content,\n ].join('\\n');\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'update_article_section',\n namespace: 'help_center',\n readOnly: false,\n title: 'Update Article Section',\n description:\n 'Replace the content of a single section of an article in a given locale, keeping the rest of the body intact. The server fetches the current body, replaces the targeted section, and PUTs the full reconstructed body via the Translations API. Default format=\"html\" for fidelity. Use format=\"markdown\" only when you control the input and know it does not rely on structures that round-trip poorly (code blocks with line breaks, tables with multi-paragraph cells). The section heading is preserved and is NOT part of the replaced content.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n locale: z.string().describe('Locale of the translation to update'),\n section_index: z\n .number()\n .int()\n .min(0)\n .describe('0-based index of the section to replace (see get_article_outline)'),\n content: z\n .string()\n .describe(\n 'New content for the section (heading excluded). HTML by default, Markdown if format=\"markdown\".',\n ),\n format: z\n .enum(['html', 'markdown'])\n .default('html')\n .describe(\n 'Input format. \"html\" (default) is the safe path. \"markdown\" is converted to HTML server-side but may introduce artifacts on complex content.',\n ),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, locale, section_index, content, format } = params as {\n article_id: number;\n locale: string;\n section_index: number;\n content: string;\n format: 'html' | 'markdown';\n };\n const token = await getToken();\n const { translation } = await helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n );\n const newSectionHtml = format === 'markdown' ? markdownToHtml(content) : content;\n const newBody = replaceSectionContent(translation.body, section_index, newSectionHtml);\n const { translation: updated } = await helpCenterPut<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${locale}`,\n { translation: { body: newBody } },\n );\n const updatedSections = parseSections(updated.body);\n const updatedSection = updatedSections[section_index];\n const newWordCount = updatedSection?.wordCount ?? 0;\n const headingLabel = updatedSection?.heading ?? '(intro)';\n const text = [\n `Section [${section_index}] \"${headingLabel}\" updated for article #${article_id} (${locale}).`,\n `New word count: ${newWordCount}.`,\n ].join('\\n');\n return { content: [{ type: 'text', text }] };\n },\n },\n {\n name: 'compare_translations',\n namespace: 'help_center',\n readOnly: true,\n title: 'Compare Article Translations',\n description:\n 'Compare section structure between two locales of the same article, matched by index. Returns a compact table (one row per section) with status: \"ok\" (both present, source/target word count ratio within 25%), \"different\" (word count ratio diverges by more than 25% — size signal only, NOT a semantic divergence: two locales may legitimately differ in verbosity) or \"missing\" (section absent in target). Useful to spot structurally stale or missing sections; do not interpret \"different\" as an edit regression on its own.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n source_locale: z.string().describe('Source (reference) locale'),\n target_locale: z.string().describe('Target locale to compare against source'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, source_locale, target_locale } = params as {\n article_id: number;\n source_locale: string;\n target_locale: string;\n };\n const token = await getToken();\n const [sourceRes, targetRes] = await Promise.all([\n helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${source_locale}`,\n ),\n helpCenterGet<{ translation: ZendeskTranslation }>(\n subdomain,\n token,\n `/articles/${article_id}/translations/${target_locale}`,\n ),\n ]);\n const sourceSections = parseSections(sourceRes.translation.body);\n const targetSections = parseSections(targetRes.translation.body);\n const maxLen = Math.max(sourceSections.length, targetSections.length);\n\n const rows: string[] = [];\n rows.push(`| Idx | Heading | Status | Source words | Target words |`);\n rows.push(`| --- | --- | --- | --- | --- |`);\n for (let i = 0; i < maxLen; i += 1) {\n const src = sourceSections[i];\n const tgt = targetSections[i];\n const heading = src?.heading ?? tgt?.heading ?? '';\n const sourceWords = src?.wordCount ?? 0;\n const targetWords = tgt?.wordCount ?? 0;\n let status: 'ok' | 'missing' | 'different';\n if (!tgt) status = 'missing';\n else if (!src) status = 'different';\n else {\n const denom = Math.max(sourceWords, 1);\n const diffRatio = Math.abs(sourceWords - targetWords) / denom;\n status = diffRatio > 0.25 ? 'different' : 'ok';\n }\n rows.push(`| ${i} | ${heading} | ${status} | ${sourceWords} | ${targetWords} |`);\n }\n\n const text = [\n `# Translation diff — Article #${article_id} (${source_locale} → ${target_locale})`,\n '',\n ...rows,\n ].join('\\n');\n return { content: [{ type: 'text', text }] };\n },\n },\n {\n name: 'create_article_attachment',\n namespace: 'help_center',\n readOnly: false,\n title: 'Create Article Attachment',\n description:\n 'Upload an attachment to an article. Provide file content as base64-encoded string.',\n inputSchema: z.object({\n article_id: z.number().int().describe('Article ID'),\n file_name: z.string().min(1).describe('File name (e.g., \"screenshot.png\")'),\n file_base64: z.string().min(1).describe('File content encoded as base64'),\n content_type: z\n .string()\n .default('application/octet-stream')\n .describe('MIME type (e.g., \"image/png\", \"application/pdf\")'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { article_id, file_name, file_base64, content_type } = params as {\n article_id: number;\n file_name: string;\n file_base64: string;\n content_type: string;\n };\n const token = await getToken();\n const buffer = Buffer.from(file_base64, 'base64');\n const blob = new Blob([buffer], { type: content_type });\n const formData = new FormData();\n formData.append('file', blob, file_name);\n const { article_attachment } = await helpCenterUpload<{\n article_attachment: ZendeskArticleAttachment;\n }>(subdomain, token, `/articles/${article_id}/attachments`, formData);\n return {\n content: [\n {\n type: 'text',\n text: `Attachment created for article #${article_id}.\\n\\n${formatAttachment(article_attachment)}`,\n },\n ],\n };\n },\n },\n ];\n};\n","import { getBaseUrl, getHelpCenterBaseUrl } from '../constants.js';\n\nexport class ZendeskApiError extends Error {\n constructor(\n public readonly status: number,\n public readonly statusText: string,\n public readonly body: string,\n ) {\n super(ZendeskApiError.buildMessage(status, statusText, body));\n this.name = 'ZendeskApiError';\n }\n\n private static buildMessage(status: number, statusText: string, body: string): string {\n switch (status) {\n case 401:\n return 'Authentication failed. Your Zendesk token may be expired or invalid. Re-authenticate to get a new token.';\n case 403:\n return 'Permission denied. Your Zendesk account does not have access to this resource.';\n case 404:\n return `Resource not found. Please verify the ID is correct. (${statusText})`;\n case 422:\n return `Validation error: ${body}`;\n case 429:\n return 'Rate limit exceeded. Please wait before making more requests.';\n default:\n return `Zendesk API error ${status}: ${statusText}. ${body}`;\n }\n }\n}\n\nexport interface ZendeskRequestOptions {\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE';\n body?: unknown;\n params?: Record<string, string>;\n}\n\n// token is either a Bearer OAuth token or a \"Basic xxx\" string (stdio API token mode)\nconst buildAuthHeader = (token: string): string =>\n token.startsWith('Basic ') ? token : `Bearer ${token}`;\n\nconst buildUrl = (base: string, path: string, params?: Record<string, string>): string => {\n const url = new URL(`${base}${path}`);\n if (params) {\n for (const [key, value] of Object.entries(params)) {\n url.searchParams.set(key, value);\n }\n }\n return url.toString();\n};\n\nconst executeRequest = async <T>(\n url: string,\n token: string,\n options: ZendeskRequestOptions = {},\n): Promise<T> => {\n const { method = 'GET', body } = options;\n\n const headers: Record<string, string> = {\n Authorization: buildAuthHeader(token),\n Accept: 'application/json',\n };\n\n if (body) {\n headers['Content-Type'] = 'application/json';\n }\n\n const init: RequestInit = { method, headers };\n if (body) {\n init.body = JSON.stringify(body);\n }\n\n const response = await fetch(url, init);\n\n if (!response.ok) {\n const responseBody = await response.text();\n throw new ZendeskApiError(response.status, response.statusText, responseBody);\n }\n\n if (response.status === 204) {\n return {} as T;\n }\n\n return response.json() as Promise<T>;\n};\n\nexport const zendeskGet = <T>(\n subdomain: string,\n token: string,\n path: string,\n params?: Record<string, string>,\n): Promise<T> => {\n const url = buildUrl(getBaseUrl(subdomain), path, params);\n return executeRequest<T>(url, token);\n};\n\nexport const zendeskPost = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'POST', body });\n};\n\nexport const zendeskPut = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'PUT', body });\n};\n\nexport const helpCenterGet = <T>(\n subdomain: string,\n token: string,\n path: string,\n params?: Record<string, string>,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path, params);\n return executeRequest<T>(url, token);\n};\n\nexport const helpCenterPost = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'POST', body });\n};\n\nexport const helpCenterPut = <T>(\n subdomain: string,\n token: string,\n path: string,\n body: unknown,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);\n return executeRequest<T>(url, token, { method: 'PUT', body });\n};\n\nexport const fetchZendeskBinary = async (\n subdomain: string,\n token: string,\n contentUrl: string,\n): Promise<{ data: Buffer; contentType: string }> => {\n const expectedHost = `${subdomain}.zendesk.com`;\n const headers: Record<string, string> = {};\n if (new URL(contentUrl).hostname === expectedHost) {\n headers['Authorization'] = buildAuthHeader(token);\n }\n const response = await fetch(contentUrl, { headers });\n if (!response.ok) {\n const body = await response.text();\n throw new ZendeskApiError(response.status, response.statusText, body);\n }\n const contentType = response.headers.get('content-type') ?? 'application/octet-stream';\n const arrayBuffer = await response.arrayBuffer();\n return { data: Buffer.from(arrayBuffer), contentType };\n};\n\nexport const helpCenterUpload = async <T>(\n subdomain: string,\n token: string,\n path: string,\n formData: FormData,\n): Promise<T> => {\n const url = buildUrl(getHelpCenterBaseUrl(subdomain), path);\n const response = await fetch(url, {\n method: 'POST',\n headers: { Authorization: buildAuthHeader(token) },\n body: formData,\n });\n\n if (!response.ok) {\n const responseBody = await response.text();\n throw new ZendeskApiError(response.status, response.statusText, responseBody);\n }\n\n return response.json() as Promise<T>;\n};\n","import * as cheerio from 'cheerio';\nimport type { Element } from 'hast';\nimport { toHtml } from 'hast-util-to-html';\nimport type { Handle } from 'hast-util-to-mdast';\nimport rehypeParse from 'rehype-parse';\nimport rehypeRaw from 'rehype-raw';\nimport rehypeRemark from 'rehype-remark';\nimport rehypeStringify from 'rehype-stringify';\nimport remarkGfm from 'remark-gfm';\nimport remarkParse from 'remark-parse';\nimport remarkRehype from 'remark-rehype';\nimport remarkStringify from 'remark-stringify';\nimport { unified } from 'unified';\n\nexport interface Section {\n index: number;\n heading: string;\n headingTag: string;\n level: number;\n html: string;\n wordCount: number;\n}\n\nconst HEADING_LEVELS = new Set(['h1', 'h2', 'h3']);\n\nconst countWords = (text: string): number => {\n const trimmed = text.trim();\n if (!trimmed) return 0;\n return trimmed.split(/\\s+/).length;\n};\n\nconst textOf = (html: string): string => {\n if (!html) return '';\n const $ = cheerio.load(`<div>${html}</div>`, null, false);\n return $('div').first().text();\n};\n\nexport const parseSections = (html: string): Section[] => {\n if (!html || !html.trim()) return [];\n\n const $ = cheerio.load(html, null, false);\n const children = $.root().contents().toArray();\n\n const introParts: string[] = [];\n const sections: Array<{\n heading: string;\n headingTag: string;\n level: number;\n contentParts: string[];\n }> = [];\n let current: (typeof sections)[number] | null = null;\n\n for (const node of children) {\n const tagName = node.type === 'tag' ? node.name.toLowerCase() : '';\n\n if (HEADING_LEVELS.has(tagName)) {\n const level = Number.parseInt(tagName.slice(1), 10);\n current = {\n heading: $(node).text().trim(),\n headingTag: tagName,\n level,\n contentParts: [],\n };\n sections.push(current);\n continue;\n }\n\n const outer = $.html(node);\n if (current) {\n current.contentParts.push(outer);\n } else {\n introParts.push(outer);\n }\n }\n\n const result: Section[] = [];\n\n if (introParts.length > 0) {\n const introHtml = introParts.join('');\n result.push({\n index: 0,\n heading: 'intro',\n headingTag: '',\n level: 0,\n html: introHtml,\n wordCount: countWords(textOf(introHtml)),\n });\n }\n\n for (const s of sections) {\n const sectionHtml = s.contentParts.join('');\n result.push({\n index: result.length,\n heading: s.heading,\n headingTag: s.headingTag,\n level: s.level,\n html: sectionHtml,\n wordCount: countWords(textOf(sectionHtml)),\n });\n }\n\n return result;\n};\n\nexport const replaceSectionContent = (\n html: string,\n sectionIndex: number,\n newHtml: string,\n): string => {\n const sections = parseSections(html);\n if (sectionIndex < 0 || sectionIndex >= sections.length) {\n throw new Error(\n `Section index ${sectionIndex} out of range (valid: 0-${Math.max(0, sections.length - 1)})`,\n );\n }\n\n return sections\n .map((section, idx) => {\n const content = idx === sectionIndex ? newHtml : section.html;\n if (section.level === 0) return content;\n return `<${section.headingTag}>${section.heading}</${section.headingTag}>${content}`;\n })\n .join('');\n};\n\n// Keep structural HTML that markdown flattens lossily: <pre> with inline <br>\n// collapses to a single line, and <table> cells with multiple <p> break GFM\n// pipe tables. Leaving them as raw HTML is safer for round-trip.\nconst keepAsHtml: Handle = (_state, node) => ({\n type: 'html',\n value: toHtml(node as Element),\n});\n\nconst htmlToMdProcessor = unified()\n .use(rehypeParse, { fragment: true })\n .use(rehypeRemark, { handlers: { table: keepAsHtml, pre: keepAsHtml } })\n .use(remarkGfm)\n .use(remarkStringify, { bullet: '-', emphasis: '_', fences: true });\n\nconst mdToHtmlProcessor = unified()\n .use(remarkParse)\n .use(remarkGfm)\n .use(remarkRehype, { allowDangerousHtml: true })\n .use(rehypeRaw)\n .use(rehypeStringify);\n\nexport const htmlToMarkdown = (html: string): string => {\n if (!html) return '';\n return String(htmlToMdProcessor.processSync(html));\n};\n\nexport const markdownToHtml = (markdown: string): string => {\n if (!markdown) return '';\n return String(mdToHtmlProcessor.processSync(markdown));\n};\n","import { CHARACTER_LIMIT } from '../constants.js';\nimport type {\n PaginationMeta,\n ZendeskArticle,\n ZendeskArticleAttachment,\n ZendeskCategory,\n ZendeskComment,\n ZendeskContentTag,\n ZendeskLabel,\n ZendeskOrganization,\n ZendeskPermissionGroup,\n ZendeskSection,\n ZendeskTicket,\n ZendeskTranslation,\n ZendeskUser,\n ZendeskUserSegment,\n} from '../types.js';\n\nexport const truncateIfNeeded = (text: string): string => {\n if (text.length <= CHARACTER_LIMIT) return text;\n return `${text.slice(0, CHARACTER_LIMIT)}\\n\\n--- Response truncated (${text.length} chars, limit ${CHARACTER_LIMIT}). Use pagination or filters to reduce results. ---`;\n};\n\nconst formatPagination = (meta: PaginationMeta): string => {\n const parts = [`Results: ${meta.count}`];\n if (meta.has_more) {\n parts.push(`More available (cursor: ${meta.after_cursor})`);\n }\n return parts.join(' | ');\n};\n\nexport const formatTicket = (ticket: ZendeskTicket): string =>\n [\n `## Ticket #${ticket.id}: ${ticket.subject}`,\n `- **Status**: ${ticket.status} | **Priority**: ${ticket.priority ?? 'none'} | **Type**: ${ticket.type ?? 'none'}`,\n `- **Requester**: ${ticket.requester_id} | **Assignee**: ${ticket.assignee_id ?? 'unassigned'}`,\n `- **Tags**: ${ticket.tags.length > 0 ? ticket.tags.join(', ') : 'none'}`,\n `- **Created**: ${ticket.created_at} | **Updated**: ${ticket.updated_at}`,\n ticket.description ? `\\n${ticket.description}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatComment = (comment: ZendeskComment): string => {\n const lines = [\n `### ${comment.public ? 'Public comment' : 'Internal note'} by ${comment.author_id}`,\n `*${comment.created_at}*`,\n ];\n if (comment.attachments?.length) {\n const summary = comment.attachments.map((a) => `#${a.id} (${a.content_type})`).join(', ');\n lines.push(`Attachments: ${summary}`);\n }\n lines.push('', comment.body);\n return lines.join('\\n');\n};\n\nexport const formatUser = (user: ZendeskUser): string =>\n [\n `## ${user.name} (${user.id})`,\n `- **Email**: ${user.email}`,\n `- **Role**: ${user.role}`,\n user.role_type != null ? `- **Role type**: ${user.role_type}` : '',\n `- **Active**: ${user.active}`,\n user.organization_id ? `- **Organization**: ${user.organization_id}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatOrganization = (org: ZendeskOrganization): string =>\n [\n `## ${org.name} (${org.id})`,\n org.details ? `- **Details**: ${org.details}` : '',\n org.domain_names.length > 0 ? `- **Domains**: ${org.domain_names.join(', ')}` : '',\n org.tags.length > 0 ? `- **Tags**: ${org.tags.join(', ')}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatArticleSummary = (article: ZendeskArticle): string =>\n [\n `## ${article.title} (${article.id})`,\n `- **Locale**: ${article.locale} | **Source locale**: ${article.source_locale}`,\n `- **Section**: ${article.section_id} | **Draft**: ${article.draft}`,\n article.label_names.length > 0 ? `- **Labels**: ${article.label_names.join(', ')}` : '',\n `- **Created**: ${article.created_at} | **Updated**: ${article.updated_at}`,\n ]\n .filter(Boolean)\n .join('\\n');\n\nexport const formatArticle = (article: ZendeskArticle): string =>\n [formatArticleSummary(article), '', article.body].join('\\n');\n\nexport const formatTranslationSummary = (translation: ZendeskTranslation): string =>\n [\n `## Translation: ${translation.locale} (${translation.id})`,\n `- **Title**: ${translation.title}`,\n `- **Draft**: ${translation.draft}`,\n `- **Updated**: ${translation.updated_at}`,\n ].join('\\n');\n\nexport const formatTranslation = (translation: ZendeskTranslation): string =>\n [formatTranslationSummary(translation), '', translation.body].join('\\n');\n\nexport const formatCategory = (category: ZendeskCategory): string =>\n `- **${category.name}** (${category.id}) — ${category.description || 'No description'}`;\n\nexport const formatSection = (section: ZendeskSection): string =>\n `- **${section.name}** (${section.id}) — Category: ${section.category_id} — ${section.description || 'No description'}`;\n\nexport const formatPermissionGroup = (group: ZendeskPermissionGroup): string =>\n `- **${group.name}** (${group.id})${group.built_in ? ' — Built-in' : ''}`;\n\nexport const formatContentTag = (tag: ZendeskContentTag): string => `- **${tag.name}** (${tag.id})`;\n\nexport const formatLabel = (label: ZendeskLabel): string => `- **${label.name}** (${label.id})`;\n\nexport const formatUserSegment = (segment: ZendeskUserSegment): string =>\n `- **${segment.name}** (${segment.id}) — ${segment.user_type}${segment.built_in ? ' — Built-in' : ''}`;\n\nexport const formatAttachment = (attachment: ZendeskArticleAttachment): string =>\n `- **${attachment.file_name}** (${attachment.id}) — ${attachment.content_type} — ${attachment.size} bytes`;\n\nexport const formatList = <T>(\n items: T[],\n formatter: (item: T) => string,\n meta?: PaginationMeta,\n): string => {\n const header = meta ? formatPagination(meta) : '';\n const body = items.map(formatter).join('\\n\\n');\n const text = [header, body].filter(Boolean).join('\\n\\n');\n return truncateIfNeeded(text);\n};\n","import type { PaginationMeta, ZendeskListResponse } from '../types';\n\n// Cursor-based pagination (for list endpoints: /tickets, /organizations, etc.)\nexport const buildCursorParams = (pageSize: number, cursor?: string): Record<string, string> => {\n const params: Record<string, string> = {\n 'page[size]': String(pageSize),\n };\n if (cursor) {\n params['page[after]'] = cursor;\n }\n return params;\n};\n\n// Offset-based pagination (for search endpoints: /search, /help_center/articles/search)\nexport const buildOffsetParams = (perPage: number, page?: number): Record<string, string> => {\n const params: Record<string, string> = {\n per_page: String(perPage),\n };\n if (page && page > 1) {\n params['page'] = String(page);\n }\n return params;\n};\n\nexport const extractPaginationMeta = <T>(response: ZendeskListResponse<T>): PaginationMeta => ({\n has_more: response.meta?.has_more ?? response.next_page != null,\n after_cursor: response.meta?.after_cursor ?? null,\n count: response.count ?? 0,\n});\n\n// For search responses — offset-based, count is always present\nexport const extractSearchPaginationMeta = <T>(\n response: ZendeskListResponse<T>,\n perPage: number,\n page: number,\n): PaginationMeta => {\n const count = response.count ?? 0;\n const has_more = count > page * perPage;\n return {\n has_more,\n after_cursor: has_more ? String(page + 1) : null,\n count,\n };\n};\n","import * as z from 'zod/v4';\nimport { zendeskGet } from '../client/zendesk-api';\nimport { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../constants';\nimport type { ZendeskListResponse } from '../types';\nimport { truncateIfNeeded } from '../utils/formatting';\nimport { buildOffsetParams, extractSearchPaginationMeta } from '../utils/pagination';\nimport type { ToolContext, ToolDefinition } from './definitions';\n\nconst formatSearchResult = (result: Record<string, unknown>): string => {\n const lines: string[] = [`## [${result['result_type']}] #${result['id']}`];\n if (result['subject']) lines.push(`**Subject**: ${result['subject']}`);\n if (result['name']) lines.push(`**Name**: ${result['name']}`);\n if (result['title']) lines.push(`**Title**: ${result['title']}`);\n if (result['email']) lines.push(`**Email**: ${result['email']}`);\n if (result['status']) lines.push(`**Status**: ${result['status']}`);\n if (result['description']) {\n const desc = String(result['description']);\n lines.push(desc.length > 200 ? `${desc.slice(0, 200)}...` : desc);\n }\n return lines.join('\\n');\n};\n\nexport const createSearchTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'search',\n namespace: 'tickets',\n readOnly: true,\n title: 'Zendesk Unified Search',\n description:\n 'Search across tickets, users, and organizations. Supports filters like \"type:ticket status:open\", \"type:user role:agent\". Returns total count and paginated results (100 per page). Organization results include name and ID only — use get_organization for full details (tags, domains, details).',\n inputSchema: z.object({\n query: z.string().min(1).describe('Zendesk search query'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page (max 100)'),\n page: z.number().int().min(1).default(1).describe('Page number (1-based)'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, per_page, page } = params as {\n query: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<Record<string, unknown>>>(\n subdomain,\n token,\n '/search',\n {\n query,\n ...buildOffsetParams(per_page, page),\n },\n );\n const results = response.results ?? [];\n const meta = extractSearchPaginationMeta(response, per_page, page);\n const header = `Total: ${meta.count} | Page ${page} (${results.length} results)${meta.has_more ? ` | Next page: ${meta.after_cursor}` : ''}`;\n const body = results.map(formatSearchResult).join('\\n\\n');\n return {\n content: [\n { type: 'text', text: truncateIfNeeded([header, body].filter(Boolean).join('\\n\\n')) },\n ],\n };\n },\n },\n ];\n};\n","import * as z from 'zod/v4';\nimport {\n fetchZendeskBinary,\n ZendeskApiError,\n zendeskGet,\n zendeskPost,\n zendeskPut,\n} from '../client/zendesk-api';\nimport {\n DEFAULT_PAGE_SIZE,\n MAX_ATTACHMENT_BYTES,\n MAX_COMMENT_PAGES,\n MAX_EMBEDDED_IMAGE_COUNT,\n MAX_PAGE_SIZE,\n} from '../constants';\nimport type {\n ZendeskComment,\n ZendeskListResponse,\n ZendeskTicket,\n ZendeskTicketAttachment,\n} from '../types';\nimport { formatComment, formatList, formatTicket, truncateIfNeeded } from '../utils/formatting';\nimport {\n buildCursorParams,\n buildOffsetParams,\n extractPaginationMeta,\n extractSearchPaginationMeta,\n} from '../utils/pagination';\nimport type { ToolContext, ToolDefinition, ToolImageContent, ToolTextContent } from './definitions';\n\nconst formatReference = (attachment: ZendeskTicketAttachment): string =>\n `**${attachment.file_name}** (id ${attachment.id}, ${attachment.content_type}, ${attachment.size} bytes) — ${attachment.content_url}`;\n\nconst buildEmbeddedImageBlocks = async (\n subdomain: string,\n token: string,\n attachment: ZendeskTicketAttachment,\n reference: string,\n): Promise<Array<ToolTextContent | ToolImageContent>> => {\n const { data, contentType } = await fetchZendeskBinary(subdomain, token, attachment.content_url);\n return [\n { type: 'image', data: data.toString('base64'), mimeType: contentType },\n { type: 'text', text: reference },\n ];\n};\n\n// Zendesk has no endpoint to list a ticket's attachments directly.\n// Attachments are always attached to comments, so the only way to collect\n// them all is to walk through every comment page and extract their attachments.\nconst fetchAllTicketComments = async (\n subdomain: string,\n token: string,\n ticketId: number,\n): Promise<ZendeskComment[]> => {\n const all: ZendeskComment[] = [];\n let cursor: string | undefined;\n let pages = 0;\n while (pages < MAX_COMMENT_PAGES) {\n const response = await zendeskGet<{\n comments: ZendeskComment[];\n meta?: { has_more: boolean; after_cursor: string };\n }>(subdomain, token, `/tickets/${ticketId}/comments`, buildCursorParams(MAX_PAGE_SIZE, cursor));\n all.push(...response.comments);\n pages += 1;\n if (!response.meta?.has_more || !response.meta?.after_cursor) break;\n cursor = response.meta.after_cursor;\n }\n return all;\n};\n\nconst collectAttachmentBlocks = async (\n subdomain: string,\n token: string,\n attachments: ZendeskTicketAttachment[],\n): Promise<Array<ToolTextContent | ToolImageContent>> => {\n const blocks: Array<ToolTextContent | ToolImageContent> = [];\n let embeddedCount = 0;\n\n for (const attachment of attachments) {\n const reference = formatReference(attachment);\n const isImage = attachment.content_type.startsWith('image/');\n\n if (!isImage) {\n blocks.push({ type: 'text', text: reference });\n continue;\n }\n\n let skipReason: string | null = null;\n if (attachment.size > MAX_ATTACHMENT_BYTES) {\n skipReason = 'skipped: exceeds 5 MB per-image limit';\n } else if (embeddedCount >= MAX_EMBEDDED_IMAGE_COUNT) {\n skipReason = `skipped: max ${MAX_EMBEDDED_IMAGE_COUNT} embedded images reached`;\n }\n\n if (skipReason) {\n blocks.push({ type: 'text', text: `${reference} — ${skipReason}` });\n continue;\n }\n\n try {\n blocks.push(...(await buildEmbeddedImageBlocks(subdomain, token, attachment, reference)));\n embeddedCount += 1;\n } catch (error) {\n const reason =\n error instanceof ZendeskApiError\n ? `download failed: ${error.status} ${error.statusText}`\n : 'download failed';\n blocks.push({ type: 'text', text: `${reference} — ${reason}` });\n }\n }\n\n return blocks;\n};\n\nexport const createTicketTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'get_ticket',\n namespace: 'tickets',\n readOnly: true,\n title: 'Get Zendesk Ticket',\n description:\n 'Retrieve a Zendesk ticket by ID, including its comments if requested. Returns ticket details (subject, status, priority, assignee, tags, description) and optionally all comments/internal notes.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n include_comments: z.boolean().default(false).describe('Include ticket comments'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, include_comments } = params as {\n ticket_id: number;\n include_comments: boolean;\n };\n const token = await getToken();\n const { ticket } = await zendeskGet<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n );\n let text = formatTicket(ticket);\n if (include_comments) {\n const { comments } = await zendeskGet<{ comments: ZendeskComment[] }>(\n subdomain,\n token,\n `/tickets/${ticket_id}/comments`,\n );\n text += `\\n\\n---\\n# Comments\\n\\n${comments.map(formatComment).join('\\n\\n')}`;\n }\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'get_ticket_attachments',\n namespace: 'tickets',\n readOnly: true,\n title: 'Get Zendesk Ticket Attachments',\n description:\n 'Retrieve ticket attachments. Images are embedded inline; other files are listed as text references.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n attachment_ids: z\n .array(z.number().int())\n .optional()\n .describe(\n 'Attachment IDs to fetch directly (e.g. extracted from a previous get_ticket(include_comments=true) call). When provided, skips the comments fetch entirely. When omitted, all attachments of the ticket are returned.',\n ),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, attachment_ids } = params as {\n ticket_id: number;\n attachment_ids?: number[];\n };\n const token = await getToken();\n\n let attachments: ZendeskTicketAttachment[];\n if (attachment_ids && attachment_ids.length > 0) {\n attachments = [];\n for (const id of attachment_ids) {\n try {\n const { attachment } = await zendeskGet<{ attachment: ZendeskTicketAttachment }>(\n subdomain,\n token,\n `/attachments/${id}`,\n );\n attachments.push(attachment);\n } catch (error) {\n if (!(error instanceof ZendeskApiError) || error.status !== 404) throw error;\n }\n }\n } else {\n const comments = await fetchAllTicketComments(subdomain, token, ticket_id);\n attachments = comments.flatMap((c) => c.attachments ?? []);\n }\n\n if (attachments.length === 0) {\n return {\n content: [{ type: 'text', text: `No attachments found on ticket #${ticket_id}.` }],\n };\n }\n const blocks = await collectAttachmentBlocks(subdomain, token, attachments);\n return {\n content: [\n {\n type: 'text',\n text: `# Attachments for ticket #${ticket_id} (${attachments.length} total)`,\n },\n ...blocks,\n ],\n };\n },\n },\n {\n name: 'search_tickets',\n namespace: 'tickets',\n readOnly: true,\n title: 'Search Zendesk Tickets',\n description:\n 'Search tickets using Zendesk query syntax (e.g., \"status:open assignee:me\", \"priority:urgent type:incident\"). Returns total count.',\n inputSchema: z.object({\n query: z.string().min(1).describe('Zendesk search query string'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page'),\n page: z.number().int().min(1).default(1).describe('Page number'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, per_page, page } = params as {\n query: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskTicket>>(\n subdomain,\n token,\n '/search',\n {\n query: `type:ticket ${query}`,\n ...buildOffsetParams(per_page, page),\n },\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.results ?? [],\n formatTicket,\n extractSearchPaginationMeta(response, per_page, page),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'create_ticket',\n namespace: 'tickets',\n readOnly: false,\n title: 'Create Zendesk Ticket',\n description:\n 'Create a new Zendesk support ticket with subject, description, and optional priority/type/assignee/tags.',\n inputSchema: z.object({\n subject: z.string().min(1).describe('Ticket subject'),\n description: z.string().min(1).describe('Ticket description'),\n priority: z.enum(['urgent', 'high', 'normal', 'low']).optional(),\n type: z.enum(['problem', 'incident', 'question', 'task']).optional(),\n assignee_id: z.number().int().optional(),\n group_id: z.number().int().optional(),\n tags: z.array(z.string()).optional(),\n custom_fields: z.array(z.object({ id: z.number().int(), value: z.unknown() })).optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { subject, description, ...rest } = params as Record<string, unknown>;\n const token = await getToken();\n const { ticket } = await zendeskPost<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n '/tickets',\n {\n ticket: { subject, comment: { body: description }, ...rest },\n },\n );\n return {\n content: [\n { type: 'text', text: `Ticket #${ticket.id} created.\\n\\n${formatTicket(ticket)}` },\n ],\n };\n },\n },\n {\n name: 'update_ticket',\n namespace: 'tickets',\n readOnly: false,\n title: 'Update Zendesk Ticket',\n description:\n 'Update an existing ticket (status, priority, type, assignee, group, subject, tags, custom fields).',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n status: z.enum(['new', 'open', 'pending', 'hold', 'solved', 'closed']).optional(),\n priority: z.enum(['urgent', 'high', 'normal', 'low']).optional(),\n type: z.enum(['problem', 'incident', 'question', 'task']).optional(),\n assignee_id: z.number().int().optional(),\n group_id: z.number().int().optional(),\n subject: z.string().optional(),\n tags: z.array(z.string()).optional(),\n custom_fields: z.array(z.object({ id: z.number().int(), value: z.unknown() })).optional(),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, ...updates } = params as { ticket_id: number } & Record<string, unknown>;\n const token = await getToken();\n const { ticket } = await zendeskPut<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n { ticket: updates },\n );\n return {\n content: [\n { type: 'text', text: `Ticket #${ticket.id} updated.\\n\\n${formatTicket(ticket)}` },\n ],\n };\n },\n },\n {\n name: 'add_private_note',\n namespace: 'tickets',\n readOnly: false,\n title: 'Add Private Note',\n description: 'Add an internal note (not visible to requester) to a ticket.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n body: z.string().min(1).describe('Note content'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, body } = params as { ticket_id: number; body: string };\n const token = await getToken();\n await zendeskPut(subdomain, token, `/tickets/${ticket_id}`, {\n ticket: { comment: { body, public: false } },\n });\n return { content: [{ type: 'text', text: `Private note added to ticket #${ticket_id}.` }] };\n },\n },\n {\n name: 'add_public_comment',\n namespace: 'tickets',\n readOnly: false,\n title: 'Add Public Comment',\n description: 'Add a public comment (visible to requester) to a ticket.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n body: z.string().min(1).describe('Comment content'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: false,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, body } = params as { ticket_id: number; body: string };\n const token = await getToken();\n await zendeskPut(subdomain, token, `/tickets/${ticket_id}`, {\n ticket: { comment: { body, public: true } },\n });\n return {\n content: [{ type: 'text', text: `Public comment added to ticket #${ticket_id}.` }],\n };\n },\n },\n {\n name: 'list_tickets',\n namespace: 'tickets',\n readOnly: true,\n title: 'List Zendesk Tickets',\n description: 'List tickets with cursor-based pagination, sorted by most recently updated.',\n inputSchema: z.object({\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional().describe('Pagination cursor'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { page_size, cursor } = params as { page_size: number; cursor?: string };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskTicket>>(\n subdomain,\n token,\n '/tickets',\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.tickets ?? [],\n formatTicket,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'get_linked_incidents',\n namespace: 'tickets',\n readOnly: true,\n title: 'Get Linked Incidents',\n description: 'Get all incident tickets linked to a problem ticket.',\n inputSchema: z.object({\n problem_id: z.number().int().describe('Problem ticket ID'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { problem_id } = params as { problem_id: number };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskTicket>>(\n subdomain,\n token,\n `/tickets/${problem_id}/incidents`,\n );\n const incidents = response.tickets ?? [];\n const text =\n incidents.length > 0\n ? `# Incidents linked to problem #${problem_id}\\n\\n${incidents.map(formatTicket).join('\\n\\n')}`\n : `No incidents linked to problem #${problem_id}.`;\n return { content: [{ type: 'text', text: truncateIfNeeded(text) }] };\n },\n },\n {\n name: 'manage_tags',\n namespace: 'tickets',\n readOnly: false,\n title: 'Manage Ticket Tags',\n description: 'Add or remove tags on a ticket.',\n inputSchema: z.object({\n ticket_id: z.number().int().describe('Ticket ID'),\n add: z.array(z.string()).optional().describe('Tags to add'),\n remove: z.array(z.string()).optional().describe('Tags to remove'),\n }),\n annotations: {\n readOnlyHint: false,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { ticket_id, add, remove } = params as {\n ticket_id: number;\n add?: string[];\n remove?: string[];\n };\n const token = await getToken();\n const { ticket } = await zendeskGet<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n );\n const tags = new Set(ticket.tags);\n add?.forEach((t) => {\n tags.add(t);\n });\n remove?.forEach((t) => {\n tags.delete(t);\n });\n const { ticket: updated } = await zendeskPut<{ ticket: ZendeskTicket }>(\n subdomain,\n token,\n `/tickets/${ticket_id}`,\n { ticket: { tags: [...tags] } },\n );\n return {\n content: [\n {\n type: 'text',\n text: `Tags updated on ticket #${ticket_id}. Current: ${updated.tags.join(', ') || 'none'}`,\n },\n ],\n };\n },\n },\n ];\n};\n","import * as z from 'zod/v4';\nimport { zendeskGet } from '../client/zendesk-api';\nimport { DEFAULT_PAGE_SIZE, MAX_PAGE_SIZE } from '../constants';\nimport type { ZendeskListResponse, ZendeskOrganization, ZendeskUser } from '../types';\nimport { formatList, formatOrganization, formatUser } from '../utils/formatting';\nimport {\n buildCursorParams,\n buildOffsetParams,\n extractPaginationMeta,\n extractSearchPaginationMeta,\n} from '../utils/pagination';\nimport type { ToolContext, ToolDefinition } from './definitions';\n\nexport const createUserTools = (ctx: ToolContext): ToolDefinition[] => {\n const { subdomain, getToken } = ctx;\n\n return [\n {\n name: 'get_current_user',\n namespace: 'users',\n readOnly: true,\n title: 'Get Current Zendesk User',\n description:\n 'Get the currently authenticated Zendesk user. Useful to verify identity and permissions.',\n inputSchema: z.object({}),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async () => {\n const token = await getToken();\n const { user } = await zendeskGet<{ user: ZendeskUser }>(subdomain, token, '/users/me');\n return { content: [{ type: 'text', text: formatUser(user) }] };\n },\n },\n {\n name: 'search_users',\n namespace: 'users',\n readOnly: true,\n title: 'Search Zendesk Users',\n description:\n 'Search for users by name, email, or other criteria using Zendesk search query syntax. Returns total count.',\n inputSchema: z.object({\n query: z.string().min(1).describe('Search query'),\n per_page: z\n .number()\n .int()\n .min(1)\n .max(MAX_PAGE_SIZE)\n .default(DEFAULT_PAGE_SIZE)\n .describe('Results per page'),\n page: z.number().int().min(1).default(1).describe('Page number'),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { query, per_page, page } = params as {\n query: string;\n per_page: number;\n page: number;\n };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskUser>>(\n subdomain,\n token,\n '/search',\n {\n query: `type:user ${query}`,\n ...buildOffsetParams(per_page, page),\n },\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.results ?? [],\n formatUser,\n extractSearchPaginationMeta(response, per_page, page),\n ),\n },\n ],\n };\n },\n },\n {\n name: 'get_user',\n namespace: 'users',\n readOnly: true,\n title: 'Get Zendesk User',\n description: 'Retrieve a user by ID.',\n inputSchema: z.object({ user_id: z.number().int().describe('User ID') }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { user_id } = params as { user_id: number };\n const token = await getToken();\n const { user } = await zendeskGet<{ user: ZendeskUser }>(\n subdomain,\n token,\n `/users/${user_id}`,\n );\n return { content: [{ type: 'text', text: formatUser(user) }] };\n },\n },\n {\n name: 'get_organization',\n namespace: 'users',\n readOnly: true,\n title: 'Get Zendesk Organization',\n description: 'Retrieve an organization by ID.',\n inputSchema: z.object({ organization_id: z.number().int().describe('Organization ID') }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { organization_id } = params as { organization_id: number };\n const token = await getToken();\n const { organization } = await zendeskGet<{ organization: ZendeskOrganization }>(\n subdomain,\n token,\n `/organizations/${organization_id}`,\n );\n return { content: [{ type: 'text', text: formatOrganization(organization) }] };\n },\n },\n {\n name: 'list_organizations',\n namespace: 'users',\n readOnly: true,\n title: 'List Zendesk Organizations',\n description: 'List all organizations with pagination.',\n inputSchema: z.object({\n page_size: z.number().int().min(1).max(MAX_PAGE_SIZE).default(DEFAULT_PAGE_SIZE),\n cursor: z.string().optional(),\n }),\n annotations: {\n readOnlyHint: true,\n destructiveHint: false,\n idempotentHint: true,\n openWorldHint: true,\n },\n handler: async (params) => {\n const { page_size, cursor } = params as { page_size: number; cursor?: string };\n const token = await getToken();\n const response = await zendeskGet<ZendeskListResponse<ZendeskOrganization>>(\n subdomain,\n token,\n '/organizations',\n buildCursorParams(page_size, cursor),\n );\n return {\n content: [\n {\n type: 'text',\n text: formatList(\n response.organizations ?? [],\n formatOrganization,\n extractPaginationMeta(response),\n ),\n },\n ],\n };\n },\n },\n ];\n};\n","import type { ToolContext, ToolDefinition } from './definitions';\nimport { createHelpCenterTools } from './help-center';\nimport { createSearchTools } from './search';\nimport { createTicketTools } from './tickets';\nimport { createUserTools } from './users';\n\nexport type { ToolContext, ToolDefinition } from './definitions';\n\nexport const createAllTools = (ctx: ToolContext): ToolDefinition[] => [\n ...createTicketTools(ctx),\n ...createSearchTools(ctx),\n ...createHelpCenterTools(ctx),\n ...createUserTools(ctx),\n];\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\n\nexport const startStdioTransport = async (server: McpServer): Promise<void> => {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('Zendesk MCP server running via stdio');\n};\n","import { buildBasicAuthHeader } from './auth/api-token';\nimport { createTokenStore } from './auth/token-store';\nimport { loadConfig } from './config';\nimport { createMcpServer } from './server';\nimport { startStdioTransport } from './transports/stdio';\n\nconst main = async (): Promise<void> => {\n const config = loadConfig();\n\n if (config.zendeskEmail && config.zendeskApiToken) {\n // API token mode — static Basic auth\n const staticToken = buildBasicAuthHeader(config.zendeskEmail, config.zendeskApiToken);\n const getToken = () => staticToken;\n const server = createMcpServer(config, getToken);\n await startStdioTransport(server);\n } else {\n // OAuth mode — browser-based auth on first tool call\n const tokenStore = createTokenStore({\n subdomain: config.subdomain,\n oauthClientId: config.oauthClientId,\n });\n const server = createMcpServer(config, tokenStore.getToken);\n await startStdioTransport(server);\n }\n};\n\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n"],"mappings":"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","names":["z","z","record","z","z","z"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fruggr/zendesk-mcp-server",
3
- "version": "1.0.0",
3
+ "version": "1.1.2",
4
4
  "description": "MCP server for Zendesk Support & Help Center APIs with OAuth 2.1 PKCE",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -47,7 +47,7 @@
47
47
  "engines": {
48
48
  "node": ">=20"
49
49
  },
50
- "packageManager": "pnpm@10.32.1",
50
+ "packageManager": "pnpm@10.33.4+sha512.1c67b3b359b2d408119ba1ed289f34b8fc3c6873412bec6fd264fbdc82489e510fcbecb9ce9d22dae7f3b76269d8441046014bdca53b9979cd7a561ad631b800",
51
51
  "dependencies": {
52
52
  "@modelcontextprotocol/sdk": "1.29.0",
53
53
  "cheerio": "1.2.0",
@@ -65,6 +65,11 @@
65
65
  "unified": "11.0.5",
66
66
  "zod": "4.3.6"
67
67
  },
68
+ "pnpm": {
69
+ "overrides": {
70
+ "ip-address": "^10.2.0"
71
+ }
72
+ },
68
73
  "devDependencies": {
69
74
  "@biomejs/biome": "^2.4.7",
70
75
  "@semantic-release/changelog": "^6.0.3",
@@ -79,7 +84,7 @@
79
84
  "conventional-changelog-conventionalcommits": "^9.3.1",
80
85
  "msw": "^2.12.13",
81
86
  "semantic-release": "^25.0.3",
82
- "shx": "^0.3.4",
87
+ "shx": "^0.4.0",
83
88
  "tsup": "^8.5.1",
84
89
  "tsx": "^4.21.0",
85
90
  "typescript": "^5.9.3",