Skip to main content

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.md gives 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 zd-cli --help

# Set up credentials (see Authentication below)
uvx zd-cli auth login

# Verify it works
uvx 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

  1. In Zendesk: Admin Center → Apps and integrations → APIs → Zendesk API → Add API token
  2. 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)

  1. In Zendesk: Admin Center → Apps and integrations → APIs → OAuth Clients → Add OAuth client
  2. 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
    
  3. 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

uvx 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:

  1. Regex detection — known prompt injection patterns (instruction overrides, prompt extraction, leetspeak evasion)
  2. Semantic matching — fuzzy similarity against known injection templates
  3. 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 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 to false to 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

Metadata

Release files for zd-cli 1.3.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for zd-cli 1.3.5
File Size Uploaded Provenance
zd_cli-1.3.5.tar.gz 169.5 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for zd-cli 1.3.5
File Interpreter ABI Platform
zd_cli-1.3.5-py3-none-any.whl Python 3 none any Details

Total release size: 249.1 kB

Release files / zd_cli-1.3.5.tar.gz

Download URL zd_cli-1.3.5.tar.gz
Size 169.5 kB
Tags Source
SHA-256 checksum
How to use checksums
bd6420230131d37c58cfa32f82bce86eef605655d46869f4d4a62fd44dcaff63
BLAKE2b-256 checksum
How to use checksums
059915e23b3fc3e436c406298778c74710db6813444911719d907f5b603fad2a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","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}

Release files / zd_cli-1.3.5-py3-none-any.whl

Download URL zd_cli-1.3.5-py3-none-any.whl
Size 79.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
82500943424eb7582e0655575f6e098f4c79cf0676d5fb774263218e900558ca
BLAKE2b-256 checksum
How to use checksums
f3ae3923c25bd33fe2dc8b598dcb9456636fb5984359250bfb3d64d045696c08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","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}

Security for zd-cli 1.3.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page