Skip to main content
Glama
princegrg17

google-workspace-mcp-server

by princegrg17
README.md
# Google Workspace MCP Server

A generic, agent-agnostic **Model Context Protocol (MCP) server** that exposes Gmail and Google Docs capabilities as tools. Any MCP-compatible client (Antigravity, Claude Desktop, custom agents) can connect and use these tools without code changes.

## Available Tools

| Tool | Description |
|---|---|
| `gmail_send_email` | Send an email via Gmail on behalf of the authenticated user |
| `gmail_create_draft` | Create a draft email in Gmail without sending |
| `gdocs_append_content` | Append text content to the end of a Google Doc |

## Prerequisites

- **Node.js** 18 or later
- A **Google Cloud** project with billing enabled (or free tier)

## Google Cloud Setup

### 1. Create a Google Cloud Project

1. Go to [Google Cloud Console](https://console.cloud.google.com/).
2. Create a new project (or select an existing one).

### 2. Enable APIs

Enable the following APIs for your project:

- **Gmail API**: [Enable here](https://console.cloud.google.com/apis/library/gmail.googleapis.com)
- **Google Docs API**: [Enable here](https://console.cloud.google.com/apis/library/docs.googleapis.com)

### 3. Create OAuth 2.0 Credentials

1. Go to **APIs & Services → Credentials**.
2. Click **Create Credentials → OAuth client ID**.
3. Select **Desktop app** as the application type.
4. Name it (e.g., "MCP Server") and click **Create**.
5. Download or copy the **Client ID** and **Client Secret**.

### 4. Configure the OAuth Consent Screen

1. Go to **APIs & Services → OAuth consent screen**.
2. Select **External** user type (or Internal if using Workspace).
3. Fill in the required app info and add the following scopes:
   - `https://www.googleapis.com/auth/gmail.send`
   - `https://www.googleapis.com/auth/gmail.compose`
   - `https://www.googleapis.com/auth/documents`
4. Add your Google account as a **test user** (required for external apps in testing).

## Installation

```bash
# Clone or navigate to the project directory
cd mcp-server

# Install dependencies
npm install

# Copy the environment template
cp .env.example .env
```

Edit `.env` and fill in your Google credentials:

```env
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your-client-secret
GOOGLE_REDIRECT_URI=urn:ietf:wg:oauth:2.0:oob
GOOGLE_TOKEN_PATH=./token.json
```

## Authorization

Run the one-time authorization flow to grant the server access to your Google account:

```bash
npm run authorize
```

This will:
1. Display a URL — open it in your browser.
2. Sign in with your Google account and grant access.
3. Paste the authorization code back into the terminal.
4. Save the OAuth tokens to `token.json`.

> **Note:** You only need to do this once. Tokens refresh automatically after that.

## Running the Server

### Development (with hot reload)
```bash
npm run dev
```

### Production
```bash
npm run build
npm start
```

## Connecting to MCP Clients

### Antigravity

Add to your Antigravity MCP settings:

```json
{
  "mcpServers": {
    "google-workspace": {
      "command": "node",
      "args": ["C:/path/to/mcp-server/dist/index.js"]
    }
  }
}
```

### Claude Desktop

Add to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "google-workspace": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-server/dist/index.js"]
    }
  }
}
```

### MCP Inspector (Testing)

Use the MCP Inspector to test your tools interactively:

```bash
npx @modelcontextprotocol/inspector node dist/index.js
```

## Tool Schemas

### gmail_send_email

```json
{
  "to": "recipient@example.com",
  "subject": "Hello from MCP",
  "body": "This email was sent by an AI agent via the MCP server.",
  "cc": "cc@example.com",
  "bcc": ["bcc1@example.com", "bcc2@example.com"],
  "body_html": "<h1>Hello</h1><p>HTML email body</p>"
}
```

### gmail_create_draft

Same schema as `gmail_send_email`. Creates a draft without sending.

### gdocs_append_content

```json
{
  "document_id": "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVf2oVzk",
  "content": "This text was appended by an AI agent.",
  "add_newline": true
}
```

## Troubleshooting

| Problem | Solution |
|---|---|
| `Missing GOOGLE_CLIENT_ID` | Copy `.env.example` to `.env` and fill in your credentials |
| `No OAuth tokens found` | Run `npm run authorize` to complete the consent flow |
| `Token refresh failed` | Delete `token.json` and run `npm run authorize` again |
| `403 Forbidden` | Ensure the Gmail and Docs APIs are enabled in your Google Cloud project |
| `Invalid document ID` | The document ID is the long string in the URL: `docs.google.com/document/d/{ID}/edit` |
| `Access denied` | Make sure your account is added as a test user in the OAuth consent screen |
| `401 Unauthorized` (cloud) | Set `Authorization: Bearer <API_KEY>` header when connecting to the remote server |
| `GOOGLE_TOKENS_JSON decode error` | Re-run `npm run export-token` locally and update the env var |

## Deploy to Railway

### Prerequisites
- The MCP server running locally with a valid `token.json` (complete the [Authorization](#authorization) steps first)
- A [Railway](https://railway.app) account
- A GitHub repository with this code pushed

### Step 1: Export Your Token

```bash
npm run export-token
```

This outputs a Base64-encoded string of your `token.json`. Copy it — you'll need it in Step 3.

### Step 2: Create Railway Service

1. Go to [Railway Dashboard](https://railway.app/dashboard).
2. Click **New Project → Deploy from GitHub Repo**.
3. Select your repository.
4. Railway will auto-detect the `Dockerfile` and begin building.

### Step 3: Set Environment Variables

In the Railway service dashboard, go to **Variables** and add:

| Variable | Value |
|---|---|
| `TRANSPORT` | `http` |
| `GOOGLE_CLIENT_ID` | Your Google OAuth client ID |
| `GOOGLE_CLIENT_SECRET` | Your Google OAuth client secret |
| `GOOGLE_TOKENS_JSON` | The Base64 string from Step 1 |
| `API_KEY` | A secret key of your choice (for securing the endpoint) |

> **Note:** `PORT` is injected automatically by Railway. Do not set it manually.

### Step 4: Deploy

Railway will automatically build and deploy. Once live, you'll get a public URL like:
```
https://your-app-name.up.railway.app
```

### Step 5: Verify

```bash
# Health check
curl https://your-app-name.up.railway.app/health

