Skip to main content
Glama
jcontini

macOS Contacts MCP

by jcontini

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

NameRequiredDescriptionDefault
limitNoMaximum number of results to return
queryNoSearch 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

  • 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, }, }, }, },
  • 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;
  • 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}`); } }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jcontini/macos-contacts-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server