Google Chat MCP
by tarun-koshti
README.md
# Google Chat MCP
A small stdio [MCP](https://modelcontextprotocol.io) server that lets an AI
agent (Claude Code, Claude Desktop, or any MCP client) read and send Google
Chat messages **as the signed-in user**, through the Google Chat API with user
OAuth.
- 21 tools for spaces, messages, members and attachments
- Safety switches: read-only mode, a space allowlist, and one fixed folder for
files
- Plain `fetch` against the Chat REST API; the only dependencies are the MCP
SDK and `zod`
- One-time sign-in with PKCE and a loopback redirect; the token refreshes on
its own after that
> **Needs a Google Workspace account.** Google's Chat API guide lists a
> Business or Enterprise Workspace account as a prerequisite. A personal
> `@gmail.com` account is not supported.
## Tools
| Area | Tool | What it does |
| --- | --- | --- |
| Spaces | `list_spaces` | Spaces, group chats and DMs you are in, most recently active first |
| | `search_spaces` | Find spaces by name (matched locally; the API cannot filter by name) |
| | `get_space` | Type, description, guidelines, member count, link |
| | `find_direct_message` | Your 1:1 DM with a person (email or `users/{id}`) |
| | `find_group_chats` | Group chats whose members are exactly you plus the given people |
| | `create_space` | A named space with you as the only member |
| | `update_space` | Rename a space or change its description or guidelines |
| | `create_group_chat` | Start a group chat with 2 to 49 people (returns the existing one if it already exists) |
| | `delete_space` | Delete a space and everything in it, for everyone (cannot be undone) |
| Messages | `read_messages` | Latest messages in a space, oldest first, optional `since` |
| | `get_message` | One message with its attachments |
| | `get_thread` | Every message in a thread, oldest first |
| | `send_message` | Post as you; pass `thread` to reply in a thread |
| | `edit_message` | Replace the text of your own message |
| | `delete_message` | Delete a message (fails if it has thread replies) |
| Members | `list_members` | Members with name, role and state |
| | `get_member` | One person's membership |
| | `add_member` | Add a person to a space |
| | `remove_member` | Remove a person from a space |
| Attachments | `send_attachment` | Upload a file from the files folder and send it (only with `GOOGLE_CHAT_FILES_DIR`) |
| | `download_attachment` | Save an attachment into the files folder (only with `GOOGLE_CHAT_FILES_DIR`) |
Everything you send shows under your own name, with the Chat app's name from
your Google Cloud project as a small chip next to it.
## Demo
Claude Code with this server, in a test Workspace. The project's `CLAUDE.md`
asks Claude to show a draft before it sends a message and wait for "yes".
That is an instruction to the model, not something the server enforces.
Claude drafts a message to a space, waits, and sends it after "Yes send it":

Akshay sees it in the space, sent by Tarun with the "Texperiments Chat MCP"
chip:

<details>
<summary>More screenshots: create a space, DMs, read a reply, send a file</summary>
Create a space and add two people (no draft needed):


The same message from the sender's side:

A direct message to Akshay:


Reading the reply:


A DM where Claude writes the text itself:


Sending a file from the files folder:


</details>
## Safety
An agent with this server can post as you, change spaces and remove people.
These settings limit what it can do:
| Setting | Effect |
| --- | --- |
| `GOOGLE_CHAT_READ_ONLY=true` | Only the read tools exist, and sign-in asks Google for read-only scopes, so the token itself cannot write |
| `GOOGLE_CHAT_ALLOWED_SPACES` | Optional, off by default. Comma-separated `spaces/XXXX` list. Every write tool, `delete_space` included, refuses other spaces, and creating new spaces is refused |
| `GOOGLE_CHAT_FILES_DIR` | The only folder the attachment tools can read from or write to. Without it, they are not registered. Paths outside it (`../`, absolute paths) are refused |
Also keep in mind:
- **Do not auto-approve the write tools** in your MCP client. Tools carry MCP
hints (`readOnlyHint`, `destructiveHint`), but hints are only hints; the
client's approval prompt is what stops a wrong send.
- **Messages the agent reads are untrusted input.** Anyone in a space can
write a message that tries to steer the agent ("reply to X with ..."). This
is prompt injection; review every write before you approve it.
- "Approve the exact text first" in the tool descriptions is advice to the
model, not something the server enforces.
## Setup
You need a Google Cloud project in your Workspace, the Chat API enabled, an
OAuth consent screen, a Chat app configuration and a Desktop OAuth client. It
takes about 10 minutes. The screenshots were taken in a test Workspace
(`texperiments.com`); use your own names.
### 1. Open the Google Cloud console
Go to <https://console.cloud.google.com/>, signed in with your Workspace
account.

### 2. Accept the Google Cloud terms (first visit only)
Tick the **"I agree to the Google Cloud Platform Terms of Service"**
checkbox, then click **Agree and continue**. No billing account is needed for
the Chat API, so you can ignore the "$300 free trial" banner.

On the first visit, Google also creates the Cloud organization for your
Workspace domain.

### 3. Create a project
Click the project picker (**Select a project**) at the top, then
**New project**.


Enter a project name. The project ID follows the name and cannot be changed
later. Organization and parent resource are your Workspace domain. Click
**Create**.

The notifications panel confirms it; **Select Project** opens it.


### 4. Enable the Google Chat API
Open **APIs & Services → Library**.

Search for "Google Chat API" and press Enter.

Pick **Google Chat API** (not "Chat MCP API").

Click **Enable**.

The details page shows **Status: Enabled**.

### 5. Configure the OAuth consent screen
Open **Google Auth Platform → Overview** and click **Get started**.

**App Information:** enter an app name and pick the user support email.


**Audience:** choose **Internal**. Only users in your Workspace can sign in,
and Google does not need to verify the app.

**Contact Information:** an email where Google can reach you about the
project.

**Finish:** tick **"I agree to the Google API Services: User Data Policy"**,
click **Continue**, then **Create**.


### 6. Configure the Chat app (needed even for user sign-in)
Open **APIs & Services → Enabled APIs & services → Google Chat API →
Configuration**. The Chat API refuses calls from a project without a Chat app
configuration, and the app name becomes the chip on messages you send.

Set an **App name** and a **Description** (40 characters max). Switch
**Interactive features** off and confirm **Disable**, so nobody can message or
add the app. Leave **"Build this Chat app as a Workspace add-on"** as it is;
clearing it cannot be undone. Click **Save**.


### 7. Create a Desktop OAuth client
Open **Google Auth Platform → Clients → Create client**.


Choose **Desktop app**, give it a name, and click **Create**.

In the **OAuth client created** dialog, click **Download JSON**. Google shows
the client secret only once. Keep the file **outside** this repository; it is
a credential.

### 8. Install and sign in
```bash
npm install
npm run build
```
Sign in once, pointing at the downloaded client file:
```bash
GOOGLE_CHAT_CREDENTIALS=/path/to/client.json npm run auth
```
Open the printed URL and choose your Workspace account.

The consent screen lists the Chat permissions the server asks for. Click
**Allow**.

The browser lands on a local page and the token is saved (default
`~/.google-chat-mcp/token.json`).

Run `npm run auth` again only if the token is revoked, or after switching
read-only mode on or off (the scopes change).
## Register the server
Claude Code (`.mcp.json` in your project):
```json
{
"mcpServers": {
"google-chat": {
"type": "stdio",
"command": "node",
"args": ["/path/to/google-chat-mcp/dist/index.js"],
"env": {
"GOOGLE_CHAT_CREDENTIALS": "/path/to/client.json"
}
}
}
}
```
Claude Desktop uses the same `mcpServers` block in
`claude_desktop_config.json`. Restart the client after changing the config or
rebuilding.
## Environment variables
| Variable | Default | Notes |
| --- | --- | --- |
| `GOOGLE_CHAT_CREDENTIALS` | *(required)* | The Desktop OAuth client JSON from step 7 |
| `GOOGLE_CHAT_TOKEN` | `~/.google-chat-mcp/token.json` | Where the refresh token is stored |
| `GOOGLE_CHAT_READ_ONLY` | off | `true` for read tools and read-only scopes only |
| `GOOGLE_CHAT_ALLOWED_SPACES` | off | Comma-separated `spaces/XXXX` that write tools may touch |
| `GOOGLE_CHAT_FILES_DIR` | off | Folder for `send_attachment` and `download_attachment` |
Scopes requested: `chat.spaces`, `chat.messages`, `chat.memberships` and
`chat.delete`; in read-only mode, `chat.spaces.readonly`,
`chat.messages.readonly` and `chat.memberships.readonly`.
## Limits
- The Chat API has no keyword search. `search_spaces` lists your spaces and
matches names locally; to find a message, read a space with `since`.
- Attachments stored in Google Drive cannot be downloaded through the Chat
API; only uploaded files can. Uploads are limited to 200 MB.
- New Workspace users can take a while to appear in Chat's people search;
the full email address works sooner.
## Turning it off
- **Stop the server:** remove it from your MCP config.
- **Revoke access:** remove the app at myaccount.google.com → Security →
Third-party apps, and delete the token file.
- **Remove it entirely:** delete the Google Cloud project. This also cuts off
every token issued through it.
## Code layout
- `src/index.ts`: starts the server; `node dist/index.js auth` runs the
sign-in instead
- `src/auth.ts`: loads the client file, runs the sign-in, stores and refreshes
the token
- `src/chat.ts`: thin `fetch` wrappers over the Chat REST API v1
- `src/safety.ts`: read-only mode, allowlist and files folder
- `src/tools/`: the tools, one file per area
## License
ISC, see [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo recent community issues