Apple Contacts

io.github.mgcreaPublished by GitHub account mgcreav1.37.0Updated Nov 7, 2026

Search and read Apple Contacts — resolves numbers and emails to names, writes off by default

Overview

AI-generated overview

Reads the macOS Apple Contacts address book so an assistant can resolve phone numbers and emails to names, search and list contacts, with writes off by default.

What you can do
  • Resolve batches of up to 500 phone numbers and email addresses to names, with ambiguity reported as a status rather than a guess
  • Search, list and fetch individual contacts from the local address book
  • Run diagnostics on the contacts store and lookup index
  • Create and update contacts, only when writes are explicitly enabled
When to use it
Useful when an assistant needs to put names to phone numbers or email addresses from the user's own Mac address book, or to look up and edit contact records locally. It is macOS-only and reads the address book already on the machine.
Requirements
Runs locally as an npm package via npx on macOS. The Contacts permission must be granted, which triggers a prompt on first use; writes additionally need the Automation to Contacts permission. Optional environment variables configure write access, phone suffix length, index mode, store path and script timeout.
Before you install
Write tools create and update contacts and are only registered when the write flag is enabled; with it off they are invisible to the model. Writes can appear to succeed without persisting, so results should be re-checked. The server is unofficial and not affiliated with Apple. It reads the user's personal address book data.

Installation

In SourceWeft

  1. Open Apple Contacts in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

@mgcrea/mcp-apple-contacts

Model Context Protocol server for the macOS Apple Contacts address book.

Unofficial. Not affiliated with Apple. It reads the address book already on your Mac.

Why it exists: resolving handles

apple_contacts_resolve_handles turns phone numbers and email addresses into names, in batches of up to 500. Everything else here is in service of that.

This is the surface where the file-lane rule is about capability, not speed. Contacts' scripting dictionary answers in ~65 ms — comfortably fast, and still useless for this: resolving a phone number means a suffix-keyed index over every stored number, and no quantity of Apple Events round trips produces one. So reads go through read-only SQLite, and there is no Apple Events read lane.

The lookup builds in 3 ms over 947 phone keys and 295 email keys, then is kept for the life of the process.

Permissions — this one is different

PermissionNeeded forNotes
Contacts (its own)readsprompts — answer the dialog, and that's it
Automation → Contactswrites onlyreads are unaffected

Contacts fails differently from every other surface in this family: it sits behind its own TCC service rather than behind Full Disk Access, and unlike Full Disk Access that permission prompts. So the fix is usually "answer the dialog", not "go to System Settings" — and nothing here asks you to hand over whole-disk access for an address book.

Tools

Read: diagnostics, resolve_handles, search_contacts, list_contacts, get_contact.

Write, registered only when APPLE_CONTACTS_ALLOW_WRITES=1 — with the flag off they are invisible to the model, not merely refused: create_contact, update_contact.

resolveHandles() is also exported from the package root, for callers already inside Node that would rather not go through MCP to reach it.

Configuration

VariableDefault
APPLE_CONTACTS_ALLOW_WRITESoffRegister the mutating tools.
APPLE_CONTACTS_PHONE_SUFFIX_DIGITS9Suffix key length; 6–15.
APPLE_CONTACTS_INDEX_MODEautoauto | ro | immutable | off.
APPLE_CONTACTS_STOREautoExplicit store path.
APPLE_CONTACTS_OSASCRIPT_TIMEOUT_MS30000Sized for the first-run permission prompt.

Notes that will bite you

  • The store is plural. locate.ts returns a list and every query fans out — on a real machine, stores=2/2, contacts=421, matching Apple Events exactly. A server reading only the first store silently loses an account.
  • Nine-digit suffix keys, and the length travels inside the lookup object so the index and the query cannot diverge. A self-join over a real address book at 7, 9 and 10 digits settles it: 7 and 9 collide identically (10 of 947 keys, 1.1%), and 10 drops a key while losing the national-to-E.164 join.
  • Ambiguity is a status, never a guess — resolved / unknown / ambiguous / shortcode. unknown is documented in the tool description as expected, not as an error.
  • Z_ENT filters to ABCDContact. Without it, a list tool returns your groups as people.
  • A write can succeed and still not persist. Contacts holds changes in an unsaved buffer, so a mutation can read back correctly inside the same script and never reach the store. Every write script saves and then re-reads.

Licence

MIT.

Source: packages/contacts/README.md at commit 2398a54

Tools

0
SourceWeft has not started this package in its sandbox yet, so its tools are not known.

Version history

18
  1. v1.37.0LatestNov 7, 2026
  2. v1.36.2Nov 4, 2026
  3. v1.36.1Nov 3, 2026
  4. v1.36.0Oct 30, 2026
  5. v1.35.0Oct 30, 2026
  6. v1.34.0Oct 29, 2026
  7. v1.31.0Oct 26, 2026
  8. v1.30.0Oct 22, 2026
  9. v1.29.1Oct 21, 2026
  10. v1.28.0Oct 13, 2026
  11. v1.27.0Oct 13, 2026
  12. v1.26.0Oct 6, 2026
  13. v1.25.0Oct 3, 2026
  14. v1.24.1Sep 29, 2026
  15. v1.24.0Sep 27, 2026
  16. v1.23.0Sep 19, 2026
  17. v1.22.1Sep 16, 2026
  18. v1.21.1Sep 16, 2026

Score

50% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts

    Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.

  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts