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

@tekmidian/coogle

v0.2.22

Published

Coogle — Google Workspace MCP multiplexer for Claude Code. One persistent daemon, no credential conflicts across multiple sessions.

Readme


links: "[[Ideaverse/AI/coogle/coogle|coogle]]"

Coogle

Google Workspace MCP multiplexer for Claude Code. One persistent daemon holds the single coogle-mcp connection. Every Claude Code session goes through it. No more credential conflicts, no more 142 tools registering simultaneously.


The problem it solves

Coogle is the MCP server that gives Claude access to Gmail, Calendar, Drive, Docs, Sheets, and the rest of Google Workspace — across multiple sessions simultaneously.

The naive setup — running Google Workspace MCP directly — works fine for one session. The moment you open a second Claude Code window, both sessions try to own the same Google OAuth credentials. They fight, one wins, the other gets errors or stale tokens.

Coogle solves this with a daemon pattern: one persistent process holds the Google Workspace connection and serializes all calls through a queue. Every Claude Code session runs a thin MCP shim that forwards tool calls to the daemon over a Unix Domain Socket. From Claude's perspective nothing changes — 142 tools are available. Under the hood, every call goes through a single, stable connection.

Claude Code (session 1)
Claude Code (session 2)  ──>  coogle daemon  ──>  coogle-mcp  ──>  Google APIs
Claude Code (session 3)

Quick start

Tell Claude Code:

Clone https://github.com/mnott/Coogle and set it up for me

Claude clones the repo, finds the setup skill, and handles everything autonomously — prerequisites, build, config, daemon install, and Google OAuth. You just approve the permissions in your browser when prompted.

Alternative: npx

If you prefer a traditional install without cloning:

npx -y @tekmidian/coogle setup

The wizard handles everything: environment check, credentials, config, daemon install, launchd service, and Claude config patching.

Prerequisites

  • Node.js >= 18
  • uvx (from uv): brew install uv or pip install uv
  • Google OAuth credentials (Client ID + Client Secret from Google Cloud Console)

Manual clone and build

git clone https://github.com/mnott/Coogle ~/dev/apps/coogle
cd ~/dev/apps/coogle
npm install
npm run build
node dist/index.js setup

The wizard walks you through eight steps:

  1. Environment check — verifies Node and uvx are available
  2. Credentials — finds Google OAuth Client ID and Secret from ~/.claude.json (any MCP server entry with GOOGLE_OAUTH_CLIENT_ID in its env block) or prompts for them manually
  3. Config — writes ~/.config/coogle/config.json
  4. Build check — confirms dist/index.js exists
  5. Daemon test — starts a temporary daemon, verifies the IPC socket, counts available tools
  6. launchd service — installs com.pai.coogle as a macOS launch agent (auto-starts on login)
  7. Claude config — updates ~/.claude.json to point the coogle MCP server at the coogle shim
  8. Summary — shows what was done and how to roll back

After setup, restart Claude Code. The coogle shim starts automatically when Claude loads, discovers all tools from the daemon, and proxies every call.


How it works

Coogle has two runtime components:

Daemon (src/daemon.ts) — a long-running process that spawns and owns a single coogle-mcp child via stdio. It listens on a Unix Domain Socket (/tmp/coogle.sock) and serializes all incoming tool calls through a queue. If the child crashes, it auto-respawns with a 3-second cooldown.

MCP shim (src/mcp-server.ts) — a thin proxy started by Claude Code. On startup it connects to the daemon socket, dynamically discovers all available tools, registers them with the MCP SDK, and forwards every tools/call request to the daemon over IPC.

Claude Code (MCP stdio)
       |
       |  JSON-RPC (stdio)
       |
  MCP shim (coogle mcp)
       |
       |  NDJSON (Unix socket /tmp/coogle.sock)
       |
  Coogle daemon (coogle serve)
       |
       |  MCP stdio
       |
  coogle-mcp backend
       |
       |  HTTPS
       |
  Google APIs

CLI commands

# Start the daemon (normally managed by launchd)
node dist/index.js serve

# Start the MCP shim (used as the Claude MCP command)
node dist/index.js mcp

# Check daemon status
node dist/index.js status

# Restart the coogle-mcp child process
node dist/index.js restart

# Print the resolved configuration
node dist/index.js config

# Generate the launchd plist for this system (outputs to stdout)
node dist/index.js generate-plist

# Interactive first-time setup
node dist/index.js setup

Configuration

Config lives at ~/.config/coogle/config.json. It is created automatically by setup or on first serve.

{
  "socketPath": "/tmp/coogle.sock",
  "mcp": {
    "command": "uvx",
    "args": ["workspace-mcp", "--tool-tier", "core"]
  },
  "credentials": {
    "source": "claude-json",
    "claudeJsonPath": "~/.claude.json",
    "mcpServerName": "coogle"
  },
  "callTimeoutMs": 120000,
  "logLevel": "info"
}

Credential sources

| source | How credentials are loaded | |----------|---------------------------| | claude-json (default) | Read GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET from the named MCP server's env block in ~/.claude.json | | env | Read from GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET environment variables | | manual | Stored directly in config as clientId and clientSecret |

All config fields

| Field | Default | Description | |-------|---------|-------------| | socketPath | /tmp/coogle.sock | Unix Domain Socket path for IPC | | mcp.command | uvx | Command to run coogle-mcp | | mcp.args | ["workspace-mcp", "--tool-tier", "core"] | Arguments for the Google Workspace MCP backend | | credentials.source | claude-json | Where to load Google OAuth credentials from | | credentials.claudeJsonPath | ~/.claude.json | Path to Claude config (for claude-json source) | | credentials.mcpServerName | coogle | MCP server key to read credentials from | | callTimeoutMs | 120000 | Per-call timeout in milliseconds | | logLevel | info | Log verbosity: debug, info, warn, error |


Multi-account (Google Workspace)

Coogle supports managing multiple Google accounts simultaneously. Each account needs a one-time OAuth authorization, after which all 142 tools work for any authorized account — just pass the appropriate user_google_email parameter.

How it works

OAuth tokens are stored per user in ~/.google_workspace_mcp/credentials/:

~/.google_workspace_mcp/credentials/
├── [email protected]
├── [email protected]
└── [email protected]

The OAuth Client ID and Client Secret (app credentials) are shared across all accounts — they come from your Google Cloud project. Each user gets their own refresh token after completing the consent flow once.

Adding a new account

  1. Ensure credentials are configured. The daemon needs the OAuth Client ID and Client Secret. The recommended approach is manual source in ~/.config/coogle/config.json:
{
  "credentials": {
    "source": "manual",
    "clientId": "your-client-id.apps.googleusercontent.com",
    "clientSecret": "GOCSPX-your-client-secret"
  }
}

You can find these values in an existing token file at ~/.google_workspace_mcp/credentials/<email>.json (fields client_id and client_secret) or in your Google Cloud Console.

  1. Restart the daemon so it picks up the credentials:
# Kill the daemon (launchd auto-restarts it)
launchctl kickstart -k gui/$(id -u)/com.pai.coogle
  1. Trigger the OAuth flow for the new account. From Claude Code, call:
start_google_auth(service_name="people", user_google_email="[email protected]")

Or call any tool with the new email — workspace-mcp will return an authorization URL if no token exists.

  1. Open the authorization URL in a browser, sign in as the target account, and approve the permissions. The callback goes to localhost:8000 (the OAuth server built into workspace-mcp).

  2. Done. A token file is saved to ~/.google_workspace_mcp/credentials/[email protected]. All subsequent tool calls with that email work immediately.

Google Workspace family/team domains

If all accounts are on the same Google Workspace domain (e.g. @example.com) and you are the domain admin, you can authorize all accounts yourself — just sign in as each user in the browser when the consent screen appears. No need for each person to do it themselves.

Important notes

  • Calendar sharing vs. Contacts: Google Calendar supports delegation — you can access shared calendars with just one account's token. Google Contacts has no sharing model. Each account must be individually authorized to manage its contacts.
  • Token refresh: Tokens are long-lived (refresh tokens). They only expire if the user revokes access or the OAuth app credentials change.
  • Port 8000: The workspace-mcp OAuth callback server listens on localhost:8000. If this port is occupied when you trigger an auth flow, restart the daemon first.

Manual Claude Code configuration

If you prefer not to use the setup wizard, edit ~/.claude.json directly. Find the coogle entry under mcpServers and replace its command/args with the coogle shim:

{
  "mcpServers": {
    "coogle": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/coogle/dist/index.js", "mcp"]
    }
  }
}

The env block with GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET is no longer needed in the Claude config — the daemon reads credentials directly and injects them into the coogle-mcp child environment.

Keep a backup of the original config before editing:

cp ~/.claude.json ~/.claude.json.backup

The setup wizard creates this backup automatically.


launchd service

The daemon is designed to run as a persistent macOS launch agent. The setup wizard installs it automatically. To manage it manually:

# Generate the plist (uses the correct node and index.js paths for your system)
node dist/index.js generate-plist > ~/Library/LaunchAgents/com.pai.coogle.plist

# Load (start)
launchctl load ~/Library/LaunchAgents/com.pai.coogle.plist

# Unload (stop)
launchctl unload ~/Library/LaunchAgents/com.pai.coogle.plist

# Restart
launchctl kickstart -k gui/$(id -u)/com.pai.coogle

Logs go to /tmp/coogle.log.

tail -f /tmp/coogle.log

Google Workspace tools

The 142 available tools span 12 Google services. They are discovered dynamically from coogle-mcp on daemon startup — no hardcoded list.

| Service | Example tools | |---------|--------------| | Gmail | search_gmail_messages, send_gmail_message, get_gmail_thread_content | | Calendar | get_events, create_event, modify_event, query_freebusy | | Drive | search_drive_files, list_drive_items, share_drive_file, copy_drive_file | | Docs | get_doc_content, modify_doc_text, create_doc, insert_doc_elements | | Sheets | read_sheet_values, modify_sheet_values, create_spreadsheet | | Slides | create_presentation, get_presentation, batch_update_presentation | | Forms | create_form, get_form, list_form_responses | | Contacts | search_contacts, create_contact, list_contact_groups | | Chat | send_message, get_messages, list_spaces | | Tasks | list_tasks, create_task, update_task, move_task | | Scripts | run_script_function, create_script_project | | Search | search_custom, get_search_engine_info |


Troubleshooting

"Coogle daemon not running"

The shim cannot reach the daemon socket. Start the daemon:

node dist/index.js serve

Or check if the launchd service is loaded:

launchctl list | grep coogle
cat /tmp/coogle.log

"coogle-mcp child is not connected"

The daemon is running but coogle-mcp failed to start or crashed. Check the log:

tail -50 /tmp/coogle.log

Common cause: uvx not in PATH, or Google OAuth credentials are missing/expired. Try restarting the child:

node dist/index.js restart

No tools discovered / tool count is 0

coogle-mcp started but returned no tools. This usually means the Google OAuth token has expired or is missing.

workspace-mcp manages its own OAuth tokens independently — they are stored in ~/.google_workspace_mcp/credentials/. To re-authenticate, delete the cached token file and restart the daemon:

rm -r ~/.google_workspace_mcp/credentials/
node dist/index.js restart

workspace-mcp will prompt for a new OAuth flow on the next call.

Note: re-running node dist/index.js setup will not fix expired tokens. The setup wizard only handles the OAuth Client ID and Client Secret (app credentials). Token lifecycle is managed entirely by workspace-mcp.

Daemon keeps crashing

Check /tmp/coogle.log for error messages. The daemon has a 3-second respawn cooldown — launchd will restart it automatically but the ThrottleInterval in the plist prevents tight restart loops.

Multiple Claude sessions getting stale results

This is the condition coogle was built to prevent. Verify all sessions are using the coogle shim:

node dist/index.js status

Check that ~/.claude.json shows node .../coogle/dist/index.js mcp as the coogle MCP command.

Rollback to pre-coogle configuration

cp ~/.claude.json.backup ~/.claude.json

Restart Claude Code to apply.


Security

  • Google OAuth app credentials (Client ID and Client Secret) are read from ~/.claude.json or ~/.config/coogle/config.json. OAuth tokens obtained after authentication are managed by workspace-mcp and stored in ~/.google_workspace_mcp/credentials/. All files are local and not transmitted anywhere by Coogle.
  • The daemon communicates with coogle-mcp over stdio (same machine, same user).
  • The IPC socket at /tmp/coogle.sock is local only and accessible only to the current user.
  • No credentials are ever sent over the network by coogle itself — all OAuth flows are handled by coogle-mcp.

Requirements

  • Node.js >= 18
  • uvx (from uv) for running coogle-mcp
  • Google Cloud project with OAuth 2.0 credentials (Client ID + Client Secret)
  • macOS for launchd auto-start (Linux works for manual daemon operation)

Development

# Install dependencies
npm install

# Build
npm run build

# Watch mode
npm run dev

# Run the daemon directly
npm start

# Run the MCP shim directly
npm run mcp

License

MIT — see LICENSE

Author

Matthias Nott — github.com/mnott


Links: [[Ideaverse/AI/coogle/coogle|coogle]]