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

@theethosteam/gtm-mcp

v1.1.0

Published

Google Tag Manager (API v2) as an MCP server + CLI — manage tags, triggers, variables, versions and publishing for any container.

Downloads

169

Readme

@theethosteam/gtm-mcp

Programmatic control of Google Tag Manager (API v2) for Claude and humans. One shared TypeScript core (core/), exposed two ways:

  • MCP server — native tools for Claude (gtm_*)
  • CLIgtm <command> (run anywhere via a shell)

Works against any GTM account the authenticated user can access; defaults to container GTM-WHRH7CHV (override with --container / GTM_CONTAINER_PUBLIC_ID).


Install on any project (global MCP)

Publish once, then register at user scope so every project gets the tools:

# 1) publish (from this directory). Public — the code has no secrets;
#    all auth is runtime env vars. (Private needs a paid npm org.)
npm login
npm publish              # publishConfig.access is "public"

# 2) register globally for the Claude Code CLI/desktop (one time):
claude mcp add gtm --scope user \
  -e GTM_OAUTH_CLIENT_ID=<client-id> \
  -e GTM_OAUTH_CLIENT_SECRET=<client-secret> \
  -e GTM_OAUTH_REFRESH_TOKEN=<refresh-token> \
  -- npx -y @theethosteam/gtm-mcp

The theethosteam npm scope must be an org/user you can publish to (create the free org at npmjs.com, or change the name to your own scope). On Claude Code web, add the same server + env to each environment's config instead of user scope. The CLI is also exposed: npx -y -p @theethosteam/gtm-mcp gtm <command>.


1. Auth — OAuth (recommended)

Google currently has a bug that blocks adding service accounts as GA4 / Tag Manager users via the UI ("This email doesn't match a Google Account"). Until that's fixed, use OAuth, which acts as a real Google user (e.g. the GTM account owner) — so nothing needs to be added inside GTM at all.

  1. Enable the Tag Manager API: https://console.cloud.google.com/apis/library/tagmanager.googleapis.com
  2. Configure the OAuth consent screen (APIs & Services → OAuth consent screen): User type External, fill app name + your email, add yourself as a Test user. (No verification needed while in "Testing".)
  3. Create an OAuth client (APIs & Services → Credentials → Create credentials → OAuth client ID), application type Desktop app. Copy the client ID and client secret.
  4. Put them in tools/gtm/.env (copy from .env.example) or export them:
    export GTM_OAUTH_CLIENT_ID=...
    export GTM_OAUTH_CLIENT_SECRET=...
  5. Log in to mint a refresh token:
    pnpm gtm auth:url           # prints a consent URL — open it, approve
    # the browser redirects to a "localhost" page that fails to load;
    # copy the `code=...` value out of the URL bar, then:
    pnpm gtm auth:exchange <code>   # saves GTM_OAUTH_REFRESH_TOKEN to .env
  6. Verify:
    pnpm gtm whoami

For permanent / MCP use, store GTM_OAUTH_CLIENT_ID, GTM_OAUTH_CLIENT_SECRET, and GTM_OAUTH_REFRESH_TOKEN as environment secrets.

Fallback — service account

If the service-account UI block is lifted, set GTM_SA_KEY (full JSON) or GTM_SA_KEY_FILE (path) instead, and add the SA email as a GTM user with Publish. The tool prefers OAuth when both are present.

3. CLI usage

# discovery
pnpm gtm accounts:list
pnpm gtm containers:list
pnpm gtm container:show                 # resolves the default container

# inventory (defaults to the Default Workspace)
pnpm gtm tags:list
pnpm gtm triggers:list
pnpm gtm variables:list
pnpm gtm builtins:list
pnpm gtm workspace:status               # pending changes

# create things (recipes)
pnpm gtm recipe:ga4-config --measurement-id G-XXXXXXX
pnpm gtm recipe:meta-pixel --pixel-id 1234567890
pnpm gtm recipe:custom-event-trigger --name "Booking Click" --event-name booking_click
pnpm gtm recipe:ga4-event --name "GA4 - Booking" --event-name booking --trigger 12345

# raw create from a JSON object/file/stdin
pnpm gtm tag:create ./mytag.json
echo '{"name":"X","type":"html","parameter":[...]}' | pnpm gtm tag:create -

# versioning + publish
pnpm gtm version:live
pnpm gtm publish --name "v2" --notes "Add GA4"   # version + publish in one step

# escape hatch: any API method by dotted path
pnpm gtm raw accounts.list
pnpm gtm raw accounts.containers.workspaces.folders.list '{"parent":"accounts/123/containers/456/workspaces/7"}'

Global flags (any command): --container GTM-XXXX, --account <id>, --container-id <id>, --workspace <nameOrId>.

4. MCP usage (Claude)

.mcp.json at the repo root registers a gtm stdio server. Claude exposes the core as gtm_* tools (e.g. gtm_list_tags, gtm_recipe_ga4_config, gtm_publish, gtm_raw). The server reads the same GTM_SA_KEY / GTM_SA_KEY_FILE env vars. After adding the key to the environment, reload the session so the MCP server picks it up.

Notes

  • Workspaces & versions: edits land in a workspace; nothing is live until you create a version and publish it (pnpm gtm publish).
  • Scopes requested: read, edit containers + versions, delete, publish, manage accounts + users (full capability).
  • The raw command/tool reaches every endpoint (folders, zones, clients, templates, environments, user permissions, gtag config, destinations) even without a dedicated wrapper.