Skip to main content
Glama
Switchboard666

HaloPSA MCP Server

halopsa_query

Execute SQL queries to retrieve data from HaloPSA tables including tickets, users, sites, actions, and request types through the reporting API.

Instructions

Execute a SQL query against HaloPSA reporting API. Use this to retrieve data from any HaloPSA table including tickets (FAULTS), users (USERS), sites (SITE), actions (ACTIONS), request types (REQUESTTYPE), and more. Returns the full report response with data rows, column metadata, and available filters.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sqlYesSQL query to execute against HaloPSA database. Supports standard SQL syntax including SELECT, JOIN, WHERE, ORDER BY, GROUP BY, etc. Example: SELECT * FROM FAULTS WHERE Status = 1
loadReportOnlyNoWhether to load report data only (default: true)

Implementation Reference

  • Core implementation of halopsa_query tool: executes SQL query via HaloPSA /api/Report endpoint. Handles authentication, constructs request payload with _loadreportonly=true and sql, sends POST request, and returns full report response.
    async executeQuery(sql: string): Promise<any> {
      // Ensure we have a valid token
      await this.authenticate();
    
      const reportUrl = `${this.config.url}/api/Report`;
      const queryUrl = `${reportUrl}?tenant=${this.config.tenant}`;
    
      const query: ReportQuery = {
        _loadreportonly: true,
        sql: sql
      };
    
      try {
        const response = await fetch(queryUrl, {
          method: 'POST',
          headers: {
            'accept': '*/*',
            'accept-language': 'en-GB,en-US;q=0.9,en;q=0.8',
            'authorization': `Bearer ${this.accessToken}`,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify([query])
        });
    
        if (!response.ok) {
          const errorText = await response.text();
          throw new Error(`Query execution failed: ${response.status} - ${errorText}`);
        }
    
        const result = await response.json();
        // HaloPSA returns a single object for reporting API, not an array
        return result;
        
      } catch (error) {
        throw new Error(`Failed to execute query: ${error}`);
      }
    }
  • MCP tool handler dispatcher for halopsa_query: validates sql argument, delegates to HaloPSAClient.executeQuery(), formats result as MCP text content response.
    case 'halopsa_query': {
      const { sql } = args as any;
      if (!sql) {
        throw new Error('SQL query is required');
      }
      
      result = await haloPSAClient.executeQuery(sql);
      
      return {
        content: [{
          type: 'text',
          text: JSON.stringify(result, null, 2)
        }]
      };
    }
  • Tool registration object defining name 'halopsa_query', description, and inputSchema requiring 'sql' string parameter with optional loadReportOnly boolean.
    {
      name: 'halopsa_query',
      description: 'Execute a SQL query against HaloPSA reporting API. Use this to retrieve data from any HaloPSA table including tickets (FAULTS), users (USERS), sites (SITE), actions (ACTIONS), request types (REQUESTTYPE), and more. Returns the full report response with data rows, column metadata, and available filters.',
      inputSchema: {
        type: 'object',
        properties: {
          sql: {
            type: 'string',
            description: 'SQL query to execute against HaloPSA database. Supports standard SQL syntax including SELECT, JOIN, WHERE, ORDER BY, GROUP BY, etc. Example: SELECT * FROM FAULTS WHERE Status = 1'
          },
          loadReportOnly: {
            type: 'boolean',
            description: 'Whether to load report data only (default: true)',
            default: true
          }
        },
        required: ['sql']
      }
    },
  • src/index.ts:279-281 (registration)
    MCP server registration for ListToolsRequestSchema which returns the tools array containing halopsa_query definition.
    server.setRequestHandler(ListToolsRequestSchema, async () => {
      return { tools };
    });
  • Authentication helper used by executeQuery: obtains and refreshes Bearer token via /auth/token endpoint using client credentials.
    private async authenticate(): Promise<void> {
      // Check if we have a valid token
      if (this.accessToken && this.tokenExpiry && this.tokenExpiry > new Date()) {
        return;
      }
    
      const tokenUrl = `${this.config.url}/auth/token`;
      
      const params = new URLSearchParams({
        grant_type: 'client_credentials',
        client_id: this.config.clientId,
        client_secret: this.config.clientSecret,
        scope: 'all'
      });
    
      try {
        const response = await fetch(tokenUrl, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'application/json'
          },
          body: params.toString()
        });
    
        if (!response.ok) {
          const errorText = await response.text();
          throw new Error(`Authentication failed: ${response.status} - ${errorText}`);
        }
    
        const tokenData: TokenResponse = await response.json();
        this.accessToken = tokenData.access_token;
        
        // Set token expiry (subtract 60 seconds for safety)
        const expiryMs = (tokenData.expires_in - 60) * 1000;
        this.tokenExpiry = new Date(Date.now() + expiryMs);
        
      } catch (error) {
        throw new Error(`Failed to authenticate with HaloPSA: ${error}`);
      }
    }
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden. It discloses the tool's behavior by specifying it returns 'full report response with data rows, column metadata, and available filters', which is valuable. However, it lacks details on permissions, rate limits, error handling, or data modification risks (though 'retrieve' implies read-only).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured in two sentences: the first states the purpose and scope with examples, the second details the return format. Every sentence adds value without redundancy, making it front-loaded and appropriately sized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (executing arbitrary SQL queries) and lack of annotations and output schema, the description is reasonably complete. It covers purpose, usage context, and return structure. However, it could benefit from more behavioral details like safety warnings or limitations, slightly reducing completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already fully documents both parameters. The description does not add any parameter-specific information beyond what the schema provides (e.g., no extra syntax details or usage examples for parameters). Baseline 3 is appropriate when schema does all the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('Execute a SQL query') and target resource ('against HaloPSA reporting API'), with explicit examples of retrievable tables (tickets, users, sites, etc.). It distinguishes from siblings by focusing on direct SQL execution rather than query building or API endpoint management.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool ('to retrieve data from any HaloPSA table'), but does not explicitly state when not to use it or name specific alternatives among the sibling tools. The implied usage is strong but lacks explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Switchboard666/halopsa-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server