UNPKG

@coretext-ai/qa-google-contacts-a58500d5-8331-4ce9-a140-d204a9fae815

Version:
748 lines 35.7 kB
import { Logger } from '../services/logger.js'; export class GoogleContactsTools { constructor(client) { this.initialized = false; this.client = client; // Get logger from client if available, otherwise create fallback this.logger = client.logger || new Logger({ logLevel: 'ERROR', component: 'tools', enableConsole: true, enableShipping: false, serverName: '' }); } async ensureInitialized() { if (!this.initialized) { // Log tools initialization now that client is ready this.logger.info('TOOLS_INIT', 'Tools instance initialization started', { integration: 'google-contacts', isOAuth: true }); this.logger.info('CLIENT_INITIALIZATION', 'Starting client initialization', { isOAuth: true }); await this.client.initialize(); this.initialized = true; this.logger.info('CLIENT_INITIALIZATION', 'Client initialization completed', { initialized: this.initialized }); } } getToolDefinitions() { return [ { name: 'google-contacts_create_contact', description: 'Create a new contact with specified fields', inputSchema: { type: 'object', properties: { personFields: { type: 'string', description: 'Comma-separated list of fields to return (e.g., 'names,emailAddresses,phoneNumbers,addresses,organizations')' }, sources: { type: 'string', description: 'Sources to create the contact in (default: 'CONTACT')' }, names: { type: 'object', description: 'Array of name objects with givenName, familyName, displayName, etc.' }, emailAddresses: { type: 'object', description: 'Array of email address objects with value, type, etc.' }, phoneNumbers: { type: 'object', description: 'Array of phone number objects with value, type, etc.' }, addresses: { type: 'object', description: 'Array of address objects with formattedValue, type, etc.' }, organizations: { type: 'object', description: 'Array of organization objects with name, title, etc.' }, biographies: { type: 'object', description: 'Array of biography objects with value, contentType, etc.' }, birthdays: { type: 'object', description: 'Array of birthday objects with date information' }, urls: { type: 'object', description: 'Array of URL objects with value, type, etc.' }, }, required: ['personFields',] } }, { name: 'google-contacts_get_person', description: 'Get a specific contact by resource name', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the contact (e.g., 'people/c1234567890')' }, personFields: { type: 'string', description: 'Comma-separated list of fields to return (e.g., 'names,emailAddresses,phoneNumbers,addresses,organizations,biographies,birthdays,urls,photos,metadata')' }, sources: { type: 'string', description: 'Comma-separated list of sources to read from (READ_SOURCE_TYPE_CONTACT, READ_SOURCE_TYPE_DOMAIN_CONTACT)' }, }, required: ['resourceName', 'personFields',] } }, { name: 'google-contacts_update_contact', description: 'Update an existing contact', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the contact (e.g., 'people/c1234567890')' }, updatePersonFields: { type: 'string', description: 'Comma-separated list of fields to update (e.g., 'names,emailAddresses,phoneNumbers')' }, personFields: { type: 'string', description: 'Comma-separated list of fields to return in response' }, sources: { type: 'string', description: 'Sources to update the contact in' }, names: { type: 'object', description: 'Array of name objects to update' }, emailAddresses: { type: 'object', description: 'Array of email address objects to update' }, phoneNumbers: { type: 'object', description: 'Array of phone number objects to update' }, addresses: { type: 'object', description: 'Array of address objects to update' }, organizations: { type: 'object', description: 'Array of organization objects to update' }, biographies: { type: 'object', description: 'Array of biography objects to update' }, birthdays: { type: 'object', description: 'Array of birthday objects to update' }, urls: { type: 'object', description: 'Array of URL objects to update' }, etag: { type: 'string', description: 'ETag for concurrency control' }, }, required: ['resourceName', 'updatePersonFields',] } }, { name: 'google-contacts_delete_contact', description: 'Delete a contact permanently', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the contact to delete (e.g., 'people/c1234567890')' }, }, required: ['resourceName'] } }, { name: 'google-contacts_list_connections', description: 'List authenticated user's contacts', inputSchema: { type: 'object', properties: { pageSize: { type: 'number', description: 'Number of contacts to return (max 1000, default 100)' }, pageToken: { type: 'string', description: 'Page token for pagination' }, personFields: { type: 'string', description: 'Comma-separated list of fields to return (e.g., 'names,emailAddresses,phoneNumbers,addresses,organizations,biographies,birthdays,urls,photos,metadata')' }, sortOrder: { type: 'string', description: 'Sort order: LAST_MODIFIED_ASCENDING, LAST_MODIFIED_DESCENDING, FIRST_NAME_ASCENDING, LAST_NAME_ASCENDING' }, sources: { type: 'string', description: 'Comma-separated list of sources (READ_SOURCE_TYPE_CONTACT, READ_SOURCE_TYPE_DOMAIN_CONTACT)' }, syncToken: { type: 'string', description: 'Sync token for incremental synchronization' }, requestSyncToken: { type: 'boolean', description: 'Whether to request a sync token in the response' }, }, required: ['personFields',] } }, { name: 'google-contacts_search_contacts', description: 'Search across all contacts with text query', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Text search query to match against contact fields' }, pageSize: { type: 'number', description: 'Number of results to return (max 30, default 10)' }, readMask: { type: 'string', description: 'Comma-separated list of fields to return (e.g., 'names,emailAddresses,phoneNumbers')' }, sources: { type: 'string', description: 'Comma-separated list of sources to search (READ_SOURCE_TYPE_CONTACT, READ_SOURCE_TYPE_DOMAIN_CONTACT)' }, }, required: ['query',] } }, { name: 'google-contacts_batch_get_people', description: 'Get multiple contacts by resource names', inputSchema: { type: 'object', properties: { resourceNames: { type: 'string', description: 'Comma-separated list of resource names (e.g., 'people/c1,people/c2')' }, personFields: { type: 'string', description: 'Comma-separated list of fields to return for each contact' }, sources: { type: 'string', description: 'Comma-separated list of sources to read from' }, }, required: ['resourceNames', 'personFields',] } }, { name: 'google-contacts_list_contact_groups', description: 'List all contact groups', inputSchema: { type: 'object', properties: { pageSize: { type: 'number', description: 'Number of groups to return (max 1000, default 30)' }, pageToken: { type: 'string', description: 'Page token for pagination' }, groupFields: { type: 'string', description: 'Comma-separated list of group fields to return (e.g., 'name,memberCount,groupType')' }, syncToken: { type: 'string', description: 'Sync token for incremental synchronization' }, }, required: [] } }, { name: 'google-contacts_create_contact_group', description: 'Create a new contact group', inputSchema: { type: 'object', properties: { contactGroup: { type: 'object', description: 'Contact group object with name and optional metadata' }, readGroupFields: { type: 'string', description: 'Comma-separated list of fields to return in response' }, }, required: ['contactGroup',] } }, { name: 'google-contacts_get_contact_group', description: 'Get a specific contact group by resource name', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the contact group (e.g., 'contactGroups/myContactGroup')' }, maxMembers: { type: 'number', description: 'Maximum number of members to return (max 20000, default 0)' }, groupFields: { type: 'string', description: 'Comma-separated list of group fields to return' }, }, required: ['resourceName',] } }, { name: 'google-contacts_update_contact_group', description: 'Update an existing contact group', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the contact group to update' }, contactGroup: { type: 'object', description: 'Updated contact group object' }, readGroupFields: { type: 'string', description: 'Comma-separated list of fields to return in response' }, }, required: ['resourceName', 'contactGroup',] } }, { name: 'google-contacts_delete_contact_group', description: 'Delete a contact group', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the contact group to delete' }, deleteContacts: { type: 'boolean', description: 'Whether to delete the contacts in the group as well' }, }, required: ['resourceName',] } }, { name: 'google-contacts_modify_contact_group_members', description: 'Add or remove members from a contact group', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the contact group' }, resourceNamesToAdd: { type: 'string', description: 'Comma-separated list of contact resource names to add' }, resourceNamesToRemove: { type: 'string', description: 'Comma-separated list of contact resource names to remove' }, }, required: ['resourceName',] } }, { name: 'google-contacts_list_directory_people', description: 'List people in the authenticated user's domain directory (G Suite/Workspace)', inputSchema: { type: 'object', properties: { pageSize: { type: 'number', description: 'Number of people to return (max 1000, default 100)' }, pageToken: { type: 'string', description: 'Page token for pagination' }, readMask: { type: 'string', description: 'Comma-separated list of fields to return (e.g., 'names,emailAddresses,organizations')' }, sources: { type: 'string', description: 'Must be 'DIRECTORY_SOURCE_TYPE_DOMAIN_CONTACT' for directory people' }, mergeSources: { type: 'string', description: 'Additional sources to merge (e.g., 'DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE')' }, syncToken: { type: 'string', description: 'Sync token for incremental synchronization' }, requestSyncToken: { type: 'boolean', description: 'Whether to request a sync token in the response' }, }, required: ['readMask', 'sources',] } }, { name: 'google-contacts_search_directory_people', description: 'Search people in the authenticated user's domain directory', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Text search query to match against directory people' }, pageSize: { type: 'number', description: 'Number of results to return (max 500, default 100)' }, pageToken: { type: 'string', description: 'Page token for pagination' }, readMask: { type: 'string', description: 'Comma-separated list of fields to return' }, sources: { type: 'string', description: 'Must be 'DIRECTORY_SOURCE_TYPE_DOMAIN_CONTACT' for directory search' }, mergeSources: { type: 'string', description: 'Additional sources to merge' }, }, required: ['query', 'readMask', 'sources',] } }, { name: 'google-contacts_list_other_contacts', description: 'List other contacts (auto-created contacts from interactions)', inputSchema: { type: 'object', properties: { pageSize: { type: 'number', description: 'Number of other contacts to return (max 1000, default 100)' }, pageToken: { type: 'string', description: 'Page token for pagination' }, readMask: { type: 'string', description: 'Comma-separated list of fields to return (e.g., 'names,emailAddresses')' }, sources: { type: 'string', description: 'Sources to read from (READ_SOURCE_TYPE_OTHER_CONTACT)' }, syncToken: { type: 'string', description: 'Sync token for incremental synchronization' }, requestSyncToken: { type: 'boolean', description: 'Whether to request a sync token in the response' }, }, required: ['readMask',] } }, { name: 'google-contacts_search_other_contacts', description: 'Search other contacts with text query', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Text search query to match against other contacts' }, pageSize: { type: 'number', description: 'Number of results to return (max 30, default 10)' }, readMask: { type: 'string', description: 'Comma-separated list of fields to return' }, }, required: ['query',] } }, { name: 'google-contacts_copy_other_contact', description: 'Copy an other contact to the authenticated user's contacts', inputSchema: { type: 'object', properties: { resourceName: { type: 'string', description: 'Resource name of the other contact to copy (e.g., 'otherContacts/c1234567890')' }, copyMask: { type: 'string', description: 'Comma-separated list of fields to copy (e.g., 'names,emailAddresses,phoneNumbers')' }, sources: { type: 'string', description: 'Sources to copy from' }, }, required: ['resourceName', 'copyMask',] } } ]; } canHandle(toolName) { const supportedTools = [ 'google-contacts_create_contact', 'google-contacts_get_person', 'google-contacts_update_contact', 'google-contacts_delete_contact', 'google-contacts_list_connections', 'google-contacts_search_contacts', 'google-contacts_batch_get_people', 'google-contacts_list_contact_groups', 'google-contacts_create_contact_group', 'google-contacts_get_contact_group', 'google-contacts_update_contact_group', 'google-contacts_delete_contact_group', 'google-contacts_modify_contact_group_members', 'google-contacts_list_directory_people', 'google-contacts_search_directory_people', 'google-contacts_list_other_contacts', 'google-contacts_search_other_contacts', 'google-contacts_copy_other_contact' ]; return supportedTools.includes(toolName); } async executeTool(name, args) { const startTime = Date.now(); this.logger.logToolStart(name, args); await this.ensureInitialized(); // Validate tool is supported if (!this.canHandle(name)) { this.logger.error('TOOL_ERROR', 'Unknown tool requested', { tool: name, supportedTools: ['google-contacts_create_contact', 'google-contacts_get_person', 'google-contacts_update_contact', 'google-contacts_delete_contact', 'google-contacts_list_connections', 'google-contacts_search_contacts', 'google-contacts_batch_get_people', 'google-contacts_list_contact_groups', 'google-contacts_create_contact_group', 'google-contacts_get_contact_group', 'google-contacts_update_contact_group', 'google-contacts_delete_contact_group', 'google-contacts_modify_contact_group_members', 'google-contacts_list_directory_people', 'google-contacts_search_directory_people', 'google-contacts_list_other_contacts', 'google-contacts_search_other_contacts', 'google-contacts_copy_other_contact'] }); throw new Error(`Unknown tool: ${name}`); } // Validate required parameters this.logger.debug('PARAM_VALIDATION', 'Validating tool parameters', { tool: name, providedArgs: Object.keys(args || {}) }); try { let result; switch (name) { case 'google-contacts_create_contact': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_create_contact', clientMethod: 'createContact' }); result = await this.client.createContact(args); break; case 'google-contacts_get_person': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_get_person', clientMethod: 'getPerson' }); result = await this.client.getPerson(args); break; case 'google-contacts_update_contact': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_update_contact', clientMethod: 'updateContact' }); result = await this.client.updateContact(args); break; case 'google-contacts_delete_contact': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_delete_contact', clientMethod: 'deleteContact' }); result = await this.client.deleteContact(args); break; case 'google-contacts_list_connections': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_list_connections', clientMethod: 'listConnections' }); result = await this.client.listConnections(args); break; case 'google-contacts_search_contacts': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_search_contacts', clientMethod: 'searchContacts' }); result = await this.client.searchContacts(args); break; case 'google-contacts_batch_get_people': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_batch_get_people', clientMethod: 'batchGetPeople' }); result = await this.client.batchGetPeople(args); break; case 'google-contacts_list_contact_groups': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_list_contact_groups', clientMethod: 'listContactGroups' }); result = await this.client.listContactGroups(args); break; case 'google-contacts_create_contact_group': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_create_contact_group', clientMethod: 'createContactGroup' }); result = await this.client.createContactGroup(args); break; case 'google-contacts_get_contact_group': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_get_contact_group', clientMethod: 'getContactGroup' }); result = await this.client.getContactGroup(args); break; case 'google-contacts_update_contact_group': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_update_contact_group', clientMethod: 'updateContactGroup' }); result = await this.client.updateContactGroup(args); break; case 'google-contacts_delete_contact_group': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_delete_contact_group', clientMethod: 'deleteContactGroup' }); result = await this.client.deleteContactGroup(args); break; case 'google-contacts_modify_contact_group_members': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_modify_contact_group_members', clientMethod: 'modifyContactGroupMembers' }); result = await this.client.modifyContactGroupMembers(args); break; case 'google-contacts_list_directory_people': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_list_directory_people', clientMethod: 'listDirectoryPeople' }); result = await this.client.listDirectoryPeople(args); break; case 'google-contacts_search_directory_people': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_search_directory_people', clientMethod: 'searchDirectoryPeople' }); result = await this.client.searchDirectoryPeople(args); break; case 'google-contacts_list_other_contacts': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_list_other_contacts', clientMethod: 'listOtherContacts' }); result = await this.client.listOtherContacts(args); break; case 'google-contacts_search_other_contacts': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_search_other_contacts', clientMethod: 'searchOtherContacts' }); result = await this.client.searchOtherContacts(args); break; case 'google-contacts_copy_other_contact': this.logger.debug('TOOL_EXECUTE', 'Calling client method', { tool: 'google-contacts_copy_other_contact', clientMethod: 'copyOtherContact' }); result = await this.client.copyOtherContact(args); break; default: throw new Error(`Unknown tool: ${name}`); } const duration = Date.now() - startTime; this.logger.logToolSuccess(name, duration, result); // Format the result for MCP (OAuth templates only) return { content: [ { type: 'text', text: typeof result === 'string' ? result : JSON.stringify(result, null, 2) } ] }; } catch (error) { const duration = Date.now() - startTime; const errorMessage = error instanceof Error ? error.message : String(error); this.logger.logToolError(name, error, duration, args); return { content: [ { type: 'text', text: `Error: ${errorMessage}` } ], isError: true }; } } } //# sourceMappingURL=google-contacts-tools.js.map