update_contact
Modify contact details in macOS Contacts, including name, organization, emails, phones, URLs, and notes, by specifying the contact identifier.
Instructions
Update an existing contact
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| identifier | Yes | Contact name or unique ID | |
| name | No | Updated full name | |
| organization | No | Updated organization or company name | |
| job_title | No | Updated job title or position | |
| emails | No | Updated email addresses (replaces all existing) | |
| phones | No | Updated phone numbers (replaces all existing) | |
| urls | No | Updated URLs (replaces all existing) | |
| note | No | Updated notes |
Implementation Reference
- src/index.ts:504-689 (handler)The main handler function for the 'update_contact' tool. It retrieves the contact by identifier, then updates specified fields (name, organization, job_title, note, emails, phones, urls) by executing AppleScript commands to modify the macOS Contacts app.private async updateContact(args: any): Promise<any> { const { identifier, ...updates } = args; // First get the contact to verify it exists and get the correct ID const existingContact = await this.getContact({ identifier }); if (!existingContact.success) { throw new Error('Contact not found'); } const contactId = existingContact.contact.id; const updatedFields: string[] = []; // Update name if provided if (updates.name !== undefined) { try { // Parse name into first/last name const nameParts = updates.name.trim().split(' '); const firstName = nameParts[0] || ''; const lastName = nameParts.length > 1 ? nameParts.slice(1).join(' ') : ''; const script = `tell application "Contacts" set targetPerson to person id "${contactId}" set first name of targetPerson to "${this.escapeForAppleScript(firstName)}" set last name of targetPerson to "${this.escapeForAppleScript(lastName)}" save end tell`; this.executeAppleScript(script); updatedFields.push('name'); } catch (error) { console.error('Failed to update name:', error); } } // Update basic properties one by one if (updates.organization !== undefined) { try { const script = `tell application "Contacts" set targetPerson to person id "${contactId}" set organization of targetPerson to "${this.escapeForAppleScript(updates.organization)}" save end tell`; this.executeAppleScript(script); updatedFields.push('organization'); } catch (error) { console.error('Failed to update organization:', error); } } if (updates.job_title !== undefined) { try { const script = `tell application "Contacts" set targetPerson to person id "${contactId}" set job title of targetPerson to "${this.escapeForAppleScript(updates.job_title)}" save end tell`; this.executeAppleScript(script); updatedFields.push('job_title'); } catch (error) { console.error('Failed to update job title:', error); } } if (updates.note !== undefined) { try { const script = `tell application "Contacts" set targetPerson to person id "${contactId}" set note of targetPerson to "${this.escapeForAppleScript(updates.note)}" save end tell`; this.executeAppleScript(script); updatedFields.push('note'); } catch (error) { console.error('Failed to update note:', error); } } // Update URLs if provided if (updates.urls !== undefined) { try { // First, remove all existing URLs const clearUrlScript = `tell application "Contacts" set targetPerson to person id "${contactId}" delete every url of targetPerson save end tell`; this.executeAppleScript(clearUrlScript); // Then add new URLs if (updates.urls.length > 0) { let addUrlScript = `tell application "Contacts" set targetPerson to person id "${contactId}"`; updates.urls.forEach((url: any) => { addUrlScript += ` make new url at end of urls of targetPerson with properties {label:"${this.escapeForAppleScript(url.label)}", value:"${this.escapeForAppleScript(url.value)}"}`; }); addUrlScript += ` save end tell`; this.executeAppleScript(addUrlScript); } updatedFields.push('urls'); } catch (error) { console.error('Failed to update URLs:', error); } } // Update emails if provided if (updates.emails !== undefined) { try { // First, remove all existing emails const clearEmailScript = `tell application "Contacts" set targetPerson to person id "${contactId}" delete every email of targetPerson save end tell`; this.executeAppleScript(clearEmailScript); // Then add new emails if (updates.emails.length > 0) { let addEmailScript = `tell application "Contacts" set targetPerson to person id "${contactId}"`; updates.emails.forEach((email: string, index: number) => { const label = index === 0 ? 'home' : index === 1 ? 'work' : `email${index + 1}`; addEmailScript += ` make new email at end of emails of targetPerson with properties {label:"${label}", value:"${this.escapeForAppleScript(email)}"}`; }); addEmailScript += ` save end tell`; this.executeAppleScript(addEmailScript); } updatedFields.push('emails'); } catch (error) { console.error('Failed to update emails:', error); } } // Update phones if provided if (updates.phones !== undefined) { try { // First, remove all existing phones const clearPhoneScript = `tell application "Contacts" set targetPerson to person id "${contactId}" delete every phone of targetPerson save end tell`; this.executeAppleScript(clearPhoneScript); // Then add new phones if (updates.phones.length > 0) { let addPhoneScript = `tell application "Contacts" set targetPerson to person id "${contactId}"`; updates.phones.forEach((phone: string, index: number) => { const label = index === 0 ? 'home' : index === 1 ? 'work' : `phone${index + 1}`; addPhoneScript += ` make new phone at end of phones of targetPerson with properties {label:"${label}", value:"${this.escapeForAppleScript(phone)}"}`; }); addPhoneScript += ` save end tell`; this.executeAppleScript(addPhoneScript); } updatedFields.push('phones'); } catch (error) { console.error('Failed to update phones:', error); } } return { success: true, message: `Updated contact: ${identifier}`, updated_fields: updatedFields, }; }
- src/index.ts:128-179 (schema)The input schema definition for the 'update_contact' tool, specifying parameters like identifier (required), name, organization, job_title, emails (array), phones (array), urls (array of objects), and note.{ name: 'update_contact', description: 'Update an existing contact', inputSchema: { type: 'object', properties: { identifier: { type: 'string', description: 'Contact name or unique ID', }, name: { type: 'string', description: 'Updated full name', }, organization: { type: 'string', description: 'Updated organization or company name', }, job_title: { type: 'string', description: 'Updated job title or position', }, emails: { type: 'array', items: { type: 'string' }, description: 'Updated email addresses (replaces all existing)', }, phones: { type: 'array', items: { type: 'string' }, description: 'Updated phone numbers (replaces all existing)', }, urls: { type: 'array', items: { type: 'object', properties: { label: { type: 'string' }, value: { type: 'string' }, }, required: ['label', 'value'], }, description: 'Updated URLs (replaces all existing)', }, note: { type: 'string', description: 'Updated notes', }, }, required: ['identifier'], }, },
- src/index.ts:225-227 (registration)The dispatch case in the CallToolRequest handler that routes 'update_contact' calls to the updateContact method.case 'update_contact': result = await this.updateContact(args); break;