Skip to main content
Glama
resource.handler.ts5.92 kB
// Autotask Resource Handler // Handles MCP resource requests for read-only access to Autotask data import { AutotaskService } from '../services/autotask.service.js'; import { Logger } from '../utils/logger.js'; export interface McpResource { uri: string; name: string; description?: string; mimeType?: string; } export interface McpResourceContent { uri: string; mimeType: string; text?: string; blob?: string; } export class AutotaskResourceHandler { private autotaskService: AutotaskService; private logger: Logger; constructor(autotaskService: AutotaskService, logger: Logger) { this.autotaskService = autotaskService; this.logger = logger; } /** * List all available resources */ async listResources(): Promise<McpResource[]> { this.logger.debug('Listing available Autotask resources'); const resources: McpResource[] = [ // Company resources { uri: 'autotask://companies', name: 'All Companies', description: 'List of all companies in Autotask', mimeType: 'application/json' }, { uri: 'autotask://companies/{id}', name: 'Company by ID', description: 'Get specific company details by ID', mimeType: 'application/json' }, // Contact resources { uri: 'autotask://contacts', name: 'All Contacts', description: 'List of all contacts in Autotask', mimeType: 'application/json' }, { uri: 'autotask://contacts/{id}', name: 'Contact by ID', description: 'Get specific contact details by ID', mimeType: 'application/json' }, // Ticket resources { uri: 'autotask://tickets', name: 'All Tickets', description: 'List of all tickets in Autotask', mimeType: 'application/json' }, { uri: 'autotask://tickets/{id}', name: 'Ticket by ID', description: 'Get specific ticket details by ID', mimeType: 'application/json' }, // Time entry resources { uri: 'autotask://time-entries', name: 'Time Entries', description: 'List of time entries in Autotask', mimeType: 'application/json' } ]; this.logger.debug(`Listed ${resources.length} available resources`); return resources; } /** * Read a specific resource by URI */ async readResource(uri: string): Promise<McpResourceContent> { this.logger.debug(`Reading resource: ${uri}`); // Parse the URI to determine the resource type and ID const { resourceType, resourceId } = this.parseUri(uri); let data: any; let description: string; switch (resourceType) { case 'companies': if (resourceId) { data = await this.autotaskService.getCompany(parseInt(resourceId, 10)); if (!data) { throw new Error(`Company with ID ${resourceId} not found`); } description = `Company: ${data.companyName || 'Unknown'}`; } else { data = await this.autotaskService.searchCompanies({ pageSize: 100 }); description = `List of ${data.length} companies`; } break; case 'contacts': if (resourceId) { data = await this.autotaskService.getContact(parseInt(resourceId, 10)); if (!data) { throw new Error(`Contact with ID ${resourceId} not found`); } description = `Contact: ${data.firstName} ${data.lastName}`; } else { data = await this.autotaskService.searchContacts({ pageSize: 100 }); description = `List of ${data.length} contacts`; } break; case 'tickets': if (resourceId) { data = await this.autotaskService.getTicket(parseInt(resourceId, 10)); if (!data) { throw new Error(`Ticket with ID ${resourceId} not found`); } description = `Ticket: ${data.title || data.ticketNumber || 'Unknown'}`; } else { data = await this.autotaskService.searchTickets({ pageSize: 100 }); description = `List of ${data.length} tickets`; } break; case 'time-entries': data = await this.autotaskService.getTimeEntries({ pageSize: 100 }); description = `List of ${data.length} time entries`; break; default: throw new Error(`Unknown resource type: ${resourceType}`); } const content: McpResourceContent = { uri, mimeType: 'application/json', text: JSON.stringify({ description, uri, data, metadata: { timestamp: new Date().toISOString(), resourceType, resourceId: resourceId || null, count: Array.isArray(data) ? data.length : 1 } }, null, 2) }; this.logger.debug(`Successfully read resource: ${uri}`); return content; } /** * Parse a resource URI to extract type and ID */ private parseUri(uri: string): { resourceType: string; resourceId?: string } { const match = uri.match(/^autotask:\/\/([^\/]+)(?:\/(.+))?$/); if (!match) { throw new Error(`Invalid Autotask URI format: ${uri}`); } const [, resourceType, resourceId] = match; // Handle template URIs like "companies/{id}" if (resourceId === '{id}') { throw new Error(`Template URI not supported for reading: ${uri}. Please provide a specific ID.`); } return { resourceType, resourceId }; } /** * Get available resource templates for documentation */ getResourceTemplates(): string[] { return [ 'autotask://companies', 'autotask://companies/{id}', 'autotask://contacts', 'autotask://contacts/{id}', 'autotask://tickets', 'autotask://tickets/{id}', 'autotask://time-entries' ]; } }

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/asachs01/autotask-mcp'

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