# stape-io/google-tag-manager-mcp-server [Health: Active]

**Category:** 🎯 Marketing  
**Repository:** https://github.com/stape-io/google-tag-manager-mcp-server  
**GitHub Stars:** 212  
**npm Downloads (last month):** 1241  
**Views:** 2  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/stape-io-google-tag-manager-mcp-server

## Description
This server supports remote MCP connections, includes built-in Google OAuth, and provide an interface to the Google Tag Manager API.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "google-tag-manager-mcp-server": {
    "command": "npx",
    "args": ["-y","google-tag-manager-mcp-server"],
    "env": {
      "GOOGLE_CLIENT_ID": "",
      "GOOGLE_CLIENT_SECRET": "",
      "COOKIE_ENCRYPTION_KEY": "",
      "WORKER_HOST": "",
      "HOSTED_DOMAIN": ""
    }
  }
}
```

**Requires environment variables:** `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET`, `COOKIE_ENCRYPTION_KEY`, `WORKER_HOST`, `HOSTED_DOMAIN` — the values above are empty placeholders; fill in real credentials before running (see the repository for what each one is for).

## Documentation & README

# MCP Server for Google Tag Manager
[![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/stape-io/google-tag-manager-mcp-server)](https://archestra.ai/mcp-catalog/stape-io__google-tag-manager-mcp-server)

An interface to the Google Tag Manager API over MCP, in two flavours: a hosted server with Google OAuth built in, and a local CLI that runs on your own credentials.

## Table of Contents

- [MCP Server for Google Tag Manager](#mcp-server-for-google-tag-manager)
  - [Table of Contents](#table-of-contents)
  - [Repository layout](#repository-layout)
  - [Installation](#installation)
    - [Claude Desktop](#claude-desktop)
    - [Claude Code](#claude-code)
    - [VS Code](#vs-code)
    - [GitHub Copilot](#github-copilot)
    - [Copilot CLI](#copilot-cli)
    - [Cursor](#cursor)
    - [Antigravity](#antigravity)
    - [ChatGPT](#chatgpt)
    - [Other MCP clients](#other-mcp-clients)
    - [Troubleshooting](#troubleshooting)
  - [Test your changes locally](#test-your-changes-locally)
    - [Changes to `packages/core` or `packages/cli`](#changes-to-packagescore-or-packagescli)
    - [Changes to `apps/worker`](#changes-to-appsworker)
      - [1. Set up a Google Cloud OAuth client](#1-set-up-a-google-cloud-oauth-client)
      - [2. Configure local environment variables](#2-configure-local-environment-variables)
      - [3. Start the server](#3-start-the-server)
      - [4. Point your MCP client at the local server](#4-point-your-mcp-client-at-the-local-server)
  - [Releasing](#releasing)
  - [Development](#development)
  - [Useful resources](#useful-resources)
  - [Open Source](#open-source)

## Repository layout

npm workspace with one app and two published packages:

| Path | Package | What it is |
| --- | --- | --- |
| `apps/worker` | *(private)* | The hosted Cloudflare Worker at `gtm-mcp.stape.ai`: Google OAuth, the approval flow, the public pages, session removal. |
| `packages/cli` | [`google-tag-manager-mcp-server`](https://github.com/stape-io/google-tag-manager-mcp-server/blob/HEAD/packages/cli/README.md) | The npm package: a local MCP server over stdio, authenticating with credentials you supply. |
| `packages/core` | [`google-tag-manager-mcp-core`](https://github.com/stape-io/google-tag-manager-mcp-server/blob/HEAD/packages/core/README.md) | Every GTM tool and schema, independent of how credentials are obtained. |

Tools reach Google through a `GtmAuthProvider` (`getAccessToken(): Promise<string>`) rather than through any particular session, which is what lets the same tool set back both servers — and a private one with your own auth. See the [core package README](https://github.com/stape-io/google-tag-manager-mcp-server/blob/HEAD/packages/core/README.md).

## Installation

This server comes in two flavours: Hosted server and Local CLI. Both give you the same 18 GTM tools; the difference is who handles Google auth.

| | Hosted server | Local CLI |
| --- | --- | --- |
| Auth | Google OAuth in your browser, handled for you | You supply a service account key, refresh token, or access token |
| Data | Passes through `gtm-mcp.stape.ai` | Only ever leaves your machine |
| Setup | None | Set one environment variable |

If you're a contributor testing an unreleased change rather than just using the tools, skip everything below and see [Test your changes locally](#test-your-changes-locally) instead.

Pick your client below. The hosted server needs the [`mcp-remote`](https://github.com/geelen/mcp-remote#readme) bridge on clients whose MCP support doesn't complete Google's OAuth flow natively; where a client does that itself, it connects straight to `https://gtm-mcp.stape.ai/mcp`.

