Skip to main content
Glama
jcontini

macOS Contacts MCP

by jcontini

get_contact

Retrieve contact details from macOS Contacts using a name or unique identifier to access phone numbers, emails, and other information.

Instructions

Get full contact details by name or ID

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
identifierYesContact name or unique ID

Implementation Reference

  • The core handler function for the 'get_contact' tool. It uses AppleScript to query the macOS Contacts application for a contact by ID or name, fetches basic info first, then retrieves emails, phones, and URLs separately, and returns a structured contact object.
      private async getContact(args: any): Promise<any> {
        const { identifier } = args;
    
        // Simple approach - get basic info first, then build up
        let script = `tell application "Contacts"
      try
        set targetPerson to person id "${identifier}"
      on error
        try
          set targetPerson to person "${identifier}"
        on error
          return "Contact not found"
        end try
      end try
      
      return id of targetPerson & "|" & name of targetPerson & "|" & organization of targetPerson & "|" & job title of targetPerson & "|" & note of targetPerson
    end tell`;
    
        try {
          const result = this.executeAppleScript(script);
          if (result === 'Contact not found') {
            return { success: false, message: 'Contact not found' };
          }
          
          const parts = result.split('|');
          const contact: any = {
            id: parts[0] || '',
            name: parts[1] || '',
            organization: parts[2] || '',
            job_title: parts[3] || '',
            note: parts[4] || '',
          };
    
          // Get emails separately
          try {
            const emailScript = `tell application "Contacts"
      set targetPerson to person id "${contact.id}"
      set emailList to {}
      repeat with anEmail in emails of targetPerson
        set end of emailList to value of anEmail
      end repeat
      return emailList
    end tell`;
            const emailResult = this.executeAppleScript(emailScript);
            contact.emails = emailResult ? emailResult.split(', ') : [];
          } catch {
            contact.emails = [];
          }
    
          // Get phones separately
          try {
            const phoneScript = `tell application "Contacts"
      set targetPerson to person id "${contact.id}"
      set phoneList to {}
      repeat with aPhone in phones of targetPerson
        set end of phoneList to value of aPhone
      end repeat
      return phoneList
    end tell`;
            const phoneResult = this.executeAppleScript(phoneScript);
            contact.phones = phoneResult ? phoneResult.split(', ') : [];
          } catch {
            contact.phones = [];
          }
    
          // Get URLs separately  
          try {
            const urlScript = `tell application "Contacts"
      set targetPerson to person id "${contact.id}"
      set urlList to {}
      repeat with aUrl in urls of targetPerson
        set end of urlList to (label of aUrl & ":" & value of aUrl)
      end repeat
      return urlList
    end tell`;
            const urlResult = this.executeAppleScript(urlScript);
            if (urlResult) {
              contact.urls = urlResult.split(', ').map(item => {
                const [label, ...valueParts] = item.split(':');
                return { label: label || '', value: valueParts.join(':') || '' };
              });
            } else {
              contact.urls = [];
            }
          } catch {
            contact.urls = [];
          }
    
          return { success: true, contact };
        } catch (error) {
          throw new Error(`Get contact failed: ${error}`);
        }
      }
  • Tool registration entry defining the name, description, and input schema for 'get_contact', which requires an 'identifier' string (contact name or ID).
    {
      name: 'get_contact',
      description: 'Get full contact details by name or ID',
      inputSchema: {
        type: 'object',
        properties: {
          identifier: {
            type: 'string',
            description: 'Contact name or unique ID',
          },
        },
        required: ['identifier'],
      },
    },
  • src/index.ts:219-221 (registration)
    Dispatches the 'get_contact' tool call to the handler function within the CallToolRequestHandler switch statement.
    case 'get_contact':
      result = await this.getContact(args);
      break;
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It states it 'Get[s] full contact details', implying a read-only operation, but does not address potential side effects, error conditions, authentication needs, rate limits, or return format. For a tool with zero annotation coverage, this is a significant gap in transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's purpose without redundancy. It is front-loaded with the core action and resource, making it easy to parse, and every word earns its place by specifying key details like 'full contact details' and 'by name or ID'.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (single parameter, no output schema, no annotations), the description is minimally adequate. It covers the basic purpose but lacks behavioral context, usage guidelines, and output details, which are needed for a complete understanding. Without annotations or output schema, the description should do more to compensate, but it meets the bare minimum for a simple retrieval tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with the parameter 'identifier' documented as 'Contact name or unique ID'. The description adds no additional meaning beyond this, such as format examples, validation rules, or disambiguation between name and ID. With high schema coverage, the baseline score of 3 is appropriate, as the description does not compensate but also does not detract.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('Get') and resource ('full contact details'), specifying it retrieves information by name or ID. It distinguishes from siblings like 'create_contact' (creation) and 'update_contact' (modification), but does not explicitly differentiate from 'get_recent_contacts' (which likely retrieves multiple recent contacts) or 'search_contacts' (which may allow broader queries).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives like 'get_recent_contacts' or 'search_contacts'. It implies usage for retrieving a single contact by identifier, but does not specify scenarios, exclusions, or prerequisites, leaving the agent to infer based on tool names alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other 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