Connects to HaloPSA's REST API with OAuth 2.0 credentials to manage PSA workflows. Uses a decision tree architecture where you start with a navigation tool, select a domain (tickets, clients, assets, agents, or invoices), then get domain-specific operations loaded on demand. For tickets you can list, create, update, and add actions. Clients and assets support CRUD and search. Agents and invoices are read-only. The hierarchical loading keeps the initial tool set small instead of exposing everything upfront. Reach for this if you're running a service desk on HaloPSA and want Claude to query ticket status, create client records, or look up asset configurations without switching contexts.
A Model Context Protocol (MCP) server for interacting with HaloPSA, featuring a decision tree architecture for efficient tool loading.
[!IMPORTANT] Before you click: this server depends on
@wyre-technology/node-halopsa, which is hosted on the GitHub Packages npm registry. GitHub Packages has no anonymous access — even though the package is public, everynpm installneeds a token. The cloud builder runsnpm installfor you, so you must give it one, or the build fails withnpm error 401 Unauthorized ... npm.pkg.github.com.
- Create a GitHub Personal Access Token with the
read:packagesscope (classic token). Any GitHub account works — you do not need to be a member of thewyre-technologyorg to read its public packages.- Add it as a build variable when prompted by the deploy flow:
- Cloudflare Workers → set a build variable named
NODE_AUTH_TOKENto your PAT (Workers → Settings → Build → Variables and Secrets).- DigitalOcean App Platform → set an encrypted env var named
GITHUB_TOKENwith scope Build Time to your PAT (the.do/app.yamlalready declares it).
[!NOTE] The DigitalOcean target builds the full Docker image and runs the complete MCP server over HTTP — this is the recommended path for operators. The Cloudflare Workers target is currently a thin entrypoint (the
/mcproute returns 501 until the Workers transport adapter lands) and is best suited to gateway-style deployments; for a full self-hosted server prefer DigitalOcean or the prebuilt container image (ghcr.io/wyre-technology/halopsa-mcp).
This MCP server uses a hierarchical tool loading approach instead of exposing all tools upfront:
halopsa_navigate)This architecture provides:
This package is published to the GitHub Packages npm registry, which requires a token even for public packages. Authenticate once, then install:
# Authenticate npm to GitHub Packages (token needs the read:packages scope)
export NODE_AUTH_TOKEN=$(gh auth token) # or a PAT with read:packages
npm install @wyre-technology/halopsa-mcp
The repo's .npmrc already points the @wyre-technology scope at GitHub Packages and
reads the token from NODE_AUTH_TOKEN, so no further config is needed.
Set the following environment variables:
| Variable | Required | Description |
|---|---|---|
HALOPSA_CLIENT_ID | Yes | OAuth 2.0 Client ID |
HALOPSA_CLIENT_SECRET | Yes | OAuth 2.0 Client Secret |
HALOPSA_TENANT | One of | Tenant name (e.g., yourcompany) |
HALOPSA_BASE_URL | these | Explicit base URL (e.g., https://yourcompany.halopsa.com) |
# Set credentials
export HALOPSA_CLIENT_ID="your-client-id"
export HALOPSA_CLIENT_SECRET="your-client-secret"
export HALOPSA_TENANT="yourcompany"
# Run the server
npx @wyre-technology/halopsa-mcp
Add to your Claude Desktop claude_desktop_config.json:
{
"mcpServers": {
"halopsa": {
"command": "npx",
"args": ["@wyre-technology/halopsa-mcp"],
"env": {
"HALOPSA_CLIENT_ID": "your-client-id",
"HALOPSA_CLIENT_SECRET": "your-client-secret",
"HALOPSA_TENANT": "yourcompany"
}
}
}
}
docker build -t halopsa-mcp .
docker run -e HALOPSA_CLIENT_ID=xxx -e HALOPSA_CLIENT_SECRET=xxx -e HALOPSA_TENANT=yourcompany halopsa-mcp
Manage support tickets, create new tickets, update status, add actions/notes.
Tools:
halopsa_tickets_list - List tickets with filtershalopsa_tickets_get - Get ticket detailshalopsa_tickets_create - Create a new tickethalopsa_tickets_update - Update an existing tickethalopsa_tickets_add_action - Add a note/action to a ticketManage companies/clients in HaloPSA.
Tools:
halopsa_clients_list - List clientshalopsa_clients_get - Get client detailshalopsa_clients_create - Create a new clienthalopsa_clients_search - Search clients by nameManage configuration items/assets.
Tools:
halopsa_assets_list - List assets with filtershalopsa_assets_get - Get asset detailshalopsa_assets_search - Search assetshalopsa_assets_list_types - List available asset typesView technicians and teams.
Tools:
halopsa_agents_list - List agents/technicianshalopsa_agents_get - Get agent detailshalopsa_teams_list - List teamsView billing and invoices.
Tools:
halopsa_invoices_list - List invoices with filtershalopsa_invoices_get - Get invoice detailsAlways available:
halopsa_navigate - Select a domain to work withhalopsa_status - Show current state and credential statushalopsa_back - Return to main menu (when in a domain)User: Check my tickets
Claude: [calls halopsa_navigate with domain="tickets"]
-> Navigated to tickets domain. Available tools: ...
User: List open tickets
Claude: [calls halopsa_tickets_list with open_only=true]
-> [ticket list results]
User: Now show me clients
Claude: [calls halopsa_back]
-> Navigated back to main menu.
[calls halopsa_navigate with domain="clients"]
-> Navigated to clients domain.
HaloPSA has a rate limit of 500 requests per 3-minute window. The underlying @asachs01/node-halopsa client handles this automatically with request throttling.
Apache-2.0
HALOPSA_CLIENT_ID*HaloPSA OAuth client ID
HALOPSA_CLIENT_SECRET*secretHaloPSA OAuth client secret
HALOPSA_TENANTHaloPSA tenant identifier (subdomain). Provide this or HALOPSA_BASE_URL.
HALOPSA_BASE_URLHaloPSA base URL (e.g. https://your-instance.halopsa.com). Provide this or HALOPSA_TENANT.
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