### Claude Desktop

<details>
<summary>⬇️ Click to expand ⬇️</summary>

**Hosted server** — Claude Desktop connects to remote HTTP MCP servers natively, no bridge needed. Go to Settings → Connectors → Add custom connector, set the name to `gtm-mcp-server` and the URL to `https://gtm-mcp.stape.ai/mcp`, then save. Click the new connector to complete the Google OAuth flow in the browser window that opens.

> `mcp-remote` is also possible for the hosted server, for anyone who'd rather configure it through the JSON config file (Settings -> Developer -> Edit Config) instead of the Connectors UI — less recommended, but still supported:
>
> ```json
> {
>   "mcpServers": {
>     "gtm-mcp-server": {
>       "command": "npx",
>       "args": [
>         "-y",
>         "mcp-remote",
>         "https://gtm-mcp.stape.ai/mcp"
>       ]
>     }
>   }
> }
> ```

**Local CLI** — no OAuth flow, no data through anyone else's server, you supply a service account key or a refresh token. Open Settings -> Developer -> Edit Config and add:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "command": "npx",
      "args": ["-y", "google-tag-manager-mcp-server"],
      "env": {
        "GOOGLE_SERVICE_ACCOUNT_KEY": "{\"type\":\"service_account\", ... }"
      }
    }
  }
}
```

See the [CLI README](https://github.com/stape-io/google-tag-manager-mcp-server/blob/HEAD/packages/cli/README.md) for every credential option.

</details>

### Claude Code

<details>
<summary>⬇️ Click to expand ⬇️</summary>

Claude Code speaks HTTP directly, including the OAuth handshake, so the hosted server needs no bridge.

**Hosted server**:

```bash
claude mcp add --transport http gtm-mcp-server https://gtm-mcp.stape.ai/mcp
```

A browser window opens for the Google OAuth flow the first time a tool is used. Run `/mcp` inside Claude Code to confirm it connected.

**Local CLI**:

```bash
claude mcp add gtm-mcp-server -e GOOGLE_SERVICE_ACCOUNT_KEY='{"type":"service_account", ... }' -- npx -y google-tag-manager-mcp-server
```

Both write into `.mcp.json` / your Claude Code MCP config.

</details>

### VS Code

<details>
<summary>⬇️ Click to expand ⬇️</summary>

VS Code's MCP client supports HTTP servers and their OAuth flow natively, no `mcp-remote` needed. Add this to `.vscode/mcp.json`:

**Hosted server**:

```json
{
  "servers": {
    "gtm-mcp-server": {
      "type": "http",
      "url": "https://gtm-mcp.stape.ai/mcp"
    }
  }
}
```

**Local CLI**:

```json
{
  "servers": {
    "gtm-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "google-tag-manager-mcp-server"],
      "env": {
        "GOOGLE_SERVICE_ACCOUNT_KEY": "{\"type\":\"service_account\", ... }"
      }
    }
  }
}
```

</details>

### GitHub Copilot

<details>
<summary>⬇️ Click to expand ⬇️</summary>

GitHub Copilot Chat in VS Code uses VS Code's own MCP client, so it reads the same `.vscode/mcp.json` file — see [VS Code](#vs-code) above. No separate configuration is needed.

</details>

### Copilot CLI

<details>
<summary>⬇️ Click to expand ⬇️</summary>

Copilot CLI also completes OAuth natively for remote HTTP servers. Add this to `~/.copilot/mcp-config.json`:

**Hosted server**:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "type": "http",
      "url": "https://gtm-mcp.stape.ai/mcp"
    }
  }
}
```

**Local CLI**:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "command": "npx",
      "args": ["-y", "google-tag-manager-mcp-server"],
      "env": {
        "GOOGLE_SERVICE_ACCOUNT_KEY": "{\"type\":\"service_account\", ... }"
      }
    }
  }
}
```

See [GitHub's docs](https://docs.github.com/en/copilot/how-tos/copilot-cli/customize-copilot/add-mcp-servers) for the equivalent `copilot mcp add` subcommand.

</details>

### Cursor

<details>
<summary>⬇️ Click to expand ⬇️</summary>

Cursor speaks HTTP directly too, no `mcp-remote` needed. Add this to `.cursor/mcp.json` (project-level) or `~/.cursor/mcp.json` (global — Settings → MCP → Add new global MCP server):

**Hosted server**:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "url": "https://gtm-mcp.stape.ai/mcp"
    }
  }
}
```

A browser window opens for the Google OAuth flow the first time a tool is used.

**Local CLI**:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "command": "npx",
      "args": ["-y", "google-tag-manager-mcp-server"],
      "env": {
        "GOOGLE_SERVICE_ACCOUNT_KEY": "{\"type\":\"service_account\", ... }"
      }
    }
  }
}
```

</details>

### Antigravity

<details>
<summary>⬇️ Click to expand ⬇️</summary>

Antigravity's own OAuth support for remote HTTP servers doesn't reliably reach a token to the server yet ([antigravity-cli#25](https://github.com/google-antigravity/antigravity-cli/issues/25)), so use `mcp-remote` for the hosted server here too. Add this to `~/.gemini/config/mcp_config.json` (global) or `.agents/mcp_config.json` (workspace-local) — accessible from the editor's agent panel via **… → MCP Servers → Manage MCP Servers → View raw config**:

**Hosted server**:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://gtm-mcp.stape.ai/mcp"
      ]
    }
  }
}
```

**Local CLI**:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "command": "npx",
      "args": ["-y", "google-tag-manager-mcp-server"],
      "env": {
        "GOOGLE_SERVICE_ACCOUNT_KEY": "{\"type\":\"service_account\", ... }"
      }
    }
  }
}
```

</details>

### ChatGPT

<details>
<summary>⬇️ Click to expand ⬇️</summary>

1. In ChatGPT, enable Developer mode: Settings → Apps & Connectors → Advanced settings → Developer mode.
2. Go to Settings → Connectors → Create, and set the server URL to `https://gtm-mcp.stape.ai/mcp`.
3. Set Authentication to **OAuth** and complete the Google login in the browser window that opens.

ChatGPT only reaches servers over the public internet, it can't spawn a local process — so there's no Local CLI option here, only the hosted server.

</details>

### Other MCP clients

<details>
<summary>⬇️ Click to expand ⬇️</summary>

Any other MCP-compatible client that expects a stdio-style `command`/`args` config can use the same `mcp-remote` block for the hosted server:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://gtm-mcp.stape.ai/mcp"
      ]
    }
  }
}
```

Or the local CLI directly, with your credentials:

```json
{
  "mcpServers": {
    "gtm-mcp-server": {
      "command": "npx",
      "args": ["-y", "google-tag-manager-mcp-server"],
      "env": {
        "GOOGLE_SERVICE_ACCOUNT_KEY": "{\"type\":\"service_account\", ... }"
      }
    }
  }
}
```

</details>

### Troubleshooting

**MCP Server Name Length Limit**

Some MCP clients (like Cursor AI) have a 60-character limit for the combined MCP server name + tool name length. If you use a longer server name in your configuration (e.g., `gtm-mcp-server-your-additional-long-name`), some tools may be filtered out.

To avoid this issue:
- Use shorter server names in your MCP configuration (e.g., `gtm-mcp-server`)

**Clearing MCP Cache**

If you're connecting through `mcp-remote` (Antigravity, or Claude Desktop configured that way), it stores all the credential information inside `~/.mcp-auth` (or wherever your `MCP_REMOTE_CONFIG_DIR` points to). If you're having persistent issues, try running:
```bash
rm -rf ~/.mcp-auth
```
Then, restart your MCP client.

## Test your changes locally

Which workflow you need depends on what you changed. Most changes are in the first
category — reach for the second only if you're touching the Worker itself.

### Changes to `packages/core` or `packages/cli`

This is the tool logic itself (schemas, GTM API calls, error handling) — almost
everything you'd fix or add lives here. You don't need a Google Cloud OAuth client
or any Worker setup: build from source and run the CLI directly with credentials
you already have.

```bash
git clone https://github.com/stape-io/google-tag-manager-mcp-server
cd google-tag-manager-mcp-server
gh pr checkout <PR number>   # or: git checkout <your-branch>
npm install
npm run build
```

Point your MCP client at the local build instead of `npx` — same credential
options as the [Claude Desktop](#claude-desktop) Local CLI example above, an access
token from the [OAuth Playground](https://developers.google.com/oauthplayground) is
the fastest way to test a single change:

```json
{
  "mcpServers": {
    "gtm-mcp-local": {
      "command": "node",
      "args": ["/absolute/path/to/google-tag-manager-mcp-server/packages/cli/dist/index.js"],
      "env": {
        "GOOGLE_ACCESS_TOKEN": "..."
      }
    }
  }
}
```

See the [CLI README](https://github.com/stape-io/google-tag-manager-mcp-server/blob/HEAD/packages/cli/README.md) for every credential option.

### Changes to `apps/worker`

Only needed for the hosted server's own code: the OAuth flow, routing, session
handling, the approval and status pages. This runs that code on your own machine
against your own Google Cloud OAuth credentials instead of `gtm-mcp.stape.ai`.

#### 1. Set up a Google Cloud OAuth client

1. In the [Google Cloud Console](https://console.cloud.google.com/), create or select a project, then enable the **Tag Manager API**.
2. Go to **APIs & Services > OAuth consent screen** and configure it (External is fine). While the app is in **Testing** publishing status, only accounts listed as test users can log in.
3. Go to **Audience**, under **Test users** add your own Google account.
4. Go to **APIs & Services > Credentials > Create Credentials > OAuth client ID**, type **Web application**.
5. Under **Authorized redirect URIs**, add `http://localhost:8788/callback`. (You can leave **Authorized JavaScript origins** empty — this flow is server-side only, no browser JS calls Google directly.)
6. Save, then copy the generated **Client ID** and **Client secret**.

