autotask_create_quote
Create a new quote for an opportunity by providing company ID, contact ID, effective and expiration dates, and optional description.
Instructions
Create a new quote
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Quote name | |
| description | No | Quote description | |
| companyId | Yes | Company ID for the quote | |
| contactId | No | Contact ID for the quote | |
| opportunityId | No | Associated opportunity ID | |
| effectiveDate | No | Effective date (YYYY-MM-DD format) | |
| expirationDate | No | Expiration date (YYYY-MM-DD format) |
Implementation Reference
- Input schema definition for autotask_create_quote tool. Defines parameters: name, description, companyId, contactId, opportunityId, effectiveDate, expirationDate. Only companyId is required.
{ name: 'autotask_create_quote', description: 'Create a new quote', inputSchema: { type: 'object', properties: { name: { type: 'string', description: 'Quote name' }, description: { type: 'string', description: 'Quote description' }, companyId: { type: 'number', description: 'Company ID for the quote' }, contactId: { type: 'number', description: 'Contact ID for the quote' }, opportunityId: { type: 'number', description: 'Associated opportunity ID' }, effectiveDate: { type: 'string', description: 'Effective date (YYYY-MM-DD format)' }, expirationDate: { type: 'string', description: 'Expiration date (YYYY-MM-DD format)' } }, required: ['companyId'] } }, - src/handlers/tool.handler.ts:1161-1193 (handler)Handler function for autotask_create_quote. Elicits company if companyId not provided (via MCP server interaction), elicits opportunity selection based on the company, then delegates to autotaskService.createQuote() with mapped field names (companyID, contactID, opportunityID).
['autotask_create_quote', async (a) => { // Elicit company if not provided if (!a.companyId && this.mcpServer) { try { const companyId = await this.elicitCompanyId(); if (companyId) a = { ...a, companyId: companyId }; } catch { /* proceed without company */ } } // Elicit opportunity if not provided but company is known if (!a.opportunityId && a.companyId && this.mcpServer) { try { const opps = await s.searchOpportunities({ companyId: a.companyId }); if (opps.length > 0) { const options: PicklistValue[] = opps .filter(o => o.id != null) .map(o => ({ value: String(o.id), label: o.title || `Opportunity #${o.id}`, })); const selected = await this.elicitSelection( `Found ${opps.length} opportunities for this company. Which one should the quote be attached to?`, 'opportunityId', options ); if (selected) a = { ...a, opportunityId: Number(selected) }; } } catch { /* proceed without opportunity */ } } const id = await s.createQuote({ name: a.name, description: a.description, companyID: a.companyId, contactID: a.contactId, opportunityID: a.opportunityId, effectiveDate: a.effectiveDate, expirationDate: a.expirationDate }); return { result: id, message: `Successfully created quote with ID: ${id}` }; }], - Service method createQuote that performs the actual API call. Auto-populates billToLocationID, shipToLocationID, and soldToLocationID from the company's first CompanyLocation if not provided (Autotask requires these). Then sends POST to 'Quotes' entity via the HTTP client.
async createQuote(quote: Partial<AutotaskQuote>): Promise<number> { const http = await this.ensureClient(); try { // Autotask requires location IDs on the quote. Auto-populate from the // company's first location if the caller didn't supply them. if ( quote.companyID && (!quote.billToLocationID || !quote.shipToLocationID || !quote.soldToLocationID) ) { try { const locations = await http.query<{ id: number }>( 'CompanyLocations', [{ op: 'eq', field: 'companyID', value: quote.companyID }], { maxRecords: 10 } ); if (locations.length > 0) { const defaultLocationId = locations[0].id; if (!quote.billToLocationID) quote.billToLocationID = defaultLocationId; if (!quote.shipToLocationID) quote.shipToLocationID = defaultLocationId; if (!quote.soldToLocationID) quote.soldToLocationID = defaultLocationId; } } catch (locError) { this.logger.warn('Could not auto-populate location IDs for quote:', locError); } } this.logger.debug('Creating quote:', quote); const id = await http.create('Quotes', quote); this.logger.info(`Quote created with ID: ${id}`); return id; } catch (error) { this.logger.error('Failed to create quote:', error); throw error; } } - src/types/autotask.ts:299-310 (schema)TypeScript interface defining the AutotaskQuote type used by createQuote and other quote operations.
export interface AutotaskQuote { id?: number; companyID?: number; contactID?: number; quoteNumber?: string; quoteDate?: string; title?: string; description?: string; totalAmount?: number; status?: number; [key: string]: any; } - src/handlers/tool.definitions.ts:3017-3020 (registration)Registration of autotask_create_quote in the 'financial' tool category within TOOL_CATEGORIES.
financial: { description: 'Quotes, quote items, opportunities, invoices, and contracts', tools: ['autotask_get_quote', 'autotask_search_quotes', 'autotask_create_quote', 'autotask_get_quote_item', 'autotask_search_quote_items', 'autotask_create_quote_item', 'autotask_update_quote_item', 'autotask_delete_quote_item', 'autotask_get_opportunity', 'autotask_search_opportunities', 'autotask_create_opportunity', 'autotask_search_invoices', 'autotask_search_contracts'] },