Halo ITSM MCP Server
README.md
# Halo ITSM MCP Server
A [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that provides AI assistants with access to the [Halo ITSM/PSA/CRM REST API](https://haloitsm.com/). This enables Large Language Models (LLMs) like Claude, GPT, and others to interact with your Halo instance through a standardized protocol.
## Table of Contents
- [Overview](#overview)
- [Features](#features)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Configuration](#configuration)
- [Usage](#usage)
- [stdio Mode (Local)](#stdio-mode-local)
- [SSE Mode (Remote/HTTP)](#sse-mode-remotehttp)
- [Available Tools](#available-tools)
- [Architecture](#architecture)
- [Development](#development)
- [Troubleshooting](#troubleshooting)
- [License](#license)
---
## Overview
The Model Context Protocol (MCP) is an open standard that allows AI applications to securely connect to external data sources and tools. This server implements MCP for Halo ITSM, enabling AI assistants to:
- **Query tickets, users, clients, and other entities** from your Halo instance
- **Create and update tickets** programmatically
- **Manage assets, projects, appointments, and more**
- **Run reports and retrieve business intelligence data**
### What is Halo ITSM?
[Halo ITSM](https://haloitsm.com/) (also known as HaloPSA and HaloCRM) is a comprehensive IT Service Management platform used by MSPs, IT departments, and service organizations. It provides ticketing, asset management, project management, invoicing, and CRM capabilities through a unified platform.
### What is MCP?
The [Model Context Protocol](https://modelcontextprotocol.io/) is an open protocol that standardizes how AI applications connect to external data sources and tools. It enables:
- **Tool calling**: AI can invoke specific functions with parameters
- **Secure authentication**: Credentials are managed by the MCP server, not exposed to the AI
- **Structured data exchange**: Responses are formatted for optimal AI consumption
---
## Features
### 18 Resource Groups with 60+ Tools
This MCP server provides comprehensive coverage of the Halo ITSM API:
| Resource | Tools | Description |
|----------|-------|-------------|
| **Tickets** | 4 | List, get, create, update tickets |
| **Actions** | 4 | List, get, create, delete ticket actions/notes |
| **Users** | 4 | List, get, find by email, get current user |
| **Clients** | 4 | List, get, create, update clients |
| **Agents** | 2 | List, get agents |
| **Teams** | 2 | List, get teams |
| **Status** | 2 | List, get ticket statuses |
| **Ticket Types** | 2 | List, get ticket types |
| **Assets** | 4 | List, get, create, delete assets |
| **Sites** | 4 | List, get, create, update sites |
| **Projects** | 4 | List, get, create, update projects |
| **Opportunities** | 4 | List, get, create, update opportunities |
| **Appointments** | 3 | List, get, create, delete appointments |
| **Attachments** | 3 | List, get, delete attachments |
| **Items** | 3 | List, get, create catalog items |
| **Invoices** | 3 | List, get, void invoices |
| **Suppliers** | 4 | List, get, create, update suppliers |
| **Reports** | 3 | List, get, run reports |
### Two Transport Modes
1. **stdio Mode**: For local usage via command line (npx, direct execution)
2. **SSE Mode**: HTTP server with Server-Sent Events for remote/web deployments
### Authentication Support
- **Client Credentials Flow**: Machine-to-machine authentication (recommended)
- **Password Grant Flow**: Username/password authentication (fallback)
- **Automatic Token Management**: Tokens are cached and refreshed automatically
---
## Prerequisites
- **Node.js** v18.0.0 or higher
- **Halo ITSM instance** with API access enabled
- **API credentials** (Client ID + Client Secret, or Username + Password)
### Obtaining Halo API Credentials
1. Log into your Halo ITSM instance as an administrator
2. Navigate to **Configuration** → **Integrations** → **Halo API**
3. Create a new API application:
- Choose **Client Credentials** for server-to-server integration
- Note the **Client ID** and **Client Secret**
4. Configure appropriate API permissions for the application
---
## Installation
### From Source
```bash
# Clone the repository
git clone https://github.com/your-org/halo-mcp.git
cd halo-mcp
# Install dependencies
npm install
# Build the TypeScript code
npm run build
```
### Using npx (Coming Soon)
```bash
npx halo-mcp
```
---
## Configuration
The server is configured via environment variables. Create a `.env` file or set them in your shell:
### Required Variables
| Variable | Description | Example |
|----------|-------------|---------|
| `HALO_BASE_URL` | Your Halo instance URL | `https://yourcompany.halopsa.com` |
| `HALO_CLIENT_ID` | API Client ID | `abc123-def456-...` |
### Authentication Variables (choose one set)
**Option A: Client Credentials (Recommended)**
| Variable | Description |
|----------|-------------|
| `HALO_CLIENT_SECRET` | API Client Secret |
**Option B: Password Grant**
| Variable | Description |
|----------|-------------|
| `HALO_USERNAME` | Halo username |
| `HALO_PASSWORD` | Halo password |
### Optional Variables
| Variable | Description | Default |
|----------|-------------|---------|
| `HALO_TENANT` | Tenant identifier (for hosted/multi-tenant) | (none) |
| `HALO_SCOPE` | OAuth scope | `all` |
| `PORT` | HTTP server port (SSE mode only) | `3000` |
### Example .env File
```bash
# Halo Instance
HALO_BASE_URL=https://yourcompany.halopsa.com
HALO_TENANT=yourcompany
# Client Credentials Auth (recommended)
HALO_CLIENT_ID=your-client-id
HALO_CLIENT_SECRET=your-client-secret
# OR Password Grant Auth
# HALO_CLIENT_ID=your-client-id
# HALO_USERNAME=your-username
# HALO_PASSWORD=your-password
# Optional
HALO_SCOPE=all
PORT=3000
```
---
## Usage
### stdio Mode (Local)
The stdio mode is ideal for local development and direct integration with MCP clients like Claude Desktop.
#### Running Directly
```bash
# Development (with hot reload)
npm run dev
# Production
npm run build
npm start
```
#### With MCP Inspector
The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is useful for testing:
```bash
npx @modelcontextprotocol/inspector node dist/index.js
```
#### Claude Desktop Configuration
Add to your Claude Desktop config (`claude_desktop_config.json`):
```json
{
"mcpServers": {
"halo-itsm": {
"command": "node",
"args": ["/path/to/halo-mcp/dist/index.js"],
"env": {
"HALO_BASE_URL": "https://yourcompany.halopsa.com",
"HALO_CLIENT_ID": "your-client-id",
"HALO_CLIENT_SECRET": "your-client-secret"
}
}
}
}
```
### SSE Mode (Remote/HTTP)
The SSE (Server-Sent Events) mode runs an HTTP server, enabling remote access and browser-based MCP clients.
#### Running the SSE Server
```bash
# Development
npm run dev:sse
# Production
npm run build
npm run start:sse
```
The server starts on `http://localhost:3000` by default (configurable via `PORT` env var).
#### Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/sse` | GET | SSE connection endpoint (establish session) |
| `/messages` | POST | JSON-RPC message endpoint |
#### Connecting with MCP Inspector (SSE)
```bash
npx @modelcontextprotocol/inspector
```
Then connect to: `http://localhost:3000/sse`
#### Architecture for SSE Mode
```
┌─────────────────┐ GET /sse ┌──────────────────┐
│ MCP Client │ ─────────────────→│ │
│ (Inspector, │ SSE Stream │ Halo MCP SSE │
│ Browser, etc) │ ←─────────────────│ Server │
│ │ │ (Express.js) │
│ │ POST /messages │ │
│ │ ─────────────────→│ │
└─────────────────┘ └────────┬─────────┘
│
│ HTTPS
▼
┌──────────────────┐
│ Halo ITSM API │
│ (Your Instance) │
└──────────────────┘
```
---
## Available Tools
### Tickets
| Tool | Description |
|------|-------------|
| `halo_list_tickets` | List tickets with filters (search, client, status, agent, pagination) |
| `halo_get_ticket` | Get a single ticket by ID with full details |
| `halo_create_ticket` | Create a new ticket |
| `halo_update_ticket` | Update an existing ticket |
### Actions (Ticket Notes)
| Tool | Description |
|------|-------------|
| `halo_list_actions` | List actions/notes on tickets |
| `halo_get_action` | Get a single action by ID |
| `halo_create_action` | Add a note/action to a ticket |
| `halo_delete_action` | Delete an action |
### Users
| Tool | Description |
|------|-------------|
| `halo_list_users` | List users with filters |
| `halo_get_user` | Get a user by ID |
| `halo_find_user_by_email` | Find a user by email address |
| `halo_get_me` | Get the current authenticated user |
### Clients
| Tool | Description |
|------|-------------|
| `halo_list_clients` | List clients/customers |
| `halo_get_client` | Get a client by ID |
| `halo_create_client` | Create a new client |
| `halo_update_client` | Update an existing client |
### Agents
| Tool | Description |
|------|-------------|
| `halo_list_agents` | List all agents |
| `halo_get_agent` | Get an agent by ID |
### Teams
| Tool | Description |
|------|-------------|
| `halo_list_teams` | List all teams |
| `halo_get_team` | Get a team by ID |
### Status
| Tool | Description |
|------|-------------|
| `halo_list_statuses` | List all ticket statuses |
| `halo_get_status` | Get a status by ID |
### Ticket Types
| Tool | Description |
|------|-------------|
| `halo_list_ticket_types` | List all ticket types |
| `halo_get_ticket_type` | Get a ticket type by ID |
### Assets
| Tool | Description |
|------|-------------|
| `halo_list_assets` | List assets with filters |
| `halo_get_asset` | Get an asset by ID |
| `halo_create_asset` | Create a new asset |
| `halo_delete_asset` | Delete an asset |
### Sites
| Tool | Description |
|------|-------------|
| `halo_list_sites` | List sites |
| `halo_get_site` | Get a site by ID |
| `halo_create_site` | Create a new site |
| `halo_update_site` | Update an existing site |
### Projects
| Tool | Description |
|------|-------------|
| `halo_list_projects` | List projects |
| `halo_get_project` | Get a project by ID |
| `halo_create_project` | Create a new project |
| `halo_update_project` | Update an existing project |
### Opportunities (Sales/CRM)
| Tool | Description |
|------|-------------|
| `halo_list_opportunities` | List sales opportunities |
| `halo_get_opportunity` | Get an opportunity by ID |
| `halo_create_opportunity` | Create a new opportunity |
| `halo_update_opportunity` | Update an existing opportunity |
### Appointments
| Tool | Description |
|------|-------------|
| `halo_list_appointments` | List appointments |
| `halo_get_appointment` | Get an appointment by ID |
| `halo_create_appointment` | Create a new appointment |
| `halo_delete_appointment` | Delete an appointment |
### Attachments
| Tool | Description |
|------|-------------|
| `halo_list_attachments` | List attachments for a ticket |
| `halo_get_attachment` | Get attachment metadata by ID |
| `halo_delete_attachment` | Delete an attachment |
### Items (Catalog)
| Tool | Description |
|------|-------------|
| `halo_list_items` | List catalog items |
| `halo_get_item` | Get an item by ID |
| `halo_create_item` | Create a new catalog item |
### Invoices
| Tool | Description |
|------|-------------|
| `halo_list_invoices` | List invoices |
| `halo_get_invoice` | Get an invoice by ID |
| `halo_void_invoice` | Void an invoice |
### Suppliers
| Tool | Description |
|------|-------------|
| `halo_list_suppliers` | List suppliers |
| `halo_get_supplier` | Get a supplier by ID |
| `halo_create_supplier` | Create a new supplier |
| `halo_update_supplier` | Update an existing supplier |
### Reports
| Tool | Description |
|------|-------------|
| `halo_list_reports` | List available reports |
| `halo_get_report` | Get report metadata by ID |
| `halo_run_report` | Execute a report and get results |
---
## Architecture
### Project Structure
```
halo-mcp/
├── src/
│ ├── index.ts # stdio mode entry point
│ ├── httpServer.ts # SSE mode entry point
│ ├── config.ts # Configuration loader
│ ├── auth/
│ │ └── haloAuth.ts # OAuth authentication client
│ ├── api/
│ │ ├── httpClient.ts # HTTP client with auth injection
│ │ ├── tickets.ts # Tickets API wrapper
│ │ ├── users.ts # Users API wrapper
│ │ ├── teams.ts # Teams API wrapper
│ │ ├── agents.ts # Agents API wrapper
│ │ ├── status.ts # Status API wrapper
│ │ ├── actions.ts # Actions API wrapper
│ │ ├── appointments.ts # Appointments API wrapper
│ │ ├── assets.ts # Assets API wrapper
│ │ ├── attachments.ts # Attachments API wrapper
│ │ ├── clients.ts # Clients API wrapper
│ │ ├── invoices.ts # Invoices API wrapper
│ │ ├── items.ts # Items API wrapper
│ │ ├── opportunities.ts # Opportunities API wrapper
│ │ ├── projects.ts # Projects API wrapper
│ │ ├── reports.ts # Reports API wrapper
│ │ ├── sites.ts # Sites API wrapper
│ │ ├── suppliers.ts # Suppliers API wrapper
│ │ └── ticketTypes.ts # Ticket Types API wrapper
│ └── mcp/
│ ├── server.ts # MCP server setup
│ └── tools/
│ ├── ticketsTools.ts
│ ├── usersTools.ts
│ ├── teamsTools.ts
│ ├── agentsTools.ts
│ ├── statusTools.ts
│ ├── actionsTools.ts
│ ├── appointmentsTools.ts
│ ├── assetsTools.ts
│ ├── attachmentsTools.ts
│ ├── clientsTools.ts
│ ├── invoicesTools.ts
│ ├── itemsTools.ts
│ ├── opportunitiesTools.ts
│ ├── projectsTools.ts
│ ├── reportsTools.ts
│ ├── sitesTools.ts
│ ├── suppliersTools.ts
│ └── ticketTypesTools.ts
├── dist/ # Compiled JavaScript
├── Documentation/
│ └── HaloApiDocs/ # Halo API reference documentation
├── package.json
├── tsconfig.json
└── README.md
```
### Component Layers
```
┌─────────────────────────────────────────────────────────────────┐
│ MCP Transport Layer │
│ ┌─────────────────────┐ ┌──────────────────────────────┐ │
│ │ stdio Transport │ │ SSE Transport (HTTP) │ │
│ │ (index.ts) │ │ (httpServer.ts) │ │
│ └─────────────────────┘ └──────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ MCP Server Layer │
│ (mcp/server.ts) │
│ - Tool registration │
│ - Request routing │
│ - Response formatting │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Tools Layer │
│ (mcp/tools/*.ts) │
│ - Input validation │
│ - Parameter mapping │
│ - Response transformation │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ API Wrappers Layer │
│ (api/*.ts) │
│ - Resource-specific methods │
│ - Type definitions │
│ - Query building │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ HTTP Client Layer │
│ (api/httpClient.ts) │
│ - Request execution │
│ - Error handling │
│ - Query serialization │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ Authentication Layer │
│ (auth/haloAuth.ts) │
│ - Token acquisition │
│ - Token caching │
│ - Automatic refresh │
└─────────────────────────────────────────────────────────────────┘
```
### Authentication Flow
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ MCP Tool │ │ Auth Client │ │ Halo API │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
│ 1. Request (needs auth) │ │
│─────────────────────────────────→│ │
│ │ │
│ │ 2. Check cached token │
│ │────────┐ │
│ │ │ │
│ │←───────┘ │
│ │ │
│ │ 3. Token expired? │
│ │ POST /auth/token │
│ │─────────────────────────────────→│
│ │ │
│ │ 4. New access_token │
│ │←─────────────────────────────────│
│ │ │
│ │ 5. Cache token │
│ │────────┐ │
│ │ │ │
│ │←───────┘ │
│ │ │
│ 6. Return access token │ │
│←─────────────────────────────────│ │
│ │ │
│ 7. API request with Bearer token │
│────────────────────────────────────────────────────────────────────→│
│ │ │
│ 8. API response │
│←────────────────────────────────────────────────────────────────────│
```
---
## Development
### Scripts
| Script | Description |
|--------|-------------|
| `npm run build` | Compile TypeScript to JavaScript |
| `npm run dev` | Run stdio server in development mode |
| `npm run dev:sse` | Run SSE server in development mode |
| `npm start` | Run stdio server (production) |
| `npm run start:sse` | Run SSE server (production) |
| `npm run typecheck` | Run TypeScript type checking |
### Adding a New Resource
1. **Create API wrapper** in `src/api/<resource>.ts`:
```typescript
export class ResourceApi {
constructor(private http: HaloHttpClient) {}
async list(params?: ListParams): Promise<Resource[]> {
return this.http.get<Resource[]>("/Resource", params);
}
async getById(id: number): Promise<Resource> {
return this.http.get<Resource>(`/Resource/${id}`);
}
}
```
2. **Create tool definitions** in `src/mcp/tools/<resource>Tools.ts`:
```typescript
export const listResourceTool = {
name: "halo_list_resources",
description: "List resources with optional filters",
inputSchema: {
type: "object" as const,
properties: {
// Define input properties
},
additionalProperties: false,
},
handler: async (input, api) => {
const results = await api.list(input);
return { resources: results };
},
};
```
3. **Register in server** (`src/mcp/server.ts`):
- Import the API class and tools
- Create API instance
- Add tools to `allTools` array
### Testing with MCP Inspector
```bash
# stdio mode
npx @modelcontextprotocol/inspector node dist/index.js
# SSE mode
npm run dev:sse
# Then in another terminal:
npx @modelcontextprotocol/inspector
# Connect to http://localhost:3000/sse
```
---
## Troubleshooting
### Authentication Errors
**"Auth failed (401)"**
- Verify your `HALO_CLIENT_ID` and `HALO_CLIENT_SECRET` are correct
- Check that the API application has appropriate permissions in Halo
- Ensure the API is enabled on your Halo instance
**"Missing credentials"**
- Provide either `HALO_CLIENT_SECRET` OR both `HALO_USERNAME` and `HALO_PASSWORD`
### Connection Issues
**"ECONNREFUSED"**
- Verify `HALO_BASE_URL` is correct and accessible
- Check for firewall or network restrictions
- Ensure the URL doesn't have a trailing slash
**SSE connection closes immediately**
- Ensure `req.body` is passed to `handlePostMessage()` (fixed in latest version)
- Check browser console for CORS errors
### Tool Errors
**"Unknown tool: <name>"**
- Verify the tool is registered in `src/mcp/server.ts`
- Rebuild with `npm run build`
**Empty results**
- Check that your API credentials have permission to access the resource
- Verify filters are correct (e.g., `statusId` vs `status_id`)
### Debug Mode
Enable verbose logging by checking the server console output. Each SSE connection and message is logged.
---
## Authors
- **Michel Braga Guimaraes** - Lead Developer
- **Claude Code** (Anthropic) - AI Pair Programmer
---
## License
MIT License
---
## Contributing
Contributions are welcome! Please:
1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Submit a pull request
### Resources
- [Halo ITSM API Documentation](https://haloitsm.com/apidoc/)
- [Model Context Protocol Specification](https://modelcontextprotocol.io/specification)
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues