The osTicket MCP Server enables Claude to interact directly with your osTicket instance through the REST API. Manage support tickets without leaving your development environment.
Model Context Protocol (MCP) is an open protocol that enables AI assistants like Claude to interact with external tools and services. This MCP server provides 11 tools for complete osTicket ticket management including subticket relationships.
What makes this MCP server essential:
| Requirement | Version | Notes |
|---|---|---|
| Node.js | 18+ | Recommended: Node.js 20 LTS for best compatibility |
| npm | 9+ | Or pnpm 8+ / yarn 3+ |
| Claude Desktop | Latest | Or Claude CLI / other MCP-compatible client |
| osTicket | 1.18.x | With REST API enabled |
| API Endpoints Plugin | Latest | Required for extended API operations |
| Subticket Manager Plugin | Latest | Required for subticket management tools |
β οΈ This MCP server requires the API Endpoints Plugin installed on your osTicket instance.
cd /path/to/osticket/include/plugins
git clone https://github.com/markus-michalski/osticket-plugins.git
ln -s osticket-plugins/api-endpoints api-endpoints
# Enable in osTicket Admin Panel
# Admin Panel β Manage β Plugins β API Endpoints β Click "Enable"
β οΈ For subticket management features, you must install the Subticket Manager Plugin.
cd /path/to/osticket/include/plugins
ln -s osticket-plugins/subticket-manager subticket-manager
# Enable in osTicket Admin Panel
# Admin Panel β Manage β Plugins β Subticket Manager β Click "Enable"
Without this plugin, the following tools will return HTTP 501 errors:
get_parent_ticketget_child_ticketscreate_subticket_linkunlink_subticket# Create MCP server directory
mkdir -p ~/.claude/mcp-servers/osticket
# Clone repository
git clone https://github.com/markus-michalski/claude-mcp-osTicket.git ~/.claude/mcp-servers/osticket
# Install dependencies
cd ~/.claude/mcp-servers/osticket
npm install
# Build TypeScript
npm run build
0.0.0.0can_read_ticketscan_search_ticketscan_update_ticketscan_delete_ticketscan_read_statscan_manage_subtickets (if Subticket Manager Plugin is installed)Create .env file:
cd ~/.claude/mcp-servers/osticket
cp .env.example .env
Edit .env:
# Required
OSTICKET_API_URL=https://tickets.example.com
OSTICKET_API_KEY=YOUR_API_KEY_HERE
OSTICKET_API_REJECT_UNAUTHORIZED=false # true for production with valid SSL
# Optional defaults for ticket creation
OSTICKET_DEFAULT_NAME=Claude AI
OSTICKET_DEFAULT_EMAIL=claude@example.com
OSTICKET_DEFAULT_TOPIC_ID=1
# Logging
LOG_LEVEL=info # debug, info, warn, error
Edit ~/.claude/config.json (or Claude Desktop config):
{
"mcpServers": {
"osticket": {
"command": "node",
"args": ["/Users/yourname/.claude/mcp-servers/osticket/dist/index.js"]
}
}
}
Note: The .env file is automatically loaded by the server.
Restart Claude Desktop or Claude CLI. Verify with /mcp - you should see "osticket" with status "β connected".
| Variable | Required | Default | Description |
|---|---|---|---|
OSTICKET_API_URL |
β Yes | - | Base URL of your osTicket instance |
OSTICKET_API_KEY |
β Yes | - | API key for authentication |
OSTICKET_API_REJECT_UNAUTHORIZED |
β No | false |
Validate SSL certificates (set to true for production) |
OSTICKET_DEFAULT_NAME |
β No | - | Default user name for ticket creation |
OSTICKET_DEFAULT_EMAIL |
β No | - | Default user email for ticket creation |
OSTICKET_DEFAULT_TOPIC_ID |
β No | - | Default help topic ID for ticket creation |
LOG_LEVEL |
β No | info |
Logging level: debug, info, warn, error |
In Claude Desktop/CLI, you can now use:
"Show me all open tickets"
"Search for tickets about Dashboard Widget"
"Get ticket #123456"
"Create a ticket about the bug I just found"
"Update ticket #123456 to Closed"
"Show me all child tickets of #123456"
"Link ticket #234567 as child of #123456"
The MCP server automatically handles API calls and returns formatted results.
Search and fix bug:
You: "Search osTicket for tickets about Dashboard Widget"
Claude: *Searches via search_tickets*
Found 3 tickets:
- #123456 "Dashboard Widget not loading" (Open)
- #234567 "Widget shows wrong data" (Open)
- #345678 "Widget performance issue" (Closed)
You: "Show me ticket #123456 in detail"
Claude: *Retrieves via get_ticket*
Displays complete ticket with all messages
You: "I found the issue. Update to In Progress and assign to me"
Claude: *Updates via update_ticket*
β
Ticket #123456 updated
| Tool | Description | Required Permission | Plugin Required |
|---|---|---|---|
get_ticket |
Get single ticket with all messages | can_read_tickets |
API Endpoints |
list_tickets |
List tickets with filters | can_read_tickets |
API Endpoints |
search_tickets |
Full-text search | can_search_tickets |
API Endpoints |
get_ticket_stats |
Get ticket statistics | can_read_stats |
API Endpoints |
create_ticket |
Create new ticket | can_create_tickets (native) |
- |
update_ticket |
Update ticket properties | can_update_tickets |
API Endpoints |
delete_ticket |
Delete ticket permanently | can_delete_tickets |
API Endpoints |
get_parent_ticket |
Get parent of subticket | can_manage_subtickets |
API Endpoints, Subticket Manager |
get_child_tickets |
Get list of child tickets | can_manage_subtickets |
API Endpoints, Subticket Manager |
create_subticket_link |
Create parent-child relationship | can_manage_subtickets |
API Endpoints, Subticket Manager |
unlink_subticket |
Remove parent-child relationship | can_manage_subtickets |
API Endpoints, Subticket Manager |
Purpose: Retrieve a complete ticket with all messages
Parameters:
number (optional) - Ticket number (e.g., "123456")id (optional) - Ticket IDExample:
{
"number": "123456"
}
Purpose: List tickets with optional filters and pagination
Parameters:
status (optional) - Filter by status (e.g., "open", "closed")departmentId (optional) - Filter by department IDlimit (optional) - Maximum results (default: 20)offset (optional) - Pagination offset (default: 0)Example:
{
"status": "open",
"limit": 50
}
Purpose: Full-text search across ticket subjects and numbers
Parameters:
query (required) - Search querylimit (optional) - Maximum results (default: 20)Example:
{
"query": "Dashboard Widget",
"limit": 10
}
Purpose: Get aggregated ticket statistics
Parameters: None (empty object {})
Example:
{}
Purpose: Create a new osTicket ticket
Parameters:
name (optional) - User name (uses OSTICKET_DEFAULT_NAME if not provided)email (optional) - User email (uses OSTICKET_DEFAULT_EMAIL if not provided)subject (required) - Ticket subjectmessage (required) - Ticket message/descriptionformat (optional) - Message format: "markdown" (default), "html", or "text"topicId (optional) - Help Topic ID (uses OSTICKET_DEFAULT_TOPIC_ID if not provided)Markdown Support:
Requires markdown-support plugin. Without it, content is treated as HTML.
Example:
{
"subject": "Bug Report",
"message": "## Critical Bug\\n\\n**Issue:** Payment calculation error\\n\\n```php\\n$total = calculateTotal();\\n```"
}
Purpose: Update ticket properties
Parameters:
number (required) - Ticket numberdepartmentId (optional) - Department ID or namestatusId (optional) - Status ID or nametopicId (optional) - Help Topic ID or namestaffId (optional) - Staff ID or usernameslaId (optional) - SLA Plan ID or nameparentTicketNumber (optional) - Parent ticket numbernote (optional) - Add internal notenoteTitle (optional) - Title for note (default: "API Update")noteFormat (optional) - Format: "text", "html", "markdown" (default: "markdown")Smart ID Resolution:
β¨ You don't need to memorize IDs! The MCP server dynamically resolves names to IDs by querying your osTicket instance.
Supported for:
How it works:
Example:
{
"number": "123456",
"statusId": "Closed",
"departmentId": "IT Support",
"note": "## Resolution\\n\\nIssue fixed and deployed."
}
Numeric IDs still work:
{
"number": "123456",
"statusId": 3,
"departmentId": 5
}
Purpose: Permanently delete a ticket
β οΈ Warning: This operation is irreversible!
Parameters:
number (required) - Ticket numberExample:
{
"number": "123456"
}
β οΈ Requires: Subticket Manager Plugin
Purpose: Get the parent ticket of a subticket
Parameters:
number (required) - Child ticket numberExample:
{
"number": "234567"
}
Response:
{
"success": true,
"parent": {
"ticket_id": 78,
"number": "123456",
"subject": "Main Issue",
"status": "Open"
}
}
β οΈ Requires: Subticket Manager Plugin
Purpose: Get list of child tickets for a parent ticket
Parameters:
number (required) - Parent ticket numberExample:
{
"number": "123456"
}
Response:
{
"success": true,
"children": [
{
"ticket_id": 79,
"number": "234567",
"subject": "Subtask 1",
"status": "Open"
},
{
"ticket_id": 80,
"number": "345678",
"subject": "Subtask 2",
"status": "Closed"
}
],
"total": 2
}
β οΈ Requires: Subticket Manager Plugin
Purpose: Create a parent-child relationship between two tickets
Parameters:
parentNumber (required) - Parent ticket numberchildNumber (required) - Child ticket number or IDExample:
{
"parentNumber": "123456",
"childNumber": "234567"
}
Response:
{
"success": true,
"parent": {
"ticket_id": 78,
"number": "123456",
"subject": "Main Issue",
"status": "Open"
},
"child": {
"ticket_id": 79,
"number": "234567",
"subject": "Subtask 1",
"status": "Open"
},
"message": "Subticket link created: 234567 is now a child of 123456"
}
β οΈ Requires: Subticket Manager Plugin
Purpose: Remove parent-child relationship (make ticket independent again)
Parameters:
number (required) - Child ticket number to unlinkExample:
{
"number": "234567"
}
Response:
{
"success": true,
"child": {
"ticket_id": 79,
"number": "234567",
"subject": "Subtask 1",
"status": "Open"
},
"message": "Subticket 234567 has been unlinked from its parent"
}
Symptoms:
Check:
node -v (must be 18+)~/.claude/config.json syntax (valid JSON).env~/Library/Logs/Claude/mcp*.log%APPDATA%\\Claude\\logs\\mcp*.logSolution:
# Rebuild server
cd ~/.claude/mcp-servers/osticket
npm run build
# Test manually
node dist/index.js
Symptoms: Invalid API key
Check:
.envSolution: Regenerate API key and update .env
Symptoms: Missing permissions
Check:
can_read_ticketscan_search_ticketscan_update_ticketscan_delete_ticketscan_read_statscan_manage_subtickets (if using subticket tools)Symptoms: Ticket does not exist
Solution:
Symptoms: Subticket tools return 501 error
Solution:
can_manage_subtickets)Symptoms: .env file not found
Solution:
.env exists at ~/.claude/mcp-servers/osticket/.env.env.exampleView server logs:
# Live tail
tail -f ~/.claude/mcp-servers/osticket/logs/server.log
# Enable debug logging in .env
LOG_LEVEL=debug
βββββββββββββββββββββββββββββββββββββββ
β Claude Code β
β ββ MCP Protocol β
βββββββββββββββββββββββββββββββββββββββ€
β MCP Server (Node.js/TypeScript) β
β ββ Application Layer β
β β ββ Tool Handlers β
β ββ Infrastructure Layer β
β ββ HTTP Client β
β β ββ Smart ID Resolution β
β ββ Logger β
βββββββββββββββββββββββββββββββββββββββ€
β osTicket REST API β
β ββ API Endpoints Plugin β
β ββ tickets-statuses.php β
β ββ tickets-subtickets-*.php β
β ββ Other endpoints β
βββββββββββββββββββββββββββββββββββββββ
claude-mcp-osTicket/
βββ dist/ # Compiled JavaScript
βββ src/
β βββ index.ts # MCP server entry point
β βββ config/
β β βββ Configuration.ts # Environment configuration
β βββ application/
β β βββ handlers/
β β βββ ToolHandlers.ts # Tool implementations
β βββ infrastructure/
β βββ http/
β β βββ OsTicketApiClient.ts # REST API client with ID resolution
β β βββ types/
β β βββ SubticketTypes.ts # TypeScript types for subtickets
β βββ logging/
β βββ Logger.ts # File-based logger
βββ package.json
βββ tsconfig.json
βββ .env # Configuration (not in Git)
βββ .env.example # Template
| Tool | API Endpoint | Method |
|---|---|---|
| get_ticket | /api/tickets-get.php/:number.json |
GET |
| list_tickets | /api/tickets-search.php |
GET |
| search_tickets | /api/tickets-search.php?query=... |
GET |
| get_ticket_stats | /api/tickets-stats.php |
GET |
| create_ticket | /api/tickets.json |
POST |
| update_ticket | /api/tickets-update.php/:number.json |
PATCH |
| delete_ticket | /api/tickets-delete.php/:number.json |
DELETE |
| get_parent_ticket | /api/tickets-subtickets-parent.php/:number.json |
GET |
| get_child_tickets | /api/tickets-subtickets-list.php/:number.json |
GET |
| create_subticket_link | /api/tickets-subtickets-create.php/:parent.json |
POST |
| unlink_subticket | /api/tickets-subtickets-unlink.php/:child.json |
DELETE |
| ID Resolution | /api/tickets-statuses.php |
GET |
API Key Encryption:
Input Validation:
Permission System:
Q: What is MCP?
A: MCP (Model Context Protocol) is a standard protocol for connecting AI assistants to external tools. This server implements MCP to allow Claude to interact with osTicket.
Q: Do I need to restart Claude after configuration changes?
A: Yes. Claude Desktop and Claude CLI must be restarted to reload MCP configurations.
Q: Can I use this with other AI assistants?
A: Yes! Any MCP-compatible client can use this server. Primarily tested with Claude Desktop and Claude CLI.
Q: Is it compatible with Node.js 16?
A: No. Requires Node.js 18+ for ESM support and modern JavaScript features.
Q: Does it work on Windows?
A: Yes! Tested on macOS, Linux, and Windows.
Q: Does it work with osTicket 1.17?
A: Not tested. Designed for osTicket 1.18.x. May work with 1.17 but compatibility not guaranteed.
Q: Can I use status names instead of IDs?
A: Yes! The MCP server automatically resolves status names (like "Open", "Closed", "Testing") to IDs by querying the /api/tickets-statuses.php endpoint. This works with your custom status names.
Q: What happens if I use an invalid status name?
A: You'll get a helpful error message listing all available status names from your osTicket instance.
Q: Does name resolution work for departments, topics, and SLA plans too?
A: Yes! The same smart resolution works for:
/api/tickets-statuses.php)Q: Are the resolved IDs cached?
A: Yes! Status names are loaded once per MCP server session and cached in memory for fast subsequent lookups.
Q: What are subtickets?
A: Subtickets allow you to create parent-child relationships between tickets. This is useful for organizing complex issues into main tickets with subtasks.
Q: Do I need the Subticket Manager Plugin for all tools?
A: No. Only for the 4 subticket-specific tools (get_parent_ticket, get_child_tickets, create_subticket_link, unlink_subticket). All other tools work without it.
Q: What happens if I try to use subticket tools without the plugin?
A: You'll receive an HTTP 501 error with message "Subticket plugin not available".
Q: Can a ticket have multiple parents?
A: No. Each ticket can only have one parent. If you try to link a ticket that already has a parent, you'll get an HTTP 422 error.
Q: Is it safe to use 0.0.0.0 as API key IP?
A: Only in development! For production, always use specific IP addresses. The 0.0.0.0 option requires the api-key-wildcard plugin and should only be used behind firewalls.
Q: Where are API keys stored?
A: In the .env file, which is excluded from Git via .gitignore. Never commit API keys to version control.
Q: Why am I getting 403 Forbidden errors?
A: Check permissions in Admin Panel β Plugins β API Endpoints β Configure. Ensure all required permissions are checked for your API key.
Q: Can I create read-only API keys?
A: Yes! In API Endpoints Plugin configuration, enable only can_read_tickets, can_search_tickets, and can_read_stats.
This MCP Server is released under the MIT License.
See LICENSE for details.
For questions or issues, please create an issue on GitHub:
Issue Tracker: https://github.com/markus-michalski/claude-mcp-osTicket/issues
When reporting issues, please include:
node -v)npm -v)Developed by Markus Michalski
Contributions welcome!
0.0.0.0 IP)See CHANGELOG.md for version history.