Skip to main content
Glama
atfinke

contacts-mcp

by atfinke

contacts-mcp

Local MCP server that exposes Apple Contacts data through a Contacts.framework helper app.

Built entirely by OpenAI GPT-5.4 via Codex.

Install

git clone https://github.com/<your-account>/contacts-mcp.git
cd contacts-mcp
./bootstrap.sh

Related MCP server: apple-mcp

Run

npm run start

Permissions

Run contacts_permissions once with prompt: true.

The helper app is intended to be built with the project's normal code signing so macOS can attribute Contacts access to a stable app identity.

If the prompt does not appear from inside Codex, launch the helper app directly once:

open ContactsMCPHelperApp/build/Build/Products/Release/ContactsMCPHelperApp.app

When opened directly, the app will request Contacts access and show a status alert. After that initial grant, the MCP tools can read visible contacts normally.

Lookup behavior is intentionally narrow: contacts_lookup_phone, contacts_lookup_email, and contacts_search_name return zero or more ranked matches, contacts_get_contact fetches one unified contact by identifier, and the server does not expose any write path.

Phone lookup uses the framework predicate first, then falls back to canonical digit matching when needed. Email lookup uses the framework predicate first, then falls back to exact case-insensitive comparison. Name search uses the framework name predicate first, then backfills ranked matches across full name, nickname, organization, and component fields when needed.

MCP config

{
  "mcpServers": {
    "contacts": {
      "command": "node",
      "args": ["/absolute/path/to/contacts-mcp/dist/index.js"],
      "env": {
        "CONTACTS_MCP_HELPER_APP_PATH": "/absolute/path/to/contacts-mcp/ContactsMCPHelperApp/build/Build/Products/Release/ContactsMCPHelperApp.app"
      }
    }
  }
}

Verify

npm run verify

Available Tools

5 tools
contacts_get_contactGet ContactA
Read-only

Fetch one Apple Contact by unified contact identifier.

ParametersJSON Schema
NameRequiredDescriptionDefault
contactIdentifierYes

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, so the safety profile is covered by structured data. The description adds only the singular 'one contact' scope and the ID-based access pattern; it says nothing about not-found behavior or what the returned contact contains, so it earns only a baseline-plus score.

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?

A single front-loaded sentence with no filler; the identifier semantics are delivered immediately.

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?

Adequate for a trivial one-parameter read tool with annotations covering safety, but it leaves the routing question (why not contacts_lookup_email/phone) and any failure/lookup semantics unaddressed, which is a real gap given four overlapping siblings.

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 0% on a single required parameter, but the description labels it 'unified contact identifier', giving the agent the key semantic that this is Apple's unified ID rather than a phone/email. With one parameter and the schema doing none of the describing, this is the minimum acceptable compensation.

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

Purpose5/5

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

States a specific verb (Fetch) and resource (one Apple Contact) with the scope qualifier 'by unified contact identifier', which cleanly distinguishes it from the lookup_phone, lookup_email, and search_name siblings.

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?

No when-to-use guidance and no mention of the alternatives. An agent must infer that this is the direct-ID retrieval path versus the sibling search/lookup-by-attribute tools; the description does not say so explicitly.

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

contacts_lookup_emailLookup EmailA
Read-only

Resolve one email address to matching Apple Contacts entries. Returns zero or more ranked matches.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxResultsNo
emailAddressYes

TDQS

A3.9/5.0
Behavior4/5

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

The description adds meaningful context beyond the readOnlyHint annotation: it clarifies that it returns zero or more matches (not guaranteed a single result), and that results are ranked. However, it doesn't disclose ranking criteria, pagination behavior, or whether it performs fuzzy matching. For a read-only lookup, this is good but not complete.

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?

Two concise sentences, front-loaded with the core operation and result behavior. No wasted words; every sentence earns its place.

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 no output schema, no annotation beyond readOnlyHint, and 0% schema coverage, the description is minimal but covers the essential purpose and return cardinality. It lacks details on ranking, maxResults, and error handling, but provides enough to invoke the tool correctly for a simple lookup operation.

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 0%, so the description must compensate for undocumented parameters. It names the input implicitly ('email address') but doesn't explain the maxResults parameter at all. The baseline when schema coverage is low is 2, but the description adds minimal value by naming the input; however, it fails to compensate for the missing maxResults semantics.

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

Purpose5/5

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

Specific verb ('Resolve') and resource ('email address to matching Apple Contacts entries'), clearly distinguishing it from siblings like contacts_lookup_phone and contacts_search_name. The scope is well-defined and immediately actionable.

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

Usage Guidelines3/5

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

The description implies use when you have an email address and need to find contacts, but it doesn't explicitly state when to use this tool versus alternatives or what prerequisites might exist. Sibling tools are not mentioned, leaving the agent to infer selection based on input type.

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

contacts_lookup_phoneLookup PhoneB
Read-only

Resolve one phone number to matching Apple Contacts entries. Returns zero or more ranked matches.

ParametersJSON Schema
NameRequiredDescriptionDefault
maxResultsNo
phoneNumberYes

TDQS

B3.2/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, so safety is covered. The description adds useful return semantics ('zero or more ranked matches'), indicating fuzzy matching and possible multiplicity, but says nothing about permissions, error cases, or ranking criteria.

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

Conciseness4/5

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

Two short, front-loaded sentences with no filler; the core purpose leads and the return behavior follows. Efficient, though extremely terse given the unsupported parameters.

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?

With no output schema, the description partially covers returns ('zero or more ranked matches'), and annotations cover safety. However, it omits parameter format guidance and any usage routing, so an agent has gaps for maxResults and phone number formatting.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate, and it largely does not. It implies the phoneNumber input ('one phone number') but gives no format guidance, and maxResults is never mentioned at all, leaving half the parameters undocumented everywhere.

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?

States a specific verb and resource: 'Resolve one phone number to matching Apple Contacts entries.' The resource ('phone number') naturally separates it from contacts_lookup_email and contacts_search_name, so an agent can distinguish it without opening the schema, though no sibling is named explicitly.

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

Usage Guidelines3/5

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

The phrase 'one phone number' implicitly signals a single-value lookup versus the name-search sibling, but there is no explicit when-to-use, when-not-to-use, or alternative routing. Usage is only inferable from the phrasing.

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

contacts_permissionsContacts PermissionsA

Check and optionally prompt for Apple Contacts access used by the helper app.

ParametersJSON Schema
NameRequiredDescriptionDefault
promptNo

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations, the description carries the full burden. It usefully discloses the optional prompt side effect, but says nothing about what a denied result looks like, whether the prompt surfaces a system dialog, whether results are cached, or whether calling it blocks.

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?

A single front-loaded sentence with no filler; the core action and the optional behavior are both stated without waste.

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?

For a simple no-output-schema permission tool this covers the basic action, but an agent still lacks the outcome/return shape and any precondition (e.g. call before other contacts tools) needed to use it confidently.

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?

The single 'prompt' boolean has 0% schema description coverage. "Optionally prompt" maps the flag to forcing a permission prompt, partially compensating, but it does not state the default, or the behavioral difference between prompt=true and false.

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 gives a specific verb and resource ("Check ... Apple Contacts access") and clarifies the optional side effect ("optionally prompt"). It is implicitly distinct from the data-retrieval siblings, but it never names them or states how it differs, so it falls short of a 5.

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

Usage Guidelines3/5

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

There is a hint that a caller may choose to prompt, but no explicit guidance on when to invoke this versus the sibling lookup tools, nor when prompting is appropriate. Usage must be inferred from the name and sentence.

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

contacts_search_nameSearch NameB
Read-only

Search Apple Contacts by name, nickname, or organization. Returns zero or more ranked matches.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameQueryYes
maxResultsNo

TDQS

B3.1/5.0
Behavior3/5

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

readOnlyHint=true already tells the agent this is a safe read, so the description only needs to add context — and it does add the return cardinality (zero or more) and ranking behavior, which matters given there is no output schema. However, it says nothing about permissions requirements, ranking criteria, or the cap behavior of maxResults.

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?

Two sentences, no filler, with the core purpose stated first and the return shape second. Nothing redundant.

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?

With no output schema the description correctly covers return cardinality, but it omits parameter behavior (maxResults default/cap) and permission prerequisites, leaving an agent with gaps for a two-parameter tool.

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

Parameters2/5

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

Schema description coverage is 0% for both parameters, so the description must compensate and largely does not. It never explains that nameQuery is a single string matched against name/nickname/organization, nor what maxResults does or what its default is despite the 1-25 bound in the schema.

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?

States a specific verb (Search) and resource (Apple Contacts), plus the matching fields (name, nickname, organization). That scope implicitly separates it from the phone/email lookup siblings, but no sibling is named so the differentiation is inferential rather than explicit.

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?

There is no when-to-use guidance, no mention of prerequisites such as contacts_permissions, and no routing advice toward the lookup_phone/lookup_email/get_contact alternatives. The agent must infer that name-based lookup is the only reason to pick this tool.

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.

  1. 5 tool updatesv0.1.0
    • First observedcontacts_get_contact
    • First observedcontacts_lookup_email
    • First observedcontacts_lookup_phone
    • First observedcontacts_permissions
    • First observedcontacts_search_name

TDQS

A3.7/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a distinct query modality: permission check, lookup by phone, lookup by email, fetch by ID, and search by name. No two tools overlap in input type or purpose, so misselection is unlikely.

Naming Consistency4/5

All names use snake_case with a consistent `contacts_` prefix, and four of five follow a verb_noun pattern. `contacts_permissions` is a slight noun-form deviation but remains predictable.

Tool Count5/5

Five tools is well-scoped for a read-focused Contacts helper: permissions, three query modalities, and one ID fetch. Each tool has a clear role and none feels redundant.

Completeness4/5

The surface covers access check and all common read paths (ID, phone, email, name). It lacks any list-all/browse operation or mutation tools, but those may be outside the stated read-lookup scope; core retrieval is covered.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers