
Connects Claude to Kaseya Autotask PSA with 39 tools covering the daily workflow of MSP teams: ticket search and triage, time entry logging, company and contact lookups, project management, billing item review, and attachment handling. Built by Wyre Technology as part of their MSP Claude Plugins ecosystem, which includes similar integrations for Datto RMM, IT Glue, HaloPSA, ConnectWise Automate, and NinjaOne. Supports both stdio for local Claude Desktop use and HTTP Streamable transport for remote deployments. Ships with MCPB bundles for one-click installation, Docker images with health checks, and a gateway mode for multi-tenant deployments where credentials are injected via HTTP headers. If you run an MSP on Autotask and want to eliminate context switching between browser tabs and AI chat, this gives Claude direct API access to your PSA environment.
Give your AI assistant direct access to Autotask. Search tickets, create time entries, look up companies, manage projects — all through natural language. No more copy-pasting between browser tabs and chat windows.
This is a Model Context Protocol (MCP) server that connects Claude (or any MCP-compatible AI) to your Autotask PSA environment. Your AI assistant gets 101 tools covering the operations MSP teams use daily: ticket triage, time logging, company lookups, project management, billing review, and more.
If you run an MSP on Autotask and you're tired of the context-switching tax, this is for you.
Part of the MSP Claude Plugins ecosystem — a growing suite of AI integrations for the MSP stack including Datto RMM, IT Glue, HaloPSA, ConnectWise Automate, NinjaOne, Huntress, and more. Built by MSPs, for MSPs.
Note — no GitHub Packages token required. Unlike most WYRE MCP servers,
autotask-mcpdoes not depend on a private@wyre-ai/*package on GitHub Packages. Its only WYRE dependency is theautotask-nodeSDK, declared as a git dependency on the publicWYRE-AI/autotask-noderepo, whichnpm installresolves anonymously. The DigitalOcean one-click deploy therefore works without anyNODE_AUTH_TOKEN/GITHUB_TOKENbuild variable.
Claude Desktop — download, open, done:
autotask-mcp.mcpb from the latest releaseNo terminal, no JSON editing, no Node.js install required.
Claude Code (CLI):
claude mcp add autotask-mcp \
-e AUTOTASK_USERNAME=your-user@company.com \
-e AUTOTASK_SECRET=your-secret \
-e AUTOTASK_INTEGRATION_CODE=your-code \
-- npx -y github:WYRE-AI/autotask-mcp
See Installation for Docker and from-source methods.
autotask_get_ticket_details renders as an interactive card in MCP Apps hosts (Claude Desktop/web) with an in-card "Add note" round-trip; neutral theme by default, brandable via MCP_BRAND_* env vars; plain-JSON behavior is unchanged in other hostsThe simplest method — no terminal, no JSON editing, no Node.js install required.
autotask-mcp.mcpb from the latest releaseFor Claude Code (CLI), one command:
claude mcp add autotask-mcp \
-e AUTOTASK_USERNAME=your-user@company.com \
-e AUTOTASK_SECRET=your-secret \
-e AUTOTASK_INTEGRATION_CODE=your-code \
-- npx -y github:WYRE-AI/autotask-mcp
Local (stdio — for Claude Desktop or Claude Code):
{
"mcpServers": {
"autotask": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "MCP_TRANSPORT=stdio",
"-e", "AUTOTASK_USERNAME=your-user@company.com",
"-e", "AUTOTASK_SECRET=your-secret",
"-e", "AUTOTASK_INTEGRATION_CODE=your-code",
"--entrypoint", "node",
"ghcr.io/wyre-ai/autotask-mcp:latest",
"dist/entry.js"
]
}
}
}
Remote (HTTP Streamable — for server deployments):
docker run -d \
--name autotask-mcp \
-p 127.0.0.1:8080:8080 \
-e CONDUIT_S2S_SECRET="your-real-s2s-secret" \
-e AUTOTASK_USERNAME="your-user@company.com" \
-e AUTOTASK_SECRET="your-secret" \
-e AUTOTASK_INTEGRATION_CODE="your-code" \
--restart unless-stopped \
ghcr.io/wyre-ai/autotask-mcp:latest
# Verify (health does not require X-Gateway-S2S)
curl http://127.0.0.1:8080/health
The HTTP server refuses to start when CONDUIT_S2S_SECRET is empty or a known placeholder. Clients connect to http://127.0.0.1:8080/mcp using MCP Streamable HTTP transport and must send X-Gateway-S2S. See X-Gateway-S2S signing.
Gateway Mode (for MCP Gateway deployments):
When deploying behind an MCP Gateway that injects credentials via HTTP headers. This container has no static Autotask credentials:
docker run -d \
--name autotask-mcp \
-p 127.0.0.1:8080:8080 \
-e CONDUIT_S2S_SECRET="your-real-s2s-secret" \
-e AUTH_MODE=gateway \
--restart unless-stopped \
ghcr.io/wyre-ai/autotask-mcp:latest
The gateway injects credentials via headers:
X-Gateway-S2S: service-to-service proof (required on /mcp)X-API-Key: Autotask usernameX-API-Secret: Autotask secretX-Integration-Code: Autotask integration codeX-Impersonation-Resource-Id: (optional) Autotask resource ID to act on behalf ofA /mcp request missing any of the three Autotask headers returns 401 and does not fall back to AUTOTASK_* in the environment. See Gateway Mode for details.
git clone https://github.com/WYRE-AI/autotask-mcp.git
cd autotask-mcp
npm ci && npm run build
Then point your MCP client at dist/entry.js:
{
"mcpServers": {
"autotask": {
"command": "node",
"args": ["/path/to/autotask-mcp/dist/entry.js"],
"env": {
"AUTOTASK_USERNAME": "your-user@company.com",
"AUTOTASK_SECRET": "your-secret",
"AUTOTASK_INTEGRATION_CODE": "your-code"
}
}
}
}
Create a .env file with your configuration:
# Required Autotask API credentials (Local Mode)
AUTOTASK_USERNAME=your-api-user@example.com
AUTOTASK_SECRET=your-secret-key
AUTOTASK_INTEGRATION_CODE=your-integration-code
# Optional configuration
# AUTOTASK_API_URL is auto-detected from AUTOTASK_USERNAME via Autotask's
# unauthenticated zoneInformation endpoint on first connect. Only set this
# explicitly to override auto-detection (e.g. for an on-prem proxy).
# AUTOTASK_API_URL=https://webservices2.autotask.net/atservicesrest/
MCP_SERVER_NAME=autotask-mcp
# Authentication mode
AUTH_MODE=env # env (local), gateway (hosted)
# Required to start HTTP. Empty and known placeholders are rejected.
# Never commit a real value. stdio does not use this.
CONDUIT_S2S_SECRET=
# Local HTTP only. Exactly "1" skips X-Gateway-S2S and forces 127.0.0.1.
# MCP_ALLOW_INSECURE_DEV=1
# Transport (stdio for local/desktop, http for remote/Docker)
MCP_TRANSPORT=stdio # stdio, http
MCP_HTTP_PORT=8080 # HTTP transport port (only used when MCP_TRANSPORT=http)
# Honored when CONDUIT_S2S_SECRET is set. Without a usable secret the bind is 127.0.0.1.
MCP_HTTP_HOST=0.0.0.0 # HTTP transport bind address
# Logging
LOG_LEVEL=info # error, warn, info, debug
LOG_FORMAT=simple # simple, json
# Search-result name enrichment
# Max concurrent Autotask API calls used to resolve company/resource names on
# search results. Kept low to stay under Autotask's per-integration
# concurrent-thread limit (raising it risks HTTP 429 "thread threshold").
AUTOTASK_ENHANCE_CONCURRENCY=3
# Max Autotask REST calls in flight per tenant. Further calls queue instead of
# tripping the concurrent-thread limit (HTTP 429 "thread threshold").
AUTOTASK_MAX_INFLIGHT=3
# Environment
NODE_ENV=production
When deployed behind an MCP Gateway (e.g., mcp.wyre.ai), the server operates in gateway mode where credentials are injected via HTTP headers on each request.
Enable Gateway Mode:
AUTH_MODE=gateway
MCP_TRANSPORT=http
CONDUIT_S2S_SECRET=<gateway-provisioned secret>
Every /mcp request must include a valid X-Gateway-S2S header and the three Autotask credential headers. A request missing any credential header returns 401. The server does not fall back to AUTOTASK_USERNAME, AUTOTASK_SECRET, or AUTOTASK_INTEGRATION_CODE in the process environment.
Expected Headers:
| Header | Description |
|---|---|
X-Gateway-S2S | Service-to-service proof. t=<unix seconds>,v1=<hex hmac-sha256>. Required on /mcp whenever CONDUIT_S2S_SECRET is set. See X-Gateway-S2S signing. |
X-API-Key | Autotask API username (email) |
X-API-Secret | Autotask API secret key |
X-Integration-Code | Autotask integration code |
X-API-URL | (Optional) Custom Autotask API URL |
X-Impersonation-Resource-Id | (Optional) Autotask resource ID to act on behalf of. Forwarded to Autotask as its ImpersonationResourceId header, so actions are attributed to that resource instead of the API user, and recorded in the entity's read-only impersonatorCreatorResourceID field. Must be a positive integer; anything else is ignored with a warning. The impersonated resource must itself have permission for the action, and the API user's security level must permit impersonation. |
MCP_TRANSPORT=http refuses to start unless CONDUIT_S2S_SECRET is a real secret. Empty values and known placeholders are rejected, including changeme, placeholder, your-s2s-secret, secret, password, test, and any value that is only an unresolved ${...} template. The process logs an error and exits non-zero. It never prints the secret.
MCP_ALLOW_INSECURE_DEV=1 is the local-only escape hatch. The process logs a warning, does not check X-Gateway-S2S, and listens on 127.0.0.1 only. A non-loopback MCP_HTTP_HOST (including 0.0.0.0, localhost, and ::1) is ignored in that mode and the override is logged.
Without a usable secret the bind address defaults to 127.0.0.1. A configured secret honors MCP_HTTP_HOST (default 0.0.0.0 when that variable is unset, which is what the container image sets). Publish the host port on loopback unless a proxy sits in front.
/health stays unauthenticated and does not read credentials. The stdio transport does not use CONDUIT_S2S_SECRET.
With a usable secret, every /mcp request must include:
X-Gateway-S2S: t=<unix seconds>,v1=<lowercase hex>
v1 is HMAC-SHA256, hex-encoded, of the ASCII string t=<unix seconds> (the same t= prefix that starts the header), keyed with CONDUIT_S2S_SECRET. The timestamp must be within 300 seconds of the server clock. A missing or invalid header returns HTTP 401. The secret is never written to logs or the response body.
# t is the current unix time. v1 is HMAC-SHA256 of the literal "t=$t".
t=$(date +%s)
v1=$(printf 't=%s' "$t" | openssl dgst -sha256 -hmac "$CONDUIT_S2S_SECRET" | awk '{print $NF}')
curl -sS http://127.0.0.1:8080/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "X-Gateway-S2S: t=${t},v1=${v1}" \
-H "X-API-Key: api-user@example.com" \
-H "X-API-Secret: the-api-secret" \
-H "X-Integration-Code: the-integration-code" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
In AUTH_MODE=env, /mcp still requires a valid X-Gateway-S2S header. Autotask credentials then come from AUTOTASK_*. In AUTH_MODE=gateway, the three X-API-* headers above are required as well and are the only credential source for that request.
Health Check Response (Gateway Mode):
{
"status": "ok",
"transport": "http",
"authMode": "gateway",
"timestamp": "2026-02-05T10:00:00.000Z"
}
For detailed migration instructions, see the Migration Guide.
💡 Pro Tip: Copy the above content to a .env file in your project root.
For detailed setup instructions, see the Autotask API documentation.
# Start the MCP server (stdio transport, for piping to an MCP client)
node dist/entry.js
# HTTP refuses to start until CONDUIT_S2S_SECRET is a real secret
CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" MCP_TRANSPORT=http node dist/index.js
# Local HTTP only, without a service-to-service secret (always binds 127.0.0.1)
MCP_ALLOW_INSECURE_DEV=1 MCP_TRANSPORT=http node dist/index.js
See Installation for all setup methods.
Resources provide read-only access to Autotask data:
autotask://companies - List all companiesautotask://companies/{id} - Get specific companyautotask://contacts - List all contactsautotask://contacts/{id} - Get specific contactautotask://tickets - List all ticketsautotask://tickets/{id} - Get specific ticketautotask://time-entries - List time entriesThe server provides 101 tools for interacting with Autotask:
autotask_search_companies - Search companies with filtersautotask_create_company - Create new companyautotask_update_company - Update existing companyautotask_search_contacts - Search contacts with filtersautotask_create_contact - Create new contactautotask_search_tickets - Search tickets with filtersautotask_get_ticket_details - Get full ticket details by IDautotask_create_ticket - Create new ticketautotask_create_time_entry - Log time entryautotask_search_time_entries - Search time entries with filters (resource, ticket, task, date range)autotask_search_billing_items - Search approved and posted billing itemsautotask_get_billing_item - Get specific billing item by IDautotask_search_billing_item_approval_levels - Search multi-level approval records for time entriesautotask_search_projects - Search projects with filtersautotask_create_project - Create new projectautotask_search_resources - Search resources (technicians/users)autotask_get_ticket_note / autotask_search_ticket_notes / autotask_create_ticket_noteautotask_get_project_note / autotask_search_project_notes / autotask_create_project_noteautotask_get_company_note / autotask_search_company_notes / autotask_create_company_noteautotask_get_ticket_attachment - Get ticket attachmentautotask_search_ticket_attachments - Search ticket attachmentsautotask_get_ticket_note_attachment - Get an attachment on a ticket note (e.g. a pasted screenshot)autotask_search_ticket_note_attachments - Search attachments on a ticket noteautotask_get_expense_report / autotask_search_expense_reports / autotask_create_expense_reportautotask_get_quote / autotask_search_quotes / autotask_create_quoteautotask_get_opportunity / autotask_search_opportunities / autotask_create_opportunityautotask_update_opportunity - Update an opportunity (stage, status, revenue/cost lines, UDFs)autotask_search_invoices - Search invoicesautotask_search_contracts - Search contracts (name, company, status, type, end-date range)autotask_get_contract - Get a single contract by IDautotask_list_expiring_contracts - Expiring/expired contracts report (next N days, per company or org-wide)autotask_create_contract / autotask_create_contracts_bulk - Create contract shells, one or manyautotask_update_contract - Update a contract (e.g. extend/renew end date)autotask_create_contract_service / autotask_update_contract_service - Manage contract service linesautotask_search_configuration_items - Search configuration items (assets)autotask_search_tasks - Search project tasksautotask_create_task - Create project taskautotask_test_connection - Test API connectivity// Search for companies
{
"name": "autotask_search_companies",
"arguments": {
"searchTerm": "Acme Corp",
"isActive": true,
"pageSize": 10
}
}
// Create a new ticket
{
"name": "autotask_create_ticket",
"arguments": {
"companyID": 12345,
"title": "Server maintenance request",
"description": "Need to perform monthly server maintenance",
"priority": 2,
"status": 1
}
}
The Autotask MCP server includes intelligent ID-to-name mapping that automatically resolves company and resource IDs to human-readable names, making API responses much more useful for AI assistants and human users.
All search and detail tools automatically include an _enhanced field with resolved names:
{
"id": 12345,
"title": "Sample Ticket",
"companyID": 678,
"assignedResourceID": 90,
"_enhanced": {
"companyName": "Acme Corporation",
"assignedResourceName": "John Smith"
}
}
ID-to-name mapping is applied automatically to all search and detail tool results. No additional tools are needed — the _enhanced field is added transparently to every response that contains company or resource IDs.
Test the mapping functionality:
npm run test:mapping
For detailed mapping documentation, see docs/mapping.md.
The server supports the MCP Streamable HTTP transport for remote deployments (e.g., Docker, cloud hosting). Set MCP_TRANSPORT=http to enable it.
# Start with HTTP transport (exits unless CONDUIT_S2S_SECRET is a real secret)
CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" MCP_TRANSPORT=http MCP_HTTP_PORT=8080 node dist/index.js
The HTTP transport exposes:
POST /mcp — MCP Streamable HTTP endpoint. Requires X-Gateway-S2S when CONDUIT_S2S_SECRET is set. See X-Gateway-S2S signing.GET /health — Unauthenticated health check (returns {"status":"ok"}). Does not read credentials.Clients must send requests to /mcp with Accept: application/json, text/event-stream headers per the MCP Streamable HTTP specification.
The Docker image uses HTTP transport by default (port 8080) with a built-in health check.
The Docker image defaults to HTTP transport on port 8080 — suitable for remote/server deployments where clients connect over the network.
# Pull the latest image
docker pull ghcr.io/wyre-ai/autotask-mcp:latest
# Run container with HTTP transport (default). The image binds 0.0.0.0 inside
# the container; publish on loopback and pass the S2S secret.
docker run -d \
--name autotask-mcp \
-p 127.0.0.1:8080:8080 \
-e CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" \
-e AUTOTASK_USERNAME="your-api-user@example.com" \
-e AUTOTASK_SECRET="your-secret-key" \
-e AUTOTASK_INTEGRATION_CODE="your-integration-code" \
--restart unless-stopped \
ghcr.io/wyre-ai/autotask-mcp:latest
# Verify it's running (health does not require X-Gateway-S2S)
curl http://127.0.0.1:8080/health
Compose will not start when CONDUIT_S2S_SECRET is unset. The checked-in gateway service sets AUTH_MODE=gateway, publishes 127.0.0.1:8080:8080, and does not inject AUTOTASK_*:
CONDUIT_S2S_SECRET="$CONDUIT_S2S_SECRET" docker compose up
For stdio usage with Claude Desktop, see Installation Option 2.
# Clone repository
git clone https://github.com/WYRE-AI/autotask-mcp.git
cd autotask-mcp
# Create environment file
cp .env.example .env
# Edit .env with your credentials
# Start with docker-compose
docker compose up -d
# Build production image locally
docker build -t autotask-mcp:latest .
# Run container
docker run -d \
--name autotask-mcp \
--env-file .env \
--restart unless-stopped \
autotask-mcp:latest
# Start development environment with hot reload
docker compose --profile dev up autotask-mcp-dev
git clone https://github.com/WYRE-AI/autotask-mcp.git
cd autotask-mcp
npm install
npm run dev # Start development server with hot reload
npm run build # Build for production
npm run test # Run test suite
npm run test:watch # Run tests in watch mode
npm run test:coverage # Run tests with coverage
npm run lint # Run ESLint
npm run lint:fix # Fix ESLint issues
autotask-mcp/
├── src/
│ ├── handlers/ # MCP request handlers
│ ├── mcp/ # MCP server implementation
│ ├── services/ # Autotask service layer
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utility functions (config, logger, cache)
│ ├── entry.ts # Entry point (stdout guard + .env loader)
│ └── index.ts # Server bootstrap (config, logger, server init)
├── tests/ # Test files
├── scripts/ # Build and packaging scripts
│ └── pack-mcpb.js # MCPB bundle creation
├── manifest.json # MCPB manifest for desktop distribution
├── Dockerfile # Container definition (HTTP transport)
├── docker-compose.yml # Multi-service orchestration
└── package.json # Project configuration
# Run all tests
npm test
# Run with coverage
npm run test:coverage
# Run in watch mode
npm run test:watch
# Run specific test file
npm test -- tests/autotask-service.test.ts
| Variable | Required | Default | Description |
|---|---|---|---|
AUTOTASK_USERNAME | ✅ | - | Autotask API username (email) |
AUTOTASK_SECRET | ✅ | - | Autotask API secret key |
AUTOTASK_INTEGRATION_CODE | ✅ | - | Autotask integration code |
AUTOTASK_API_URL | ❌ | Auto-detected | Autotask API endpoint URL |
MCP_SERVER_NAME | ❌ | autotask-mcp | MCP server name |
MCP_TRANSPORT | ❌ | stdio | Transport type (stdio or http) |
MCP_HTTP_PORT | ❌ | 8080 | HTTP transport port |
MCP_HTTP_HOST | ❌ | 0.0.0.0 when a secret is set; 127.0.0.1 without one | HTTP bind address. A configured CONDUIT_S2S_SECRET honors this variable. MCP_ALLOW_INSECURE_DEV=1 forces 127.0.0.1. |
CONDUIT_S2S_SECRET | Yes for HTTP | — | Service-to-service secret for X-Gateway-S2S. HTTP exits if this is empty or a known placeholder. Never commit a real value. |
MCP_ALLOW_INSECURE_DEV | ❌ | unset | Set to exactly 1 for local HTTP without a usable secret. Logs a warning, skips X-Gateway-S2S, and listens on 127.0.0.1 only. |
LOG_LEVEL | ❌ | info | Logging level |
LOG_FORMAT | ❌ | simple | Log output format |
AUTOTASK_ENHANCE_CONCURRENCY | ❌ | 3 | Max concurrent Autotask API calls used to resolve company/resource names on search results. Kept low to stay under Autotask's concurrent-thread limit. |
AUTOTASK_MAX_INFLIGHT | ❌ | 3 | Max Autotask REST calls in flight per tenant. Further calls queue in the HTTP client instead of tripping the concurrent-thread limit. |
NODE_ENV | ❌ | development | Node.js environment |
error: Only error messageswarn: Warnings and errorsinfo: General information, warnings, and errorsdebug: Detailed debugging informationsimple: Human-readable console outputjson: Structured JSON output (recommended for production)Autotask enforces per-integration-code API thresholds on a rolling 1-hour window:
HTTP 429 responsesHTTP 429 until the window rollsLLM-driven workflows fan out easily — "status report on all open projects with notes" can issue hundreds of requests across a few minutes. The server tries to make this safer:
error_type: "rate_limited" and a retry_after_seconds field parsed from Autotask's Retry-After header. The error message explicitly tells the LLM not to retry and to ask the user to scope the query — this prevents repeated retries from extending the cooldown.AUTOTASK_MAX_INFLIGHT calls in flight per tenant (default 3) and queues the rest. A thread-threshold 429 on an idempotent call (GET, DELETE, or POST /{Entity}/query) is retried with a short backoff and does not arm the 60s cooldown. Hourly-threshold 429s still arm it. Create/update calls are not retried automatically.autotask_search_ticket_notes, autotask_search_project_notes, autotask_search_company_notes, autotask_search_time_entries, autotask_search_ticket_attachments, autotask_search_ticket_note_attachments) include a hint reminding the LLM to scope the parent record list before iterating.Per-integration thresholds can be increased in Autotask:
This is the right answer when a single integration code is shared between Claude/Copilot/etc. and other tooling. For LLM-heavy workloads, dedicate a separate API user (and integration code) so a fan-out from one client doesn't starve others.
autotask_get_field_info to discover picklist values once per session rather than refetching them per call.If you're seeing threshold warnings from Autotask but the server seems fine, the LLM driver is probably issuing fan-out patterns. Tighten the prompt to scope before iterating.
Error: Missing required Autotask credentials
Solution: Ensure all required environment variables are set correctly.
Error: Connection to Autotask API failed
Solutions:
Error: User does not have permission to access this resource
Solution: Review Autotask API user permissions and security level settings.
Enable debug logging for detailed troubleshooting:
LOG_LEVEL=debug npm start
Test server connectivity:
# Run test suite
npm run test
# For HTTP transport, check the health endpoint
curl http://localhost:8080/health
# Returns: {"status":"ok"}
# Test API connection with debug logging
LOG_LEVEL=debug npm start
Problem: 429 Too Many Requests or "thread limit exceeded" errors when Claude queries aggressively
Autotask enforces 3 concurrent threads per endpoint per API tracking identifier. When an LLM issues multiple tool calls simultaneously (e.g., searching tickets, companies, and contacts at once), requests can pile up and hit this limit.
Built-in mitigation: The HTTP client caps in-flight requests per tenant (AUTOTASK_MAX_INFLIGHT, default 3) and queues the rest, so a parallel burst waits for a free slot instead of tripping the thread threshold. You may notice slower responses under heavy load. A thread-threshold 429 on an idempotent call is retried briefly; the hourly request threshold still surfaces as a structured rate-limit error and a short tenant cooldown.
Critical for team/multi-user deployments: If multiple users or the MCP Gateway share the same API credentials, they compete for the same 3-thread budget. This can cause noticeable slowdowns and, in severe cases, queued requests that time out.
Solution — one API key per team: Create a dedicated Autotask API user per team or integration. Each user has an independent integrationCode with its own thread budget:
AUTOTASK_USERNAME, AUTOTASK_SECRET, and AUTOTASK_INTEGRATION_CODE per teamSupport Team → AUTOTASK_INTEGRATION_CODE=SUPPORT_TEAM_CODE (3 threads)
Projects Team → AUTOTASK_INTEGRATION_CODE=PROJECTS_TEAM_CODE (3 threads, independent)
Additionally, Autotask limits 10,000 total requests per hour across all integrations hitting your tenant. If you hit this limit, all integrations will start receiving 429s — another reason to use targeted queries with appropriate filters.
Problem: MCP server not appearing in Claude Desktop Solutions:
Problem: "Invalid JSON-RPC message: [dotenv@...] injecting env" / Server disconnected
Cause: The autotask-node library calls dotenv.config() at module load time. dotenv v17+ writes status messages via console.log to stdout, which corrupts the MCP stdio JSON-RPC channel.
Solution: Ensure you're using dist/entry.js (not dist/index.js) as the entry point. The entry wrapper redirects console.log to stderr before any libraries load.
Problem: Slow responses Solutions:
LOG_LEVEL=debug) to identify bottlenecksgit checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)This project is licensed under the Apache License 2.0. See the LICENSE file for details.
By submitting a pull request, you agree to the terms of our Contributor License Agreement. This ensures that contributions can be properly licensed and that you have the right to submit the code.
| Avatar | Name | Contributions |
|---|---|---|
![]() | @asachs01 | Maintainer |
![]() | @Baphomet480 | CLI bin fix |
Built by WYRE Technology — part of the MSP Claude Plugins ecosystem
AUTOTASK_USERNAME*Autotask API user resource email (e.g. apiuser@example.com)
AUTOTASK_SECRET*secretAutotask API user secret
AUTOTASK_INTEGRATION_CODE*secretAutotask API integration code (tracking identifier)
AUTOTASK_API_URLAutotask API zone URL — auto-detected per tenant if omitted
MCP_TRANSPORTdefault: stdioTransport mode for the server. Set to 'stdio' for local CLI use; the image defaults to 'http' for gateway hosting.
AUTH_MODEdefault: envCredential source: 'env' reads vars locally, 'gateway' expects header injection from the WYRE MCP Gateway.
LOG_LEVELdefault: infoLog verbosity: debug, info, warn, error