Zendesk MCP Server

Zendesk MCP Server

Enables AI-powered ticket analysis and comprehensive Zendesk API integration via the Model Context Protocol, supporting both API token (CLI) and OAuth 2.1 (web) authentication modes.

Category
Visit Server

README

<div align="center">

Zendesk MCP Server

npm version License: MIT Node.js Version MCP Compatible

A Model Context Protocol server for Zendesk API integration with AI-powered ticket analysis

Quick StartConfigurationToolsArchitectureDevelopment

</div>


Overview

Zendesk MCP Server provides comprehensive access to the Zendesk API through the Model Context Protocol. It supports two transport modes that are auto-detected from environment variables:

  • Stdio mode — API token auth, for CLI-based MCP clients (Claude Code, Cursor, etc.)
  • HTTP mode — OAuth 2.1 with PKCE, for web-based MCP clients

Both modes expose the same set of tools. No code changes are needed to switch between them.

Based on mattcoatsworth/zendesk-mcp-server with significant enhancements including AI-powered features, dual-mode authentication, improved error handling, and comprehensive retry logic.

Quick Start

Stdio Mode (API Token)

Best for CLI-based MCP clients like Claude Code or Cursor. Each user only needs their own email + API token.

1. Get your API token from Zendesk Admin Center → Apps and integrations → APIs → Zendesk API → Add API token.

2. Configure your MCP client:

{
  "zendesk": {
    "type": "stdio",
    "command": "npx",
    "args": ["@sshadows/zendesk-mcp-server"],
    "env": {
      "ZENDESK_SUBDOMAIN": "your-subdomain",
      "ZENDESK_EMAIL": "you@example.com",
      "ZENDESK_API_TOKEN": "your-api-token"
    }
  }
}

That's it. The server auto-detects stdio mode and connects.

HTTP Mode (OAuth 2.1)

Best for web-based MCP clients or multi-user deployments with centralized OAuth.

1. Create an OAuth app in Zendesk Admin Center → Apps and integrations → APIs → OAuth Clients.

2. Create a .env file:

ZENDESK_SUBDOMAIN=your-subdomain
ZENDESK_OAUTH_CLIENT_ID=your_client_id
ZENDESK_OAUTH_CLIENT_SECRET=your_client_secret
ZENDESK_OAUTH_REDIRECT_URI=http://localhost:3030/zendesk/oauth/callback

3. Start and authorize:

npm start
# Visit http://localhost:3030/oauth/authorize in your browser

4. Use the token with your MCP client: Authorization: Bearer mcp_...

Installation

Requirement Version Notes
Node.js >= 18.0.0 Required
Zendesk Account Any plan Required
Anthropic API Key - Only for AI analysis features
# npm (recommended)
npm install -g @sshadows/zendesk-mcp-server

# Or from source
git clone https://github.com/SShadowS/zendesk-mcp-server.git
cd zendesk-mcp-server
npm install

Configuration

Environment Variables

The server auto-detects which mode to use based on which variables are set.

Stdio mode (set ZENDESK_EMAIL + ZENDESK_API_TOKEN, without ZENDESK_OAUTH_CLIENT_ID):

ZENDESK_SUBDOMAIN=mycompany
ZENDESK_EMAIL=user@example.com
ZENDESK_API_TOKEN=your-api-token

HTTP mode (set ZENDESK_OAUTH_CLIENT_ID):

ZENDESK_SUBDOMAIN=mycompany
ZENDESK_OAUTH_CLIENT_ID=your_client_id
ZENDESK_OAUTH_CLIENT_SECRET=your_client_secret
ZENDESK_OAUTH_REDIRECT_URI=http://localhost:3030/zendesk/oauth/callback

Common (both modes):

MODE=full                    # 'full' (all 55 tools) or 'lite' (10 essential tools)
ANTHROPIC_API_KEY=sk-ant-... # Required for AI image/document analysis
ZENDESK_DEBUG=false          # Enable debug logging

HTTP mode only:

