npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jdickey1/mcp-google-contacts

v0.1.0

Published

Google Contacts MCP server. Six tools (search, get, list labels, apply label, remove label, additive update). Grants OAuth scopes contacts.readonly + contacts.other.readonly + contacts (full write); the write surface is tool-limited to label CRUD and sele

Downloads

81

Readme

mcp-google-contacts

A small Google Contacts MCP server. Searches and reads contacts, manages user labels, and selectively enriches missing contact fields. Six tools, official googleapis client, OS keychain for credentials.

Built because the popular Google Contacts MCPs on the registry are abandoned, ship third-party auth handlers, or expose a sprawling write surface that's hard to audit. This one stays narrow on purpose: explicit OAuth scopes, six tools, and a write surface tool-limited to label CRUD plus additive-only field updates.

npm version

Tools

| Tool | What it does | |---|---| | search_contacts(query, max?) | Read. Search Google Contacts by name (primary + "Other contacts"). Returns up to max records (default 10, cap 30) with names, emails, phones, and applied user-label names. | | get_contact(resource_name) | Read. Fetch one contact by resource name (e.g. people/c1234567890123456789). Returns names, emails, phones, addresses, organizations, biographies, and labels. | | list_label_groups() | Read. List user-defined contact label groups (Clients, Vendors, etc.) with current member counts. System groups (myContacts, etc.) are filtered out. | | apply_label(person_resource_name, label_name) | Write. Apply a label to a contact. Idempotent (returns action: "noop" if already labeled); auto-creates the label group on first use. | | remove_label(person_resource_name, label_name) | Write. Remove a label from a contact. No-op if the contact doesn't have it. | | update_contact(person_resource_name, …) | Write (additive-only). Fills in missing contact fields: phone, address, organization, title, biography. Only writes a field when the existing value is empty — never overwrites. Returns added and skipped lists so callers can verify what changed. |

OAuth scopes

This server requests three scopes:

  • https://www.googleapis.com/auth/contacts.readonly — primary contact read.
  • https://www.googleapis.com/auth/contacts.other.readonly — read "Other contacts" (the implicitly auto-saved set).
  • https://www.googleapis.com/auth/contactsfull contacts write.

The write scope grants the API permission to mutate any contact field. The tools choose to restrain themselves to label CRUD (apply_label, remove_label) plus additive-only field updates (update_contact never overwrites existing values), but the scope itself is not narrowed. If you only want read access, fork the auth CLI and drop the third scope before running it. A future minor version may split the package into read-only and read-write variants.

Install

You need Node.js 20 or newer and a Google Cloud OAuth Desktop client (free; setup steps below).

Option A — Claude Code marketplace (recommended)

Install the google-contacts-mcp plugin from the claude-skills marketplace. The MCP wires itself up; only the one-time auth flow remains.

Option B — Manual MCP config

Add the server to your MCP client (~/.claude.json for Claude Code, claude_desktop_config.json for Claude Desktop):

{
  "mcpServers": {
    "google-contacts": {
      "command": "npx",
      "args": ["-y", "@jdickey1/mcp-google-contacts"]
    }
  }
}

In ~/.claude/settings.json, allow the tools you want to use:

{
  "permissions": {
    "allow": [
      "mcp__google-contacts__search_contacts",
      "mcp__google-contacts__get_contact",
      "mcp__google-contacts__list_label_groups",
      "mcp__google-contacts__apply_label",
      "mcp__google-contacts__remove_label",
      "mcp__google-contacts__update_contact"
    ]
  }
}

Setup

1. Enable the People API and create a Desktop OAuth client

  1. Open the Google Cloud Console. Create a project or select one.
  2. APIs & Services → Library → search People APIEnable.
  3. APIs & Services → CredentialsCreate Credentials → OAuth client ID.
    • Application type: Desktop app
    • Name: anything (e.g. mcp-google-contacts)
  4. Copy the Client ID and Client secret.

If your project is in Testing publishing status (the default), add your own Google account as a test user under OAuth consent screen → Test users.

2. Run the auth flow once

GOOGLE_OAUTH_CLIENT_ID=<your-client-id> \
GOOGLE_OAUTH_CLIENT_SECRET=<your-client-secret> \
  npx -p @jdickey1/mcp-google-contacts mcp-google-contacts-auth

A browser tab opens for Google consent. After approval the refresh token is stored in the macOS login keychain. Re-runs reuse the stored client credentials, so subsequent invocations don't need the env vars.

If your default browser doesn't open, copy the URL printed to the terminal.

3. Verify

Restart your MCP client, then ask: "Use the google-contacts MCP to list my label groups." You should see your user-defined contact labels.

Credential storage

Credentials live in the macOS login keychain under three entries:

| Service | Account | Holds | |---|---|---| | cos-cron.google-contacts | $USER (or $MCP_GOOGLE_CONTACTS_ACCOUNT) | Refresh token | | cos-cron.google-contacts.client_id | same | OAuth client ID | | cos-cron.google-contacts.client_secret | same | OAuth client secret |

The cos-cron service prefix is internal substrate naming preserved across the package's history to keep existing tokens valid for adopters who migrated from earlier internal builds. The prefix has no functional meaning to new adopters.

Overrides

| Variable | Effect | |---|---| | MCP_GOOGLE_CONTACTS_ACCOUNT | macOS keychain account label (default $USER). Useful for multi-account setups or when running under a service account whose $USER doesn't match the keychain you want to read. |

Limitations

  • macOS-only credential storage in v1. The keychain is the only backing store. Linux and Windows are not supported in this version. A future minor version may add a file-backed fallback (mode 0600 JSON file under $XDG_CONFIG_HOME).
  • No MCP_GOOGLE_CONTACTS_* read-time credential override layer. The sibling @jdickey1/mcp-gmail package has one (MCP_GMAIL_CLIENT_ID, etc.) for headless/Docker/CI contexts; this package does not yet. If you need it, pre-populate the keychain or watch for a follow-up minor version. The account-label override (MCP_GOOGLE_CONTACTS_ACCOUNT) is in place.

Inspecting and re-running auth

# Drop the cached refresh token and re-authorize:
security delete-generic-password -s cos-cron.google-contacts -a "$USER"

GOOGLE_OAUTH_CLIENT_ID=<id> GOOGLE_OAUTH_CLIENT_SECRET=<secret> \
  npx -p @jdickey1/mcp-google-contacts mcp-google-contacts-auth

To rotate the OAuth client itself, also delete cos-cron.google-contacts.client_id and cos-cron.google-contacts.client_secret before re-running.

Design notes

  • Write surface is intentional and tool-limited. apply_label and remove_label are idempotent label CRUD; update_contact is additive-only (never overwrites). The scope grant is contacts (full write); the tools choose to restrain themselves. No batch endpoints — every write is one API call to one contact.
  • Idempotent label operations. apply_label returns action: "noop" when the contact already has the label; remove_label returns the same when the contact doesn't have it. Repeated calls with the same args produce the same end state.
  • Optimistic concurrency on update_contact. Reads the contact's etag before writing and includes it in the update request so concurrent edits surface as Google API errors instead of silent overwrites.
  • No raw API responses leak past tools.ts. Every tool projects to a stable shape so a People API change doesn't silently reshape your MCP responses.
  • Label cache. LabelCache is per-process; it lists groups once at boot and reuses the resource-name lookup for subsequent label operations. Auto-created labels are written into the cache on creation so the next call doesn't re-list.

Why a new MCP?

The popular community Google Contacts MCPs were unsuitable for production use:

  • Several vendored their own OAuth handler instead of using the official googleapis client (large attack surface, harder to audit).
  • Some were abandoned (no commits in over a year).
  • Some exposed every People API write tool as default — full create/update/delete on every field — with no scope discipline.

This one is intentionally minimal so other people can read every line in one sitting.

Contributing

Source lives in the private claude-skills-private repo at mcp-servers/google-contacts/. The repo is closed source for now; the published JS is public. Issues for adopters: please file at claude-skills/issues.

For local development (if you have access):

git clone <private-source>
cd mcp-servers/google-contacts
npm install                                       # installs Node deps + tsx
npx tsx --test src/tools.test.ts cli/auth.test.ts # 28 unit tests
npx tsc --noEmit                                  # typecheck
npx tsc -p tsconfig.build.json                    # build dist/

If you have Bun installed locally, bun install works alongside npm install. Note: running npm install in this directory deletes bun.lock; restore it via git checkout bun.lock after.

Source layout:

src/
  index.ts          # MCP server, tool registration
  auth.ts           # OAuth client construction
  keychain.ts       # macOS keychain wrapper for OAuth secrets
  tools.ts          # the six tools + LabelCache
  tools.test.ts     # 21 unit tests
cli/
  auth.ts           # one-time OAuth Desktop flow
  auth.test.ts      # 7 unit tests on Keychain (file is mislabeled)

License

MIT. See LICENSE.