{
  "markdown": "# Autotask MCP Server\n\n[![Build Status](https://github.com/WYRE-AI/autotask-mcp/actions/workflows/release.yml/badge.svg)](https://github.com/WYRE-AI/autotask-mcp/actions/workflows/release.yml)\n[![codecov](https://codecov.io/gh/WYRE-AI/autotask-mcp/graph/badge.svg)](https://codecov.io/gh/WYRE-AI/autotask-mcp)\n[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n[![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org/)\n\n**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.\n\nThis is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 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.\n\nIf you run an MSP on Autotask and you're tired of the context-switching tax, this is for you.\n\n> **Part of the [MSP Claude Plugins](https://github.com/WYRE-AI/msp-claude-plugins) ecosystem** — a growing suite of AI integrations for the MSP stack including [Datto RMM](https://github.com/WYRE-AI/datto-rmm-mcp), [IT Glue](https://github.com/WYRE-AI/itglue-mcp), [HaloPSA](https://github.com/WYRE-AI/halopsa-mcp), [ConnectWise Automate](https://github.com/WYRE-AI/connectwise-automate-mcp), [NinjaOne](https://github.com/WYRE-AI/ninjaone-mcp), [Huntress](https://github.com/WYRE-AI/huntress-mcp), and more. Built by MSPs, for MSPs.\n\n<a href=\"https://glama.ai/mcp/servers/@wyre-ai/autotask-mcp\">\n  <img width=\"380\" height=\"200\" src=\"https://glama.ai/mcp/servers/@wyre-ai/autotask-mcp/badge\" alt=\"Autotask MCP server\" />\n</a>\n\n## One-Click Deployment\n\n[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/WYRE-AI/autotask-mcp/tree/main)\n\n[![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button)](https://deploy.workers.cloudflare.com/?url=https://github.com/WYRE-AI/autotask-mcp)\n\n> **Note — no GitHub Packages token required.** Unlike most WYRE MCP servers,\n> `autotask-mcp` does **not** depend on a private `@wyre-ai/*` package on\n> GitHub Packages. Its only WYRE dependency is the `autotask-node` SDK, declared\n> as a git dependency on the **public** `WYRE-AI/autotask-node` repo, which\n> `npm install` resolves anonymously. The DigitalOcean one-click deploy therefore\n> works without any `NODE_AUTH_TOKEN`/`GITHUB_TOKEN` build variable.\n\n## Quick Start\n\n**Claude Desktop** — download, open, done:\n\n1. Download `autotask-mcp.mcpb` from the [latest release](https://github.com/WYRE-AI/autotask-mcp/releases/latest)\n2. Open the file (double-click or drag into Claude Desktop)\n3. Enter your Autotask credentials when prompted (Username, Secret, Integration Code)\n\nNo terminal, no JSON editing, no Node.js install required.\n\n**Claude Code (CLI):**\n\n```bash\nclaude mcp add autotask-mcp \\\n  -e AUTOTASK_USERNAME=your-user@company.com \\\n  -e AUTOTASK_SECRET=your-secret \\\n  -e AUTOTASK_INTEGRATION_CODE=your-code \\\n  -- npx -y github:WYRE-AI/autotask-mcp\n```\n\nSee [Installation](#installation) for Docker and from-source methods.\n\n## Features\n\n- **🔌 MCP Protocol Compliance**: Full support for MCP resources and tools\n- **🎴 Interactive Ticket Card (MCP Apps)**: `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 hosts\n- **🛠️ Comprehensive API Coverage**: 101 tools spanning companies, contacts, tickets, projects, billing items, time entries, notes, attachments, and more\n- **🔍 Advanced Search**: Powerful search capabilities with filters across all entities\n- **📝 CRUD Operations**: Create, read, update operations for core Autotask entities\n- **🔄 ID-to-Name Mapping**: Automatic resolution of company and resource IDs to human-readable names\n- **⚡ Intelligent Caching**: Smart caching system for improved performance and reduced API calls\n- **🔒 Secure Authentication**: Enterprise-grade API security with Autotask credentials\n- **🌐 Dual Transport**: Supports both stdio (local) and HTTP Streamable (remote/Docker) transports\n- **📦 MCPB Packaging**: One-click installation via MCP Bundle for desktop clients\n- **🐳 Docker Ready**: Containerized deployment with HTTP transport and health checks\n- **📊 Structured Logging**: Comprehensive logging with configurable levels and formats\n- **🧪 Test Coverage**: Comprehensive test suite with 80%+ coverage\n\n## Table of Contents\n\n- [Installation](#installation)\n- [Configuration](#configuration)\n  - [Gateway Mode](#gateway-mode)\n- [Usage](#usage)\n- [API Reference](#api-reference)\n- [ID-to-Name Mapping](#id-to-name-mapping)\n- [HTTP Transport](#http-transport)\n- [Docker Deployment](#docker-deployment)\n- [Migration Guide](docs/MIGRATION_GUIDE.md)\n- [Development](#development)\n- [Testing](#testing)\n- [Troubleshooting](#troubleshooting)\n- [Contributing](#contributing)\n- [Contributors](#contributors)\n- [License](#license)\n\n## Installation\n\n### Option 1: MCPB Bundle (Claude Desktop)\n\nThe simplest method — no terminal, no JSON editing, no Node.js install required.\n\n1. Download `autotask-mcp.mcpb` from the [latest release](https://github.com/WYRE-AI/autotask-mcp/releases/latest)\n2. Open the file (double-click or drag into Claude Desktop)\n3. Enter your Autotask credentials when prompted (Username, Secret, Integration Code)\n\nFor **Claude Code (CLI)**, one command:\n\n```bash\nclaude mcp add autotask-mcp \\\n  -e AUTOTASK_USERNAME=your-user@company.com \\\n  -e AUTOTASK_SECRET=your-secret \\\n  -e AUTOTASK_INTEGRATION_CODE=your-code \\\n  -- npx -y github:WYRE-AI/autotask-mcp\n```\n\n### Option 2: Docker\n\n**Local (stdio — for Claude Desktop or Claude Code):**\n\n```json\n{\n  \"mcpServers\": {\n    \"autotask\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"--rm\", \"-i\",\n        \"-e\", \"MCP_TRANSPORT=stdio\",\n        \"-e\", \"AUTOTASK_USERNAME=your-user@company.com\",\n        \"-e\", \"AUTOTASK_SECRET=your-secret\",\n        \"-e\", \"AUTOTASK_INTEGRATION_CODE=your-code\",\n        \"--entrypoint\", \"node\",\n        \"ghcr.io/wyre-ai/autotask-mcp:latest\",\n        \"dist/entry.js\"\n      ]\n    }\n  }\n}\n```\n\n**Remote (HTTP Streamable — for server deployments):**\n\n```bash\ndocker run -d \\\n  --name autotask-mcp \\\n  -p 8080:8080 \\\n  -e AUTOTASK_USERNAME=\"your-user@company.com\" \\\n  -e AUTOTASK_SECRET=\"your-secret\" \\\n  -e AUTOTASK_INTEGRATION_CODE=\"your-code\" \\\n  --restart unless-stopped \\\n  ghcr.io/wyre-ai/autotask-mcp:latest\n\n# Verify\ncurl http://localhost:8080/health\n```\n\nClients connect to `http://host:8080/mcp` using MCP Streamable HTTP transport.\n\n**Gateway Mode (for MCP Gateway deployments):**\n\nWhen deploying behind an MCP Gateway that injects credentials via HTTP headers:\n\n```bash\ndocker run -d \\\n  --name autotask-mcp \\\n  -p 8080:8080 \\\n  -e AUTH_MODE=gateway \\\n  --restart unless-stopped \\\n  ghcr.io/wyre-ai/autotask-mcp:latest\n```\n\nThe gateway injects credentials via headers:\n- `X-API-Key`: Autotask username\n- `X-API-Secret`: Autotask secret\n- `X-Integration-Code`: Autotask integration code\n- `X-Impersonation-Resource-Id`: (optional) Autotask resource ID to act on behalf of\n\nSee [Gateway Mode](#gateway-mode) for details.\n\n### Option 3: From Source (Development)\n\n```bash\ngit clone https://github.com/WYRE-AI/autotask-mcp.git\ncd autotask-mcp\nnpm ci && npm run build\n```\n\nThen point your MCP client at `dist/entry.js`:\n\n```json\n{\n  \"mcpServers\": {\n    \"autotask\": {\n      \"command\": \"node\",\n      \"args\": [\"/path/to/autotask-mcp/dist/entry.js\"],\n      \"env\": {\n        \"AUTOTASK_USERNAME\": \"your-user@company.com\",\n        \"AUTOTASK_SECRET\": \"your-secret\",\n        \"AUTOTASK_INTEGRATION_CODE\": \"your-code\"\n      }\n    }\n  }\n}\n```\n\n### Prerequisites\n\n- Valid Autotask API credentials (API user email, secret, integration code)\n- MCP-compatible client (Claude Desktop, Claude Code, etc.)\n- Docker (for Option 2) or Node.js 18+ (for Option 3)\n\n## Configuration\n\n### Environment Variables\n\nCreate a `.env` file with your configuration:\n\n```bash\n# Required Autotask API credentials (Local Mode)\nAUTOTASK_USERNAME=your-api-user@example.com\nAUTOTASK_SECRET=your-secret-key\nAUTOTASK_INTEGRATION_CODE=your-integration-code\n\n# Optional configuration\n# AUTOTASK_API_URL is auto-detected from AUTOTASK_USERNAME via Autotask's\n# unauthenticated zoneInformation endpoint on first connect. Only set this\n# explicitly to override auto-detection (e.g. for an on-prem proxy).\n# AUTOTASK_API_URL=https://webservices2.autotask.net/atservicesrest/\nMCP_SERVER_NAME=autotask-mcp\n\n# Authentication mode\nAUTH_MODE=env               # env (local), gateway (hosted)\n\n# Transport (stdio for local/desktop, http for remote/Docker)\nMCP_TRANSPORT=stdio          # stdio, http\nMCP_HTTP_PORT=8080           # HTTP transport port (only used when MCP_TRANSPORT=http)\nMCP_HTTP_HOST=0.0.0.0        # HTTP transport bind address\n\n# Logging\nLOG_LEVEL=info          # error, warn, info, debug\nLOG_FORMAT=simple       # simple, json\n\n# Search-result name enrichment\n# Max concurrent Autotask API calls used to resolve company/resource names on\n# search results. Kept low to stay under Autotask's per-integration\n# concurrent-thread limit (raising it risks HTTP 429 \"thread threshold\").\nAUTOTASK_ENHANCE_CONCURRENCY=3\n\n# Environment\nNODE_ENV=production\n```\n\n### Gateway Mode\n\nWhen 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.\n\n**Enable Gateway Mode:**\n\n```bash\nAUTH_MODE=gateway\nMCP_TRANSPORT=http\n```\n\n**Expected Headers:**\n\n| Header | Description |\n|--------|-------------|\n| `X-API-Key` | Autotask API username (email) |\n| `X-API-Secret` | Autotask API secret key |\n| `X-Integration-Code` | Autotask integration code |\n| `X-API-URL` | (Optional) Custom Autotask API URL |\n| `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. |\n\n**Health Check Response (Gateway Mode):**\n\n```json\n{\n  \"status\": \"ok\",\n  \"transport\": \"http\",\n  \"authMode\": \"gateway\",\n  \"timestamp\": \"2026-02-05T10:00:00.000Z\"\n}\n```\n\nFor detailed migration instructions, see the [Migration Guide](docs/MIGRATION_GUIDE.md).\n\n💡 **Pro Tip**: Copy the above content to a `.env` file in your project root.\n\n### Autotask API Setup\n\n1. **Create API User**: In Autotask, create a dedicated API user with appropriate permissions\n2. **Generate Secret**: Generate an API secret for the user\n3. **Integration Code**: Obtain your integration code from Autotask\n4. **Permissions**: Ensure the API user has read/write access to required entities\n\nFor detailed setup instructions, see the [Autotask API documentation](https://ww3.autotask.net/help/DeveloperHelp/Content/AdminSetup/2ExtensionsIntegrations/APIs/REST/REST_API_Home.htm).\n\n## Usage\n\n### Command Line\n\n```bash\n# Start the MCP server (stdio transport, for piping to an MCP client)\nnode dist/entry.js\n\n# Start with HTTP transport\nMCP_TRANSPORT=http node dist/index.js\n```\n\n### MCP Client Configuration\n\nSee [Installation](#installation) for all setup methods.\n\n## API Reference\n\n### Resources\n\nResources provide read-only access to Autotask data:\n\n- `autotask://companies` - List all companies\n- `autotask://companies/{id}` - Get specific company\n- `autotask://contacts` - List all contacts  \n- `autotask://contacts/{id}` - Get specific contact\n- `autotask://tickets` - List all tickets\n- `autotask://tickets/{id}` - Get specific ticket\n- `autotask://time-entries` - List time entries\n\n### Tools\n\nThe server provides 101 tools for interacting with Autotask:\n\n#### Company Operations\n- `autotask_search_companies` - Search companies with filters\n- `autotask_create_company` - Create new company\n- `autotask_update_company` - Update existing company\n\n#### Contact Operations\n- `autotask_search_contacts` - Search contacts with filters\n- `autotask_create_contact` - Create new contact\n\n#### Ticket Operations\n- `autotask_search_tickets` - Search tickets with filters\n- `autotask_get_ticket_details` - Get full ticket details by ID\n- `autotask_create_ticket` - Create new ticket\n\n#### Time Entry Operations\n- `autotask_create_time_entry` - Log time entry\n- `autotask_search_time_entries` - Search time entries with filters (resource, ticket, project, date range)\n\n#### Billing Items (Approve and Post Workflow)\n- `autotask_search_billing_items` - Search approved and posted billing items\n- `autotask_get_billing_item` - Get specific billing item by ID\n- `autotask_search_billing_item_approval_levels` - Search multi-level approval records for time entries\n\n#### Project Operations\n- `autotask_search_projects` - Search projects with filters\n- `autotask_create_project` - Create new project\n\n#### Resource Operations\n- `autotask_search_resources` - Search resources (technicians/users)\n\n#### Note Operations\n- `autotask_get_ticket_note` / `autotask_search_ticket_notes` / `autotask_create_ticket_note`\n- `autotask_get_project_note` / `autotask_search_project_notes` / `autotask_create_project_note`\n- `autotask_get_company_note` / `autotask_search_company_notes` / `autotask_create_company_note`\n\n#### Attachment Operations\n- `autotask_get_ticket_attachment` - Get ticket attachment\n- `autotask_search_ticket_attachments` - Search ticket attachments\n\n#### Financial Operations\n- `autotask_get_expense_report` / `autotask_search_expense_reports` / `autotask_create_expense_report`\n- `autotask_get_quote` / `autotask_search_quotes` / `autotask_create_quote`\n- `autotask_search_invoices` - Search invoices\n\n#### Contract Operations\n- `autotask_search_contracts` - Search contracts (name, company, status, type, end-date range)\n- `autotask_get_contract` - Get a single contract by ID\n- `autotask_list_expiring_contracts` - Expiring/expired contracts report (next N days, per company or org-wide)\n- `autotask_create_contract` / `autotask_create_contracts_bulk` - Create contract shells, one or many\n- `autotask_update_contract` - Update a contract (e.g. extend/renew end date)\n- `autotask_create_contract_service` / `autotask_update_contract_service` - Manage contract service lines\n\n#### Configuration Items\n- `autotask_search_configuration_items` - Search configuration items (assets)\n\n#### Task Operations\n- `autotask_search_tasks` - Search project tasks\n- `autotask_create_task` - Create project task\n\n#### Utility Operations\n- `autotask_test_connection` - Test API connectivity\n\n### Example Tool Usage\n\n```javascript\n// Search for companies\n{\n  \"name\": \"autotask_search_companies\",\n  \"arguments\": {\n    \"searchTerm\": \"Acme Corp\",\n    \"isActive\": true,\n    \"pageSize\": 10\n  }\n}\n\n// Create a new ticket\n{\n  \"name\": \"autotask_create_ticket\",\n  \"arguments\": {\n    \"companyID\": 12345,\n    \"title\": \"Server maintenance request\",\n    \"description\": \"Need to perform monthly server maintenance\",\n    \"priority\": 2,\n    \"status\": 1\n  }\n}\n```\n\n## ID-to-Name Mapping\n\nThe 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.\n\n### Automatic Enhancement\n\nAll search and detail tools automatically include an `_enhanced` field with resolved names:\n\n```json\n{\n  \"id\": 12345,\n  \"title\": \"Sample Ticket\",\n  \"companyID\": 678,\n  \"assignedResourceID\": 90,\n  \"_enhanced\": {\n    \"companyName\": \"Acme Corporation\",\n    \"assignedResourceName\": \"John Smith\"\n  }\n}\n```\n\n### How It Works\n\nID-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.\n\n### Performance Features\n\n- **Smart Caching**: Names are cached for 30 minutes to reduce API calls\n- **Bulk Operations**: Efficient batch lookups for multiple IDs\n- **Graceful Fallback**: Returns \"Unknown Company (123)\" if lookup fails\n- **Parallel Processing**: Multiple mappings resolved simultaneously\n\n### Testing Mapping\n\nTest the mapping functionality:\n\n```bash\nnpm run test:mapping\n```\n\nFor detailed mapping documentation, see [docs/mapping.md](docs/mapping.md).\n\n## HTTP Transport\n\nThe server supports the MCP Streamable HTTP transport for remote deployments (e.g., Docker, cloud hosting). Set `MCP_TRANSPORT=http` to enable it.\n\n```bash\n# Start with HTTP transport\nMCP_TRANSPORT=http MCP_HTTP_PORT=8080 node dist/index.js\n```\n\nThe HTTP transport exposes:\n- `POST /mcp` — MCP Streamable HTTP endpoint\n- `GET /health` — Health check (returns `{\"status\":\"ok\"}`)\n\nClients must send requests to `/mcp` with `Accept: application/json, text/event-stream` headers per the MCP Streamable HTTP specification.\n\n## Docker Deployment\n\nThe Docker image uses HTTP transport by default (port 8080) with a built-in health check.\n\n### Using Pre-built Image from GitHub Container Registry\n\nThe Docker image defaults to **HTTP transport** on port 8080 — suitable for remote/server deployments where clients connect over the network.\n\n```bash\n# Pull the latest image\ndocker pull ghcr.io/wyre-ai/autotask-mcp:latest\n\n# Run container with HTTP transport (default)\ndocker run -d \\\n  --name autotask-mcp \\\n  -p 8080:8080 \\\n  -e AUTOTASK_USERNAME=\"your-api-user@example.com\" \\\n  -e AUTOTASK_SECRET=\"your-secret-key\" \\\n  -e AUTOTASK_INTEGRATION_CODE=\"your-integration-code\" \\\n  --restart unless-stopped \\\n  ghcr.io/wyre-ai/autotask-mcp:latest\n\n# Verify it's running\ncurl http://localhost:8080/health\n```\n\nFor **stdio** usage with Claude Desktop, see [Installation Option 2](#option-2-docker).\n\n### Quick Start (From Source)\n\n```bash\n# Clone repository\ngit clone https://github.com/WYRE-AI/autotask-mcp.git\ncd autotask-mcp\n\n# Create environment file\ncp .env.example .env\n# Edit .env with your credentials\n\n# Start with docker-compose\ndocker compose up -d\n```\n\n### Production Deployment\n\n```bash\n# Build production image locally\ndocker build -t autotask-mcp:latest .\n\n# Run container\ndocker run -d \\\n  --name autotask-mcp \\\n  --env-file .env \\\n  --restart unless-stopped \\\n  autotask-mcp:latest\n```\n\n### Development Mode\n\n```bash\n# Start development environment with hot reload\ndocker compose --profile dev up autotask-mcp-dev\n```\n\n## Development\n\n### Setup\n\n```bash\ngit clone https://github.com/WYRE-AI/autotask-mcp.git\ncd autotask-mcp\nnpm install\n```\n\n### Available Scripts\n\n```bash\nnpm run dev          # Start development server with hot reload\nnpm run build        # Build for production\nnpm run test         # Run test suite\nnpm run test:watch   # Run tests in watch mode\nnpm run test:coverage # Run tests with coverage\nnpm run lint         # Run ESLint\nnpm run lint:fix     # Fix ESLint issues\n```\n\n### Project Structure\n\n```\nautotask-mcp/\n├── src/\n│   ├── handlers/           # MCP request handlers\n│   ├── mcp/               # MCP server implementation\n│   ├── services/          # Autotask service layer\n│   ├── types/             # TypeScript type definitions\n│   ├── utils/             # Utility functions (config, logger, cache)\n│   ├── entry.ts           # Entry point (stdout guard + .env loader)\n│   └── index.ts           # Server bootstrap (config, logger, server init)\n├── tests/                 # Test files\n├── scripts/               # Build and packaging scripts\n│   └── pack-mcpb.js       # MCPB bundle creation\n├── manifest.json          # MCPB manifest for desktop distribution\n├── Dockerfile             # Container definition (HTTP transport)\n├── docker-compose.yml     # Multi-service orchestration\n└── package.json          # Project configuration\n```\n\n## Testing\n\n### Running Tests\n\n```bash\n# Run all tests\nnpm test\n\n# Run with coverage\nnpm run test:coverage\n\n# Run in watch mode\nnpm run test:watch\n\n# Run specific test file\nnpm test -- tests/autotask-service.test.ts\n```\n\n### Test Categories\n\n- **Unit Tests**: Service layer and utility functions\n- **Integration Tests**: MCP protocol compliance\n- **API Tests**: Autotask API integration (requires credentials)\n\n### Coverage Requirements\n\n- Minimum 80% coverage for all metrics\n- 100% coverage for critical paths (authentication, data handling)\n\n## Configuration Reference\n\n### Environment Variables\n\n| Variable | Required | Default | Description |\n|----------|----------|---------|-------------|\n| `AUTOTASK_USERNAME` | ✅ | - | Autotask API username (email) |\n| `AUTOTASK_SECRET` | ✅ | - | Autotask API secret key |\n| `AUTOTASK_INTEGRATION_CODE` | ✅ | - | Autotask integration code |\n| `AUTOTASK_API_URL` | ❌ | Auto-detected | Autotask API endpoint URL |\n| `MCP_SERVER_NAME` | ❌ | `autotask-mcp` | MCP server name |\n| `MCP_TRANSPORT` | ❌ | `stdio` | Transport type (`stdio` or `http`) |\n| `MCP_HTTP_PORT` | ❌ | `8080` | HTTP transport port |\n| `MCP_HTTP_HOST` | ❌ | `0.0.0.0` | HTTP transport bind address |\n| `LOG_LEVEL` | ❌ | `info` | Logging level |\n| `LOG_FORMAT` | ❌ | `simple` | Log output format |\n| `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. |\n| `NODE_ENV` | ❌ | `development` | Node.js environment |\n\n### Logging Levels\n\n- `error`: Only error messages\n- `warn`: Warnings and errors\n- `info`: General information, warnings, and errors\n- `debug`: Detailed debugging information\n\n### Log Formats\n\n- `simple`: Human-readable console output\n- `json`: Structured JSON output (recommended for production)\n\n## Rate Limits\n\nAutotask enforces per-integration-code API thresholds on a rolling 1-hour window:\n\n- **~10,000 req/hr (soft)** — warning email, sporadic `HTTP 429` responses\n- **~20,000 req/hr (hard)** — sustained `HTTP 429` until the window rolls\n\nLLM-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:\n\n- **429 responses are surfaced as structured errors.** Tool results carry `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.\n- **Fan-out tool descriptions include rate-limit tips.** Tools that are commonly looped over (`autotask_search_ticket_notes`, `autotask_search_project_notes`, `autotask_search_company_notes`, `autotask_search_time_entries`, `autotask_search_ticket_attachments`) include a hint reminding the LLM to scope the parent record list before iterating.\n\n### Raising the limit\n\nPer-integration thresholds can be increased in Autotask:\n\n1. Autotask Admin → **Resources/Users (HR) → Resources**\n2. Edit the dedicated API user → **Workflow Rules → API Tracking Identifier**\n3. Adjust the threshold for the integration code your MCP server uses\n\nThis 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.\n\n### Patterns that help\n\n- **Always scope by date range** when searching notes, time entries, attachments. Even a 30-day window can drop call count by an order of magnitude.\n- **Cache parent lookups.** If you're iterating over 100 tickets, fetch the ticket list once and reuse it across follow-up queries; don't re-search per child.\n- **Use `autotask_get_field_info`** to discover picklist values once per session rather than refetching them per call.\n\nIf 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.\n\n## Troubleshooting\n\n### Common Issues\n\n#### Authentication Errors\n\n```\nError: Missing required Autotask credentials\n```\n**Solution**: Ensure all required environment variables are set correctly.\n\n#### Connection Timeouts\n\n```\nError: Connection to Autotask API failed\n```\n**Solutions**:\n- Check network connectivity\n- Verify API endpoint URL\n- Confirm API user has proper permissions\n\n#### Permission Denied\n\n```\nError: User does not have permission to access this resource\n```\n**Solution**: Review Autotask API user permissions and security level settings.\n\n### Debug Mode\n\nEnable debug logging for detailed troubleshooting:\n\n```bash\nLOG_LEVEL=debug npm start\n```\n\n### Health Checks\n\nTest server connectivity:\n\n```bash\n# Run test suite\nnpm run test\n\n# For HTTP transport, check the health endpoint\ncurl http://localhost:8080/health\n# Returns: {\"status\":\"ok\"}\n\n# Test API connection with debug logging\nLOG_LEVEL=debug npm start\n```\n\n### Autotask API Rate Limits\n\n**Problem**: `429 Too Many Requests` or \"thread limit exceeded\" errors when Claude queries aggressively\n\nAutotask 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.\n\n**Built-in mitigation**: The underlying `autotask-node` SDK automatically queues excess requests rather than failing immediately. Requests wait for a slot to free up, so you generally won't see 429 errors — but you may notice slower responses under heavy load.\n\n**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.\n\n**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:\n\n1. **Admin > Resources (Users) > Resources/Users** → Add Resource\n2. Set Security Level to **API User**\n3. Note the username, secret, and integration code\n4. Set `AUTOTASK_USERNAME`, `AUTOTASK_SECRET`, and `AUTOTASK_INTEGRATION_CODE` per team\n\n```\nSupport Team  → AUTOTASK_INTEGRATION_CODE=SUPPORT_TEAM_CODE  (3 threads)\nProjects Team → AUTOTASK_INTEGRATION_CODE=PROJECTS_TEAM_CODE (3 threads, independent)\n```\n\nAdditionally, 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.\n\n### MCP Client Issues\n\n**Problem**: MCP server not appearing in Claude Desktop\n**Solutions**:\n1. Check configuration file syntax (valid JSON)\n2. Verify file path in the configuration\n3. Ensure environment variables are set correctly\n4. Restart Claude Desktop completely\n\n**Problem**: \"Invalid JSON-RPC message: [dotenv@...] injecting env\" / Server disconnected\n**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.\n**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.\n\n**Problem**: Slow responses\n**Solutions**:\n1. Check network connectivity to Autotask API\n2. Enable debug logging (`LOG_LEVEL=debug`) to identify bottlenecks\n3. The server caches company/resource names for 30 minutes automatically\n\n### Security Best Practices\n\n- Store credentials in environment variables, not directly in config files\n- Limit Autotask API user permissions to the minimum required\n- Rotate API credentials regularly\n- For Docker deployments, use secrets management rather than plain environment variables\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n### Development Guidelines\n\n- Follow TypeScript best practices\n- Maintain test coverage above 80%\n- Use conventional commit messages\n- Update documentation for API changes\n- Add tests for new features\n\n## License\n\nThis project is licensed under the **Apache License 2.0**. See the [LICENSE](LICENSE) file for details.\n\n### Contributor License Agreement\n\nBy submitting a pull request, you agree to the terms of our [Contributor License Agreement](CLA.md). This ensures that contributions can be properly licensed and that you have the right to submit the code.\n\n## Contributors\n\n| Avatar | Name | Contributions |\n| --- | --- | --- |\n| <a href=\"https://github.com/asachs01\"><img src=\"https://github.com/asachs01.png\" width=\"60\" /></a> | [@asachs01](https://github.com/asachs01) | Maintainer |\n| <a href=\"https://github.com/Baphomet480\"><img src=\"https://github.com/Baphomet480.png\" width=\"60\" /></a> | [@Baphomet480](https://github.com/Baphomet480) | CLI bin fix |\n\n## Support\n\n- 📚 [Documentation](https://github.com/WYRE-AI/autotask-mcp/wiki)\n- 🐛 [Issue Tracker](https://github.com/WYRE-AI/autotask-mcp/issues)\n- 💬 [Discussions](https://github.com/WYRE-AI/autotask-mcp/discussions)\n\n## Acknowledgments\n\n- [Model Context Protocol](https://modelcontextprotocol.io/) by Anthropic\n- [Autotask REST API](https://ww3.autotask.net/help/DeveloperHelp/Content/APIs/REST/REST_API_Home.htm) by Kaseya\n- [autotask-node](https://www.npmjs.com/package/autotask-node) library\n\n---\n\nBuilt by [WYRE Technology](https://github.com/WYRE-AI) — part of the [MSP Claude Plugins](https://github.com/WYRE-AI/msp-claude-plugins) ecosystem ",
  "bytes": 30154,
  "sha": "453b49444ac2285dbd1c3ab6af7cfaff156da0f695ee24ce6e2d6305d60088ea",
  "repo_slug": "wyre-ai/autotask-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_wyre_ai_autotask_mcp_a023dcfe/readme"
}