halopsa_api_call
Execute authenticated API calls to HaloPSA endpoints for managing tickets, actions, and other PSA data operations using HTTP methods like GET, POST, PUT, PATCH, and DELETE.
Instructions
Make authenticated API calls to any HaloPSA endpoint. Use this after finding the right endpoint with schema tools.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | API endpoint path (e.g., "/api/Ticket", "/api/Actions") | |
| method | No | HTTP method to use | GET |
| body | No | Request body data for POST/PUT/PATCH requests | |
| queryParams | No | URL query parameters as key-value pairs |
Input Schema (JSON Schema)
{
"properties": {
"body": {
"description": "Request body data for POST/PUT/PATCH requests",
"type": "object"
},
"method": {
"default": "GET",
"description": "HTTP method to use",
"enum": [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE"
],
"type": "string"
},
"path": {
"description": "API endpoint path (e.g., \"/api/Ticket\", \"/api/Actions\")",
"type": "string"
},
"queryParams": {
"additionalProperties": {
"type": "string"
},
"description": "URL query parameters as key-value pairs",
"type": "object"
}
},
"required": [
"path"
],
"type": "object"
}
Implementation Reference
- src/index.ts:574-587 (handler)MCP tool handler that validates input, calls haloPSAClient.makeApiCall with parameters, and formats the response as MCP content.case 'halopsa_api_call': { const { path, method, body, queryParams } = args as any; if (!path) { throw new Error('API path is required'); } result = await haloPSAClient.makeApiCall(path, method || 'GET', body, queryParams); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] }; }
- src/index.ts:248-274 (schema)Input schema definition and tool registration in the tools array, defining parameters for path, method, body, and queryParams.name: 'halopsa_api_call', description: 'Make authenticated API calls to any HaloPSA endpoint. Use this after finding the right endpoint with schema tools.', inputSchema: { type: 'object', properties: { path: { type: 'string', description: 'API endpoint path (e.g., "/api/Ticket", "/api/Actions")' }, method: { type: 'string', enum: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], description: 'HTTP method to use', default: 'GET' }, body: { type: 'object', description: 'Request body data for POST/PUT/PATCH requests' }, queryParams: { type: 'object', description: 'URL query parameters as key-value pairs', additionalProperties: { type: 'string' } } }, required: ['path'] }
- src/index.ts:278-281 (registration)Registration of the tools list handler, making the halopsa_api_call tool discoverable via ListToolsRequestSchema.// Handler for listing tools server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; });
- src/halopsa-client.ts:132-191 (helper)Core helper function implementing the authenticated HTTP request to HaloPSA API endpoints using fetch, handling authentication, query parameters, request body, and response parsing.async makeApiCall( path: string, method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' = 'GET', body?: any, queryParams?: Record<string, string> ): Promise<any> { // Ensure we have a valid token await this.authenticate(); // Build the full URL let url = `${this.config.url}${path}`; // Add tenant to query params const params = new URLSearchParams({ tenant: this.config.tenant }); // Add additional query parameters if provided if (queryParams) { Object.entries(queryParams).forEach(([key, value]) => { if (value !== undefined && value !== null) { params.append(key, value); } }); } const paramString = params.toString(); if (paramString) { url += (path.includes('?') ? '&' : '?') + paramString; } const options: RequestInit = { method, headers: { 'accept': 'application/json', 'authorization': `Bearer ${this.accessToken}`, 'Content-Type': 'application/json' } }; if (body && (method === 'POST' || method === 'PUT' || method === 'PATCH')) { options.body = typeof body === 'object' ? JSON.stringify(body) : body; } try { const response = await fetch(url, options); if (!response.ok) { const errorText = await response.text(); throw new Error(`API call failed: ${response.status} - ${errorText}`); } const contentType = response.headers.get('content-type'); if (contentType && contentType.includes('application/json')) { return await response.json(); } else { return await response.text(); } } catch (error) { throw new Error(`Failed to make API call: ${error}`); } }