Standalone MCP server exposing 23 Autotask PSA tools to Claude Desktop, CLI, and any MCP client.
1.4K
Standalone MCP (Model Context Protocol) server for the Autotask PSA REST API. Exposes 24 tools for querying tickets, companies, projects, contracts, time entries, charges, User Defined Fields, and more -- consumable by Claude Desktop, Claude CLI, and any MCP-compatible client.
docker run --rm -i \
-e TRANSPORT=stdio \
-e [email protected] \
-e AUTOTASK_API_SECRET=your-api-secret \
-e AUTOTASK_API_INTEGRATION_CODE=your-integration-code \
-e AUTOTASK_BASE_URL=https://webservicesX.autotask.net/ATServicesRest \
-v autotask-cache:/data/cache \
alzarak/autotask-mcp:latest
docker run --rm -it \
-e [email protected] \
-e AUTOTASK_API_SECRET=your-api-secret \
-e AUTOTASK_API_INTEGRATION_CODE=your-integration-code \
-e AUTOTASK_BASE_URL=https://webservicesX.autotask.net/ATServicesRest \
-v autotask-cache:/data/cache \
-p 8523:8523 \
alzarak/autotask-mcp:latest
docker run --rm -i --env-file .env \
-v autotask-cache:/data/cache \
-e TRANSPORT=stdio \
alzarak/autotask-mcp:latest
Add to your claude_desktop_config.json:
{
"mcpServers": {
"autotask": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "TRANSPORT=stdio",
"-e", "[email protected]",
"-e", "AUTOTASK_API_SECRET=your-api-secret",
"-e", "AUTOTASK_API_INTEGRATION_CODE=your-integration-code",
"-e", "AUTOTASK_BASE_URL=https://webservicesX.autotask.net/ATServicesRest",
"-v", "autotask-cache:/data/cache",
"alzarak/autotask-mcp:latest"
]
}
}
}
| Variable | Required | Default | Description |
|---|---|---|---|
AUTOTASK_API_USERNAME | Yes | -- | API user email |
AUTOTASK_API_SECRET | Yes | -- | API password/key |
AUTOTASK_API_INTEGRATION_CODE | Yes | -- | Tracking identifier |
AUTOTASK_BASE_URL | Yes | -- | Zone base URL |
TRANSPORT | No | http | stdio or http |
AUTOTASK_DEFAULT_USER_EMAIL | No | -- | Fallback email for assigned_to="me" in stdio mode |
ENABLE_PERSISTENT_CACHE | No | false | Enable L2 persistent cache (auto-enabled for stdio) |
USE_REDIS_CACHE | No | true | Use Redis for L2 (false = SQLite) |
REDIS_HOST | No | redis | Redis hostname |
REDIS_PORT | No | 6379 | Redis port |
REDIS_PASSWORD | No | -- | Redis password |
DATA_RETENTION_YEARS | No | 4 | Years of history to retain (0 = disabled) |
BILLING_CODE_NON_BILLABLE_IDS | No | -- | Comma-separated billingCodeID integers always classified as non-billable |
BILLING_CODE_BILLABLE_IDS | No | -- | Comma-separated billingCodeID integers always classified as billable |
TICKET_SYNC_ENABLED | No | true | Background ticket sync (disabled in stdio) |
TICKET_SYNC_INTERVAL_SECONDS | No | 300 | Ticket sync interval |
CHARGE_SYNC_ENABLED | No | true | Background charge sync (disabled in stdio) |
CHARGE_SYNC_INTERVAL_SECONDS | No | 900 | Charge sync interval |
search_time_entries, get_ticket_hours, and the charge tools classify each
record as billable or non-billable. The two BILLING_CODE_* env vars let you
pin specific Autotask billingCodeID integers to one side of the split,
overriding the record's own isNonBillable flag. When both are unset, every
record falls through to its isNonBillable flag (defaulting to billable when
that flag is null), so the server runs fine without configuring them.
# Example: treat three internal work types as always non-billable
-e BILLING_CODE_NON_BILLABLE_IDS=10001,10002,10003
-e BILLING_CODE_BILLABLE_IDS=20001,20002,20003
config/company_aliases.yaml inside the image maps shorthand strings (e.g.
"ACME") to the full company names registered in your Autotask tenant, so
ticket search can resolve shorthands. The published image ships a small
generic example; to customize, mount your own file over it:
-v /path/to/your/company_aliases.yaml:/app/config/company_aliases.local.yaml
The loader prefers the .local.yaml variant when present, so this leaves the
example in place and overrides it. If you don't customize, callers can still
pass full company names directly; only shorthand expansion is affected.
Read-side UDF support spans 19 entity types (company, ticket, task, project,
resource, asset, contact, contract, service_call, configuration_item_note,
and others). UDF schema is fetched on demand from
/entityInformation/{entity}/userDefinedFields and cached for one hour.
list_udf_definitions returns the UDF schema for a given
entity, including picklist values where applicable.fields="full", "+udfs", or "udf:<Name>,udf:<Other>"
to get_entity, search_entity, and search_tickets to include UDFs in
responses. Default and minimal field tiers continue to omit UDFs.udf_filter='{"field":"...","op":"...","value":...}'
to search_entity and search_tickets to emit an Autotask {"udf": true}
clause. Autotask permits one UDF clause per query; search_tickets
bypasses the local cache when this is set so the predicate runs
server-side.coerce_udfs="true" (default) casts UDF string values to
their declared dataType (int, float, bool, ISO datetime) using the cached
schema. Set coerce_udfs="false" to receive raw strings.search_picklist_values with is_udf="true" resolves
labels/values for User Defined Fields, which are not exposed through the
standard /PicklistValues route.| Mode | Use Case | Cache | Sync |
|---|---|---|---|
stdio | Claude Desktop / CLI | SQLite L2 (auto) | Disabled by default |
http | Remote / multi-client | Redis or SQLite L2 | Enabled by default |
stdio forces SQLite L2 cache and disables background sync schedulers. Ideal for single-user local use with Claude Desktop or Claude CLI.
http exposes port 8523 with Streamable HTTP transport. Supports Redis L2 cache and background sync for multi-client deployments.
| Path | Purpose |
|---|---|
/data/cache | SQLite L2 cache persistence. Mount a named volume to retain cache across container restarts. |
curl http://localhost:8523/health
The container includes a built-in healthcheck that polls /health every 10 seconds.
coerce_udfs and fields=full|+udfs|udf:<Name> for UDF surfacing.udf_filter for server-side UDF predicates and coerce_udfs for type casting.is_udf="true" resolves UDF picklists)udf_filter, and coerce_udfsTwo-tier cache reduces API calls and improves response times:
| Entity | TTL |
|---|---|
| Companies | 24 hours |
| Picklists | 1 hour |
| UDF schema | 1 hour |
| Entity lookups | 5 minutes |
| Search results | 1 minute |
A compose.yaml is included in the GitHub repository with optional Redis support:
# SQLite L2 only
docker compose up -d
# With Redis L2 cache
docker compose --profile redis up -d
python:3.11-slimmcpuser, UID 1000)https://github.com/Alzarak/autotask-mcp
Content type
Image
Digest
sha256:aa6021bd5…
Size
84.9 MB
Last updated
16 days ago
docker pull alzahar/autotask-mcp-standalone