Apple Contacts MCP
A local-first MCP server for safely managing Apple Contacts on macOS via AppleScript automation. All write operations are dry-run by default.
contacts_status– Verify Contacts.app accessibility and retrieve aggregate counts without exposing personal data.search_contacts– Find contacts by name, organization, job title, email, or phone number; control whether actual values are revealed in results (max 25 results per query).create_contact– Add a new contact with fields like first/last name, nickname, organization, job title, department, emails, and phones. RequiresdryRun: falseandconfirm: truefor actual creation.update_contact– Modify scalar fields, notes, or add email/phone values to an existing contact by ID. RequiresdryRun: falseandconfirm: truefor actual updates.append_contact_note– Append a dated, structured interaction log entry to a contact's notes field (CRM-style), without overwriting existing notes.delete_contact– Remove a contact by ID. Requiresconfirm: trueand the confirmation phrase"delete contact"for safety.test_roundtrip– Run a full end-to-end test (create → edit → verify → delete) using a dummy contact to validate permissions and setup without touching real data.
Allows searching, creating, updating, and deleting contacts in the Apple Contacts app on macOS.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Apple Contacts MCPsearch for John Doe's phone number"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Apple Contacts MCP
Local-first MCP server for safely searching, editing, and maintaining Apple Contacts notes on macOS.
The server uses Contacts.app automation through AppleScript today. That keeps install simple and uses macOS privacy prompts instead of cloud credentials. Writes are dry-run by default and require explicit confirmation.
Tools
contacts_status: check Contacts.app access and return aggregate counts.search_contacts: search local contacts by name, organization, job title, email, or phone.create_contact: create a contact. Dry-run by default.update_contact: update scalar fields, notes, or add email/phone values. Dry-run by default.append_contact_note: append a dated interaction log entry to a contact note. Dry-run by default.delete_contact: delete a contact. Dry-run by default and requires a confirmation phrase.test_roundtrip: create, edit, verify, and delete one dummy contact.
Related MCP server: contacts-mcp
Requirements
macOS with Contacts.app
Node.js 18 or newer
Contacts/Automation permissions when macOS prompts
Quick Start
git clone <repo-url>
cd apple-contacts-mcp
npm test
npm run smokenpm run smoke verifies the MCP handshake and tool list without touching Contacts.
To run a live dummy create/edit/note/delete roundtrip:
npm run smoke:livemacOS may prompt for Contacts or Automation permissions. The live smoke test creates one dummy contact, edits it, appends a note, verifies the change, and deletes the dummy.
Install For Your Agent
This is a stdio MCP server. Any MCP-capable agent needs the same command:
node /absolute/path/to/apple-contacts-mcp/bin/apple-contacts-mcp.cjsUse an absolute path. Relative paths are easy to break when an agent launches MCP servers from another working directory.
Install In Codex
After cloning:
codex mcp add apple-contacts -- node /absolute/path/to/apple-contacts-mcp/bin/apple-contacts-mcp.cjsThen restart Codex or start a new Codex thread so the MCP tools are loaded.
To confirm the server is registered:
codex mcp listAsk Codex:
Use apple-contacts to run contacts_status.Install In Claude Desktop
Open the Claude Desktop config file on macOS:
open "$HOME/Library/Application Support/Claude/claude_desktop_config.json"Add this under the top-level mcpServers object, then restart Claude Desktop:
{
"mcpServers": {
"apple-contacts": {
"command": "node",
"args": ["/absolute/path/to/apple-contacts-mcp/bin/apple-contacts-mcp.cjs"]
}
}
}If the file already has other MCP servers, add only the apple-contacts entry inside the existing mcpServers object.
Ask Claude:
Use the Apple Contacts MCP server to run contacts_status. Do not show any contact values.Install In Other Agents
Add a stdio MCP server with:
{
"mcpServers": {
"apple-contacts": {
"command": "node",
"args": ["/absolute/path/to/apple-contacts-mcp/bin/apple-contacts-mcp.cjs"]
}
}
}If your agent has an MCP CLI, use its equivalent of:
<agent> mcp add apple-contacts -- node /absolute/path/to/apple-contacts-mcp/bin/apple-contacts-mcp.cjsGood first prompt for any agent:
Install this repository as a local MCP server named apple-contacts. Use the absolute path to bin/apple-contacts-mcp.cjs, then restart or reload your MCP tools and run contacts_status. Treat contact data as personal data and keep writes dry-run unless I explicitly approve them.Permissions
This server automates Contacts.app locally. The first live call may trigger macOS permission prompts for Contacts and/or Automation. Approve those prompts for the terminal or app that is launching the MCP server.
If a call fails because Contacts.app is not running, open Contacts and retry:
open -a ContactsWrite Safety
Create, update, and delete operations are dry-run by default. An actual write must pass both:
{
"dryRun": false,
"confirm": true
}Delete also requires:
{
"confirmPhrase": "delete contact"
}This gives agents a natural two-step flow: propose the change first, then apply only after user approval.
Contact Notes
Use append_contact_note for CRM-style interaction logs instead of overwriting the full note field.
Input:
{
"contactId": "CONTACT-ID-FROM-search_contacts",
"date": "2026-06-04",
"summary": "Met at an AI founder dinner. They are interested in local-first agent tooling.",
"openThreads": [
"Send the GitHub repo",
"Follow up about a demo next week"
],
"dryRun": true
}The appended note entry uses:
- 2026-06-04 - Met at an AI founder dinner. They are interested in local-first agent tooling.
Open threads: Send the GitHub repo; Follow up about a demo next weekAn actual append requires:
{
"dryRun": false,
"confirm": true
}Privacy
This server runs locally on your Mac. It does not call a cloud API or upload contacts on its own. Your agent will still see whatever contact data you ask the MCP server to return, so use field filters and redaction when possible.
Contacts may sync through iCloud, Google, Exchange, or another configured account. A local write can propagate to those services.
Current Backend
The first backend is AppleScript automation of Contacts.app. A future backend may use a signed Swift helper around Apple's Contacts.framework for more structured access.
Direct SQLite writes to ~/Library/Application Support/AddressBook are intentionally not supported.
License
MIT
Available Tools
6 toolscontacts_statusContacts StatusA
Check Apple Contacts access and return aggregate counts without exposing contact values.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses a key behavioral trait: 'without exposing contact values', ensuring privacy. However, it does not explicitly state whether the tool is read-only or mention any side effects, rate limits, or authentication requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence of 12 words, front-loading the action and result. No unnecessary words, every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (no parameters, no output schema) and the context of sibling tools, the description adequately conveys its purpose and a key constraint. It could be more complete by specifying the types of aggregate counts, but it is sufficient for a zero-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% because there are no parameters. Baseline is 3. The description adds no parameter information since none exist, but that is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verb ('check') and resource ('Apple Contacts access') and explains the output ('aggregate counts'). It clearly distinguishes from sibling tools (create, delete, update, search) by focusing on access verification and summary statistics.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the tool is for checking access and getting aggregate counts, but it does not explicitly state when to use it over alternatives or provide conditions like 'use this before creating contacts'. No exclusions or prerequisites are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_contactCreate ContactA
Create an Apple Contact. Dry-run by default; actual writes require dryRun=false and confirm=true.
| Name | Required | Description | Default |
|---|---|---|---|
| firstName | No | ||
| lastName | No | ||
| organization | No | ||
| jobTitle | No | ||
| department | No | ||
| nickname | No | ||
| emails | No | ||
| phones | No | ||
| dryRun | No | ||
| confirm | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses the destructive behavior (actual writes require flags) and the dry-run default. However, it does not cover other behavioral aspects such as idempotency, duplicate handling, or error responses.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences long with no redundant information. Every word serves a purpose, making it highly efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 10 parameters, no output schema, and no annotations, the description is too minimal. It explains the dry-run mode but does not describe return values, validation rules, error handling, or any side effects, leaving significant gaps for an agent to correctly invoke the tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, meaning the JSON schema provides no descriptions for any of the 10 parameters. The description only adds context for two parameters (dryRun and confirm), leaving the other eight parameters unexplained. This is insufficient for a tool with many parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Create' and the resource 'Apple Contact', making the purpose unambiguous. It distinguishes the tool from siblings like update_contact and delete_contact by focusing on creation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains the default behavior (dry-run) and the explicit conditions for actual writes (dryRun=false and confirm=true). This provides clear guidance on when to use the tool and how to trigger real changes, though it does not explicitly mention when not to use it or alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_contactDelete ContactA
Delete an Apple Contact by contactId. Dry-run by default and requires confirmPhrase='delete contact'.
| Name | Required | Description | Default |
|---|---|---|---|
| contactId | Yes | ||
| dryRun | No | ||
| confirm | No | ||
| confirmPhrase | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It reveals the dry-run default and confirmation requirement, but does not mention deletion irreversibility, side effects, or required permissions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no wasted words. Each sentence adds value: operation and key parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Adequate for a simple delete tool, but lacks return value description, error conditions, and details about dry-run behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%. The description only explains contactId (by name) and confirmPhrase (requires), leaving dryRun and confirm undocumented. It partially compensates but is insufficient.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool deletes an Apple Contact by contactId, using a specific verb and resource, which distinguishes it from sibling tools like create_contact or update_contact.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains that dry-run is default and a confirmation phrase is required, providing clear usage context. However, it does not explicitly state when to use this tool over alternatives or mention any prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_contactsSearch ContactsB
Search Apple Contacts by name, organization, job title, email, or phone.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| limit | No | ||
| includeEmails | No | ||
| includePhones | No | ||
| revealValues | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavior. It does not mention that results can be limited via the limit parameter, that emails and phones are included only if requested, or the meaning of revealValues. The tool's read-only nature is implied but not stated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence, but it omits critical parameter details. It is front-loaded with the primary action but sacrifices completeness for brevity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With five parameters, no schema descriptions, and no output schema, the description is too brief to fully inform an agent. It fails to explain key parameters or expected output, making it incomplete for effective tool usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, yet the description only explains the query parameter implicitly by listing searchable fields. The other four parameters (limit, includeEmails, includePhones, revealValues) are completely unexplained, leaving the agent to guess their purpose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with a specific verb 'Search' and resource 'Apple Contacts', and lists searchable fields (name, organization, job title, email, phone). It effectively distinguishes from sibling tools like create_contact or delete_contact.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool (to search contacts) but does not provide explicit guidance on when not to use it or alternatives. Given the sibling tools are clearly different actions, the usage context is clear but lacks exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
test_roundtripTest Contacts RoundtripA
Create, edit, verify, and delete one dummy contact. Requires confirm=true.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description is the sole source for behavioral disclosure. It states the tool performs a sequence of actions (create, edit, verify, delete) on a dummy contact, suggesting it is a test operation with no lasting side effects. However, it lacks details on error behavior, verification specifics, and what happens if confirm is false.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is very concise with two sentences and no wasted words. While a bulleted list of actions might improve readability, the current structure effectively communicates the tool's purpose and requirement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool is a simple test utility with one parameter and no output schema, the description provides the essential information: the composite action and the confirm requirement. However, it does not explain what 'verify' entails, the expected outcome, or how to interpret results, leaving some gaps for the agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The only parameter, confirm, has no description in the schema (0% coverage). The description adds crucial meaning by stating 'Requires confirm=true,' indicating that the tool only performs actions when confirm is true. This clarifies the parameter's role beyond the schema's boolean type and default value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool creates, edits, verifies, and deletes one dummy contact, which explains the roundtrip testing purpose. However, it does not explicitly distinguish itself from sibling tools like create_contact or delete_contact, which are individual operations for production use.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description includes a usage condition: 'Requires confirm=true.' This tells when the tool will actually execute. However, it does not provide guidance on when to use this composite test tool versus individual sibling tools, nor does it explain the effect of confirm=false.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_contactUpdate ContactA
Update an Apple Contact by contactId. Dry-run by default; actual writes require dryRun=false and confirm=true.
| Name | Required | Description | Default |
|---|---|---|---|
| contactId | Yes | ||
| changes | Yes | ||
| dryRun | No | ||
| confirm | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses dry-run behavior and confirmation requirement, but no mention of side effects, error handling, or permissions. With no annotations, more detail expected.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, front-loaded with purpose. No redundant words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Missing details on 'changes' object structure, return value, error states. For a mutation tool with nested parameter, this is insufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only adds meaning to dryRun and confirm parameters. The 'changes' object parameter lacks any structural description. Schema coverage is 0%, so description should compensate more.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states verb 'Update' and resource 'Apple Contact by contactId'. Distinguishes from siblings like create_contact and delete_contact.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly notes dry-run default and requirement of dryRun=false and confirm=true for actual writes. Provides clear context for safe usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v0.1.0- First observed
contacts_status - First observed
create_contact - First observed
delete_contact - First observed
search_contacts - First observed
test_roundtrip - First observed
update_contact
TDQS
Scored across 6 tools
Each tool targets a distinct operation: status check, create, delete, search, roundtrip test, and update. No overlap in functionality.
All tool names follow a consistent verb_noun snake_case pattern (e.g., create_contact, search_contacts), with only 'contacts_status' varying slightly but still adhering to the pattern.
Six tools is an appropriate and focused set for managing Apple Contacts, covering core operations without unnecessary bloat.
The tool surface covers CRUD operations (create, search/read, update, delete) plus a status check and a roundtrip test for validation. No obvious gaps for the domain.
Maintenance
Related MCP Connectors
MCP connector for iMessage & Contacts via a local Mac agent + Vercel relay
MCP server for OnceAsk, the AI-native current-address layer for people and agents.
API-first CRM for LLMs - contacts, companies, deals and activities over a native MCP server.
MCP server for Nylas — read email, calendars, events and contacts, and send email or create events.
Related MCP Servers
- AlicenseBqualityBmaintenanceMCP server for macOS Apple apps. Enables read/write access to Notes, Reminders, Calendar, Contacts, and Safari using SQLite and JXA, all running locally.2816 npm3MIT
- AlicenseAqualityDmaintenanceLocal MCP server that exposes Apple Contacts data, enabling phone, email, and name lookups via a helper app.55 npmMIT
- AlicenseBqualityBmaintenanceLocal MCP server for macOS native apps: Mail, Calendar, Reminders, Notes, Messages, and Contacts. Enables reading and organizing your Mac life through a single stdio process using AppleScript/JXA.409 npmMIT
- AlicenseNot gradedqualityBmaintenanceLocal-first macOS MCP server for searching files, running approved Shortcuts, managing Homebrew packages, and working with local models, with read-only defaults and optional gated mutations.MIT