{"id":51526847,"url":"https://github.com/ehmo/gum","last_synced_at":"2026-07-08T22:30:30.117Z","repository":{"id":365161507,"uuid":"1268892689","full_name":"ehmo/gum","owner":"ehmo","description":"CLI and MCP server for discovering and calling Google APIs from agents and scripts.","archived":false,"fork":false,"pushed_at":"2026-06-16T06:04:42.000Z","size":1939,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-16T07:45:21.613Z","etag":null,"topics":["automation","cli","golang","google-apis","google-workspace","mcp","model-context-protocol","oauth"],"latest_commit_sha":null,"homepage":"https://github.com/ehmo/gum","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ehmo.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-14T04:00:38.000Z","updated_at":"2026-06-16T06:05:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ehmo/gum","commit_stats":null,"previous_names":["ehmo/gum"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ehmo/gum","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fgum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fgum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fgum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fgum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ehmo","download_url":"https://codeload.github.com/ehmo/gum/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ehmo%2Fgum/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35280681,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-08T02:00:06.796Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","cli","golang","google-apis","google-workspace","mcp","model-context-protocol","oauth"],"created_at":"2026-07-08T22:30:28.755Z","updated_at":"2026-07-08T22:30:30.100Z","avatar_url":"https://github.com/ehmo.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# gum\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"gum logo\" src=\"docs/assets/gum-logo.png\" width=\"320\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Go 1.26.4\" src=\"https://img.shields.io/badge/Go-1.26.4-00ADD8?logo=go\u0026logoColor=white\"\u003e\n  \u003cimg alt=\"FSL 1.1, Apache 2.0 future\" src=\"https://img.shields.io/badge/license-FSL%201.1%20to%20Apache%202.0-2ea44f\"\u003e\n  \u003cimg alt=\"MCP stdio\" src=\"https://img.shields.io/badge/MCP-stdio-7c3aed\"\u003e\n  \u003cimg alt=\"agent skills\" src=\"https://img.shields.io/badge/agent%20skills-included-f97316\"\u003e\n\u003c/p\u003e\n\nMost agents can write code. Giving them access to Google APIs is the risky part.\n\nThe hard part is not sending HTTP. The hard part is finding the right method,\ngetting the right OAuth scope, trimming huge JSON responses, and stopping a bad\nprompt from turning into a real delete.\n\ngum is a single binary that gives agents and humans a safer control surface for\nGoogle APIs. It runs as a terminal CLI and as an MCP stdio server. It carries an\nembedded Google API catalog, local auth helpers, compact output shaping, and\nconfirmation gates for risky writes.\n\nUse gum when you want an agent to inspect Gmail, Drive, Docs, Sheets, Calendar,\nAdmin, or other Google services without pasting tokens into prompts or writing a\ncustom tool for each endpoint.\n\nUse it only with Google accounts, projects, and APIs you own or are authorized\nto operate.\n\n## What gum covers\n\ngum v1.0 ships with 222 operations across 32 services.\n\n| Surface | Examples | Auth |\n| --- | --- | --- |\n| Google Workspace and Google APIs | Gmail, Calendar, Drive, Docs, Sheets, Slides, Tasks, Admin, Vault, Chat, Meet, Classroom, Forms, Apps Script, People, Photos, YouTube, Search Console, Google Ads, Maps, Custom Search | OAuth, ADC, API key, service account, or Google Ads developer token |\n| Bundled plugin services | Google Flights, Google Scholar, Google Patents, Google Trends, YouTube transcripts | Plugin-managed setup, with separate trust and sandbox checks |\n\nThe Google API path is for accounts and projects you control. The plugin path is\nfor useful Google-adjacent services that do not fit the normal OAuth catalog\nmodel.\n\n```mermaid\nflowchart LR\n  User[\"Agent or CLI user\"] --\u003e Gum[\"gum\"]\n  Gum --\u003e Catalog[\"API catalog\u003cbr/\u003e222 ops / 32 services\"]\n  Gum --\u003e Auth[\"Auth resolver\u003cbr/\u003eOAuth / ADC / API key / service account\"]\n  Gum --\u003e Gates[\"Risk gates\u003cbr/\u003ewrite + destructive confirmation\"]\n  Gum --\u003e Shape[\"Output shaping\u003cbr/\u003esmall MCP-friendly results\"]\n  Catalog --\u003e Google[\"Google APIs\"]\n  Auth --\u003e Google\n  Gates --\u003e Google\n  Google --\u003e Shape\n  Shape --\u003e User\n  Gum --\u003e Plugins[\"Bundled plugins\u003cbr/\u003eFlights / Scholar / Patents / Trends\"]\n  Plugins --\u003e Shape\n```\n\n## Why this is different\n\nWithout gum, an agent usually gets one of two bad choices:\n\n- A giant tool list, where every Google method burns context before the task\n  starts.\n- A raw HTTP escape hatch, where the agent has to infer scopes, paths, request\n  bodies, pagination, and delete safety on the fly.\n\ngum keeps the first screen small. The MCP server starts with 29 tools: 9\nmeta-tools, 18 common convenience tools, and 2 skill helpers. Everything else is\nfound through `gum.search_apis` and loaded only when needed.\n\nThe current release-gate benchmark uses 200 fixture calls against a spec-scale\nnaive baseline. In that test, gum reduced MCP-layer tokens by 83.39%:\n\n| Path | Tool-list tokens | Response tokens | Total |\n| --- | ---: | ---: | ---: |\n| Naive full-catalog MCP server | 406,638 | 140,065 | 546,703 |\n| gum shaped MCP surface | 8,804 | 82,000 | 90,804 |\n\nThis measures MCP tool definitions plus API response payloads with the\n`cl100k_base` tokenizer. It is not a billing promise and it is not a latency\nclaim. The point is simpler: the agent sees less catalog noise and less raw JSON\nwhile still getting the operation it asked for.\n\n## How OAuth works\n\nOAuth is Google's consent flow. A Google Cloud project owns an OAuth client, the\nconsent screen, API enablement, quota, and verification state. gum v1.0 asks you\nto use your own Desktop OAuth client because that keeps those controls in your\nproject.\n\nThe flow is:\n\n1. You create a Google Cloud project and Desktop OAuth client.\n2. You enable the APIs you want gum to call.\n3. You register the client once with `gum auth use-oauth-client`.\n4. `gum login --service \u003cname\u003e` opens your browser and stores the resulting\n   refresh token in the OS keychain.\n5. CLI, MCP, and agent calls reuse that local credential without putting tokens\n   in prompts.\n\nNot every Google surface uses the same auth shape. Some operations use OAuth.\nSome use ADC, API keys, service accounts, or Google Ads developer tokens. The\nbundled plugin services, such as Flights and Scholar, use their own setup path\nbecause they are not normal Google API catalog endpoints.\n\n## Add gum to an agent\n\nInstall the bundled skills and MCP server config in one step:\n\n```shell\ngum setup --dry-run\ngum setup --target all --features skills,mcp --yes\ngum agents install --target all --features skills,mcp --dry-run --format json\n```\n\nUse `--target codex`, `claude`, `cursor`, or `gemini` to install for one\nagent. Use `--scope project` when you want repo-local MCP config. The default\nwrites skill files plus a stdio MCP entry that runs `gum mcp --stdio`.\n\nRun the dry run first. It prints the exact files gum would write. Reruns are\nsafe: MCP config files are merged, and existing skill files are left alone\nunless you pass `--force`.\n\n## At a glance\n\n| Need | Use |\n| --- | --- |\n| Explore Google API operations | `gum search`, `gum describe` |\n| Call read/write/destructive APIs | `gum read`, `gum write`, `gum destructive` |\n| Agent access over MCP | `gum mcp --stdio` |\n| Guided setup and diagnostics | `gum setup`, `gum doctor` |\n| Google auth | Your Google OAuth client, ADC, API key, or service account |\n| Secrets for agent workflows | [HASP](https://github.com/gethasp/hasp) for brokered local secret access |\n| Install and release downloads | Release archives, install script, or Homebrew tap |\n\n## Install\n\nPublic release assets are published on the\n[GitHub releases page](https://github.com/ehmo/gum/releases). Download the\narchive for your OS and CPU, then verify it with `checksums.txt`.\n\n```shell\ntar -xzf gum_\u003cversion\u003e_\u003cos\u003e_\u003carch\u003e.tar.gz\ninstall -m 0755 gum ~/.local/bin/gum\ngum --version\n```\n\nAfter the public release is published, install with:\n\n```shell\ncurl -fsSL https://raw.githubusercontent.com/ehmo/gum/main/install.sh | bash\n```\n\nPin a version with `GUM_VERSION=vX.Y.Z`.\n\nHomebrew:\n\n```shell\nbrew tap ehmo/tap https://github.com/ehmo/homebrew-tap\nbrew install ehmo/tap/gum\ngum setup --dry-run\ngum doctor\n```\n\nUse the qualified formula name. Plain `brew install gum` installs\nCharmbracelet's `gum`, which is a different CLI.\n\nThe public repo also includes `Formula/gum.rb` for people who want to tap this\nrepo directly and build from source. The `ehmo/tap/gum` formula installs from\nthe release archives and is the normal Homebrew path.\n\nThe source tree uses a Go module under `apps/gum`, so this release does not\ndocument a `go install` path. Use release archives for a stamped binary.\n\n## First Proof\n\nFor Gmail, Calendar, Drive, Docs, Sheets, Slides, Tasks, and most Workspace\nAPIs, gum needs a Google OAuth client from your Google Cloud project. Google\nuses that client to show the consent screen and issue your local refresh token.\n\n1. Create a Google Cloud project.\n2. Configure an OAuth consent screen.\n3. Create an OAuth client ID with application type `Desktop app`.\n4. Enable the Google APIs you plan to call.\n5. Store the client in gum:\n\n```shell\nprintf '%s' \"$GOOGLE_OAUTH_CLIENT_SECRET\" \\\n  | gum auth use-oauth-client --client-id \"$GOOGLE_OAUTH_CLIENT_ID\" --secret-stdin\n```\n\nAuthorize a small Workspace scope set:\n\n```shell\ngum login --service gmail,calendar\ngum doctor\ngum read gmail.users.messages.list --args '{\"userId\":\"me\",\"maxResults\":5}'\n```\n\nFor exact API setup, see [docs/auth-guides](docs/auth-guides/README.md).\n\n## Keep Secrets Out of Prompts\n\ngum stores Google refresh tokens in your OS keychain. It also accepts OAuth\nclient secrets through stdin. That covers gum's own auth path.\n\nYour agent may still need other secrets: API tokens for tests, deploy keys,\nstaging credentials, or service-specific config. Use\n[HASP](https://github.com/gethasp/hasp) for that job. HASP is a local secret\nbroker for coding agents. It stores secrets in an encrypted vault, gives a\ncommand only the values it is allowed to use, and keeps managed secret values\nout of the agent's prompt.\n\nInstall HASP:\n\n```shell\nbrew tap gethasp/homebrew-tap\nbrew install hasp\nhasp setup\n```\n\nRun gum work through a HASP grant when a task needs both Google API access and\nnon-Google secrets:\n\n```shell\nhasp app connect gum-work --cmd 'gum doctor' --install=never\nhasp run --project-root . \\\n  --target gum-work \\\n  --grant-project session \\\n  --grant-secret session \\\n  -- gum doctor\n```\n\nUse three rules:\n\n- Put Google OAuth client secrets into gum with `--secret-stdin`, not in chat.\n- Put project and deploy secrets into HASP, not in `.env` files or prompts.\n- Give agents short-lived HASP grants for the command they need to run.\n\nSee [docs/hasp.md](docs/hasp.md) for the gum + HASP workflow and the safety\nchecklist.\n\n## Which Auth Path Should I Use?\n\n| Use case | Path | Setup |\n| --- | --- | --- |\n| Gmail, Calendar, Drive, Docs, Sheets, Slides, Tasks, YouTube, People, Photos, Chat, Classroom, Meet, Apps Script, Admin, Vault, Search Console, Google Ads | BYO OAuth | `gum auth use-oauth-client`, then `gum login --service \u003cname\u003e` |\n| Automation in Google Cloud | ADC | Set `GOOGLE_APPLICATION_CREDENTIALS` or use a gcloud ADC cache |\n| Maps and Custom Search | API key | `gum auth use-api-key --stdin` |\n| Service-account variants | Service account | `gum auth use-service-account \u003ckey.json\u003e` |\n| Google Ads | BYO OAuth plus developer token | `gum auth use-ads-developer-token`, then `gum login --service googleads` |\n\n## MCP Setup\n\nUse setup when you want gum to write common MCP client config files:\n\n```shell\ngum setup --target all --features skills,mcp --dry-run\ngum setup --target all --features skills,mcp --yes\n```\n\nRun the local server directly:\n\n```shell\ngum mcp --stdio\n```\n\nAdd this server to your MCP client config:\n\n```json\n{\n  \"mcpServers\": {\n    \"gum\": {\n      \"command\": \"gum\",\n      \"args\": [\"mcp\", \"--stdio\"]\n    }\n  }\n}\n```\n\nUse an absolute binary path if another `gum` command is installed on your\nmachine. The Charmbracelet project also uses the name `gum`.\n\ngum exposes a compact meta-tool surface plus selected convenience tools at\nstartup. The meta-tools let clients search, describe, read, write, confirm\ndestructive actions, run bounded code, inspect cache/gain state, and poll\nlong-running work without loading the full catalog into context. The server\nalso exposes `skills_list` and `skills_get` so MCP clients can load the current\nagent guidance from the installed binary. Use `gum mcp --stdio --help`,\n`gum skills list`, and `gum describe \u003cop_id\u003e` for the exact shipped surface.\n\nMore client snippets are in [docs/mcp-client-setup.md](docs/mcp-client-setup.md).\n\n## CLI Basics\n\n```shell\ngum search \"gmail messages\"\ngum describe gmail.users.messages.list\ngum read gmail.users.messages.list --args '{\"userId\":\"me\",\"maxResults\":5}'\ngum write \u003cop_id\u003e --args '\u003cjson\u003e'\ngum destructive \u003cop_id\u003e --args '\u003cjson\u003e'\ngum doctor --format=json\n```\n\nRun `gum init --target claude-code` to patch an MCP config and write a local\n`GUM.md` operator note. It shows the diff before it edits files unless you pass\n`--yes`. New installs should start with `gum setup`; `gum init` remains for\nthe older direct Claude/Cursor patch flow.\n\n## Troubleshooting\n\n### `AUTH_REQUIRED` or `SCOPE_MISSING`\n\nThe active credential cannot satisfy the operation.\n\n```shell\ngum auth status\ngum login --service gmail,calendar\ngum auth probe --scopes gmail.readonly\n```\n\nIf gum says a BYO OAuth client is missing, create a Google Desktop OAuth client\nand run:\n\n```shell\nprintf '%s' \"$GOOGLE_OAUTH_CLIENT_SECRET\" \\\n  | gum auth use-oauth-client --client-id \"$GOOGLE_OAUTH_CLIENT_ID\" --secret-stdin\n```\n\nIf gum says a service needs product setup, OAuth worked but Google rejected the\nrequest for a service-specific reason. Examples include Chat app installation,\nPhotos Library app access, Search Console property verification, and Google Ads\ndeveloper-token approval.\n\n### `RATE_LIMITED`\n\nGoogle returned HTTP 429 or a local rate-limit bucket ran out. gum retries\ntransient 429 responses with jittered backoff. Persistent 429 means the Google\nproject quota is too low.\n\nLower request concurrency, retry later, or raise quota in Google Cloud Console.\n\n### MCP Client Does Not See Tools\n\n1. Run `gum mcp --stdio --help`.\n2. Use an absolute binary path in the MCP config.\n3. Restart the MCP client. Tool registration happens at session start.\n4. Check the client's stderr log for handshake errors.\n\n### Destructive Confirmation Fails\n\nDestructive tokens are single-use. Run the command once without `--confirmed`\nto get a fresh `confirmation_token`, then retry with:\n\n```shell\ngum destructive \u003cop_id\u003e --confirmed --token \u003cconfirmation_token\u003e --args '\u003cjson\u003e'\n```\n\n## Development\n\n```shell\ncd apps/gum\ngo test ./...\n```\n\nUseful release gates:\n\n```shell\nmake test-matrix\nmake coverage-floor\ngo vet ./...\n```\n\nThe embedded catalog is generated under `apps/gum/internal/embedded`:\n\n```shell\ncd apps/gum\ngo run ./cmd/gen-catalog -out internal/embedded/catalog.json\n```\n\n## Repo Layout\n\n```text\napps/gum/                 Go module for the CLI and MCP server\napps/gum/cmd/gum/         Cobra entry point\napps/gum/internal/auth/   BYO OAuth, ADC, API key, service account auth\napps/gum/internal/mcp/    MCP server presentation layer\napps/gum/internal/dispatch/ Shared dispatch kernel\ndocs/auth-guides/         Public Google credential setup guides\ndocs/mcp-client-setup.md  Public MCP client setup\ndocs/                     Public auth, MCP, catalog, plugin, and test references\n```\n\n## Security\n\nSee [SECURITY.md](SECURITY.md).\n\n## License\n\ngum is licensed under FSL-1.1-ALv2. Each release becomes available under\nApache License 2.0 on the second anniversary of that release date. See\n[LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehmo%2Fgum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fehmo%2Fgum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fehmo%2Fgum/lists"}