UNPKG

twenty-mcp-server

Version:

Easy-to-install Model Context Protocol server for Twenty CRM. Try instantly with 'npx twenty-mcp-server setup' or install globally for permanent use.

320 lines 13.8 kB
export function createGetCompanyContactsTool(client) { return { name: 'get_company_contacts', description: 'Get all contacts (people) associated with a specific company', inputSchema: { type: 'object', properties: { companyId: { type: 'string', description: 'The ID of the company to get contacts for' } }, required: ['companyId'] }, handler: async (args) => { try { const result = await client.getCompanyContacts(args.companyId); const contactsList = result.contacts.map(contact => `• ${contact.name.firstName} ${contact.name.lastName}` + (contact.jobTitle ? ` - ${contact.jobTitle}` : '') + (contact.email ? ` (${contact.email})` : '') + (contact.phone ? ` | Phone: ${contact.phone}` : '') + `\n ID: ${contact.id}`).join('\n'); return { content: [{ type: 'text', text: `Company Contacts for "${result.companyName}"\n` + `Company ID: ${result.companyId}\n` + `Total Contacts: ${result.totalContacts}\n\n` + (result.totalContacts > 0 ? `Contacts:\n${contactsList}` : 'No contacts found for this company.') }] }; } catch (error) { return { content: [{ type: 'text', text: `Error retrieving company contacts: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } } }; } export function createGetPersonOpportunitiesTool(client) { return { name: 'get_person_opportunities', description: 'Get all opportunities where a specific person is the point of contact', inputSchema: { type: 'object', properties: { personId: { type: 'string', description: 'The ID of the person to get opportunities for' } }, required: ['personId'] }, handler: async (args) => { try { const result = await client.getPersonOpportunities(args.personId); const opportunitiesList = result.opportunities.map(opp => { let oppText = `• ${opp.name}`; if (opp.stage) oppText += ` (${opp.stage})`; if (opp.amount) { const amount = opp.amount.amountMicros / 1000000; oppText += ` - ${opp.amount.currencyCode} ${amount.toLocaleString()}`; } if (opp.company) oppText += ` | Company: ${opp.company.name}`; if (opp.closeDate) oppText += ` | Close: ${opp.closeDate}`; oppText += `\n ID: ${opp.id}`; return oppText; }).join('\n'); return { content: [{ type: 'text', text: `Opportunities for "${result.personName}"\n` + `Person ID: ${result.personId}\n` + `Total Opportunities: ${result.totalOpportunities}\n\n` + (result.totalOpportunities > 0 ? `Opportunities:\n${opportunitiesList}` : 'No opportunities found for this person.') }] }; } catch (error) { return { content: [{ type: 'text', text: `Error retrieving person opportunities: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } } }; } export function createLinkOpportunityTool(client) { return { name: 'link_opportunity_to_company', description: 'Link an opportunity to a company and/or point of contact', inputSchema: { type: 'object', properties: { opportunityId: { type: 'string', description: 'The ID of the opportunity to update' }, companyId: { type: 'string', description: 'The ID of the company to link to (optional)' }, pointOfContactId: { type: 'string', description: 'The ID of the person to set as point of contact (optional)' } }, required: ['opportunityId'] }, handler: async (args) => { try { if (!args.companyId && !args.pointOfContactId) { return { content: [{ type: 'text', text: 'Error: At least one of companyId or pointOfContactId must be provided' }], isError: true }; } const result = await client.linkOpportunityToCompany({ opportunityId: args.opportunityId, companyId: args.companyId, pointOfContactId: args.pointOfContactId }); let relationshipInfo = ''; if (result.company) { relationshipInfo += `Company: ${result.company.name} (${result.company.id})\n`; } if (result.pointOfContact) { relationshipInfo += `Point of Contact: ${result.pointOfContact.name.firstName} ${result.pointOfContact.name.lastName} (${result.pointOfContact.id})\n`; } return { content: [{ type: 'text', text: `Successfully linked opportunity "${result.name}"\n` + `Opportunity ID: ${result.id}\n\n` + `Updated Relationships:\n${relationshipInfo}` }] }; } catch (error) { return { content: [{ type: 'text', text: `Error linking opportunity: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } } }; } export function createTransferContactTool(client) { return { name: 'transfer_contact_to_company', description: 'Transfer a contact (person) from one company to another', inputSchema: { type: 'object', properties: { contactId: { type: 'string', description: 'The ID of the contact to transfer' }, toCompanyId: { type: 'string', description: 'The ID of the company to transfer the contact to' }, fromCompanyId: { type: 'string', description: 'The ID of the current company (optional, for validation)' } }, required: ['contactId', 'toCompanyId'] }, handler: async (args) => { try { const result = await client.transferContactToCompany({ contactId: args.contactId, fromCompanyId: args.fromCompanyId, toCompanyId: args.toCompanyId }); return { content: [{ type: 'text', text: `Successfully transferred contact "${result.name.firstName} ${result.name.lastName}"\n` + `Contact ID: ${result.id}\n` + `New Company: ${result.company?.name || 'Unknown'} (${result.companyId})` }] }; } catch (error) { return { content: [{ type: 'text', text: `Error transferring contact: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } } }; } export function createGetRelationshipSummaryTool(client) { return { name: 'get_relationship_summary', description: 'Get a summary of all relationships for a specific entity (company or person)', inputSchema: { type: 'object', properties: { entityId: { type: 'string', description: 'The ID of the entity to get relationship summary for' }, entityType: { type: 'string', enum: ['company', 'person'], description: 'The type of entity (company or person)' } }, required: ['entityId', 'entityType'] }, handler: async (args) => { try { const result = await client.getRelationshipSummary(args.entityId, args.entityType); return { content: [{ type: 'text', text: `Relationship Summary for ${args.entityType}: ${args.entityId}\n\n` + `Connected Relationships:\n` + `• Companies: ${result.relationships.companies}\n` + `• Contacts: ${result.relationships.contacts}\n` + `• Opportunities: ${result.relationships.opportunities}\n` + `• Tasks: ${result.relationships.tasks}\n` + `• Activities: ${result.relationships.activities}` }] }; } catch (error) { return { content: [{ type: 'text', text: `Error getting relationship summary: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } } }; } export function createFindOrphanedRecordsTool(client) { return { name: 'find_orphaned_records', description: 'Find records that are missing important relationships (companies without contacts, contacts without companies, etc.)', inputSchema: { type: 'object', properties: {}, required: [] }, handler: async (args) => { try { const result = await client.findOrphanedRecords(); let report = 'Orphaned Records Report\n====================\n\n'; // Companies without contacts if (result.companies.length > 0) { report += `Companies without contacts (${result.companies.length}):\n`; result.companies.forEach(company => { report += `• ${company.name} (${company.opportunityCount} opportunities)\n ID: ${company.id}\n`; }); report += '\n'; } // Contacts without companies if (result.contacts.length > 0) { report += `Contacts without companies (${result.contacts.length}):\n`; result.contacts.forEach(contact => { report += `• ${contact.name} (${contact.opportunityCount} opportunities)\n ID: ${contact.id}\n`; }); report += '\n'; } // Summary report += `Summary:\n`; report += `• ${result.companies.length} companies without contacts\n`; report += `• ${result.contacts.length} contacts without companies\n`; report += `• ${result.opportunities.length} opportunities with missing relationships\n`; report += `• ${result.tasks.length} tasks without assignees`; if (result.companies.length === 0 && result.contacts.length === 0 && result.opportunities.length === 0 && result.tasks.length === 0) { report += '\n\n✅ No orphaned records found! All records have proper relationships.'; } return { content: [{ type: 'text', text: report }] }; } catch (error) { return { content: [{ type: 'text', text: `Error finding orphaned records: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true }; } } }; } //# sourceMappingURL=relationships.js.map