Skip to main content
Glama
dspray

claude-halopsa-mcp

by dspray
README.md
# claude-halopsa-mcp

PrecisionIT launcher for the HaloPSA MCP connector. Mirrors the Meraki connector
pattern: the connector authenticates to Azure with the technician's own
`az login` identity and pulls HaloPSA OAuth config from Azure Key Vault **at
runtime**. No secrets ever land in the Claude config file.

The actual MCP server is the upstream package
[`@adamhancock/halopsa-mcp`](https://www.npmjs.com/package/@adamhancock/halopsa-mcp);
this repo is the Key Vault launcher that wraps it.

## How it works

1. Claude Desktop / Claude Code spawns `node mcp-keyvault-launch.js`.
2. The launcher uses `AzureCliCredential` (the tech's `az login` session) to read
   four secrets from Key Vault — **RW vault first, whole-set fallback to RO**:

   | Vault secret      | Env var injected        |
   |-------------------|-------------------------|
   | `HaloPsaUrl`      | `HALOPSA_URL`           |
   | `HaloPsaTenant`   | `HALOPSA_TENANT`        |
   | `HaloPsaClientId` | `HALOPSA_CLIENT_ID`     |
   | `HaloPsaClientSecret` | `HALOPSA_CLIENT_SECRET` |

3. With those in the environment, it spawns `@adamhancock/halopsa-mcp` over stdio.
   stdout is the MCP JSON-RPC channel; all launcher diagnostics go to stderr.

Vaults: `PrecisionIT-MCP-RW` (read-write techs) and `PrecisionIT-MCP-RO`
(read-only techs). RW vs RO is an Entra entitlement, not a machine setting.

## Prerequisites

- git
- Node.js 18+
- Azure CLI, signed in (`az login`) with an identity entitled to one of the vaults
- Claude Desktop and/or Claude Code

## Install

**macOS / Linux**
```bash
curl -fsSL https://raw.githubusercontent.com/dspray/claude-halopsa-mcp/main/install/install.sh | bash
```

**Windows (PowerShell)**
```powershell
powershell -ExecutionPolicy Bypass -Command "iwr https://raw.githubusercontent.com/dspray/claude-halopsa-mcp/main/install/install.ps1 -OutFile $env:TEMP\h.ps1; & $env:TEMP\h.ps1"
```

The installer resolves node's absolute path, clones this repo to
`~/claude-halopsa-mcp`, runs `npm ci`, and writes the `halopsa` entry into the
Claude Desktop config (backing it up first) and Claude Code (via `claude mcp
add`, if the CLI is present). It is idempotent.

After installing, **fully quit and reopen Claude Desktop**, then confirm the
`halopsa` tools load and run a harmless read (e.g. "list a couple of Halo
clients").

## Manual config (if you skip the installer)

```json
{
  "mcpServers": {
    "halopsa": {
      "command": "/absolute/path/to/node",
      "args": ["/Users/you/claude-halopsa-mcp/mcp-keyvault-launch.js"]
    }
  }
}
```
No `env` block — the launcher fetches everything at runtime.

## Troubleshooting

- **No tools after install:** confirm a *full* quit + reopen (not just closing the
  window), and that the config was written to the app you're actually using.
- **Credential error on stderr:** `az login` session expired (`az login` again) or
  `az` isn't on the launcher's PATH.
- **401/403 from Halo on a working install:** the OAuth token cache (~1 hour after
  a scope change). Disconnect and reconnect the connector to force a fresh token.
- **Calls hang then time out:** the MCP server wedged — fully quit and relaunch
  Claude Desktop.

## Notes

- The connector authenticates as a shared PrecisionIT HaloPSA OAuth application;
  Halo action attribution reflects that app. Per-tech attribution here is at the
  Key Vault access layer (who pulled the secret), same as the Meraki connector.
- If you rename the Key Vault secrets, edit `SECRET_MAP` at the top of
  `mcp-keyvault-launch.js` to match.