#### 2. Configure local environment variables

Copy the example file and fill in the values from the previous step:

```bash
cp apps/worker/.dev.vars.example apps/worker/.dev.vars
```

```
GOOGLE_CLIENT_ID="<your client ID>"
GOOGLE_CLIENT_SECRET="<your client secret>"
COOKIE_ENCRYPTION_KEY="<any random string, at least 32 chars, e.g. output of: openssl rand -hex 32>"
WORKER_HOST="http://localhost:8788"
HOSTED_DOMAIN=""
```

`.dev.vars` is git-ignored — it's only used locally and never committed.

#### 3. Start the server

```bash
npm install
npm run build
npm run dev
```

`npm run build` compiles the core package the Worker bundles against; `npm run dev` starts the Worker on `http://localhost:8788`.

#### 4. Point your MCP client at the local server

Claude Desktop's Custom Connectors need a publicly reachable URL, so `mcp-remote` is the only option for pointing at `localhost`:

```json
{
  "mcpServers": {
    "gtm-mcp-server-local": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "http://localhost:8788/mcp"]
    }
  }
}
```

Restart Claude Desktop. A browser window will open for the Google OAuth flow; log in with the
account you added as a test user in step 1.

**Note:** if you've previously connected to the hosted server (or switch back and forth between
local and hosted), clear mcp-remote's cache first (see [Troubleshooting](#troubleshooting) above)
and fully restart your MCP client, otherwise it may reuse a stale/cached connection.

## Releasing

Versions and changelogs are managed with [Changesets](https://github.com/changesets/changesets). Along with a change that should ship, add:

```bash
npm run changeset
```

On merge to `main` the release workflow opens a "Version Packages" PR; merging that PR publishes to npm, core first and then the CLI that depends on it. The Worker is private and never published — it deploys from `main` on every push.

## Development

```bash
npm install
npm run build      # core, then the CLI, then the Worker's generated version
npm run typecheck
npm run lint
npm run smoke      # starts the built CLI and runs an MCP handshake against it
```

Pull requests run all of the above plus a Worker bundle check, and flag changes to a published package that arrive without a changeset.

Both `@modelcontextprotocol/sdk` and `agents` are pinned to exact versions in `apps/worker`. The SDK identifies tool schemas with `instanceof`, so the whole workspace has to resolve a single copy, and `agents` releases pin the SDK version they were built against. Bump them together and deploy deliberately.

## Useful resources

- [Step-by-step guide: MCP Server for Google Tag Manager](https://stape.io/blog/mcp-server-for-google-tag-manager)

## Open Source

The **MCP Server for Google Tag Manager** is developed and maintained by [Stape Team](https://stape.io/) under the Apache 2.0 license.

