Sign inSign up

alzahar/autotask-mcp-standalone

By alzahar

Updated 16 days ago

Standalone MCP server exposing 23 Autotask PSA tools to Claude Desktop, CLI, and any MCP client.

Image
Integration & delivery
API management
Developer tools
1

1.4K

alzahar/autotask-mcp-standalone repository overview

autotask-mcp

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.

Quick Start

stdio (Claude Desktop / CLI)
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
HTTP (port 8523)
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
Using an env file
docker run --rm -i --env-file .env \
  -v autotask-cache:/data/cache \
  -e TRANSPORT=stdio \
  alzarak/autotask-mcp:latest

Claude Desktop Configuration

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"
      ]
    }
  }
}

Environment Variables

VariableRequiredDefaultDescription
AUTOTASK_API_USERNAMEYes--API user email
AUTOTASK_API_SECRETYes--API password/key
AUTOTASK_API_INTEGRATION_CODEYes--Tracking identifier
AUTOTASK_BASE_URLYes--Zone base URL
TRANSPORTNohttpstdio or http
AUTOTASK_DEFAULT_USER_EMAILNo--Fallback email for assigned_to="me" in stdio mode
ENABLE_PERSISTENT_CACHENofalseEnable L2 persistent cache (auto-enabled for stdio)
USE_REDIS_CACHENotrueUse Redis for L2 (false = SQLite)
REDIS_HOSTNoredisRedis hostname
REDIS_PORTNo6379Redis port
REDIS_PASSWORDNo--Redis password
DATA_RETENTION_YEARSNo4Years of history to retain (0 = disabled)
BILLING_CODE_NON_BILLABLE_IDSNo--Comma-separated billingCodeID integers always classified as non-billable
BILLING_CODE_BILLABLE_IDSNo--Comma-separated billingCodeID integers always classified as billable
TICKET_SYNC_ENABLEDNotrueBackground ticket sync (disabled in stdio)
TICKET_SYNC_INTERVAL_SECONDSNo300Ticket sync interval
CHARGE_SYNC_ENABLEDNotrueBackground charge sync (disabled in stdio)
CHARGE_SYNC_INTERVAL_SECONDSNo900Charge sync interval
Billing Classification

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
Company Aliases (advanced)

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.

User Defined Fields (UDFs)

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.

  • Discovery: list_udf_definitions returns the UDF schema for a given entity, including picklist values where applicable.
  • Surfacing: Pass 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.
  • Filtering: Pass 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.
  • Coercion: 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.
  • UDF picklists: search_picklist_values with is_udf="true" resolves labels/values for User Defined Fields, which are not exposed through the standard /PicklistValues route.

Transport Modes

ModeUse CaseCacheSync
stdioClaude Desktop / CLISQLite L2 (auto)Disabled by default
httpRemote / multi-clientRedis or SQLite L2Enabled 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.

Volumes

PathPurpose
/data/cacheSQLite L2 cache persistence. Mount a named volume to retain cache across container restarts.

Health Check

curl http://localhost:8523/health

The container includes a built-in healthcheck that polls /health every 10 seconds.

Tools (24)

Entity Operations
  • get_entity -- Fetch single entity by ID (36 entity types: company, ticket, task, project, resource, asset, contact, contracts, charges, attachments, notes, invoice, billing_item, company_note, company_alert, company_location, configuration_item_note, ticket_category, phase, service_call, expense_report, expense_item, and more). Accepts coerce_udfs and fields=full|+udfs|udf:<Name> for UDF surfacing.
  • search_entity -- Search entities by filters (29 entity types). Accepts udf_filter for server-side UDF predicates and coerce_udfs for type casting.
  • search_attachments -- Search file attachments by parent (project, task, project_note, task_note, contract_note)
  • search_picklist_values -- Picklist/dropdown values for any entity field (is_udf="true" resolves UDF picklists)
  • list_udf_definitions -- Per-entity UDF schema (name, label, dataType, isPickList, picklistValues) for 19 entity types
Tickets
  • search_tickets -- Full ticket search with assignment, filters, notes query, enrichment, udf_filter, and coerce_udfs
  • count_tickets -- Count tickets matching filters
  • group_tickets -- Group/count tickets by field with optional hours aggregation
  • sub_issue_analytics -- Sub-issue analytics with 3 breakdown modes
  • search_ticket_notes -- Ticket note + time entry history
  • search_time_entries -- Time entries with billing classification
  • get_ticket_hours -- Aggregated billing hours per ticket
Charges
  • search_ticket_charges / search_project_charges -- Charge records by ticket or project
  • get_ticket_charge_totals / get_project_charge_totals -- Aggregated charge totals
Tasks
  • search_task_predecessors -- Task dependency queries
  • search_task_secondary_resources -- Task secondary resource assignments
Exports
  • create_excel_document / create_word_document -- OneDrive export via Microsoft Graph
  • export_tickets_to_excel / export_tickets_to_word -- Ticket-specific exports
Observability
  • check_api_connection -- API health check
  • get_sync_status -- Sync and cache health status

Cache System

Two-tier cache reduces API calls and improves response times:

  • L1 (Memory): In-process LRU, 100 MB limit, sub-millisecond reads
  • L2 (SQLite or Redis): Persistent, 1 GB limit, 30-day TTL
EntityTTL
Companies24 hours
Picklists1 hour
UDF schema1 hour
Entity lookups5 minutes
Search results1 minute

Docker Compose

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

Image Details

  • Base image: python:3.11-slim
  • Runs as: non-root user (mcpuser, UID 1000)
  • Exposed port: 8523
  • Memory limit: 2 GB (recommended)

Source

https://github.com/Alzarak/autotask-mcp

License

MIT

Tag summary

Content type

Image

Digest

sha256:aa6021bd5

Size

84.9 MB

Last updated

16 days ago

docker pull alzahar/autotask-mcp-standalone