Zendesk MCP — VS Code / Cursor Extension
Configure and launch the Zendesk MCP server for Cursor, VS Code, VSCodium, and any other Open VSX-compatible IDE. The extension handles credential storage, config file generation, and server lifecycle management automatically.
Author: Markus van Kempen
Email: markus.van.kempen@gmail.com · mvk@ca.ibm.com
Website: markusvankempen.github.io
No bug too small, no syntax too weird.
Table of contents
What the extension does
The extension is a configuration manager, not a process manager. It:
- Lets you pick a connection mode (npm npx, local JS, local Python, or Code Engine remote)
- Provides a sidebar UI (Activity Bar icon) for setup, diagnostics, and quick-start prompts
- Stores the API token in the OS keychain (SecretStorage) for local modes
- Writes
mcp.json for Cursor, VS Code, Claude Desktop, and workspace folders
- Registers an MCP provider so Copilot Chat can discover the server
The IDE's native MCP client spawns the server (stdio or SSE) — the extension does not run the process itself.
📖 Full extension guide: docs/ide/EXTENSION.md
Connection modes
| Mode |
Setting |
Server |
Credentials |
| npm (npx) |
npx |
@markusvankempen/zendesk-mcp-server |
Local keychain |
| Local TypeScript |
local-js |
node …/bin/zendesk-mcp-server.js |
Local keychain |
| Local Python |
local-py |
python3 …/zendesk_mcp_server.py |
Local keychain |
| Code Engine |
remote |
VS Code: SSE · Cursor: uvx mcp-proxy |
On gateway |
Switch modes: Zendesk MCP: Select Connection Mode or Setup Wizard.
Install
From VS Code Marketplace
- Open VS Code Extensions panel (
Ctrl/Cmd+Shift+X)
- Search for
zendesk-mcp
- Click Install
From Open VSX (Cursor)
- Open Cursor Extensions panel
- Search for
zendesk-mcp
- Click Install
Alternatively, download the .vsix from the GitHub Releases page and install via:
code --install-extension zendesk-mcp-vscode-1.0.0.vsix
# or
cursor --install-extension zendesk-mcp-vscode-1.0.0.vsix
First-time setup
Option A — Setup Wizard (recommended)
- Command Palette →
Zendesk MCP: Setup Wizard
- Choose connection mode (npx / local-js / local-py / remote)
- Enter credentials (local) or Code Engine URL (remote)
Zendesk MCP: Run Diagnostics
- Restart IDE if tools don't appear
Option B — npx only
- Command Palette →
Zendesk MCP: Configure Credentials
- Enter subdomain, email, API token
- Extension syncs
mcp.json automatically
Zendesk API token: Admin → Apps and integrations → APIs → Zendesk API → Token access.
Commands
Open the Command Palette (Ctrl/Cmd+Shift+P) and search for Zendesk MCP:
| Command |
Description |
Zendesk MCP: Setup Wizard |
Pick mode + configure credentials or remote URL in one flow |
Zendesk MCP: Select Connection Mode |
Switch npx / local-js / local-py / remote |
Zendesk MCP: Configure Credentials |
Subdomain, email, API token (local modes) |
Zendesk MCP: Configure Remote Endpoint |
Code Engine URL (remote mode — no local token) |
Zendesk MCP: Sync MCP Configuration |
Re-writes all mcp.json files from settings |
Zendesk MCP: Open Diagnostics Panel |
Visual test UI (connection + 14 tools) |
Zendesk MCP: Run Diagnostics |
Open panel and run full test suite |
Zendesk MCP: Test MCP Server |
Same as Run Diagnostics |
Zendesk MCP: Show Connection Status |
Mode, paths, and config file locations |
Diagnostics UI
Activity bar: Zendesk MCP icon → Diagnostics sidebar view.
Or Command Palette → Zendesk MCP: Open Diagnostics Panel / Run Diagnostics.
The panel runs step-by-step checks (like Code Engine /test):
| Check |
Local |
Remote |
| Extension configuration |
✓ |
✓ |
| Credentials / gateway health |
✓ |
✓ |
Zendesk API /users/me |
✓ |
via gateway |
MCP tools/list (14 tools) |
✓ |
✓ |
Live list_all_tickets call |
✓ |
via gateway |
Results show pass/fail per step, timing, JSON details, and a 14-tool checklist grid.
Settings
Configure via File → Preferences → Settings or settings.json:
| Setting |
Type |
Default |
Description |
zendeskMcp.connectionMode |
string |
npx |
npx · local-js · local-py · remote |
zendeskMcp.remoteEndpoint |
string |
— |
Code Engine base URL or …/sse (remote mode) |
zendeskMcp.npmPackage |
string |
@markusvankempen/zendesk-mcp-server |
npm package for npx mode |
zendeskMcp.localServerPath |
string |
— |
Path to packages/zendesk-mcp-server (local-js) |
zendeskMcp.localPythonPath |
string |
— |
Path to Python server (local-py) |
zendeskMcp.pythonCommand |
string |
python3 |
Python executable |
zendeskMcp.subdomain |
string |
— |
Your Zendesk subdomain (the part before .zendesk.com) |
zendeskMcp.email |
string |
— |
Service account email address for API authentication |
zendeskMcp.autoConfigureMcp |
boolean |
true |
Automatically sync mcp.json files on extension startup |
zendeskMcp.useBundledServer |
boolean |
false |
Use globally installed zendesk-mcp-server instead of npx |
Important: ZENDESK_API_TOKEN is intentionally not in settings. It is stored in the OS keychain via SecretStorage and is never written to settings.json.
How credentials are stored
| Credential |
Storage mechanism |
Where |
ZENDESK_SUBDOMAIN |
vscode.workspace.getConfiguration |
settings.json (plaintext) |
ZENDESK_EMAIL |
vscode.workspace.getConfiguration |
settings.json (plaintext) |
ZENDESK_API_TOKEN |
context.secrets (SecretStorage) |
OS keychain — encrypted at rest |
SecretStorage uses:
- macOS: macOS Keychain (accessed via Security framework)
- Linux: libsecret / GNOME Keyring / KWallet
- Windows: Windows Credential Manager
The API token is never written to settings.json, never logged, and never appears in the MCP config file in plaintext — it is read from SecretStorage and injected into the config at sync time.
When syncMcpConfig runs:
const apiToken = await context.secrets.get("zendeskMcp.apiToken");
// apiToken is read and written to mcp.json env block
// It never persists in the extension's own state after this point
What mcp.json looks like
The extension writes the correct JSON per connection mode and IDE. Full examples: docs/ide/EXTENSION.md.
npx (default)
{
"mcpServers": {
"zendesk-mcp": {
"command": "npx",
"args": ["-y", "@markusvankempen/zendesk-mcp-server"],
"env": {
"ZENDESK_SUBDOMAIN": "mycompany",
"ZENDESK_EMAIL": "bot@mycompany.com",
"ZENDESK_API_TOKEN": "from-keychain-at-sync"
}
}
}
}
VS Code uses "servers" + "type": "stdio" with the same command.
remote (Code Engine)
When connectionMode is remote, the extension writes:
- VS Code:
{ "type": "sse", "url": "https://<CE_ENDPOINT>/sse" } as zendesk-mcp-remote
- Cursor:
{ "command": "uvx", "args": ["mcp-proxy", "https://<CE_ENDPOINT>/sse"] }
No local credentials. Set URL via Configure Remote Endpoint.
local-js / local-py
- local-js:
node …/packages/zendesk-mcp-server/bin/zendesk-mcp-server.js
- local-py:
python3 …/packages/zendesk-mcp-server-py/zendesk_mcp_server.py
If zendeskMcp.useBundledServer is true, npx mode uses global zendesk-mcp-server instead.
Manual remote (without extension)
See docs/ide/README-remote.md and mcp-client-cursor-deployed.json.
Legacy manual Cursor remote snippet:
{
"mcpServers": {
"zendesk-mcp-remote": {
"command": "uvx",
"args": [
"mcp-proxy",
"https://<CE_ENDPOINT>/sse"
]
}
}
}
Copy from mcp-client-cursor-deployed.json. Do not hardcode the hostname — resolve CE_ENDPOINT after deploy.
Config file locations
The extension writes to the following locations depending on context:
| Config target |
Path |
Scope |
| Global Cursor |
~/.cursor/mcp.json |
All Cursor workspaces |
| Workspace Cursor |
<workspace>/.cursor/mcp.json |
Current workspace only |
| Claude Desktop (macOS) |
~/Library/Application Support/Claude/claude_desktop_config.json |
Claude Desktop app |
| Claude Desktop (Windows) |
%APPDATA%\Claude\claude_desktop_config.json |
Claude Desktop app |
Existing mcpServers entries from other servers are preserved — the extension only adds or updates the zendesk-mcp key.
Build from source
# From monorepo root
npm install
# Build just the extension
npm run build:extension
# Or build everything
npm run build
Compiled output goes to deployments/vscode-extension/dist/extension.js.
Development (Extension Host)
To develop and test the extension locally:
cd deployments/vscode-extension
npm install
- Open the
deployments/vscode-extension/ folder in VS Code
- Press
F5 to launch the Extension Development Host
- A new VS Code window opens with the extension loaded
- Run
Zendesk MCP: Configure Credentials in the new window to test
- Set breakpoints in
src/extension.ts to debug
Alternatively, open the monorepo root in VS Code — the .vscode/launch.json should include an Extension Host configuration.
Watch mode (auto-rebuild on save)
cd deployments/vscode-extension
npx tsc --watch
Publish to marketplaces
Prerequisites
VS Code Marketplace publisher: marketplace.visualstudio.com/manage
- Create a publisher named
markusvankempen
- Get a Personal Access Token (Azure DevOps → User Settings → Personal Access Tokens)
- Scope:
Marketplace (Manage)
Open VSX account: open-vsx.org
- Create account
- Generate access token
Manual publish
cd deployments/vscode-extension
npm install
# Package into .vsix
npm run package
# Creates: zendesk-mcp-vscode-1.0.0.vsix
# Publish to VS Marketplace
VSCE_PAT=your_azure_devops_pat npm run publish:vsce
# Publish to Open VSX (Cursor)
OVSX_PAT=your_ovsx_token npm run publish:ovsx
Automated publish (GitHub Actions)
The .github/workflows/publish.yml workflow runs automatically on git tag v*:
# Bump version in deployments/vscode-extension/package.json first
git add deployments/vscode-extension/package.json
git commit -m "chore: bump extension version to 1.0.1"
git tag v1.0.1
git push origin v1.0.1
GitHub Actions will build and publish to npm, VS Marketplace, and Open VSX in sequence. Set these repository secrets:
NPM_TOKEN
VSCE_PAT
OVSX_PAT
Architecture
flowchart TD
subgraph ext [Extension (runs on IDE startup)]
CMD1["zendeskMcp.configure\n(interactive wizard)"]
CMD2["zendeskMcp.syncMcpConfig\n(writes mcp.json)"]
CMD3["zendeskMcp.showStatus\n(read-only panel)"]
SS["context.secrets\n(SecretStorage / OS keychain)\n→ ZENDESK_API_TOKEN only"]
CFG["vscode.workspace.getConfiguration\n(settings.json)\n→ subdomain, email"]
end
subgraph files [Config files written by extension]
F1["~/.cursor/mcp.json"]
F2["workspace/.cursor/mcp.json"]
F3["Claude Desktop config"]
end
subgraph ide [IDE MCP client (not the extension)]
NPX["npx @markusvankempen/zendesk-mcp-server\nspawned as child process\nstdin/stdout JSON-RPC"]
end
CMD1 --> SS
CMD1 --> CFG
CMD2 --> SS
CMD2 --> CFG
CMD2 --> files
files --> NPX
NPX --> ZD[Zendesk API]
Key design decision: The extension writes config files but does not spawn or manage the MCP server process. The IDE's native MCP client is responsible for spawning, monitoring, and restarting the server. This means:
- The extension does not need to stay active after startup
- No port management or process lifecycle complexity in the extension code
- The server benefits from the IDE's built-in retry and error recovery
Troubleshooting
"No MCP server found" after install
- Run
Zendesk MCP: Configure Credentials if you haven't yet
- Run
Zendesk MCP: Sync MCP Configuration
- Restart the IDE — the IDE's MCP client reads
mcp.json at startup
API token not stored / lost after update
SecretStorage is scoped to extension version in some IDE builds. After extension update, run Zendesk MCP: Configure Credentials again to re-enter and re-store the token.
mcp.json is not being written
- Run
Zendesk MCP: Show Connection Status to see what the extension thinks is configured
- Check that
ZENDESK_SUBDOMAIN and ZENDESK_EMAIL are set in Settings
- Check that the API token is stored (Status panel shows "API token: stored")
- Run
Zendesk MCP: Sync MCP Configuration manually
Extension is installed but commands don't appear
The extension activates onStartupFinished. If commands are missing, check the Extensions panel to confirm the extension is enabled (not just installed).
The credentials in mcp.json are incorrect. Run Zendesk MCP: Configure Credentials to update them. Test the token with:
curl -u "email@example.com/token:YOUR_TOKEN" \
"https://subdomain.zendesk.com/api/v2/tickets/recent.json"
Cursor: remote Code Engine SSE times out (30s)
Symptom:
MCP IPC timeout: mcp.runCommand.mcp.createClient exceeded 30000ms
when using "url": "https://…codeengine…/sse" for zendesk-mcp-remote.
Fix: Use local stdio instead — this extension writes that config by default:
- Run
Zendesk MCP: Configure Credentials
- Run
Zendesk MCP: Sync MCP Configuration
- Restart Cursor
That produces a "command": "node" / npx entry with ZENDESK_* env vars (~1s connect). The Code Engine gateway remains available for VS Code SSE, Bob, test UI, and admin panel.
Details: Code Engine troubleshooting — Cursor MCP timeout.
Cursor: mcp.json invalid JSON
If MCP servers stop loading after hand-editing config:
python3 -m json.tool ~/.cursor/mcp.json
Do not nest "mcpServers" inside "mcpServers". Run Zendesk MCP: Sync MCP Configuration to repair the zendesk-mcp entry without touching other servers.
Documentation