Skip to main content
Glama
formatters.tsβ€’11.9 kB
/** * Result formatting functions for company tool configurations */ import { Company } from '../../../types/attio.js'; import { getCompanyDetails, getCompanyBasicInfo, getCompanyContactInfo, getCompanyBusinessInfo, getCompanySocialInfo, } from '../../../objects/companies/index.js'; import { DetailsToolConfig } from '../../tool-types.js'; interface SelectOption { option?: { title: string; }; } // Type-safe helper to access company values function getCompanyValue( company: Company, field: string ): unknown[] | undefined { const values = company.values as Record<string, unknown>; return values?.[field] as unknown[] | undefined; } // Company formatter configurations export const formatterConfigs = { details: { name: 'get-company-details', handler: getCompanyDetails, formatResult: (company: Company) => { const companyName = (getCompanyValue(company, 'name')?.[0] as { value: string })?.value || 'Unnamed'; const companyId = company.id?.record_id || 'unknown'; const domains = (getCompanyValue(company, 'domains')?.[0] as { domain: string }) ?.domain || 'Not available'; const categories = (getCompanyValue(company, 'categories') as SelectOption[] | undefined) ?.map((cat) => cat.option?.title) .join(', ') || 'Not available'; const description = (getCompanyValue(company, 'description')?.[0] as { value: string }) ?.value || 'No description available'; const createdAt = (company as { created_at?: string }).created_at || 'Unknown'; // Extract other key details const location = getCompanyValue(company, 'primary_location')?.[0] as | { locality?: string; region?: string; country_code?: string } | undefined; const locationStr = location ? `${location.locality || ''}, ${location.region || ''} ${ location.country_code || '' }`.trim() : 'Not available'; // Note: employee_range and foundation_date removed as they're not standard Attio fields // Custom fields should be handled through user.json mapping return `Company: ${companyName} (ID: ${companyId})\nCreated: ${createdAt}\nDomains: ${domains}\nCategories: ${categories}\nLocation: ${locationStr}\nDescription:\n${description}\n\nFor full details, use get-company-json with this ID: ${companyId}`; }, } as DetailsToolConfig, json: { name: 'get-company-json', handler: getCompanyDetails, formatResult: (company: Company) => { try { const cleanedCompany = JSON.parse( JSON.stringify(company) ) as Company & { created_at?: string; web_url?: string }; // Instead of returning the entire JSON at once, create a summary const summary = { id: cleanedCompany.id, created_at: cleanedCompany.created_at, web_url: cleanedCompany.web_url, basic_values: { name: (cleanedCompany.values as { name?: [{ value?: string }] }) .name?.[0]?.value, domains: ( cleanedCompany.values as { domains?: [{ domain?: string }] } ).domains?.[0]?.domain, description: ( cleanedCompany.values as { description?: [{ value?: string }] } ).description?.[0]?.value, categories: ( cleanedCompany.values as { categories?: Array<SelectOption> } ).categories?.map((cat) => cat.option?.title), primary_location: ( cleanedCompany.values as { primary_location?: [unknown] } ).primary_location?.[0], }, attribute_count: Object.keys(cleanedCompany.values || {}).length, message: 'Full JSON data is too large for display. Use get-company-attributes to access specific fields.', }; return JSON.stringify(summary, null, 2); } catch (error: unknown) { // If any error occurs during JSON processing, return a safe error message return JSON.stringify( { error: 'Failed to process company data', message: error instanceof Error ? error.message : 'Unknown error', companyId: company.id?.record_id || 'unknown', }, null, 2 ); } }, } as DetailsToolConfig, basicInfo: { name: 'get-company-basic-info', handler: getCompanyBasicInfo, formatResult: (company: Partial<Company>) => { const name = (getCompanyValue(company as Company, 'name')?.[0] as { value: string }) ?.value || 'Unnamed'; const domains = ( getCompanyValue(company as Company, 'domains')?.[0] as { domain: string; } )?.domain || 'Not available'; const categories = ( getCompanyValue(company as Company, 'categories') as | SelectOption[] | undefined ) ?.map((cat) => cat.option?.title) .join(', ') || 'Not available'; const location = getCompanyValue( company as Company, 'primary_location' )?.[0] as | { locality?: string; region?: string; country_code?: string } | undefined; const locationStr = location ? `${location.locality || ''}, ${location.region || ''} ${ location.country_code || '' }`.trim() : 'Not available'; const description = ( getCompanyValue(company as Company, 'description')?.[0] as { value: string; } )?.value || 'No description available'; return `Company: ${name}\nDomains: ${domains}\nCategories: ${categories}\nLocation: ${locationStr}\n\nDescription:\n${description}`; }, } as DetailsToolConfig, contactInfo: { name: 'get-company-contact-info', handler: getCompanyContactInfo, formatResult: (company: Partial<Company>) => { const name = (getCompanyValue(company as Company, 'name')?.[0] as { value: string }) ?.value || 'Unnamed'; const domains = ( getCompanyValue(company as Company, 'domains')?.[0] as { domain: string; } )?.domain || 'Not available'; const location = getCompanyValue( company as Company, 'primary_location' )?.[0] as | { locality?: string; region?: string; country_code?: string } | undefined; const locationStr = location ? `${location.locality || ''}, ${location.region || ''} ${location.country_code || ''}`.trim() : 'Not available'; const team = getCompanyValue(company as Company, 'team') || []; return `Company: ${name}\nDomains: ${domains}\nLocation: ${locationStr}\n\nTeam Members: ${team.length} people`; }, } as DetailsToolConfig, businessInfo: { name: 'get-company-business-info', handler: getCompanyBusinessInfo, formatResult: (company: Partial<Company>) => { const name = (getCompanyValue(company as Company, 'name')?.[0] as { value: string }) ?.value || 'Unnamed'; // Note: Removed non-standard fields (type, services, industry, estimated_arr_usd, // funding_raised_usd, employee_range, foundation_date) as they don't exist in default Attio API // Custom fields should be handled through user.json mapping const categories = ( getCompanyValue(company as Company, 'categories') as | SelectOption[] | undefined )?.map((cat) => cat.option?.title) || []; return `Company: ${name}\n\nCategories:\n${categories.join(', ') || 'None'}\n\nNote: Additional fields like industry, type, employees, revenue, etc. are custom fields that should be configured through user.json mapping for your specific workspace.`; }, } as DetailsToolConfig, socialInfo: { name: 'get-company-social-info', handler: getCompanySocialInfo, formatResult: (company: Partial<Company>) => { const name = (getCompanyValue(company as Company, 'name')?.[0] as { value: string }) ?.value || 'Unnamed'; const domains = ( getCompanyValue(company as Company, 'domains')?.[0] as { domain: string; } )?.domain || 'Not available'; const linkedin = ( getCompanyValue(company as Company, 'linkedin')?.[0] as { value: string; } )?.value || 'Not available'; const twitter = ( getCompanyValue(company as Company, 'twitter')?.[0] as { value: string; } )?.value || 'Not available'; const facebook = ( getCompanyValue(company as Company, 'facebook')?.[0] as { value: string; } )?.value || 'Not available'; const instagram = ( getCompanyValue(company as Company, 'instagram')?.[0] as { value: string; } )?.value || 'Not available'; const angellist = ( getCompanyValue(company as Company, 'angellist')?.[0] as { value: string; } )?.value || 'Not available'; // Note: twitter_follower_count removed as it's not a standard Attio field return `Company: ${name}\nDomains: ${domains}\n\nSocial Media:\nLinkedIn: ${linkedin}\nTwitter: ${twitter}\nFacebook: ${facebook}\nInstagram: ${instagram}\nAngelList: ${angellist}\n\nNote: Additional metrics like follower counts are custom fields that should be configured through user.json mapping for your workspace.`; }, } as DetailsToolConfig, }; // Formatter tool definitions (for the specialized info tools) export const formatterToolDefinitions = [ { name: 'get-company-details', description: 'Get details of a company', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'ID of the company to get details for (provide either this or uri)', }, uri: { type: 'string', description: "URI of the company in the format 'attio://companies/{id}' (provide either this or companyId)", }, }, }, }, { name: 'get-company-json', description: 'Get raw JSON representation of a company', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'ID of the company to get JSON for', }, }, required: ['companyId'], }, }, { name: 'get-company-basic-info', description: 'Get basic information about a company', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'ID of the company', }, }, required: ['companyId'], }, }, { name: 'get-company-contact-info', description: 'Get contact information for a company', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'ID of the company', }, }, required: ['companyId'], }, }, { name: 'get-company-business-info', description: 'Get business information about a company', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'ID of the company', }, }, required: ['companyId'], }, }, { name: 'get-company-social-info', description: 'Get social media information for a company', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'ID of the company', }, }, required: ['companyId'], }, }, ];

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/kesslerio/attio-mcp-server'

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