Zendesk CLI and MCP Server for Claude Code - Search tickets, manage support, and analyze metrics
Project description
Zendesk CLI, MCP Server & Claude Code Skill
A Claude Code skill for Zendesk Support integration. The primary interface is a skill file (SKILL.md) that gives Claude full command knowledge — backed by a CLI (zd-cli) that Claude runs to interact with Zendesk. An MCP server is also included for other AI assistants.
This project was built almost entirely by Claude Code through iterative conversation — designing, implementing, testing against a live Zendesk instance, and fixing issues together over multiple sessions. It's a tool I use often and am sharing in case others find it useful.
Features
- Claude Code skill —
SKILL.mdgives Claude full command documentation, workflows, and the save-first/query-later pattern - CLI (
zd-cli) — 28 commands covering tickets, users, organizations, views, metrics, and more - MCP server — alternative interface for other AI assistants
- Slack integration — send formatted support reports to Slack channels
- Support metrics analysis — response times, resolution rates, CSAT, after-hours and on-call tracking
- Local response storage — API responses saved to temp directory, queryable with jq without re-fetching
- Markdown formatting — write operations convert Markdown to HTML for proper rendering in Agent Workspace
- Encrypted credentials — API tokens and OAuth tokens encrypted at rest
Quick Start
# Run directly (no install needed)
uvx --from zendesk-skill zd-cli --help
# Set up credentials (see Authentication below)
uvx --from zendesk-skill zd-cli auth login
# Verify it works
uvx --from zendesk-skill zd-cli me
Authentication
Three methods are supported. API token is the simplest; OAuth adds auto-refresh. A relay server mode exists for shared team deployments but is not covered here.
Method 1: API Token
- In Zendesk: Admin Center → Apps and integrations → APIs → Zendesk API → Add API token
- Copy the token (shown only once)
# Interactive setup (prompts for email, token, subdomain)
zd-cli auth login
# Or non-interactive
zd-cli auth login --email you@company.com --token YOUR_TOKEN --subdomain yourcompany
# Or via environment variables
export ZENDESK_EMAIL="you@company.com"
export ZENDESK_TOKEN="your-api-token"
export ZENDESK_SUBDOMAIN="yourcompany"
Method 2: OAuth 2.0 (with auto-refresh)
- In Zendesk: Admin Center → Apps and integrations → APIs → OAuth Clients → Add OAuth client
- Add redirect URIs for ports 8080–8089:
http://127.0.0.1:8080/callback http://127.0.0.1:8081/callback ... http://127.0.0.1:8089/callback - Note the Client ID and Client Secret
# Opens a browser for authorization
zd-cli auth login-oauth --subdomain yourcompany --client-id YOUR_ID --client-secret YOUR_SECRET
# Headless/SSH: browser redirects to localhost (shows connection refused — that's expected),
# paste the full redirect URL back into the prompt
zd-cli auth login-oauth --subdomain yourcompany --client-id YOUR_ID --client-secret YOUR_SECRET --manual
# Check auth status
zd-cli auth status
# Remove credentials
zd-cli auth logout # API token
zd-cli auth logout-oauth # OAuth token
Installation
Via uvx (no install, recommended)
uvx --from zendesk-skill zd-cli --help
uvx runs the tool in an isolated environment on demand — nothing is permanently installed.
Via uv tool install
uv tool install zendesk-skill
zd-cli --help
Development / Claude Code skill
git clone https://github.com/andmarios/zendesk-skill zendesk-skill
cd zendesk-skill
uv sync
uv run zd-cli --help
Point Claude Code at SKILL.md to give Claude full command documentation and workflows.
Prerequisites: Python 3.12+, uv, and jq (for the query command).
Commands
Tickets
| Command | Description |
|---|---|
search "status:open priority:urgent" |
Search tickets |
ticket 12345 |
Get ticket by ID |
ticket-details 12345 |
Ticket + all comments |
linked-incidents 12345 |
Incidents linked to a problem ticket |
attachment --ticket 12345 <url> |
Download an attachment |
Write Operations
All write commands convert Markdown to HTML by default (use --plain-text to skip).
| Command | Description |
|---|---|
update-ticket 12345 --status pending --tags "waiting-customer" |
Update ticket |
create-ticket "Subject" "**Bold** description" |
Create ticket |
add-note 12345 "Internal **note**" |
Add internal note |
add-comment 12345 "Public reply" |
Add public comment |
Metrics & Analytics
| Command | Description |
|---|---|
ticket-metrics 12345 |
Reply/resolution times for a ticket |
list-metrics |
Metrics across tickets |
satisfaction-ratings --score bad |
CSAT ratings |
Views
| Command | Description |
|---|---|
views |
List available views |
view-count 123 |
Ticket count in a view |
view-tickets 123 |
Tickets from a view |
Users & Organizations
| Command | Description |
|---|---|
user 12345 |
Get user by ID |
search-users "john@example.com" |
Search users |
org 67890 |
Get organization by ID |
search-orgs "Acme" |
Search organizations |
Configuration & Info
| Command | Description |
|---|---|
me |
Current user (tests auth) |
groups |
List support groups |
tags |
Popular tags |
sla-policies |
SLA policies |
Query
# Query a saved response file with jq
zd-cli query <file> -q comments_slim # named query
zd-cli query <file> --jq '.data.ticket' # custom jq
zd-cli query <file> --list # show available named queries
All commands save their full API response to /tmp/zd-cli-$UID/ and print the path. Use zd-cli query to extract data from saved files without re-fetching.
Search Query Syntax
# Status & priority
zd-cli search "status:open priority:urgent"
zd-cli search "status:pending assignee:me"
# Time filters
zd-cli search "created>2024-01-01 status:open"
zd-cli search "updated<1week status:open"
# By person/org
zd-cli search "requester:user@example.com status:open"
zd-cli search "organization:acme type:incident"
# Tags
zd-cli search "tags:billing tags:escalated"
Slack Integration
# Configure
zd-cli auth login-slack --webhook "https://hooks.slack.com/services/..." --channel "#support"
# Send a report
zd-cli slack-report
# Check / remove
zd-cli auth status-slack
zd-cli auth logout-slack
Support Metrics Analysis
# Default: last 2 weeks
uv run python src/zendesk_skill/scripts/analyze_support_metrics.py
# Custom range with accurate reply counts from the Ticket Metrics API
uv run python src/zendesk_skill/scripts/analyze_support_metrics.py \
--start 2026-01-01 --end 2026-01-15 --fetch-metrics
# Pipe to Slack
uv run python src/zendesk_skill/scripts/analyze_support_metrics.py | zd-cli slack-report
# Generate markdown report
zd-cli markdown-report -o report.md
Business Hours & On-Call Tracking
Configure in ~/.config/zd-cli/config.json to add after-hours and on-call sections to your reports:
{
"business_hours": {
"timezone": "Europe/Berlin",
"start_hour": 9,
"end_hour": 18,
"workdays": [0, 1, 2, 3, 4]
},
"oncall": {
"enabled": true,
"start_hour": 19,
"end_hour": 9,
"customers": ["bigclient.com"],
"priorities": ["urgent"]
}
}
When configured, reports include after-hours ticket counts, messages, replies, and on-call engagements (tickets matching the configured priority + customer domain during on-call hours). FRT for on-call tickets is calculated in calendar time; all others use business hours.
Security: Prompt Injection Protection
All content from Zendesk is treated as untrusted input and screened through a multi-layer security pipeline before reaching the LLM:
- Regex detection — known prompt injection patterns (instruction overrides, prompt extraction, leetspeak evasion)
- Semantic matching — fuzzy similarity against known injection templates
- Haiku/LLM screening — when configured, an LLM-based classifier for sophisticated attacks
Every LLM-facing field (ticket subjects, comment bodies, user names, emails, org names, view titles) is wrapped with session-scoped security markers. Stored response files are also scanned at save time using both regex and semantic screening tiers, with detection results preserved in file metadata.
Attachment scanning is size-aware:
- Text files up to 1 MB are scanned inline through the full screening pipeline
- Text files over 1 MB and binary files receive a security warning with a hint to scan manually using the CLI tool:
uvx --from prompt-security-utils prompt-security-utils <file>
Security is enabled by default. Configure in ~/.config/zd-cli/config.json:
{
"security_enabled": true,
"allowlisted_tickets": ["12345", "67890"]
}
security_enabled— set tofalseto disable all screening and wrapping (default:true)allowlisted_tickets— ticket IDs to skip wrapping (for trusted/internal tickets)
# View current security status and session markers
zd-cli security-info
# Include full MCP security instructions
zd-cli security-info --instructions
Requires prompt-security-utils (included as a dependency).
MCP Server
The MCP server exposes the same functionality for AI assistants that support the Model Context Protocol.
uv run zendesk-mcp
Add to claude_desktop_config.json:
{
"mcpServers": {
"zendesk": {
"command": "uvx",
"args": ["--from", "zendesk-skill", "zendesk-mcp"]
}
}
}
Development
uv run pytest -v
uv run zd-cli --help
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zd_cli-1.3.0.tar.gz.
File metadata
- Download URL: zd_cli-1.3.0.tar.gz
- Upload date:
- Size: 166.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0375c1c2ceeb0c0646a778e48f138695ec80bda573e7a17a8805159efa7af0a3
|
|
| MD5 |
fefb111f867e3e5a916b484c3bcebd87
|
|
| BLAKE2b-256 |
415a7d952b1451da8d9e830ab2b701823ef7dc86ab94a57b9c2ba85742638fb2
|
File details
Details for the file zd_cli-1.3.0-py3-none-any.whl.
File metadata
- Download URL: zd_cli-1.3.0-py3-none-any.whl
- Upload date:
- Size: 79.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
219d2b9808dbb2a3584614ddf5023e47ed7a8e8150ee29b36639a40ce27d1c63
|
|
| MD5 |
d98c43816d19f7dbd8b490d44e82a098
|
|
| BLAKE2b-256 |
05541bb557ea716894bc05990edd114877e48f34edf2dd8e0552435c787770a1
|