{
  "markdown": "# gws-admin-mcp\n\nA local **Model Context Protocol (MCP) server** that gives your AI agent\n(Cursor, Claude Desktop, or any MCP client) a **safe Google Workspace admin\nconsole**. It talks to the Admin SDK (Directory, Reports, Groups Settings)\nthrough a **service account with domain-wide delegation**, so the agent can\nanswer questions like \"which users haven't logged in for 90 days?\" or \"who is\nin the Finance group?\" — and, only when you explicitly allow it, make changes.\n\n```\nMCP client ──stdio──► gws-admin-mcp ──service account JWT (impersonates an admin)──► admin.googleapis.com / groupssettings.googleapis.com\n```\n\nRuns entirely on your machine. No third-party service, no telemetry, no data\nleaves your laptop except the Google API calls themselves.\n\n## Safety model\n\nThis server assumes the agent driving it is fallible. Three layers:\n\n1. **Read-only by default.** Out of the box only the 17 read tools are\n   registered — write tools are not hidden behind a runtime check, they simply\n   *do not exist* in the tool list, so the agent cannot call them. Mutations\n   require starting the server with `--allow-write` (or\n   `GWS_ADMIN_ALLOW_WRITE=1`).\n2. **Confirm gate on destructive calls.** Even with writes enabled, the\n   irreversible operations — `users_delete`, `groups_delete`,\n   `orgunits_delete`, `role_assignment_delete`, mobile device *wipe* actions,\n   and ChromeOS *deprovision* — are refused unless the call includes\n   `\"confirm\": true`. The agent has to make the destructive intent explicit a\n   second time.\n3. **Audit log.** Every tool call is appended as JSON lines to\n   `~/.config/gws-admin-mcp/audit.log` (mode 600), with passwords and secrets\n   redacted. Disable with `GWS_ADMIN_AUDIT=0` if you must.\n\nRecommended pattern: run the read-only instance permanently, and start a\nsecond, write-enabled instance only for the duration of a change window.\n\n## Tools (40 total; 17 in read-only mode)\n\n| Area | Read-only tools | Write tools (require `--allow-write`) |\n|------|-----------------|----------------------------------------|\n| **Users** | `users_list`, `users_get` | `users_create`, `users_update`, `users_suspend`, `users_unsuspend`, `users_reset_password`, `users_make_admin`, `users_move_ou`, `users_delete`* |\n| **Groups** | `groups_list`, `groups_get`, `groups_list_members` | `groups_create`, `groups_update`, `groups_delete`*, `groups_add_member`, `groups_remove_member`, `groups_update_member` |\n| **Org units** | `orgunits_list`, `orgunits_get` | `orgunits_create`, `orgunits_update`, `orgunits_delete`* |\n| **Roles** | `roles_list`, `role_assignments_list` | `role_assignment_create`, `role_assignment_delete`* |\n| **Domains / customer** | `domains_list`, `customer_get` | — |\n| **Devices** | `devices_list_mobile`, `devices_list_chromeos` | `devices_action_mobile`*, `devices_action_chromeos`*, `devices_move_chromeos` |\n| **Reports** | `reports_activities` (audit log), `reports_usage_user`, `reports_usage_customer` | — |\n| **Group settings** | `groupsettings_get` | `groupsettings_update` |\n\n\\* Destructive — additionally requires `\"confirm\": true` in the call\n(device tools only for wipe/deprovision actions).\n\nList tools auto-paginate up to a `maxResults` cap, and `users_list` supports\nthe full Admin SDK search syntax (`orgUnitPath='/Sales'`, `isAdmin=true`,\n`email:jdoe*`, ...).\n\n## Requirements\n\n- Node.js >= 20\n- Super-admin access to a Google Workspace domain (to grant domain-wide\n  delegation)\n- A Google Cloud project (free — the Admin SDK has no usage cost)\n\n## Google Cloud setup\n\nYou need a service account whose key the server uses to impersonate a\nWorkspace super-admin. Two paths:\n\n### Path A — scripted (needs `gcloud`)\n\n```bash\ngcloud auth login admin@yourdomain.com\nscripts/setup-service-account.sh admin@yourdomain.com your-project-id\n```\n\nThe script creates/reuses the project, enables the Admin SDK + Groups\nSettings APIs, creates the service account, writes the key and config to\n`~/.config/gws-admin-mcp/`, and prints the client ID + scope string for the\nfinal manual step (step 5 below — Google provides no API for that part).\n\n### Path B — manual (Cloud console)\n\n1. **Create a project** at [console.cloud.google.com](https://console.cloud.google.com)\n   (or reuse one dedicated to admin tooling).\n2. **Enable APIs**: *Admin SDK API* and *Groups Settings API*\n   (APIs & Services → Library).\n3. **Create a service account** (IAM & Admin → Service Accounts → Create).\n   No project-level IAM roles are needed — its power comes entirely from the\n   delegation grant in the next steps.\n4. **Create a JSON key** for it (Keys tab → Add key → JSON) and save it as\n   `~/.config/gws-admin-mcp/service-account.json` with `chmod 600`.\n5. **Grant domain-wide delegation** — this is the step people miss:\n   - Copy the service account's **OAuth 2 client ID** (a long number, shown on\n     the service account details page).\n   - In the **Admin console** ([admin.google.com](https://admin.google.com)):\n     *Security → Access and data control → API controls → Domain-wide\n     delegation → Add new*.\n   - Paste the client ID, and paste this exact scope list as one\n     comma-separated line:\n\n```\nhttps://www.googleapis.com/auth/admin.directory.user,https://www.googleapis.com/auth/admin.directory.group,https://www.googleapis.com/auth/admin.directory.group.member,https://www.googleapis.com/auth/admin.directory.orgunit,https://www.googleapis.com/auth/admin.directory.rolemanagement,https://www.googleapis.com/auth/admin.directory.domain.readonly,https://www.googleapis.com/auth/admin.directory.customer.readonly,https://www.googleapis.com/auth/admin.directory.device.mobile,https://www.googleapis.com/auth/admin.directory.device.chromeos,https://www.googleapis.com/auth/admin.reports.audit.readonly,https://www.googleapis.com/auth/admin.reports.usage.readonly,https://www.googleapis.com/auth/apps.groups.settings\n```\n\n6. **Tell the server which admin to impersonate.** Create\n   `~/.config/gws-admin-mcp/config.json`:\n\n```json\n{\n  \"delegatedAdmin\": \"admin@yourdomain.com\",\n  \"customerId\": \"my_customer\"\n}\n```\n\n`delegatedAdmin` must be a **super-admin** of the domain. `my_customer`\nresolves to that admin's own organization.\n\nEnvironment variables override the config files: `GOOGLE_SA_KEY` (key path),\n`DELEGATED_ADMIN`, `CUSTOMER_ID`, `GWS_ADMIN_CONFIG_DIR` (alternate config\ndirectory). See `.env.example`.\n\n## Build and verify\n\n```bash\nnpm install\nnpm run build\nnode dist/cli.js doctor\n```\n\n`doctor` checks the key, mints a delegated token, and runs sample reads\nagainst users, domains, roles, and the audit reports API. All four should say\n`PASS`. Then optionally:\n\n```bash\nnpm run smoke   # spawns the real server over stdio, checks tool registration + live reads\n```\n\n## MCP client configuration\n\n### Cursor (`~/.cursor/mcp.json`)\n\nRead-only — the recommended default:\n\n```json\n{\n  \"mcpServers\": {\n    \"gws-admin\": {\n      \"command\": \"node\",\n      \"args\": [\"/ABSOLUTE/PATH/TO/gws-admin-mcp/dist/cli.js\", \"serve\"]\n    }\n  }\n}\n```\n\nWrite-enabled (use deliberately, ideally as a second entry you toggle on):\n\n```json\n{\n  \"mcpServers\": {\n    \"gws-admin-write\": {\n      \"command\": \"node\",\n      \"args\": [\"/ABSOLUTE/PATH/TO/gws-admin-mcp/dist/cli.js\", \"serve\", \"--allow-write\"]\n    }\n  }\n}\n```\n\n### Claude Desktop (`claude_desktop_config.json`)\n\nmacOS: `~/Library/Application Support/Claude/claude_desktop_config.json` ·\nWindows: `%APPDATA%\\Claude\\claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"gws-admin\": {\n      \"command\": \"node\",\n      \"args\": [\"/ABSOLUTE/PATH/TO/gws-admin-mcp/dist/cli.js\", \"serve\"]\n    }\n  }\n}\n```\n\nRestart the client after editing. You should see the `gws-admin` server with\n17 tools (read-only) or 40 (write-enabled).\n\n## Troubleshooting\n\n| Symptom | Cause / fix |\n|---------|-------------|\n| `unauthorized_client` when minting a token | The domain-wide delegation grant is missing, uses the wrong client ID, or its scope list doesn't cover every scope the server requests. Re-paste the full scope string from above against the SA's OAuth2 client ID. Grants can take a few minutes to propagate. |\n| `Service-account key not found at ...` | Put the JSON key at `~/.config/gws-admin-mcp/service-account.json` or set `GOOGLE_SA_KEY` to its path. |\n| `DELEGATED_ADMIN ... is not set` | Add `delegatedAdmin` to `config.json` or set the `DELEGATED_ADMIN` env var. |\n| `403 Not Authorized to access this resource/api` | The impersonated user is not a super-admin, or the Admin SDK API isn't enabled in the Cloud project. |\n| `404` from Groups Settings calls | The *Groups Settings API* isn't enabled in the project (it's separate from the Admin SDK). |\n| Write tools don't appear in the client | Working as intended — start the server with `--allow-write` or `GWS_ADMIN_ALLOW_WRITE=1`. |\n| A delete/wipe call returns `Refused: ... destructive/irreversible` | Working as intended — re-issue the call with `\"confirm\": true`. |\n| Client shows the server as failed on startup | Run `node dist/cli.js doctor` in a terminal; it prints the exact failing check. Also confirm the `args` path in your MCP config is absolute. |\n\n## Security notes\n\n- The service-account key impersonates a **super-admin** with org-wide power.\n  Treat `service-account.json` like a domain-admin password: keep it out of\n  git (this repo's `.gitignore` already excludes key files, `.env`, and\n  `config.json`), keep it `chmod 600`, and rotate it periodically.\n- Prefer a dedicated Cloud project for this service account so the key is\n  easy to audit and revoke.\n- Keep the permanent instance read-only. Enable writes in a separate instance\n  only when you actually intend to change things, and turn it off after.\n\n## License & purchase\n\nThis repository is **source-available, not open source**: the code is public\nso you can read and audit every line before trusting it with a super-admin\ncredential, but *using* it requires a license.\n\n- **Buy a license ($34):**\n  [antchoutine.gumroad.com/l/gws-admin-mcp](https://antchoutine.gumroad.com/l/gws-admin-mcp)\n  — perpetual, includes the full write-enabled edition and updates.\n- **Try it free:** the read-only edition (17 tools, no mutating code) is on\n  npm as [`gws-admin-mcp`](https://www.npmjs.com/package/gws-admin-mcp).\n\nSee [LICENSE](LICENSE) for the exact terms (no redistribution, no offering\nit as a hosted service).\n",
  "bytes": 10346,
  "sha": "edb9aef02e06eaf9a823408cafee917510cb2b6305a1362424f1d256b27b64ee",
  "repo_slug": "antct11/gws-admin-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_antct11_gws_admin_mcp_bd3c187d/readme"
}