search_contacts
Search macOS Contacts for entries by name, organization, or notes using a customizable query and limit results for precise matches.
Instructions
Search for contacts by name, organization, or notes
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of results to return | |
| query | No | Search term to match against name, organization, or notes |
Input Schema (JSON Schema)
{
"properties": {
"limit": {
"default": 20,
"description": "Maximum number of results to return",
"type": "integer"
},
"query": {
"description": "Search term to match against name, organization, or notes",
"type": "string"
}
},
"type": "object"
}
Implementation Reference
- src/index.ts:282-332 (handler)The main handler function that implements the search_contacts tool logic. It uses AppleScript to search for contacts by name in the macOS Contacts app and returns a list of matching contact names.private async searchContacts(args: any): Promise<any> { const { query, limit = 20 } = args; try { if (query) { // Use built-in search instead of manual loops const script = `tell application "Contacts" to return name of people whose name contains "${query}"`; const result = this.executeAppleScript(script); const names = result.split(', ').slice(0, limit); const contacts = names.map(name => ({ name: name.trim(), organization: '', // Basic search only returns names for speed })); return { success: true, count: contacts.length, contacts, }; } else { // Get first N contacts - simpler approach const script = `tell application "Contacts" set contactList to {} set allPeople to people repeat with i from 1 to ${Math.min(limit, 10)} if i > (count of allPeople) then exit repeat set aPerson to item i of allPeople set end of contactList to name of aPerson end repeat return contactList end tell`; const result = this.executeAppleScript(script); const names = result ? result.split(', ').slice(0, limit) : []; const contacts = names.map(name => ({ name: name.trim(), organization: '', // Basic search only returns names for speed })); return { success: true, count: contacts.length, contacts, }; } } catch (error) { throw new Error(`Search failed: ${error}`); } }
- src/index.ts:48-65 (registration)Tool registration in the ListTools response, including name, description, and input schema definition.{ name: 'search_contacts', description: 'Search for contacts by name, organization, or notes', inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search term to match against name, organization, or notes', }, limit: { type: 'integer', description: 'Maximum number of results to return', default: 20, }, }, }, },
- src/index.ts:51-64 (schema)Input schema definition for the search_contacts tool, specifying query and optional limit parameters.inputSchema: { type: 'object', properties: { query: { type: 'string', description: 'Search term to match against name, organization, or notes', }, limit: { type: 'integer', description: 'Maximum number of results to return', default: 20, }, }, },
- src/index.ts:216-218 (registration)Dispatch/registration case in the CallToolRequest handler that routes to the searchContacts method.case 'search_contacts': result = await this.searchContacts(args); break;
- src/index.ts:269-280 (helper)Helper method used by searchContacts to execute AppleScript commands for interacting with macOS Contacts.private executeAppleScript(script: string): string { try { // Use stdin to pass the script, avoiding shell escaping issues entirely const result = execSync(`osascript`, { input: script, encoding: 'utf8', }).trim(); return result; } catch (error: any) { throw new Error(`AppleScript execution failed: ${error}`); } }