Skip to main content
Glama
jcontini

macOS Contacts MCP

by jcontini

create_contact

Add new contacts to macOS Contacts app by providing name, organization, job title, emails, phones, URLs, and notes.

Instructions

Create a new contact

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
nameYesFull name of the contact
organizationNoOrganization or company name
job_titleNoJob title or position
emailsNoEmail addresses
phonesNoPhone numbers
urlsNoURLs (social media, websites, etc.) with labels
noteNoNotes about the contact

Implementation Reference

  • Implements the core logic for creating a new contact in the macOS Contacts app using dynamically generated AppleScript. Parses input arguments, escapes strings, constructs and executes the script to add a new person with optional fields like organization, job title, emails, phones, URLs, and notes.
    private async createContact(args: any): Promise<any> {
      const { name, organization = '', job_title = '', emails = [], phones = [], urls = [], note = '' } = args;
    
      // Parse name into first/last name
      const nameParts = name.trim().split(' ');
      const firstName = nameParts[0] || '';
      const lastName = nameParts.length > 1 ? nameParts.slice(1).join(' ') : '';
    
      let script = `
        tell application "Contacts"
          set newPerson to make new person
          
          if "${this.escapeForAppleScript(firstName)}" is not "" then
            set first name of newPerson to "${this.escapeForAppleScript(firstName)}"
          end if
          
          if "${this.escapeForAppleScript(lastName)}" is not "" then
            set last name of newPerson to "${this.escapeForAppleScript(lastName)}"
          end if
          
          if "${this.escapeForAppleScript(organization)}" is not "" then
            set organization of newPerson to "${this.escapeForAppleScript(organization)}"
          end if
          
          if "${this.escapeForAppleScript(job_title)}" is not "" then
            set job title of newPerson to "${this.escapeForAppleScript(job_title)}"
          end if
          
          if "${this.escapeForAppleScript(note)}" is not "" then
            set note of newPerson to "${this.escapeForAppleScript(note)}"
          end if
      `;
    
      // Add emails
      if (emails.length > 0) {
        emails.forEach((email: string, index: number) => {
          const label = index === 0 ? 'home' : index === 1 ? 'work' : `email${index + 1}`;
          script += `\n        make new email at end of emails of newPerson with properties {label:"${label}", value:"${this.escapeForAppleScript(email)}"}`;
        });
      }
    
      // Add phones
      if (phones.length > 0) {
        phones.forEach((phone: string, index: number) => {
          const label = index === 0 ? 'home' : index === 1 ? 'work' : `phone${index + 1}`;
          script += `\n        make new phone at end of phones of newPerson with properties {label:"${label}", value:"${this.escapeForAppleScript(phone)}"}`;
        });
      }
    
      // Add URLs
      if (urls.length > 0) {
        urls.forEach((url: any) => {
          script += `\n        make new url at end of urls of newPerson with properties {label:"${this.escapeForAppleScript(url.label)}", value:"${this.escapeForAppleScript(url.value)}"}`;
        });
      }
    
      script += `
          save
          return id of newPerson
        end tell
      `;
    
      try {
        const contactId = this.executeAppleScript(script);
        
        return {
          success: true,
          message: `Created contact: ${name}`,
          contact_id: contactId,
          contact: { name, organization, job_title, emails, phones, urls, note },
        };
      } catch (error) {
        throw new Error(`Create contact failed: ${error}`);
      }
    }
  • src/index.ts:80-127 (registration)
    Registers the 'create_contact' tool in the ListTools response, including its name, description, and detailed input schema defining parameters like name (required), organization, job_title, emails, phones, urls, and note.
    {
      name: 'create_contact',
      description: 'Create a new contact',
      inputSchema: {
        type: 'object',
        properties: {
          name: {
            type: 'string',
            description: 'Full name of the contact',
          },
          organization: {
            type: 'string',
            description: 'Organization or company name',
          },
          job_title: {
            type: 'string',
            description: 'Job title or position',
          },
          emails: {
            type: 'array',
            items: { type: 'string' },
            description: 'Email addresses',
          },
          phones: {
            type: 'array',
            items: { type: 'string' },
            description: 'Phone numbers',
          },
          urls: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                label: { type: 'string' },
                value: { type: 'string' },
              },
              required: ['label', 'value'],
            },
            description: 'URLs (social media, websites, etc.) with labels',
          },
          note: {
            type: 'string',
            description: 'Notes about the contact',
          },
        },
        required: ['name'],
      },
    },
  • Defines the input schema for the create_contact tool, specifying the structure and types for all parameters, with 'name' as the only required field.
    inputSchema: {
      type: 'object',
      properties: {
        name: {
          type: 'string',
          description: 'Full name of the contact',
        },
        organization: {
          type: 'string',
          description: 'Organization or company name',
        },
        job_title: {
          type: 'string',
          description: 'Job title or position',
        },
        emails: {
          type: 'array',
          items: { type: 'string' },
          description: 'Email addresses',
        },
        phones: {
          type: 'array',
          items: { type: 'string' },
          description: 'Phone numbers',
        },
        urls: {
          type: 'array',
          items: {
            type: 'object',
            properties: {
              label: { type: 'string' },
              value: { type: 'string' },
            },
            required: ['label', 'value'],
          },
          description: 'URLs (social media, websites, etc.) with labels',
        },
        note: {
          type: 'string',
          description: 'Notes about the contact',
        },
      },
      required: ['name'],
    },
  • Dispatcher case in the CallToolRequest handler that routes 'create_contact' calls to the createContact method.
    case 'create_contact':
      result = await this.createContact(args);
      break;
  • TypeScript interface defining the structure of a Contact object, used across tool implementations including create_contact for type consistency.
    interface Contact {
      id?: string;
      name: string;
      organization?: string;
      job_title?: string;
      emails?: string[];
      phones?: string[];
      urls?: { label: string; value: string }[];
      note?: string;
      creation_date?: string;
      modification_date?: string;
      image?: string; // base64
    }

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