contacts
Search and retrieve contact information from Apple Contacts app using partial or full name queries to find specific people in your address book.
Instructions
Search and retrieve contacts from Apple Contacts app
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Name to search for (optional - if not provided, returns all contacts). Can be partial name to search. |
Implementation Reference
- tools.ts:3-15 (schema)Defines the input schema and metadata for the 'contacts' MCP tool.const CONTACTS_TOOL: Tool = { name: "contacts", description: "Search and retrieve contacts from Apple Contacts app", inputSchema: { type: "object", properties: { name: { type: "string", description: "Name to search for (optional - if not provided, returns all contacts). Can be partial name to search." } } } };
- tools.ts:308-310 (registration)Registers the CONTACTS_TOOL in the array of tools exported for the MCP server.const tools = [CONTACTS_TOOL, NOTES_TOOL, MESSAGES_TOOL, MAIL_TOOL, REMINDERS_TOOL, WEB_SEARCH_TOOL, CALENDAR_TOOL, MAPS_TOOL]; export default tools;
- utils/contacts.ts:4-15 (helper)Utility function to check access permissions to the Contacts app before performing operations.async function checkContactsAccess(): Promise<boolean> { try { // Try to get the count of contacts as a simple test await runAppleScript(` tell application "Contacts" count every person end tell`); return true; } catch (error) { throw new Error(`Cannot access Contacts app. Please grant access in System Preferences > Security & Privacy > Privacy > Contacts.`); } }
- utils/contacts.ts:17-49 (helper)Retrieves all contacts and their associated phone numbers, used when no search name is provided.async function getAllNumbers() { try { if (!await checkContactsAccess()) { return {}; } const nums: { [key: string]: string[] } = await run(() => { const Contacts = Application('Contacts'); const people = Contacts.people(); const phoneNumbers: { [key: string]: string[] } = {}; for (const person of people) { try { const name = person.name(); const phones = person.phones().map((phone: any) => phone.value()); if (!phoneNumbers[name]) { phoneNumbers[name] = []; } phoneNumbers[name] = [...phoneNumbers[name], ...phones]; } catch (error) { // Skip contacts that can't be processed } } return phoneNumbers; }); return nums; } catch (error) { throw new Error(`Error accessing contacts: ${error instanceof Error ? error.message : String(error)}`); } }
- utils/contacts.ts:51-77 (helper)Searches for a contact by name (partial match) and returns their phone numbers, with fallback search; used when name is provided.async function findNumber(name: string) { try { if (!await checkContactsAccess()) { return []; } const nums: string[] = await run((name: string) => { const Contacts = Application('Contacts'); const people = Contacts.people.whose({name: {_contains: name}}); const phones = people.length > 0 ? people[0].phones() : []; return phones.map((phone: any) => phone.value()); }, name); // If no numbers found, run getNumbers() to find the closest match if (nums.length === 0) { const allNumbers = await getAllNumbers(); const closestMatch = Object.keys(allNumbers).find(personName => personName.toLowerCase().includes(name.toLowerCase()) ); return closestMatch ? allNumbers[closestMatch] : []; } return nums; } catch (error) { throw new Error(`Error finding contact: ${error instanceof Error ? error.message : String(error)}`); } }