PORT=3030
SERVER_BASE_URL=http://localhost:3030  # Use https:// in production

See .env.example for the full list.

Tool Modes

Control which tools are exposed with the MODE environment variable:

  • full (default) — All 55 tools available.
  • lite — 10 essential tools for reduced context usage: search, get_user, list_tickets, get_ticket, get_ticket_comments, add_ticket_comment, get_ticket_attachments, analyze_ticket_images, analyze_ticket_documents, get_document_summary.
MODE=lite npm start

Available Tools

<details> <summary><b>Ticket Management</b></summary>

Tool Description
list_tickets List tickets with filters (status, assignee, etc.)
get_ticket Get ticket details with optional comments
create_ticket Create a new ticket
update_ticket Update ticket fields
get_ticket_comments Get all comments on a ticket
add_ticket_comment Add public or internal comment
get_ticket_attachments Get ticket attachments
analyze_ticket_images AI-powered image analysis with Claude Vision
analyze_ticket_documents AI-powered document analysis
get_document_summary Quick document summary

</details>

<details> <summary><b>User Management</b></summary>

Tool Description
list_users List all users
get_user Get user details
create_user Create new user
update_user Update user info
delete_user Delete a user

</details>

<details> <summary><b>Organizations</b></summary>

Tool Description
list_organizations List all organizations
get_organization Get organization details
create_organization Create new organization
update_organization Update organization
delete_organization Delete organization

</details>

<details> <summary><b>Automation & Workflows</b></summary>

Category Tools
Groups list_groups, get_group, create_group, update_group, delete_group
Macros list_macros, get_macro, create_macro, update_macro, delete_macro
Views list_views, get_view, create_view, update_view, delete_view
Triggers list_triggers, get_trigger, create_trigger, update_trigger, delete_trigger
Automations list_automations, get_automation, create_automation, update_automation, delete_automation

</details>

<details> <summary><b>Help Center, Search, Talk & Chat</b></summary>

Category Tools
Search search — Search across all Zendesk data
Help Center list_articles, get_article, create_article, update_article, delete_article
Talk get_talk_stats — Phone support statistics
Chat list_chats — Chat conversations

</details>

Architecture

Transport Modes

src/index.js (auto-detection)
├── ZENDESK_EMAIL + ZENDESK_API_TOKEN  →  Stdio mode
│   ├── ZendeskClient.setApiTokenAuth()
│   ├── setDefaultZendeskClient(client)
│   └── StdioServerTransport (stdin/stdout)
│
└── ZENDESK_OAUTH_CLIENT_ID  →  HTTP mode
    ├── Express server (src/http-server.js)
    ├── OAuth 2.1 with PKCE (src/auth/)
    ├── Per-session ZendeskClient instances
    └── StreamableHTTPServerTransport

Tools are identical in both modes. They call getZendeskClient() which resolves to:

  • HTTP mode: Per-session client via AsyncLocalStorage
  • Stdio mode: Singleton default client

Project Structure

zendesk-mcp-server/
├── src/
│   ├── index.js                 # Entry point (auto-detects mode)
│   ├── http-server.js           # Express server with OAuth (HTTP mode only)
│   ├── server.js                # MCP server setup and tool registration
│   ├── request-context.js       # Per-session + default client context
│   ├── auth/
│   │   ├── oauth-handler.js     # OAuth 2.1 with PKCE
│   │   ├── session-store.js     # Session management
│   │   └── middleware.js        # Bearer token auth middleware
│   ├── zendesk-client/
│   │   ├── base.js              # Auth, HTTP requests, retry logic
│   │   ├── index.js             # Mixin composition
│   │   ├── tickets.js           # Ticket API methods
│   │   ├── users.js             # User API methods
│   │   └── ...                  # Other API domain mixins
│   ├── tools/                   # MCP tool implementations
│   ├── config/
│   │   └── tool-modes.js        # Full/lite mode filtering
│   └── utils/
│       ├── errors.js            # Classified error types
│       ├── retry.js             # Exponential backoff
│       ├── ticket-context.js    # AI prompt context builder
│       ├── document-handler.js  # Document routing
│       └── converter-client.js  # Office-to-PDF conversion
├── tests/                       # Vitest test suite
├── .env.example                 # Environment variable template
└── CLAUDE.md                    # AI assistant project guide

