{
  "markdown": "# GrowthBook MCP Thin\n\nA thin MCP server for GrowthBook with four tools:\n\n| Tool | Purpose |\n|------|---------|\n| `growthbook_list_skills` | List top-level skill entry points (name + description) |\n| `growthbook_read_skill` | Return a listed skill or qualified child workflow (`feature-flags` or `feature-flags/references/flag-create`) |\n| `growthbook_api_read` | Authenticated GET passthrough to the GrowthBook API |\n| `growthbook_api_write` | Authenticated POST/PUT/PATCH/DELETE passthrough |\n\nCompetence lives in the [skills](https://github.com/growthbook/skills) repo and is **bundled at build time**. Capability is split into read vs write API tools (no per-endpoint formatters) so clients can honor `readOnlyHint` / `destructiveHint` correctly.\n\nTools are prefixed with `growthbook_` so they stay unambiguous when a client has multiple MCP servers loaded.\n\n## Install / run\n\n```bash\nnpm install\nnpm run build\n```\n\nPoint your MCP client at the compiled entrypoint:\n\n```json\n{\n  \"mcpServers\": {\n    \"growthbook\": {\n      \"command\": \"node\",\n      \"args\": [\"/absolute/path/to/growthbook-mcp/server/index.js\"],\n      \"env\": {\n        \"GB_API_KEY\": \"your_api_key_or_pat\",\n        \"GB_API_URL\": \"https://api.growthbook.io\"\n      }\n    }\n  }\n}\n```\n\nOr run the published package:\n\n```bash\nnpx @growthbook/mcp\n```\n\n## Environment variables\n\n| Variable | Required | Default | Purpose |\n|----------|----------|---------|---------|\n| `GB_API_KEY` | Yes for stdio; optional for HTTP OAuth | — | GrowthBook API key or personal access token |\n| `GB_API_URL` | No | `https://api.growthbook.io` | API base URL (self-hosted) and default OAuth AS issuer |\n| `GB_MCP_TRANSPORT` | No | `stdio` | `stdio` or `http` |\n| `GB_MCP_PORT` | No | `3333` | HTTP listen port (when transport=http) |\n| `GB_MCP_HOST` | No | `127.0.0.1` | HTTP bind host |\n| `GB_MCP_URL` | Yes for HTTP | — | Public MCP base URL stamped into OAuth resource metadata (server refuses to start in HTTP mode without it) |\n| `GB_OAUTH_ISSUER` | No | `GB_API_URL` | GrowthBook OAuth AS issuer URL |\n| `GB_HTTP_HEADER_*` | No | — | Extra request headers (e.g. `GB_HTTP_HEADER_CF_ACCESS_TOKEN`) |\n| `GB_SKILLS_ENABLED` | No | `true` | Set to `false` / `0` to disable skill tools |\n\n### HTTP + OAuth mode\n\n```bash\nOAUTH_AS_ENABLED=1  # on the GrowthBook API\nGB_MCP_TRANSPORT=http GB_API_URL=http://localhost:3100 GB_MCP_PORT=3333 npm start\n```\n\nClients connect to:\n- `http://127.0.0.1:3333/mcp` — full (skills + API read/write)\n- `http://127.0.0.1:3333/mcp/api` — capability-only (`growthbook_api_read` + `growthbook_api_write`)\n\nUnauthenticated requests receive `401` with `WWW-Authenticate` pointing at `/.well-known/oauth-protected-resource`, which advertises the GrowthBook Authorization Server.\n\nBefore handling MCP, the server probes GrowthBook REST (`GET /api/v1/`) with the bearer. A `401` from that probe (or later from an API tool) yields HTTP `401` with `error=\"invalid_token\"` so the MCP client can refresh — instead of surfacing `\"This API key has expired\"` as a tool error. A `403` is treated as an accepted bearer (permission denied ≠ invalid token) so clients are not forced into a refresh loop.\n\n### Capability-only mode\n\n**HTTP (recommended for remote):** point the client at `/mcp/api` instead of `/mcp`:\n\n```json\n{\n  \"mcpServers\": {\n    \"growthbook\": {\n      \"url\": \"http://127.0.0.1:3333/mcp/api\"\n    }\n  }\n}\n```\n\n| Path | Tools |\n|------|--------|\n| `/mcp` | `growthbook_list_skills`, `growthbook_read_skill`, `growthbook_api_read`, `growthbook_api_write` (unless `GB_SKILLS_ENABLED=false`) |\n| `/mcp/api` | `growthbook_api_read`, `growthbook_api_write` only |\n\n**stdio / process-wide:** set env so skills are never registered:\n\n```json\n\"env\": {\n  \"GB_API_KEY\": \"...\",\n  \"GB_SKILLS_ENABLED\": \"false\"\n}\n```\n\nWhen skills are disabled, only the API read/write tools are registered. `growthbook_list_skills` and `growthbook_read_skill` are not exposed.\n\n## How skills are bundled\n\n```bash\nnpm run build   # tsc && bundle-skills\n```\n\n`scripts/bundle-skills.mjs` copies the top-level skill tree from the canonical skills checkout, preserving structure:\n\n```\nskills/<skill>/SKILL.md                   → server/skills/<skill>/SKILL.md\nskills/<skill>/references/<workflow>.md   → server/skills/<skill>/references/<workflow>.md\n```\n\nSource path resolution:\n\n1. `SKILLS_SRC` env var (path to the skills repo root)\n2. `agent-skills.local.json` — `{ \"path\": \"../skills\" }`, relative to the repo root. Gitignored; copy `agent-skills.local.json.example`\n3. `skills-src/` — what CI and the Docker build vendor\n\nThere is no implicit sibling lookup. `../skills` resolves to whatever happens to be at that path, which makes a local build silently disagree with the commit CI builds from.\n\nCI, cloud deploys, and releases all read `agent-skills.lock.json` and check out\nthat exact skills commit. To ship upstream skill changes, update the commit in\nthe lock file. Local development can point at any checkout with\n`agent-skills.local.json` or `SKILLS_SRC`.\n\nThe skills repo stays the source of truth — this package does not maintain a\nfork of skill content. New skills flow through automatically, except those named\nin the small blocklist in `bundle-skills.mjs`. Currently only `gb-setup` is\nblocked because it configures the `gb-call` shell adapter rather than GrowthBook\nitself.\n\nPer-skill `scripts/` directories are not copied. Relative\n`` `references/foo.md` `` links are rewritten to qualified\n`` `feature-flags/references/foo` `` paths so `growthbook_read_skill` can resolve\nthem.\n\n## Using skills with the API tools\n\nBundled skills still show workflows as:\n\n```bash\ngb-call GET /api/v1/projects\ngb-call POST /api/v2/features ./payload.json\n```\n\nThis MCP server does **not** shell out to `gb-call`. Map `GET` → `growthbook_api_read` and `POST`/`PUT`/`PATCH`/`DELETE` → `growthbook_api_write` with the same path and optional JSON body string. Server instructions and `growthbook_read_skill` output include this bridge note.\n\n## Tools detail\n\n### `growthbook_api_read` / `growthbook_api_write`\n\n```json\n{ \"path\": \"/api/v1/projects\" }\n{ \"method\": \"POST\", \"path\": \"/api/v2/features\", \"body\": \"{\\\"id\\\":\\\"my-flag\\\",...}\" }\n```\n\n- Read: GET only (`readOnlyHint: true`)\n- Write: `POST` | `PUT` | `PATCH` | `DELETE` (`destructiveHint: true`)\n- Returns raw response body on 2xx\n- On non-2xx, returns an actionable error (`isError: true`) covering auth failures, self-hosted 404 hints, and rate limits\n- Freeform paths target the [GrowthBook REST API](https://docs.growthbook.io/api)\n\n### `growthbook_list_skills` / `growthbook_read_skill`\n\nOnly registered when `GB_SKILLS_ENABLED` is not disabled.\n\n- `growthbook_list_skills` returns top-level skill entry points. An entry may contain a complete workflow or route to child workflows.\n- `growthbook_read_skill` accepts a listed top-level name or a qualified child path named by a loaded skill (`feature-flags/references/flag-create`) and returns the full markdown (workflow + guardrails).\n\n## Development\n\n```bash\ngit clone git@github.com:growthbook/skills.git ../skills\ncp agent-skills.local.json.example agent-skills.local.json  # edit if not at ../skills\n\nnpm install\nnpm run build\nnpm start\n```\n\n## Standalone HTTP mode\n\nBy default the server runs over stdio. Set `GB_MCP_TRANSPORT=http` to run it as a standalone HTTP server that exposes MCP at `/mcp` (skills + API tools) and `/mcp/api` (capability-only), behind an OAuth 2.0 protected-resource surface (RFC 9728 metadata + RFC 6750 `WWW-Authenticate`).\n\n- `GB_MCP_URL` (**required** in HTTP mode) — the server's public base URL. It is stamped into the OAuth resource (audience) and the protected-resource metadata, so it is never derived from request headers. The server refuses to start without it.\n- `GB_MCP_PORT` (default `3333`) and `GB_MCP_HOST` (default `127.0.0.1`).\n- Incoming bearers are validated by probing the GrowthBook REST API; a rejected token gets HTTP `401` + `WWW-Authenticate` so the client can refresh.\n\nRun it on a trusted network or bound to loopback. For a multi-tenant or public deployment, front it with your own gateway/auth.\n\n## Releases\n\nCutting a release is deliberate: bump the version in `package.json`, then push a matching `v*` tag:\n\n```bash\ngit tag v2.0.0\ngit push origin v2.0.0\n```\n\nThat tagged commit (with skills frozen at cut time) publishes:\n\n- `@growthbook/mcp` to npm — prereleases (versions with a `-`, e.g. `2.0.0-beta.1`) go under the `beta` dist-tag; stable versions become `latest`\n- a multi-arch (`amd64` + `arm64`) image to `ghcr.io/growthbook/growthbook-mcp` (`:<version>`, plus `:<major>`, `:<major>.<minor>`, and `:latest` for stable releases)\n- an entry in the MCP registry\n- a GitHub Release\n\nInstall a release with `npx @growthbook/mcp@<version>` or pull `ghcr.io/growthbook/growthbook-mcp:<version>`.\n",
  "bytes": 8805,
  "sha": "eff34d0b41f9bd6df109efcdcee64d0ac51400e46f615944e52f1c808ecc2084",
  "repo_slug": "growthbook/growthbook-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_growthbook_growthbook_mcp_b41e7816/readme"
}