@fruggr/zendesk-mcp-server 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +218 -91
- package/dist/index.js +435 -33
- package/dist/index.js.map +1 -1
- package/glama.json +4 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -7,17 +7,18 @@
|
|
|
7
7
|
[](https://renovatebot.com)
|
|
8
8
|
[](https://github.com/semantic-release/semantic-release)
|
|
9
9
|
|
|
10
|
-
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.
|
|
10
|
+
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. Runs locally over **stdio** or as a private **remote MCP server** over HTTP.
|
|
11
11
|
|
|
12
12
|
## Why this server?
|
|
13
13
|
|
|
14
14
|
Most Zendesk integrations use a shared admin API key, giving every user full access to every ticket. This server takes a different approach:
|
|
15
15
|
|
|
16
|
-
- **Per-user authentication** —
|
|
16
|
+
- **Per-user authentication by default** — In both transports, the default is OAuth 2.1 PKCE: each user authenticates with their own Zendesk credentials, so the LLM sees exactly what the user is allowed to see. A static API-token escape hatch is documented below for stdio-only CI / headless contexts; it's refused at boot in HTTP mode.
|
|
17
|
+
- **Two deployment shapes, same auth story** — Run it on your laptop as a stdio MCP server (Claude Desktop / Claude Code / VS Code) or deploy it as a private remote MCP server with one user, one Zendesk session per HTTP request.
|
|
17
18
|
- **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.
|
|
18
19
|
- **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.
|
|
19
20
|
- **Read-only mode** — Restrict the server to read operations only, ideal for assistants that should never modify data.
|
|
20
|
-
- **
|
|
21
|
+
- **Lean stack** — Built on the official `@modelcontextprotocol/sdk` plus `zod`.
|
|
21
22
|
|
|
22
23
|
> Built and maintained by [Digital4better](https://digital4better.com) for the [Fruggr](https://www.fruggr.io) project.
|
|
23
24
|
|
|
@@ -28,13 +29,19 @@ Most Zendesk integrations use a shared admin API key, giving every user full acc
|
|
|
28
29
|
- You want an LLM to read or triage **Zendesk tickets** and **Help Center articles** on behalf of a real user, with that user's own permissions — not a shared admin key.
|
|
29
30
|
- You're editing **large Help Center articles** and want section-scoped reads/rewrites instead of round-tripping the full HTML body through the model.
|
|
30
31
|
- You need to **cap the tool surface** — read-only assistants, a single namespace, or one unified tool to fit a tight context budget.
|
|
31
|
-
- You run a **stdio MCP client** (Claude Desktop, Claude Code, Cursor, VS Code, Cline, …) and want a `npx`-installable server with no extra infrastructure.
|
|
32
|
+
- You run a **stdio MCP client** (Claude Desktop, Claude Code, Cursor, VS Code, Cline, …) and want a `npx`-installable server with no extra infrastructure, **or** you want to **deploy it as a private remote MCP server** that web/native clients reach over HTTP — each MCP client still carries its own user's OAuth token.
|
|
32
33
|
|
|
33
34
|
**Look elsewhere when:**
|
|
34
35
|
|
|
35
36
|
- You need Zendesk products outside Support & Guide (e.g. Talk, Explore analytics, Sell) — those endpoints aren't covered.
|
|
36
|
-
- You
|
|
37
|
-
|
|
37
|
+
- You need a single shared service account for all users — that's the opposite of this server's per-user OAuth model (the API-token escape hatch exists for stdio CI only, and is refused at boot in HTTP).
|
|
38
|
+
|
|
39
|
+
## Use cases
|
|
40
|
+
|
|
41
|
+
| Persona | Transport | Auth | Quick start |
|
|
42
|
+
|---------|-----------|------|-------------|
|
|
43
|
+
| **Run it on your laptop** — single user, plugged into Claude Desktop / Claude Code / VS Code | `stdio` (default) | OAuth 2.1 PKCE in your browser (or API token for CI) | [Quick start: local](#quick-start-local-stdio) |
|
|
44
|
+
| **Deploy a private remote MCP server** — one server per Zendesk account, each MCP client carries its own user's OAuth token | `http` | Per-user OAuth 2.1 PKCE bearer in `Authorization:` header; API token refused | [Quick start: remote](#quick-start-remote-http) |
|
|
38
45
|
|
|
39
46
|
## Tool modes
|
|
40
47
|
|
|
@@ -143,58 +150,33 @@ zendesk-mcp-server acme --namespace tickets
|
|
|
143
150
|
> Contributors and maintainers run the toolchain on a newer Node + pnpm —
|
|
144
151
|
> see [Development](#development).
|
|
145
152
|
|
|
146
|
-
##
|
|
153
|
+
## Quick start: local (stdio)
|
|
154
|
+
|
|
155
|
+
The default mode. One developer, one Zendesk account, OAuth 2.1 PKCE in the browser.
|
|
156
|
+
|
|
157
|
+
### Install
|
|
147
158
|
|
|
148
159
|
```bash
|
|
149
160
|
# Run without installing
|
|
150
161
|
npx -y @fruggr/zendesk-mcp-server <your-subdomain>
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Or install globally:
|
|
154
162
|
|
|
155
|
-
|
|
163
|
+
# Or install globally
|
|
156
164
|
npm install -g @fruggr/zendesk-mcp-server
|
|
157
165
|
zendesk-mcp-server <your-subdomain>
|
|
158
166
|
```
|
|
159
167
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
git clone https://github.com/fruggr/zendesk-mcp-server.git
|
|
164
|
-
cd zendesk-mcp-server
|
|
165
|
-
pnpm install
|
|
166
|
-
pnpm build
|
|
167
|
-
node dist/index.js <your-subdomain>
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
Or run a development branch directly from GitHub (handy for testing PRs without publishing to npm) — the `prepare` script builds the package automatically on install:
|
|
171
|
-
|
|
172
|
-
```bash
|
|
173
|
-
# Latest main
|
|
174
|
-
npx -y github:fruggr/zendesk-mcp-server <your-subdomain>
|
|
175
|
-
|
|
176
|
-
# A specific branch / tag / commit
|
|
177
|
-
npx -y github:fruggr/zendesk-mcp-server#my-feature-branch <your-subdomain>
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
## Authentication
|
|
168
|
+
> Cloning from source and running a development branch is covered in the [Development](#development) section.
|
|
181
169
|
|
|
182
|
-
|
|
170
|
+
### Zendesk OAuth setup
|
|
183
171
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
No API key needed. Each user authenticates via their browser on the first tool call.
|
|
187
|
-
|
|
188
|
-
**Zendesk setup:**
|
|
189
|
-
|
|
190
|
-
1. Go to **Admin Center > Apps and integrations > APIs > OAuth Clients**
|
|
191
|
-
2. Create a public client:
|
|
172
|
+
1. Go to **Admin Center → Apps and integrations → APIs → OAuth Clients**
|
|
173
|
+
2. Create a **public** client:
|
|
192
174
|
- **Identifier**: `<your-subdomain>_zendesk` (or set `ZENDESK_OAUTH_CLIENT_ID`)
|
|
193
175
|
- **Redirect URL**: `http://localhost:27439/callback` (change the port to match
|
|
194
176
|
`ZENDESK_OAUTH_CALLBACK_PORT` / `--callback-port` if you override it; Zendesk
|
|
195
177
|
accepts several redirect URLs, one per line)
|
|
196
178
|
|
|
197
|
-
|
|
179
|
+
### Run
|
|
198
180
|
|
|
199
181
|
```bash
|
|
200
182
|
zendesk-mcp-server <your-subdomain>
|
|
@@ -220,41 +202,48 @@ browser sign-in.
|
|
|
220
202
|
> `--callback-port`) to a free port — remember to register the matching
|
|
221
203
|
> `http://localhost:<port>/callback` redirect URL in your Zendesk OAuth client.
|
|
222
204
|
|
|
223
|
-
|
|
205
|
+
> **API token escape hatch (stdio only).** For headless/CI environments where a browser is unavailable, set `ZENDESK_EMAIL` + `ZENDESK_API_TOKEN` (generate the token in **Admin Center → Apps and integrations → APIs → Zendesk API → Token Access**). The MCP server then uses Basic auth instead of starting the OAuth flow. This mode is **refused at boot in HTTP** because a shared static credential would expose every caller to the issuing user's rights.
|
|
224
206
|
|
|
225
|
-
|
|
207
|
+
### MCP client wiring
|
|
226
208
|
|
|
227
|
-
|
|
209
|
+
<details>
|
|
210
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
228
211
|
|
|
229
|
-
|
|
230
|
-
2. Enable **Token Access**, create a token
|
|
212
|
+
Add to your `claude_desktop_config.json`:
|
|
231
213
|
|
|
232
|
-
|
|
214
|
+
```json
|
|
215
|
+
{
|
|
216
|
+
"mcpServers": {
|
|
217
|
+
"zendesk": {
|
|
218
|
+
"command": "npx",
|
|
219
|
+
"args": ["-y", "@fruggr/zendesk-mcp-server", "<your-subdomain>", "--mode", "single"]
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
</details>
|
|
226
|
+
|
|
227
|
+
<details>
|
|
228
|
+
<summary><strong>Claude Code</strong></summary>
|
|
233
229
|
|
|
234
230
|
```bash
|
|
235
|
-
|
|
236
|
-
zendesk-mcp-server <your-subdomain>
|
|
231
|
+
claude mcp add zendesk -- npx -y @fruggr/zendesk-mcp-server <your-subdomain> --mode single
|
|
237
232
|
```
|
|
238
233
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
### MCP client configuration
|
|
234
|
+
</details>
|
|
242
235
|
|
|
243
236
|
<details>
|
|
244
|
-
<summary><strong>
|
|
237
|
+
<summary><strong>VS Code (Copilot / Continue / Cline)</strong></summary>
|
|
245
238
|
|
|
246
|
-
Add to your
|
|
239
|
+
Add to your `.vscode/mcp.json`:
|
|
247
240
|
|
|
248
241
|
```json
|
|
249
242
|
{
|
|
250
|
-
"
|
|
243
|
+
"servers": {
|
|
251
244
|
"zendesk": {
|
|
252
245
|
"command": "npx",
|
|
253
|
-
"args": ["-y", "@fruggr/zendesk-mcp-server", "<your-subdomain>", "--mode", "single"]
|
|
254
|
-
"env": {
|
|
255
|
-
"ZENDESK_EMAIL": "you@example.com",
|
|
256
|
-
"ZENDESK_API_TOKEN": "your-api-token"
|
|
257
|
-
}
|
|
246
|
+
"args": ["-y", "@fruggr/zendesk-mcp-server", "<your-subdomain>", "--mode", "single"]
|
|
258
247
|
}
|
|
259
248
|
}
|
|
260
249
|
}
|
|
@@ -262,32 +251,123 @@ Add to your `claude_desktop_config.json`:
|
|
|
262
251
|
|
|
263
252
|
</details>
|
|
264
253
|
|
|
254
|
+
## Quick start: remote (HTTP)
|
|
255
|
+
|
|
256
|
+
> 🧪 **Experimental.** The HTTP transport is shipped but has not yet been
|
|
257
|
+
> exercised end-to-end against a real Zendesk tenant from every supported
|
|
258
|
+
> MCP client. Local stdio is the supported path. Until this notice is
|
|
259
|
+
> removed, expect rough edges around OAuth discovery behind reverse
|
|
260
|
+
> proxies, CORS with browser clients, and 401 / refresh flows — please
|
|
261
|
+
> open an issue with the symptoms you hit.
|
|
262
|
+
|
|
263
|
+
Deploy a private MCP server for **one** Zendesk account. Every MCP client connecting to the server presents its **own** user's OAuth bearer in `Authorization:` — the server never sees a shared admin key.
|
|
264
|
+
|
|
265
|
+
### Zendesk OAuth setup
|
|
266
|
+
|
|
267
|
+
Same procedure as the [local quick start](#zendesk-oauth-setup), with one difference: the **Redirect URL** must match the callback your MCP client uses — provided by the client itself, e.g. `https://claude.ai/oauth/callback` for claude.ai on the web. Check your client's docs.
|
|
268
|
+
|
|
269
|
+
### Run the server
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
zendesk-mcp-server <your-subdomain> --transport http --port 3000 \
|
|
273
|
+
--public-url https://mcp.example.com
|
|
274
|
+
# stderr: Zendesk MCP server running via http on 0.0.0.0:3000
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Public URL
|
|
278
|
+
|
|
279
|
+
`--public-url` (or `PUBLIC_URL=…`) is the URL **clients use to reach you**. It's what gets advertised in the OAuth discovery metadata as the canonical resource identifier (RFC 8707). When the server is behind a TLS reverse proxy — Azure App Service, Heroku, Fly.io, Cloudflare Tunnel, nginx, Caddy… — the bind host and the public URL differ, and spec-compliant MCP clients will refuse the connection if the metadata advertises the wrong resource. Without it the server boots in a degraded mode and prints a warning.
|
|
280
|
+
|
|
281
|
+
| Platform | Recommended setup |
|
|
282
|
+
|---|---|
|
|
283
|
+
| **Azure App Service** | Startup command: `PUBLIC_URL="https://$WEBSITE_HOSTNAME" zendesk-mcp-server $ZENDESK_SUBDOMAIN --transport http --port $PORT` |
|
|
284
|
+
| **Heroku / Fly / Cloud Run** | `PUBLIC_URL=https://<your-app>.<provider>.app` in the env / config |
|
|
285
|
+
| **Caddy / nginx / Traefik in front of a VM** | `PUBLIC_URL=https://mcp.example.com` |
|
|
286
|
+
| **Local dev (no proxy)** | `--host 127.0.0.1 --port 3000` — the resource URL is derived automatically (the wildcard `0.0.0.0` is what triggers the warning) |
|
|
287
|
+
|
|
288
|
+
### Authentication on every request
|
|
289
|
+
|
|
290
|
+
`Authorization: Bearer …` is required on **every** `/mcp` request — a session id alone is never accepted as a credential. The most recent bearer presented on a session is the one used for Zendesk calls, so a client refreshing its token mid-session just works.
|
|
291
|
+
|
|
292
|
+
### Verify discovery endpoints
|
|
293
|
+
|
|
294
|
+
Served by the HTTP transport in `src/transports/http.ts`:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
curl -s http://localhost:3000/.well-known/oauth-protected-resource
|
|
298
|
+
# → { "authorization_servers": ["https://<subdomain>.zendesk.com"], ... }
|
|
299
|
+
|
|
300
|
+
curl -s http://localhost:3000/.well-known/oauth-authorization-server
|
|
301
|
+
# → { "issuer": "https://<subdomain>.zendesk.com", "authorization_endpoint": "...", ... }
|
|
302
|
+
|
|
303
|
+
curl -s -i http://localhost:3000/healthz # → 200 OK
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### MCP client wiring
|
|
307
|
+
|
|
308
|
+
Every major MCP client supports remote servers over Streamable HTTP and handles the OAuth 2.1 PKCE discovery flow natively — paste the URL, sign in once, you're connected. Replace `https://mcp.example.com` below with your deployed origin.
|
|
309
|
+
|
|
265
310
|
<details>
|
|
266
|
-
<summary><strong>Claude Code</strong></summary>
|
|
311
|
+
<summary><strong>Claude Code (CLI)</strong></summary>
|
|
267
312
|
|
|
268
313
|
```bash
|
|
269
|
-
claude mcp add zendesk --
|
|
314
|
+
claude mcp add zendesk --transport http https://mcp.example.com/mcp
|
|
270
315
|
```
|
|
271
316
|
|
|
272
|
-
|
|
317
|
+
</details>
|
|
318
|
+
|
|
319
|
+
<details>
|
|
320
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
321
|
+
|
|
322
|
+
**Settings → Connectors → + Add custom connector**, paste `https://mcp.example.com/mcp`, click **Connect**. Claude Desktop drives the OAuth flow in your browser on first call.
|
|
273
323
|
|
|
274
324
|
</details>
|
|
275
325
|
|
|
276
326
|
<details>
|
|
277
|
-
<summary><strong>
|
|
327
|
+
<summary><strong>claude.ai (web)</strong></summary>
|
|
328
|
+
|
|
329
|
+
**Settings → Connectors → Add custom connector**, same URL. The OAuth flow runs in the same tab.
|
|
330
|
+
|
|
331
|
+
</details>
|
|
332
|
+
|
|
333
|
+
<details>
|
|
334
|
+
<summary><strong>VS Code (GitHub Copilot / Continue / Cline)</strong></summary>
|
|
278
335
|
|
|
279
336
|
Add to your `.vscode/mcp.json`:
|
|
280
337
|
|
|
281
338
|
```json
|
|
282
339
|
{
|
|
283
340
|
"servers": {
|
|
341
|
+
"zendesk": {
|
|
342
|
+
"type": "http",
|
|
343
|
+
"url": "https://mcp.example.com/mcp"
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
</details>
|
|
350
|
+
|
|
351
|
+
<details>
|
|
352
|
+
<summary><strong>Cursor, Windsurf</strong></summary>
|
|
353
|
+
|
|
354
|
+
Both expose an MCP settings UI that accepts a remote URL. Paste `https://mcp.example.com/mcp` and sign in when prompted.
|
|
355
|
+
|
|
356
|
+
</details>
|
|
357
|
+
|
|
358
|
+
<details>
|
|
359
|
+
<summary><strong>Zed</strong></summary>
|
|
360
|
+
|
|
361
|
+
Zed added native OAuth 2.0 + PKCE for Streamable HTTP MCP servers in 2026 ([zed-industries/zed#51768](https://github.com/zed-industries/zed/pull/51768)). Configure the remote server in your Zed settings; on first use Zed opens a loopback browser callback to complete the flow.
|
|
362
|
+
|
|
363
|
+
If you're on an older Zed build that predates that change, fall back to [`mcp-remote`](https://github.com/geelen/mcp-remote) as a local shim that does the OAuth flow on your machine and proxies the session:
|
|
364
|
+
|
|
365
|
+
```json
|
|
366
|
+
{
|
|
367
|
+
"context_servers": {
|
|
284
368
|
"zendesk": {
|
|
285
369
|
"command": "npx",
|
|
286
|
-
"args": ["-y", "
|
|
287
|
-
"env": {
|
|
288
|
-
"ZENDESK_EMAIL": "you@example.com",
|
|
289
|
-
"ZENDESK_API_TOKEN": "your-api-token"
|
|
290
|
-
}
|
|
370
|
+
"args": ["-y", "mcp-remote", "https://mcp.example.com/mcp"]
|
|
291
371
|
}
|
|
292
372
|
}
|
|
293
373
|
}
|
|
@@ -295,7 +375,33 @@ Add to your `.vscode/mcp.json`:
|
|
|
295
375
|
|
|
296
376
|
</details>
|
|
297
377
|
|
|
298
|
-
|
|
378
|
+
On the first call the MCP client fetches the discovery metadata, performs the OAuth 2.1 PKCE flow against Zendesk on behalf of the **end user**, and sends the resulting access token as a `Bearer` to the server. Each subsequent tool call runs with that user's Zendesk permissions.
|
|
379
|
+
|
|
380
|
+
### CORS
|
|
381
|
+
|
|
382
|
+
The HTTP transport ships a default CORS allowlist that covers today's major **browser-based** MCP clients out of the box (ordered by user base): `chatgpt.com`, `claude.ai`, `gemini.google.com`, `copilot.microsoft.com`, `perplexity.ai`, `chat.mistral.ai`, `grok.com`, plus `chat.openai.com`. Localhost on any port (MCP Inspector, dev pages) is also always allowed.
|
|
383
|
+
|
|
384
|
+
**Native MCP clients** (Claude Desktop / Claude Code CLI / Cursor / VS Code / Zed) send no `Origin` header — CORS doesn't apply to them, they work regardless.
|
|
385
|
+
|
|
386
|
+
To allow an additional browser origin (custom dashboard, internal portal), pass `--cors-origin` (repeatable) or set `CORS_ORIGIN` as a comma-separated list:
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
zendesk-mcp-server acme --transport http --port 3000 \
|
|
390
|
+
--cors-origin https://internal-dashboard.example.com \
|
|
391
|
+
--cors-origin https://team-portal.example.com
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
The defaults are always applied — your additions extend them, they don't replace them.
|
|
395
|
+
|
|
396
|
+
### Operator responsibilities
|
|
397
|
+
|
|
398
|
+
This server provides the MCP transport and the OAuth discovery metadata. The operator is still responsible for:
|
|
399
|
+
|
|
400
|
+
- **TLS termination** (put the server behind a reverse proxy like Caddy / nginx / Cloudflare Tunnel)
|
|
401
|
+
- **Network exposure & firewall** (the server binds `0.0.0.0` by default — choose carefully)
|
|
402
|
+
- **Process supervision** (systemd, Docker, fly.io, your hosting provider's runner — none is shipped here)
|
|
403
|
+
|
|
404
|
+
## CLI reference
|
|
299
405
|
|
|
300
406
|
```
|
|
301
407
|
zendesk-mcp-server <subdomain> [options]
|
|
@@ -306,7 +412,15 @@ Options:
|
|
|
306
412
|
--tool <name> Filter by tool name (repeatable, forces --mode all)
|
|
307
413
|
--read-only Only expose read operations
|
|
308
414
|
--log-level <level> debug | info (default) | warn | error
|
|
309
|
-
--
|
|
415
|
+
--transport <t> stdio (default) | http
|
|
416
|
+
--host <host> HTTP bind host (default: 0.0.0.0)
|
|
417
|
+
--port <port> HTTP bind port (default: 3000; 0 = OS-assigned)
|
|
418
|
+
--public-url <url> Public URL clients use to reach the server (HTTP mode,
|
|
419
|
+
required behind a TLS reverse proxy)
|
|
420
|
+
--cors-origin <url> Extra browser origin allowed by CORS (repeatable;
|
|
421
|
+
adds to the default allowlist of major web MCP
|
|
422
|
+
clients + localhost-any-port)
|
|
423
|
+
--callback-port <port> Local OAuth callback port for stdio (default 27439)
|
|
310
424
|
```
|
|
311
425
|
|
|
312
426
|
`--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.
|
|
@@ -314,7 +428,7 @@ Options:
|
|
|
314
428
|
**Examples:**
|
|
315
429
|
|
|
316
430
|
```bash
|
|
317
|
-
#
|
|
431
|
+
# Local single-tool mode — minimal context, all 37 operations in one tool
|
|
318
432
|
zendesk-mcp-server acme --mode single
|
|
319
433
|
|
|
320
434
|
# Read-only tickets only
|
|
@@ -322,21 +436,30 @@ zendesk-mcp-server acme --read-only --namespace tickets
|
|
|
322
436
|
|
|
323
437
|
# Cherry-pick specific tools
|
|
324
438
|
zendesk-mcp-server acme --tool get_ticket --tool search_tickets --tool get_current_user
|
|
439
|
+
|
|
440
|
+
# Remote HTTP, read-only Help Center surface
|
|
441
|
+
zendesk-mcp-server acme --transport http --port 8080 \
|
|
442
|
+
--namespace help_center --read-only
|
|
325
443
|
```
|
|
326
444
|
|
|
327
|
-
|
|
445
|
+
## Environment variables
|
|
328
446
|
|
|
329
447
|
| Variable | Required | Default | Description |
|
|
330
448
|
|----------|----------|---------|-------------|
|
|
331
449
|
| `ZENDESK_SUBDOMAIN` | yes (or CLI arg) | — | Zendesk subdomain (e.g., `acme` for acme.zendesk.com) |
|
|
332
450
|
| `ZENDESK_OAUTH_CLIENT_ID` | no | `<subdomain>_zendesk` | OAuth client identifier |
|
|
333
|
-
| `ZENDESK_OAUTH_CALLBACK_PORT` | no | `27439` | Local port for the OAuth browser callback (also `--callback-port`). Must match the redirect URL registered in Zendesk. |
|
|
451
|
+
| `ZENDESK_OAUTH_CALLBACK_PORT` | no | `27439` | Local port for the OAuth browser callback (also `--callback-port`). Must match the redirect URL registered in Zendesk. **stdio only**. |
|
|
334
452
|
| `ZENDESK_TOKEN_FILE` | no | OS config dir | Path to the persisted OAuth token file (`0600`). |
|
|
335
|
-
| `ZENDESK_EMAIL` |
|
|
336
|
-
| `ZENDESK_API_TOKEN` |
|
|
453
|
+
| `ZENDESK_EMAIL` | stdio API-token only | — | Agent email for Basic auth — **refused in HTTP** |
|
|
454
|
+
| `ZENDESK_API_TOKEN` | stdio API-token only | — | Zendesk API token — **refused in HTTP** |
|
|
455
|
+
| `TRANSPORT` | no | `stdio` | `stdio` or `http` |
|
|
456
|
+
| `HOST` | no | `0.0.0.0` | HTTP bind host |
|
|
457
|
+
| `PORT` | no | `3000` | HTTP bind port (`0` to let the OS pick) |
|
|
458
|
+
| `PUBLIC_URL` | recommended in HTTP behind a proxy | derived from host:port | Public URL advertised in OAuth discovery metadata |
|
|
459
|
+
| `CORS_ORIGIN` | no | — | Comma-separated browser origins added to the default CORS allowlist |
|
|
337
460
|
| `LOG_LEVEL` | no | `info` | Log verbosity (`debug` surfaces the full OAuth flow trace) |
|
|
338
461
|
|
|
339
|
-
|
|
462
|
+
In stdio, if both `ZENDESK_EMAIL` and `ZENDESK_API_TOKEN` are set, the server uses API token auth; otherwise it uses OAuth 2.1 PKCE. In HTTP mode, API token credentials are refused at boot — only per-user OAuth 2.1 PKCE is accepted. Full API-token setup is documented in [`docs/api-token-stdio.md`](docs/api-token-stdio.md).
|
|
340
463
|
|
|
341
464
|
## Troubleshooting
|
|
342
465
|
|
|
@@ -399,26 +522,30 @@ test the project. The **published package** still runs on Node 20+ (see
|
|
|
399
522
|
and runs the smoke test to keep that promise honest.
|
|
400
523
|
|
|
401
524
|
```bash
|
|
402
|
-
#
|
|
403
|
-
|
|
525
|
+
# Clone, install, build
|
|
526
|
+
git clone https://github.com/fruggr/zendesk-mcp-server.git
|
|
527
|
+
cd zendesk-mcp-server && pnpm install && pnpm build
|
|
528
|
+
node dist/index.js <your-subdomain>
|
|
404
529
|
|
|
405
|
-
# Dev mode (
|
|
406
|
-
|
|
407
|
-
pnpm dev -- <your-subdomain> --mode all
|
|
530
|
+
# Dev mode, OAuth (browser opens on first tool call)
|
|
531
|
+
pnpm dev -- <your-subdomain> --mode all
|
|
408
532
|
|
|
409
|
-
#
|
|
410
|
-
pnpm
|
|
533
|
+
# Dev mode, HTTP transport (OAuth bearer from the MCP client)
|
|
534
|
+
pnpm dev -- <your-subdomain> --transport http --port 3000 --public-url http://localhost:3000
|
|
411
535
|
|
|
412
|
-
#
|
|
413
|
-
pnpm typecheck
|
|
536
|
+
# Build / typecheck / lint / test
|
|
537
|
+
pnpm build && pnpm typecheck && pnpm check && pnpm test
|
|
538
|
+
```
|
|
414
539
|
|
|
415
|
-
|
|
416
|
-
pnpm check
|
|
540
|
+
To test a PR branch without publishing to npm — the `prepare` script builds on install:
|
|
417
541
|
|
|
418
|
-
|
|
419
|
-
|
|
542
|
+
```bash
|
|
543
|
+
npx -y github:fruggr/zendesk-mcp-server <your-subdomain>
|
|
544
|
+
npx -y github:fruggr/zendesk-mcp-server#my-feature-branch <your-subdomain>
|
|
420
545
|
```
|
|
421
546
|
|
|
547
|
+
Contributor conventions (architecture, code style, submission bar, release workflow) live in [`AGENTS.md`](AGENTS.md).
|
|
548
|
+
|
|
422
549
|
## Inspiration & related projects
|
|
423
550
|
|
|
424
551
|
This project was built with reference to:
|