Key Design Decisions

  • Dual auth in one client: ZendeskClientBase supports both setApiTokenAuth() (Basic) and setAccessToken() (Bearer). The _authMode field determines which header getAuthHeader() returns.
  • Default client fallback: AsyncLocalStorage doesn't propagate through StdioServerTransport's event callbacks. Instead of fighting that, getZendeskClient() falls back to a module-level default client in stdio mode. Zero changes needed in any tool file.
  • Console.error everywhere: In stdio mode, stdout is the MCP transport. All diagnostic logging in shared code paths uses console.error.
  • HTTP mode is unchanged: src/http-server.js and src/auth/* are only imported in HTTP mode. No changes were needed.

Development

npm start          # Start server (auto-detects mode)
npm run dev        # Start with auto-reload
npm test           # Run all tests
npm run test:watch # Run tests in watch mode
npm run inspect    # Launch MCP Inspector

Testing

Tests use Vitest and are in tests/ mirroring the src/ directory:

npm test           # Run all tests
npm run test:watch # Watch mode

Integration tests (against real Zendesk + Anthropic APIs) require .env credentials and are automatically skipped when credentials are missing.

HTTP Mode Endpoints

Endpoint Description
ALL /mcp Main MCP endpoint (requires Bearer token)
GET /oauth/authorize Start OAuth flow
GET /zendesk/oauth/callback OAuth callback
POST /oauth/token Token exchange
POST /oauth/register Dynamic client registration (RFC 7591)
GET /.well-known/oauth-authorization-server OAuth metadata (RFC 8414)
GET /.well-known/oauth-protected-resource Protected resource metadata (RFC 9728)
GET /health Health check

Troubleshooting

<details> <summary><b>Missing configuration error on startup</b></summary>

The server needs either API token or OAuth credentials. Set one of:

# Stdio mode
ZENDESK_SUBDOMAIN=... ZENDESK_EMAIL=... ZENDESK_API_TOKEN=...

# HTTP mode
ZENDESK_SUBDOMAIN=... ZENDESK_OAUTH_CLIENT_ID=... ZENDESK_OAUTH_CLIENT_SECRET=...

</details>

<details> <summary><b>401 Unauthorized (OAuth / HTTP mode)</b></summary>

  • Complete OAuth flow: visit http://localhost:3030/oauth/authorize
  • Check if token expired (24-hour TTL) — re-authorize if needed
  • Ensure Bearer token is included: Authorization: Bearer mcp_xxx
  • Token format should start with mcp_

</details>

<details> <summary><b>401 Unauthorized (API token / stdio mode)</b></summary>

  • Verify ZENDESK_EMAIL is correct
  • Verify ZENDESK_API_TOKEN is a valid API token (not a password)
  • Verify ZENDESK_SUBDOMAIN is correct
  • Check the connection test output in stderr on startup

</details>

<details> <summary><b>Session lost after server restart (HTTP mode)</b></summary>

In-memory sessions are cleared on restart. Re-authorize to get a new token. For production, implement a Redis-based session store (see src/auth/session-store.js).

</details>

<details> <summary><b>AI analysis features not working</b></summary>

Set ANTHROPIC_API_KEY in your environment. This is only needed for analyze_ticket_images, analyze_ticket_documents, and get_document_summary.

</details>

<details> <summary><b>Rate limiting (429 errors)</b></summary>

The server includes exponential backoff retry logic. If you hit rate limits frequently, consider using MODE=lite to reduce API calls, or check if multiple clients share the same credentials.

</details>

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/my-feature)
  3. Run tests (npm test)
  4. Commit your changes
  5. Open a Pull Request

License

MIT License — see LICENSE for details.

Acknowledgments


<div align="center">

Made with care by SShadowS

</div>

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured