Zammad MCP Server
by basher83
README.md
# Zammad MCP Server

[](https://app.codacy.com/gh/basher83/Zammad-MCP/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade)
[](https://app.codacy.com/gh/basher83/Zammad-MCP/dashboard)
An MCP server that connects AI assistants to Zammad, providing tools for managing tickets, users, organizations, and attachments.
> **Disclaimer**: This project is not affiliated with or endorsed by Zammad GmbH or the Zammad Foundation. This is an independent integration that uses the Zammad API.
## Features
### Tools
- **Ticket Management**
- `zammad_search_tickets` - Search tickets with multiple filters
- `zammad_get_ticket` - Get detailed ticket information with articles (supports pagination)
- `zammad_create_ticket` - Create new tickets
- `zammad_update_ticket` - Update ticket properties
- `zammad_add_article` - Add comments/notes to tickets
- `zammad_add_ticket_tag` / `zammad_remove_ticket_tag` - Manage ticket tags
- `zammad_get_ticket_tags` - Get tags assigned to a specific ticket
- `zammad_list_tags` - List all tags defined in the system (requires admin.tag permission)
- **Attachment Support**
- `zammad_get_article_attachments` - List attachments for a ticket article
- `zammad_download_attachment` - Download attachment content (base64-encoded)
- `zammad_delete_attachment` - Delete attachments from ticket articles
- **User & Organization Management**
- `zammad_create_user` - Create a Zammad user
- `zammad_get_user` / `zammad_search_users` - User information and search
- `zammad_get_organization` / `zammad_search_organizations` - Organization data
- `zammad_get_current_user` - Get authenticated user info
- **System Information**
- `zammad_list_groups` - Get all available groups (cached for performance)
- `zammad_list_ticket_states` - Get all ticket states (cached for performance)
- `zammad_list_ticket_priorities` - Get all priority levels (cached for performance)
- `zammad_get_ticket_stats` - Get ticket statistics (optimized with pagination)
### Resources
Access Zammad data directly:
- `zammad://ticket/{id}` - Individual ticket details
- `zammad://user/{id}` - User profile information
- `zammad://organization/{id}` - Organization details
- `zammad://queue/{group}` - Ticket queue for a group
### Prompts
Pre-configured prompts:
- `analyze_ticket` - Comprehensive ticket analysis
- `draft_response` - Generate ticket responses
- `escalation_summary` - Summarize escalated tickets
## Installation
### Option 1: Run Directly with uvx (Recommended)
Run without installation:
```bash
# Install uv if you haven't already
# macOS/Linux:
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows:
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
# Run directly from GitHub
uvx --from git+https://github.com/basher83/zammad-mcp.git mcp-zammad
# Or with environment variables
ZAMMAD_URL=https://your-instance.zammad.com/api/v1 \
ZAMMAD_HTTP_TOKEN=your-api-token \
uvx --from git+https://github.com/basher83/zammad-mcp.git mcp-zammad
```
### Option 2: Docker Run
For production or containerized deployments:
```bash
# Basic usage with environment variables
docker run --rm -i \
-e ZAMMAD_URL=https://your-instance.zammad.com/api/v1 \
-e ZAMMAD_HTTP_TOKEN=your-api-token \
ghcr.io/basher83/zammad-mcp:latest
# If you must skip TLS verification (self-signed / internal CA), add:
# -e ZAMMAD_INSECURE=true
# Using Docker secrets for better security
docker run --rm -i \
-e ZAMMAD_URL=https://your-instance.zammad.com/api/v1 \
-e ZAMMAD_HTTP_TOKEN_FILE=/run/secrets/token \
-v ./secrets/zammad_http_token.txt:/run/secrets/token:ro \
ghcr.io/basher83/zammad-mcp:latest
# With .env file
docker run --rm -i \
--env-file .env \
ghcr.io/basher83/zammad-mcp:latest
```
#### Docker Image Versioning
The project publishes Docker images with semantic versioning:
- `latest` - Latest successful build from the default branch; may be unstable
- `1.2.3` - Specific version (recommended for production)
- `1.2` - Latest patch of 1.2 minor release
- `1` - Latest minor/patch of 1.x major release
- `main` - Latest main branch (may be unstable)
```bash
# Recommended for production - pin to specific version
docker pull ghcr.io/basher83/zammad-mcp:1.0.0
```
View all versions on [GitHub Container Registry](https://github.com/basher83/Zammad-MCP/pkgs/container/zammad-mcp).
### Option 3: For Developers
To contribute or modify the code:
```bash
# Clone the repository
git clone https://github.com/basher83/zammad-mcp.git
cd zammad-mcp
# Run the setup script
# On macOS/Linux:
./scripts/setup.sh
# On Windows (PowerShell):
.\scripts\setup.ps1
```
For manual setup, see the [Development](#development) section below.
## Configuration
The server requires Zammad API credentials. Use a `.env` file:
1. Copy the example configuration:
```bash
cp .env.example .env
```
1. Edit `.env` with your Zammad credentials:
```env
# Required: Zammad instance URL (include /api/v1)
ZAMMAD_URL=https://your-instance.zammad.com/api/v1
# Authentication (choose one method):
# Option 1: API Token (recommended)
ZAMMAD_HTTP_TOKEN=your-api-token
# Option 2: OAuth2 Token
# ZAMMAD_OAUTH2_TOKEN=your-oauth2-token
# Option 3: Username/Password
# ZAMMAD_USERNAME=your-username
# ZAMMAD_PASSWORD=your-password
# Optional: Disable TLS certificate verification (NOT recommended for production)
# Truthy values only: 1, true, yes, on. Unset (default) keeps TLS verification enabled.
# ZAMMAD_INSECURE=true
# Optional: Logging level (default: INFO)
# Valid values: DEBUG, INFO, WARNING, ERROR, CRITICAL
# LOG_LEVEL=INFO
# Optional: Transport Configuration
# MCP_TRANSPORT=stdio # Transport type: stdio (default) or http
# MCP_HOST=127.0.0.1 # Host address for HTTP transport
# MCP_PORT=8000 # Port number for HTTP transport
```
1. The server will automatically load the `.env` file on startup.
### Transport Configuration (Optional)
| Variable | Default | Description |
|----------|---------|-------------|
| `MCP_TRANSPORT` | `stdio` | Transport type: `stdio` or `http` |
| `MCP_HOST` | `127.0.0.1` | Host address for HTTP transport |
| `MCP_PORT` | - | Port number for HTTP transport (required if `MCP_TRANSPORT=http`) |
**Important**: Keep your `.env` file out of version control (already in `.gitignore`).
## Response Formats
All data-returning tools support two output formats:
- **Markdown** (default): Human-readable format optimized for LLM consumption
- **JSON**: Machine-readable format with complete metadata
Example:
```python
# Markdown (default)
zammad_search_tickets(query="network", response_format="markdown")
# JSON
zammad_search_tickets(query="network", response_format="json")
```
## Usage
### With Claude Desktop
Add to your Claude Desktop configuration:
```json
{
"mcpServers": {
"zammad": {
"command": "uvx",
"args": ["--from", "git+https://github.com/basher83/zammad-mcp.git", "mcp-zammad"],
"env": {
"ZAMMAD_URL": "https://your-instance.zammad.com/api/v1",
"ZAMMAD_HTTP_TOKEN": "your-api-token"
}
}
}
}
```
Or using Docker:
```json
{
"mcpServers": {
"zammad": {
"command": "docker",
"args": ["run", "--rm", "-i",
"-e", "ZAMMAD_URL=https://your-instance.zammad.com/api/v1",
"-e", "ZAMMAD_HTTP_TOKEN=your-api-token",
"ghcr.io/basher83/zammad-mcp:latest"]
}
}
}
```
**Note**: The server supports stdio (default) and HTTP transports. Stdio mode requires the `-i` flag for Docker. See the HTTP Transport section below for remote deployments.
**Important**: The `-i` flag is required—without it, the MCP server cannot receive stdin. Preserve this flag in wrapper scripts or shell aliases.
Or if you have it installed locally:
```json
{
"mcpServers": {
"zammad": {
"command": "python",
"args": ["-m", "mcp_zammad"],
"env": {
"ZAMMAD_URL": "https://your-instance.zammad.com/api/v1",
"ZAMMAD_HTTP_TOKEN": "your-api-token"
}
}
}
}
```
### Standalone Usage
```bash
# Run the server
python -m mcp_zammad
# Or with environment variables
ZAMMAD_URL=https://instance.zammad.com/api/v1 ZAMMAD_HTTP_TOKEN=token python -m mcp_zammad
```
### HTTP Transport (Remote/Cloud Deployment)
The server supports Streamable HTTP transport for remote deployments.
#### Environment Configuration
Set these environment variables to enable HTTP transport:
```bash
export MCP_TRANSPORT=http # Enable HTTP transport
export MCP_HOST=127.0.0.1 # Host to bind (default: 127.0.0.1)
export MCP_PORT=8000 # Port to listen on
```
#### Running with HTTP Transport
**Direct Python:**
```bash
MCP_TRANSPORT=http \
MCP_HOST=127.0.0.1 \
MCP_PORT=8000 \
ZAMMAD_URL=https://your-instance.zammad.com/api/v1 \
ZAMMAD_HTTP_TOKEN=your-api-token \
uvx --from git+https://github.com/basher83/zammad-mcp.git mcp-zammad
```
**Docker:**
```bash
docker run -d \
--name zammad-mcp-http \
-p 8000:8000 \
-e MCP_TRANSPORT=http \
-e MCP_HOST=0.0.0.0 \
-e MCP_PORT=8000 \
-e ZAMMAD_URL=https://your-instance.zammad.com/api/v1 \
-e ZAMMAD_HTTP_TOKEN=your-api-token \
ghcr.io/basher83/zammad-mcp:latest
```
Access the MCP endpoint at `http://localhost:8000/mcp`.
#### Production Deployment with Reverse Proxy
⚠️ **SECURITY WARNING**: The server does not implement inbound MCP client authentication. `ZAMMAD_*`
credentials authenticate the server to Zammad; they do not authenticate MCP clients. Bind to `0.0.0.0` only
behind an authenticated TLS proxy or inside a network restricted to trusted clients.
Use a reverse proxy for TLS and client authentication. The Caddy example below provides TLS only; add an
authentication policy appropriate for your environment before exposing it outside a trusted network.
**Example with Caddy:**
```bash
# Start the MCP server (binds to all interfaces for reverse proxy)
MCP_TRANSPORT=http \
MCP_HOST=0.0.0.0 \
MCP_PORT=8000 \
ZAMMAD_URL=https://your-instance.zammad.com/api/v1 \
ZAMMAD_HTTP_TOKEN=your-api-token \
uvx --from git+https://github.com/basher83/zammad-mcp.git mcp-zammad
```
**Caddyfile configuration:**
```caddy
mcp.yourdomain.com {
reverse_proxy localhost:8000
# Caddy automatically handles HTTPS/TLS
}
```
**Production checklist:**
1. Use `MCP_HOST=0.0.0.0` only behind a reverse proxy
2. Enable HTTPS/TLS via reverse proxy
3. Implement authentication at the proxy or application layer
4. Restrict access with firewall rules
#### Client Configuration for HTTP
Configure your MCP client to use HTTP transport:
```json
{
"mcpServers": {
"zammad": {
"url": "http://localhost:8000/mcp"
}
}
}
```
#### Security Considerations
1. **Local Development**: Use `MCP_HOST=127.0.0.1` (localhost only)
2. **Production**: Implement authentication (see [Security](#security))
3. **HTTPS**: Use reverse proxy for TLS
4. **Firewall**: Restrict access to trusted networks
5. **Host/Origin Validation**: Configure this at the authenticated proxy; the server does not add it automatically
## Examples
### Search for Open Tickets
```plaintext
Use zammad_search_tickets with state="open" to find all open tickets
```
### Create a Support Ticket
```plaintext
Use zammad_create_ticket with:
- title: "Customer needs help with login"
- group: "Support"
- customer: "customer@example.com"
- article_body: "Customer reported unable to login..."
```
### Update and Respond to a Ticket
```plaintext
1. Use zammad_get_ticket with ticket_id=123 to see the full conversation
2. Use zammad_add_article to add your response
3. Use zammad_update_ticket to change state to "pending reminder"
```
### Analyze Escalated Tickets
```plaintext
Use the escalation_summary prompt to get a report of all tickets approaching escalation
```
### Upload Attachments to a Ticket
```plaintext
Use zammad_add_article with attachments parameter:
- ticket_id: 123
- body: "See attached documentation"
- attachments: [
{
"filename": "guide.pdf",
"data": "JVBERi0xLjQKJ...", # base64-encoded content
"mime_type": "application/pdf"
}
]
```
### Delete an Attachment
```plaintext
Use zammad_delete_attachment with:
- ticket_id: 123
- article_id: 456
- attachment_id: 789
```
## Development
### Setup
#### Using Setup Scripts (Recommended)
```bash
# Clone the repository
git clone https://github.com/basher83/zammad-mcp.git
cd zammad-mcp
# Run the setup script
# On macOS/Linux:
./scripts/setup.sh
# On Windows (PowerShell):
.\scripts\setup.ps1
```
#### Manual Setup
```bash
# Clone the repository
git clone https://github.com/basher83/zammad-mcp.git
cd zammad-mcp
# Create a virtual environment with uv
uv venv
# Activate the virtual environment
# On macOS/Linux:
source .venv/bin/activate
# On Windows:
# .venv\Scripts\activate
# Install in development mode
uv pip install -e ".[dev]"
```
### Project Structure
```plaintext
zammad-mcp/
├── mcp_zammad/
│ ├── __init__.py
│ ├── __main__.py
│ ├── server.py # MCP server implementation
│ ├── client.py # Zammad API client wrapper
│ └── models.py # Pydantic models
├── tests/
├── scripts/
│ └── uv/ # UV single-file scripts
├── pyproject.toml
├── README.md
├── Dockerfile
└── .env.example
```
### Running Tests
```bash
# Install development dependencies
uv pip install -e ".[dev]"
# Run tests
uv run pytest
# Run with coverage
uv run pytest --cov=mcp_zammad
```
### Code Quality
```bash
# Format code
uv run ruff format mcp_zammad tests
# Lint
uv run ruff check mcp_zammad tests
# Type checking
uv run mypy mcp_zammad
# Run all quality checks
./scripts/quality-check.sh
```
## API Token Generation
To generate an API token in Zammad:
1. Log into your Zammad instance
1. Click on your avatar → Profile
1. Navigate to "Token Access"
1. Click "Create"
1. Name your token (e.g., "MCP Server")
1. Select appropriate permissions
1. Copy the generated token
## Troubleshooting
### Connection Issues
- Verify your Zammad URL includes the protocol (https://)
- Check that your API token has the necessary permissions
- Ensure your Zammad instance is accessible from your network
- For self-signed/internal certs only: set `ZAMMAD_INSECURE=true` to bypass TLS verification
### Authentication Errors
- Use API tokens over username/password
- Ensure tokens have permissions for the operations
- Check token expiration in Zammad settings
### Rate Limiting
The server respects Zammad's rate limits. If you hit rate limits:
- Reduce request frequency
- Paginate large result sets
- Cache frequently accessed data
## Security
The server implements multiple layers of protection following industry best practices.
### Reporting Security Issues
**⚠️ IMPORTANT**: Do not create public GitHub issues for security vulnerabilities.
Report via [GitHub Security Advisories](https://github.com/basher83/Zammad-MCP/security/advisories/new) (preferred) or see [SECURITY.md](SECURITY.md).
### Security Features
- ✅ **Request Validation**: Strict request models reject unknown fields and validate constrained inputs ([models.py](mcp_zammad/models.py))
- ⚠️ **URL Validation**: Rejects malformed and non-HTTP(S) URLs, but does not block private-network targets ([client.py](mcp_zammad/client.py))
- ✅ **HTML Sanitization**: Sanitizes selected HTML-bearing fields ([models.py](mcp_zammad/models.py))
- ✅ **Upstream Authentication**: Supports API tokens, OAuth2, and username/password for Zammad ([client.py](mcp_zammad/client.py))
- ✅ **Dependency Scanning**: CI runs pip-audit; Dependabot security alerts are enabled separately in GitHub
- ✅ **Security Testing**: CI runs Bandit, Safety, and pip-audit ([security-scan.yml](.github/workflows/security-scan.yml))
See [SECURITY.md](SECURITY.md) for complete documentation.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup, code standards, testing, and pull request guidelines.
## License
[AGPL-3.0-or-later](LICENSE) — matches the [Zammad project](https://github.com/zammad/zammad) license.
## Documentation
- [ARCHITECTURE.md](ARCHITECTURE.md) — Technical design
- [SECURITY.md](SECURITY.md) — Security policy
- [CONTRIBUTING.md](CONTRIBUTING.md) — Development guidelines
- [CHANGELOG.md](CHANGELOG.md) — Version history
## Support
- [GitHub Issues](https://github.com/basher83/Zammad-MCP/issues)
- [Zammad Documentation](https://docs.zammad.org/)
- [MCP Documentation](https://modelcontextprotocol.io/)
## Trademark Notice
"Zammad" is a trademark of Zammad GmbH. This independent integration is not affiliated with or endorsed by Zammad GmbH or the Zammad Foundation. The name "Zammad" indicates compatibility with the Zammad ticket system.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSlow