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

@zapsign-private/gepeto-mcp

v0.3.1

Published

MCP server for Google Chat. Acts as the authenticated user (OAuth) or as a bot (service account).

Readme

Gepeto MCP — Google Chat connector

A small MCP server that wraps the Google Chat REST API and authenticates either as a real user (OAuth) or as a bot (service account, Gepeto-style). Built because Google's official chatmcp.googleapis.com is gated behind the Workspace Developer Preview Program — this gives you the same surface (and more) without that gate.

TL;DR

npm install -g @zapsign-private/gepeto-mcp

Then:

  1. Make sure the OAuth client has http://localhost:53682/callback in its Authorized redirect URIs (Cloud setup).
  2. Run gepeto-mcp-auth once with GOOGLE_CHAT_OAUTH_CLIENT_ID and GOOGLE_CHAT_OAUTH_CLIENT_SECRET set — it opens a browser, prints a refresh token to your terminal.
  3. Drop a gepeto entry into your MCP client config with all three env vars (Register with your client).
  4. Smoke-test the binary, then fully restart the client.

The rest of this doc walks through each step with the gotchas we've actually hit.

Why this exists

Google ships a remote MCP at chatmcp.googleapis.com/mcp/v1 but the backend rejects every call from workspaces not enrolled in the Developer Preview Program — even with valid OAuth and the right scopes, every call returns 404. This server talks directly to the Chat REST API (which is GA) and works today.

Auth modes

Pick whichever fits the use case. You can have both env vars set on the same install — OAuth wins.

| Mode | When | Identity | What it can do | |---|---|---|---| | OAuth | "I want Cowork/Claude to act as me in Chat" | Authenticated user | Read/write across all spaces the user is in, including DMs | | Service account | Bot-side automations: deploy alerts, CI digests | The Gepeto Chat app | Read/write only in spaces Gepeto has been added to |

Tools

| Tool | OAuth | Bot | |---|---|---| | list_spaces | ✓ | ✓ (only spaces Gepeto is in) | | get_space | ✓ | ✓ | | find_direct_message | ✓ | ✗ | | list_messages | ✓ | ✓ | | get_message | ✓ | ✓ | | send_message | ✓ | ✓ | | send_card | ✓ | ✓ | | update_message | ✓ (own only) | ✓ (own only) | | delete_message | ✓ (own only) | ✓ (own only) | | search_messages | ✓ | ✓ | | list_members / get_member | ✓ | ✓ | | add_reaction / list_reactions / remove_reaction | ✓ | ✓ | | upload_file | ✓ | ✓ | | get_attachment / download_attachment | ✓ | ✓ |

Attachments

send_message accepts attachment_paths: string[] — local file paths the server uploads to Chat before posting. Files are uploaded sequentially, one media call each, then referenced in the message body.

{
  "space": "spaces/AAAA26LxVJ8",
  "text": "Postmortem attached:",
  "attachment_paths": ["C:\\reports\\incident-2026-05-10.pdf"]
}

upload_file does the upload step in isolation when you want to reuse the resulting attachmentDataRef across several messages. get_attachment returns metadata for a known attachment resource name; download_attachment writes the binary content to a local path (passing a directory writes under the original contentName).

Reactions

add_reaction accepts either a Unicode emoji directly ("👍") or a custom Workspace emoji as "customEmoji:<uid>". list_reactions supports the Chat API filter syntax — e.g. emoji.unicode = "👍" or user.name = "users/123". remove_reaction accepts either the full reaction resource name, or the (message_name, emoji) pair, in which case it looks up the matching reaction first.

One-time Cloud project setup (per Workspace)

Skip this section if your Workspace already has an OAuth client wired up for this server.

1. Enable the Chat API

gcloud services enable chat.googleapis.com --project=PROJECT_ID

You don't need chatmcp.googleapis.com for this server.

2. OAuth consent screen scopes

In Google Auth Platform → Data Access → Add or Remove Scopes, add:

https://www.googleapis.com/auth/chat.spaces
https://www.googleapis.com/auth/chat.messages
https://www.googleapis.com/auth/chat.memberships

3. Create the OAuth client

In Google Auth Platform → Clients → Create Client:

  • Type: Web application
  • Authorized redirect URIs — add both:
    • http://localhost:53682/callback — required by gepeto-mcp-auth. If this is missing, the consent screen returns redirect_uri_mismatch and you cannot get a refresh token.
    • https://claude.ai/api/mcp/auth_callback — only if you also wire this as a Claude custom connector. Optional.

Copy the Client ID and Secret — those go into GOOGLE_CHAT_OAUTH_CLIENT_ID / _SECRET.

Install

npm install -g @zapsign-private/gepeto-mcp

This puts two binaries on your PATH:

  • gepeto-mcp — the MCP server (stdio transport).
  • gepeto-mcp-auth — one-time OAuth bootstrap that prints a refresh token.

Verify they resolved:

# Mac / Linux
which gepeto-mcp gepeto-mcp-auth

# Windows
where.exe gepeto-mcp ; where.exe gepeto-mcp-auth

Authorize once (OAuth path)

You need a refresh token. The gepeto-mcp-auth command runs a local HTTP listener on port 53682, prints a Google consent URL, exchanges the authorization code, and prints the refresh token to stdout.

bash / zsh

GOOGLE_CHAT_OAUTH_CLIENT_ID="725957662152-tuif...apps.googleusercontent.com" \
GOOGLE_CHAT_OAUTH_CLIENT_SECRET="GOCSPX-..." \
gepeto-mcp-auth

PowerShell

$env:GOOGLE_CHAT_OAUTH_CLIENT_ID = "725957662152-tuif...apps.googleusercontent.com"
$env:GOOGLE_CHAT_OAUTH_CLIENT_SECRET = "GOCSPX-..."
gepeto-mcp-auth

cmd.exe

set GOOGLE_CHAT_OAUTH_CLIENT_ID=725957662152-tuif...apps.googleusercontent.com
set GOOGLE_CHAT_OAUTH_CLIENT_SECRET=GOCSPX-...
gepeto-mcp-auth

Open the printed URL, sign in with the Google account that should authorize the integration, approve the three Chat scopes. The browser hits http://localhost:53682/callback, the terminal prints:

=== Refresh token (save to GOOGLE_CHAT_REFRESH_TOKEN) ===
1//0g...

Copy that token — it goes into GOOGLE_CHAT_REFRESH_TOKEN. It's long-lived (until you revoke at https://myaccount.google.com/permissions or rotate the OAuth client secret).

If gepeto-mcp-auth says "No refresh_token returned", Google omitted it because this client has been authorized by the same user before. Revoke at the URL above and re-run.

Register with your MCP client

Claude Desktop

Edit (Mac) ~/Library/Application Support/Claude/claude_desktop_config.json or (Windows) %APPDATA%\Claude\claude_desktop_config.json. Note the filename is claude_desktop_config.json, not mcp_servers.json.

The most portable launch form across platforms (recommended):

Mac / Linux

{
  "mcpServers": {
    "gepeto": {
      "command": "npx",
      "args": ["-y", "@zapsign-private/gepeto-mcp"],
      "env": {
        "GOOGLE_CHAT_OAUTH_CLIENT_ID": "725957662152-tuif...apps.googleusercontent.com",
        "GOOGLE_CHAT_OAUTH_CLIENT_SECRET": "GOCSPX-...",
        "GOOGLE_CHAT_REFRESH_TOKEN": "1//0g..."
      }
    }
  }
}

Windows — wrap with cmd /c so the .cmd shim resolves correctly:

{
  "mcpServers": {
    "gepeto": {
      "command": "cmd",
      "args": ["/c", "npx", "-y", "@zapsign-private/gepeto-mcp"],
      "env": {
        "GOOGLE_CHAT_OAUTH_CLIENT_ID": "725957662152-tuif...apps.googleusercontent.com",
        "GOOGLE_CHAT_OAUTH_CLIENT_SECRET": "GOCSPX-...",
        "GOOGLE_CHAT_REFRESH_TOKEN": "1//0g..."
      }
    }
  }
}

The npx -y form auto-picks up new versions you publish. If you'd rather pin to whatever's globally installed, point command straight at the binary instead — gepeto-mcp on Mac/Linux, or the absolute path to gepeto-mcp.cmd on Windows (e.g. C:\\Users\\<you>\\AppData\\Roaming\\npm\\gepeto-mcp.cmd).

If claude_desktop_config.json already has a top-level preferences block (Claude Desktop UI state), keep it — just add mcpServers as a sibling key. Don't replace the file wholesale or you'll wipe the UI state.

Claude Code

claude mcp add gepeto gepeto-mcp \
  -e GOOGLE_CHAT_OAUTH_CLIENT_ID="725957662152-tuif...apps.googleusercontent.com" \
  -e GOOGLE_CHAT_OAUTH_CLIENT_SECRET="GOCSPX-..." \
  -e GOOGLE_CHAT_REFRESH_TOKEN="1//0g..."

Cowork

Cowork uses the same claude_desktop_config.json as Claude Desktop on the same machine.

Other MCP clients

Anything that runs an MCP server over stdio works the same way — point command/args at the binary or npx -y @zapsign-private/gepeto-mcp and pass the three env vars through whatever the client's env-injection mechanism is.

Verify

Before restarting your client, run the binary directly with the same env vars to make sure auth works. This catches a bad refresh token or a misconfigured OAuth client without involving the MCP layer.

bash / zsh

GOOGLE_CHAT_OAUTH_CLIENT_ID=... GOOGLE_CHAT_OAUTH_CLIENT_SECRET=... GOOGLE_CHAT_REFRESH_TOKEN=... gepeto-mcp

PowerShell

$env:GOOGLE_CHAT_OAUTH_CLIENT_ID = "..."
$env:GOOGLE_CHAT_OAUTH_CLIENT_SECRET = "..."
$env:GOOGLE_CHAT_REFRESH_TOKEN = "..."
gepeto-mcp

You should see gepeto-mcp: starting with auth mode = oauth on stderr and the process holding stdio open. That means env vars reached the process, the refresh token minted an access token, and the MCP server boot-handshake is ready. Hit Ctrl+C to exit.

If you see Configure either OAuth (...) and exit 1, the env vars didn't reach the process — check shell quoting.

Now restart your MCP client. For Claude Desktop, Quit from the tray/menu-bar icon, not just by closing the window — closing the window leaves the background process alive with the old config cached.

After restart, ask the model "list my Google Chat spaces" or invoke gepeto-list_spaces directly.

Troubleshooting

Tools don't appear in Claude Desktop after restart.

  1. Confirm the file is claude_desktop_config.json (not mcp_servers.json, not config.json) at the standard path.
  2. Confirm the JSON parses: Get-Content $path -Raw | ConvertFrom-Json (PowerShell) or python -m json.tool < $path (Mac/Linux). Claude Desktop silently ignores files that don't parse.
  3. Open Settings → Developer (Desenvolvedor on pt-BR) and look for gepeto and any error string — that's where startup failures surface.
  4. Confirm you Quit (tray icon → Quit), not just closed the window.
  5. If Claude Desktop's UI later overwrites claude_desktop_config.json and clobbers the mcpServers block, register the server through Settings → Developer → Add MCP Server instead of editing the JSON directly.

Configure either OAuth (...) and immediate exit when launching the server. The three env vars aren't reaching the process. Most often: the env block in the client config is missing or has empty strings. Run the Verify step in a terminal — if that works there, the issue is in how your client passes env to the spawned process.