# Test MCP endpoint (replace YOUR_API_KEY)
curl -X POST https://your-app-name.up.railway.app/mcp \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{}},"id":1}'
```

### Step 6: Connect Remote MCP Client

Configure your MCP client to connect to the deployed server. Example for clients that support Streamable HTTP:

```json
{
  "mcpServers": {
    "google-workspace-remote": {
      "url": "https://your-app-name.up.railway.app/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}
```

## Project Structure

```
├── src/
│   ├── index.ts                  # Server entry point (stdio + HTTP dual transport)
│   ├── auth/
│   │   └── google-auth.ts        # OAuth2 authentication (file + env var dual mode)
│   ├── services/
│   │   ├── gmail.service.ts      # Gmail API logic
│   │   └── gdocs.service.ts      # Google Docs API logic
│   ├── tools/
│   │   ├── gmail-send-email.ts   # gmail_send_email tool
│   │   ├── gmail-create-draft.ts # gmail_create_draft tool
│   │   └── gdocs-append.ts       # gdocs_append_content tool
│   └── utils/
│       └── mime.ts               # MIME message builder
├── scripts/
│   ├── authorize.ts              # OAuth consent flow script
│   └── export-token.ts           # Token export for cloud deployment
├── Dockerfile                    # Multi-stage Docker build
├── railway.toml                  # Railway deployment config
├── .env.example                  # Environment variable template
├── package.json
├── tsconfig.json
└── README.md
```

## License

MIT