@fruggr/zendesk-mcp-server 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Digital4Better
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,341 @@
1
+ # Zendesk MCP Server
2
+
3
+ [![npm](https://img.shields.io/npm/v/@fruggr/zendesk-mcp-server)](https://www.npmjs.com/package/@fruggr/zendesk-mcp-server)
4
+
5
+ A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that connects LLMs to the **Zendesk Support & Help Center APIs** — with per-user OAuth 2.1 PKCE authentication and fine-grained tool visibility controls.
6
+
7
+ ## Why this server?
8
+
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
+
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.
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
+ - **Read-only mode** — Restrict the server to read operations only, ideal for assistants that should never modify data.
15
+ - **Zero runtime dependencies beyond the MCP SDK** — Built on `@modelcontextprotocol/sdk` and `zod`. No Express, no heavyweight frameworks.
16
+
17
+ > Built and maintained by [Digital4better](https://digital4better.com) for the [Fruggr](https://www.fruggr.io) project.
18
+
19
+ ## Tool modes
20
+
21
+ The server registers tools in one of three modes, controlled by `--mode`:
22
+
23
+ | Mode | Tools exposed | Best for |
24
+ |------|--------------|----------|
25
+ | **`all`** | 36 individual tools (`get_ticket`, `search_articles`, ...) | Clients with good tool selection, full granularity |
26
+ | **`namespace`** (default) | 3 proxy tools (`zendesk_tickets`, `zendesk_help_center`, `zendesk_users`) | Balanced context usage, grouped operations |
27
+ | **`single`** | 1 proxy tool (`zendesk`) | Minimal context footprint, single entry point |
28
+
29
+ In `namespace` and `single` modes, the proxy tool accepts `{ "operation": "<tool_name>", "params": { ... } }` and dispatches to the appropriate handler after validating params through the original Zod schema. Proxy descriptions include only the first sentence of each sub-operation to stay compact; the full schema is applied when the operation is actually called.
30
+
31
+ > **Tip:** The `single` mode is particularly useful for models with limited tool slots — one tool handles all 36 operations.
32
+
33
+ ### Scoping the surface
34
+
35
+ `--namespace` and `--read-only` apply to every mode (including the default `namespace` mode) — they filter tools **before** the proxies are built, so the description of each proxy reflects only the operations that survive the filters. Combine them to register a focused surface:
36
+
37
+ ```bash
38
+ # Only the Help Center proxy, only read-only operations
39
+ zendesk-mcp-server acme --namespace help_center --read-only
40
+
41
+ # Only the Tickets proxy (read + write)
42
+ zendesk-mcp-server acme --namespace tickets
43
+ ```
44
+
45
+ `--namespace` is repeatable. `--tool` is also available for cherry-picking individual operations but forces `--mode all`.
46
+
47
+ ## Available tools
48
+
49
+ <details>
50
+ <summary><strong>Tickets</strong> (9 tools)</summary>
51
+
52
+ | Tool | Description | Mode |
53
+ |------|-------------|------|
54
+ | `get_ticket` | Retrieve a ticket by ID with optional comments | read |
55
+ | `search_tickets` | Search tickets using Zendesk query syntax | read |
56
+ | `list_tickets` | List tickets with cursor-based pagination | read |
57
+ | `get_linked_incidents` | Get incidents linked to a problem ticket | read |
58
+ | `create_ticket` | Create a new ticket with subject, description, priority, tags... | write |
59
+ | `update_ticket` | Update ticket status, priority, assignee, tags, custom fields | write |
60
+ | `add_private_note` | Add an internal note (not visible to requester) | write |
61
+ | `add_public_comment` | Add a public comment (visible to requester) | write |
62
+ | `manage_tags` | Add or remove tags on a ticket | write |
63
+
64
+ </details>
65
+
66
+ <details>
67
+ <summary><strong>Help Center</strong> (21 tools)</summary>
68
+
69
+ | Tool | Description | Mode |
70
+ |------|-------------|------|
71
+ | `search_articles` | Full-text search across Help Center articles | read |
72
+ | `get_article` | Retrieve article by ID with full HTML body | read |
73
+ | `get_article_outline` | Compact outline of an article (sections + available translations) | read |
74
+ | `get_article_section` | Retrieve a single section (html or markdown) | read |
75
+ | `list_categories` | List all Help Center categories | read |
76
+ | `list_sections` | List sections, optionally filtered by category | read |
77
+ | `list_articles` | List articles with sorting and translation info | read |
78
+ | `list_article_translations` | List available translations for an article | read |
79
+ | `list_article_attachments` | List attachments on an article | read |
80
+ | `list_permission_groups` | List Guide permission groups (needed to create articles) | read |
81
+ | `list_content_tags` | List Guide content tags (end-user visible) | read |
82
+ | `list_labels` | List article labels (search ranking, not user-visible) | read |
83
+ | `list_user_segments` | List user segments (article visibility) | read |
84
+ | `compare_translations` | Section-level diff between two locales of an article | read |
85
+ | `create_article` | Create a new article in a section | write |
86
+ | `update_article` | Update article metadata (draft, labels, tags, visibility, section) | write |
87
+ | `create_article_translation` | Create a translation for an article | write |
88
+ | `update_article_translation` | Update an article's translation (full body) | write |
89
+ | `update_article_section` | Replace a single section of an article | write |
90
+ | `create_content_tag` | Create a new Guide content tag | write |
91
+ | `create_article_attachment` | Upload an attachment to an article | write |
92
+
93
+ </details>
94
+
95
+ <details>
96
+ <summary><strong>Users & Organizations</strong> (5 tools)</summary>
97
+
98
+ | Tool | Description | Mode |
99
+ |------|-------------|------|
100
+ | `get_current_user` | Get the authenticated user (verify identity) | read |
101
+ | `search_users` | Search users by name, email, or query syntax | read |
102
+ | `get_user` | Retrieve a user by ID | read |
103
+ | `get_organization` | Retrieve an organization by ID | read |
104
+ | `list_organizations` | List all organizations with pagination | read |
105
+
106
+ </details>
107
+
108
+ <details>
109
+ <summary><strong>Search</strong> (1 tool)</summary>
110
+
111
+ | Tool | Description | Mode |
112
+ |------|-------------|------|
113
+ | `search` | Unified search across tickets, users, and organizations | read |
114
+
115
+ </details>
116
+
117
+ ## Prerequisites
118
+
119
+ - **Node.js** >= 20
120
+ - A **Zendesk** instance (Support or Suite)
121
+
122
+ ## Installation
123
+
124
+ ```bash
125
+ # Run without installing
126
+ npx -y @fruggr/zendesk-mcp-server <your-subdomain>
127
+ ```
128
+
129
+ Or install globally:
130
+
131
+ ```bash
132
+ npm install -g @fruggr/zendesk-mcp-server
133
+ zendesk-mcp-server <your-subdomain>
134
+ ```
135
+
136
+ Or clone and run locally:
137
+
138
+ ```bash
139
+ git clone https://github.com/fruggr/zendesk-mcp-server.git
140
+ cd zendesk-mcp-server
141
+ pnpm install
142
+ pnpm build
143
+ node dist/index.js <your-subdomain>
144
+ ```
145
+
146
+ ## Authentication
147
+
148
+ The server supports two authentication methods:
149
+
150
+ ### Option A: OAuth 2.1 PKCE (recommended)
151
+
152
+ No API key needed. Each user authenticates via their browser on the first tool call.
153
+
154
+ **Zendesk setup:**
155
+
156
+ 1. Go to **Admin Center > Apps and integrations > APIs > OAuth Clients**
157
+ 2. Create a public client:
158
+ - **Identifier**: `<your-subdomain>_zendesk` (or set `ZENDESK_OAUTH_CLIENT_ID`)
159
+ - **Redirect URL**: `http://localhost:3000/callback`
160
+
161
+ **Run:**
162
+
163
+ ```bash
164
+ zendesk-mcp-server <your-subdomain>
165
+ ```
166
+
167
+ On the first tool call, a browser window opens for the user to authenticate. The token is cached in memory for the session.
168
+
169
+ ### Option B: API token
170
+
171
+ For headless/CI environments or quick testing.
172
+
173
+ **Zendesk setup:**
174
+
175
+ 1. Go to **Admin Center > Apps and integrations > APIs > Zendesk API**
176
+ 2. Enable **Token Access**, create a token
177
+
178
+ **Run:**
179
+
180
+ ```bash
181
+ ZENDESK_EMAIL=you@example.com ZENDESK_API_TOKEN=dneib123... \
182
+ zendesk-mcp-server <your-subdomain>
183
+ ```
184
+
185
+ ## Configuration
186
+
187
+ ### MCP client configuration
188
+
189
+ <details>
190
+ <summary><strong>Claude Desktop</strong></summary>
191
+
192
+ Add to your `claude_desktop_config.json`:
193
+
194
+ ```json
195
+ {
196
+ "mcpServers": {
197
+ "zendesk": {
198
+ "command": "npx",
199
+ "args": ["-y", "@fruggr/zendesk-mcp-server", "<your-subdomain>", "--mode", "single"],
200
+ "env": {
201
+ "ZENDESK_EMAIL": "you@example.com",
202
+ "ZENDESK_API_TOKEN": "your-api-token"
203
+ }
204
+ }
205
+ }
206
+ }
207
+ ```
208
+
209
+ </details>
210
+
211
+ <details>
212
+ <summary><strong>Claude Code</strong></summary>
213
+
214
+ ```bash
215
+ claude mcp add zendesk -- npx -y @fruggr/zendesk-mcp-server <your-subdomain> --mode single
216
+ ```
217
+
218
+ For API token auth, set the env vars before launching Claude Code or add them to your shell profile.
219
+
220
+ </details>
221
+
222
+ <details>
223
+ <summary><strong>VS Code (Copilot / Continue / Cline)</strong></summary>
224
+
225
+ Add to your `.vscode/mcp.json`:
226
+
227
+ ```json
228
+ {
229
+ "servers": {
230
+ "zendesk": {
231
+ "command": "npx",
232
+ "args": ["-y", "@fruggr/zendesk-mcp-server", "<your-subdomain>", "--mode", "single"],
233
+ "env": {
234
+ "ZENDESK_EMAIL": "you@example.com",
235
+ "ZENDESK_API_TOKEN": "your-api-token"
236
+ }
237
+ }
238
+ }
239
+ }
240
+ ```
241
+
242
+ </details>
243
+
244
+ ### CLI reference
245
+
246
+ ```
247
+ zendesk-mcp-server <subdomain> [options]
248
+
249
+ Options:
250
+ --mode <mode> single | namespace (default) | all
251
+ --namespace <ns> Filter by namespace (repeatable): tickets, help_center, users
252
+ --tool <name> Filter by tool name (repeatable, forces --mode all)
253
+ --read-only Only expose read operations
254
+ --log-level <level> debug | info (default) | warn | error
255
+ ```
256
+
257
+ `--namespace` and `--read-only` are applied before the proxies are registered, so they narrow the surface in every mode — in the default `namespace` mode, `--namespace help_center` registers a single proxy (`zendesk_help_center`) instead of three.
258
+
259
+ **Examples:**
260
+
261
+ ```bash
262
+ # Single tool mode — minimal context, all 36 operations in one tool
263
+ zendesk-mcp-server acme --mode single
264
+
265
+ # Read-only tickets only
266
+ zendesk-mcp-server acme --read-only --namespace tickets
267
+
268
+ # Cherry-pick specific tools
269
+ zendesk-mcp-server acme --tool get_ticket --tool search_tickets --tool get_current_user
270
+ ```
271
+
272
+ ### Environment variables
273
+
274
+ | Variable | Required | Default | Description |
275
+ |----------|----------|---------|-------------|
276
+ | `ZENDESK_SUBDOMAIN` | yes (or CLI arg) | — | Zendesk subdomain (e.g., `acme` for acme.zendesk.com) |
277
+ | `ZENDESK_OAUTH_CLIENT_ID` | no | `<subdomain>_zendesk` | OAuth client identifier |
278
+ | `ZENDESK_EMAIL` | for API token auth | — | Agent email for Basic auth |
279
+ | `ZENDESK_API_TOKEN` | for API token auth | — | Zendesk API token |
280
+ | `LOG_LEVEL` | no | `info` | Log verbosity |
281
+
282
+ If both `ZENDESK_EMAIL` and `ZENDESK_API_TOKEN` are set, the server uses API token auth. Otherwise, it uses OAuth 2.1 PKCE.
283
+
284
+ ## Development
285
+
286
+ ```bash
287
+ # Install dependencies
288
+ pnpm install
289
+
290
+ # Dev mode (auto-reload)
291
+ ZENDESK_EMAIL=you@example.com ZENDESK_API_TOKEN=xxx \
292
+ pnpm dev -- <your-subdomain> --mode all
293
+
294
+ # Build
295
+ pnpm build
296
+
297
+ # Type-check
298
+ pnpm typecheck
299
+
300
+ # Lint
301
+ pnpm check
302
+
303
+ # Tests
304
+ pnpm test
305
+ ```
306
+
307
+ ## Inspiration & related projects
308
+
309
+ This project was built with reference to:
310
+ - The official [Zendesk API documentation](https://developer.zendesk.com/api-reference/)
311
+ - [mattcoatsworth/zendesk-mcp-server](https://github.com/mattcoatsworth/zendesk-mcp-server)
312
+ - [koundinya/zd-mcp-server](https://github.com/koundinya/zd-mcp-server)
313
+
314
+ ## Releases & versioning
315
+
316
+ Versions follow [SemVer](https://semver.org/) and are calculated **automatically** from commit messages — no one bumps the version by hand. Every merge to `main` triggers [semantic-release](https://github.com/semantic-release/semantic-release), which inspects the new [Conventional Commits](https://www.conventionalcommits.org/) since the previous tag, computes the next version, updates [`CHANGELOG.md`](CHANGELOG.md), publishes to npm, and creates the matching GitHub Release.
317
+
318
+ | Commit type | Resulting bump |
319
+ |---|---|
320
+ | `fix:`, `perf:` | patch |
321
+ | `feat:` | minor |
322
+ | `feat!:`, `fix!:`, or a `BREAKING CHANGE:` footer | major |
323
+ | `docs:`, `chore:`, `refactor:`, `test:`, `ci:`, `style:`, `build:` | no release |
324
+
325
+ ## Contributing
326
+
327
+ Pull requests are welcome! Whether you write code by hand or with the help of AI, contributions are appreciated.
328
+
329
+ If you'd like to contribute:
330
+
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
336
+
337
+ Please ensure `pnpm check` and `pnpm test` pass before submitting.
338
+
339
+ ## License
340
+
341
+ [MIT](LICENSE)
@@ -0,0 +1,2 @@
1
+
2
+ export { }