redirect_uri_mismatch from Google during gepeto-mcp-auth. The OAuth client doesn't have http://localhost:53682/callback in its Authorized redirect URIs. Go to Google Auth Platform → Clients → your client → add it.

No refresh_token returned from gepeto-mcp-auth. Google only issues a refresh token on the first consent for a given client+user. If this isn't your first time, revoke the app at https://myaccount.google.com/permissions and re-run. The bootstrap already passes prompt=consent, so simply re-running won't fix it without a revoke.

invalid_grant errors from the running server. Refresh token was revoked, or it was minted against a different OAuth client. Re-run gepeto-mcp-auth and replace GOOGLE_CHAT_REFRESH_TOKEN.

PERMISSION_DENIED / 403 on list_spaces.

  • OAuth path: the user lacks a Chat license in this Workspace, or the consent screen scopes don't include the three above.
  • Service account path: Gepeto isn't in any spaces yet. Add the bot to the spaces you want it to see.

Windows: command: "gepeto-mcp" fails to spawn. On Windows the binary is a gepeto-mcp.cmd shim and Claude Desktop's spawn path doesn't always resolve PATH the way a shell does. Use the cmd /c npx -y @zapsign-private/gepeto-mcp form, or the absolute path to the .cmd file.

Service-account / Gepeto-bot path

If instead of a user identity you want the server to act as the Gepeto bot:

GOOGLE_CHAT_CREDENTIALS=/absolute/path/to/gepeto-sa.json gepeto-mcp

Optional: act as a user via DWD (requires Workspace admin to grant the SA's client ID the chat scopes):

GOOGLE_CHAT_CREDENTIALS=/path/to/sa.json \
[email protected] \
gepeto-mcp

Constraints:

  • Gepeto can only see/post in spaces it's been added to.
  • DMs and find_direct_message aren't available with bot auth.

Develop locally / contribute

git clone https://github.com/ZapSign/google-chat-mcp.git
cd google-chat-mcp
npm install
npm run build

# bootstrap an OAuth refresh token (interactive)
GOOGLE_CHAT_OAUTH_CLIENT_ID=... GOOGLE_CHAT_OAUTH_CLIENT_SECRET=... npm run auth

# run the MCP server from source
GOOGLE_CHAT_OAUTH_CLIENT_ID=... \
GOOGLE_CHAT_OAUTH_CLIENT_SECRET=... \
GOOGLE_CHAT_REFRESH_TOKEN=... \
npm run dev

To use a local checkout with Claude Desktop instead of the published package, point command at the absolute path to node and args at the built entrypoint:

{
  "mcpServers": {
    "gepeto": {
      "command": "node",
      "args": ["/absolute/path/to/google-chat-mcp/dist/index.js"],
      "env": {
        "GOOGLE_CHAT_OAUTH_CLIENT_ID": "...",
        "GOOGLE_CHAT_OAUTH_CLIENT_SECRET": "...",
        "GOOGLE_CHAT_REFRESH_TOKEN": "..."
      }
    }
  }
}

Run npm run build after every source change so dist/ is fresh.

Roadmap

  • Streamable HTTP transport for hosted multi-user deploys
  • Per-user OAuth in a hosted variant
  • Drive-attachment pass-through (Chat sometimes returns Drive file refs)
  • Bulk message export

Changelog

0.3.1

  • Fix send_message rejecting OAuth user-identity uploads. The Chat media API returns attachmentDataRef.attachmentUploadToken for user-identity callers (not resourceName), so 0.3.0 threw on every successful upload. Accept either field.

0.3.0

  • send_message accepts attachment_paths for inline file uploads
  • upload_file exposes the upload step on its own
  • get_attachment / download_attachment for reading binary content
  • add_reaction / list_reactions / remove_reaction

0.2.0

  • Dual-mode auth (OAuth user-identity + service-account/bot)
  • find_direct_message, send_card, search_messages, list_members / get_member
  • gepeto-mcp-auth interactive bootstrap binary

0.1.0

  • Initial release