# gws-admin-mcp

**Category:** 🔒 Security  
**Repository:** https://github.com/antct11/gws-admin-mcp  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/gws-admin-mcp

## Description
Safe Google Workspace admin for AI agents: read-only by default, confirm-gated deletes, audit log.

## Claude Desktop Quick Installation
Heuristic fallback — verify the package name and runner against the repository README before running it. Uses `npx` (confidence: low):

```json
"mcpServers": {
  "gws-admin-mcp": {
    "command": "npx",
    "args": ["-y","gws-admin-mcp"]
  }
}
```

## Documentation & README

# gws-admin-mcp

A local **Model Context Protocol (MCP) server** that gives your AI agent
(Cursor, Claude Desktop, or any MCP client) a **safe Google Workspace admin
console**. It talks to the Admin SDK (Directory, Reports, Groups Settings)
through a **service account with domain-wide delegation**, so the agent can
answer questions like "which users haven't logged in for 90 days?" or "who is
in the Finance group?" — and, only when you explicitly allow it, make changes.

```
MCP client ──stdio──► gws-admin-mcp ──service account JWT (impersonates an admin)──► admin.googleapis.com / groupssettings.googleapis.com
```

Runs entirely on your machine. No third-party service, no telemetry, no data
leaves your laptop except the Google API calls themselves.

## Safety model

This server assumes the agent driving it is fallible. Three layers:

1. **Read-only by default.** Out of the box only the 17 read tools are
   registered — write tools are not hidden behind a runtime check, they simply
   *do not exist* in the tool list, so the agent cannot call them. Mutations
   require starting the server with `--allow-write` (or
   `GWS_ADMIN_ALLOW_WRITE=1`).
2. **Confirm gate on destructive calls.** Even with writes enabled, the
   irreversible operations — `users_delete`, `groups_delete`,
   `orgunits_delete`, `role_assignment_delete`, mobile device *wipe* actions,
   and ChromeOS *deprovision* — are refused unless the call includes
   `"confirm": true`. The agent has to make the destructive intent explicit a
   second time.
3. **Audit log.** Every tool call is appended as JSON lines to
   `~/.config/gws-admin-mcp/audit.log` (mode 600), with passwords and secrets
   redacted. Disable with `GWS_ADMIN_AUDIT=0` if you must.

Recommended pattern: run the read-only instance permanently, and start a
second, write-enabled instance only for the duration of a change window.

## Tools (40 total; 17 in read-only mode)

| Area | Read-only tools | Write tools (require `--allow-write`) |
|------|-----------------|----------------------------------------|
| **Users** | `users_list`, `users_get` | `users_create`, `users_update`, `users_suspend`, `users_unsuspend`, `users_reset_password`, `users_make_admin`, `users_move_ou`, `users_delete`* |
| **Groups** | `groups_list`, `groups_get`, `groups_list_members` | `groups_create`, `groups_update`, `groups_delete`*, `groups_add_member`, `groups_remove_member`, `groups_update_member` |
| **Org units** | `orgunits_list`, `orgunits_get` | `orgunits_create`, `orgunits_update`, `orgunits_delete`* |
| **Roles** | `roles_list`, `role_assignments_list` | `role_assignment_create`, `role_assignment_delete`* |
| **Domains / customer** | `domains_list`, `customer_get` | — |
| **Devices** | `devices_list_mobile`, `devices_list_chromeos` | `devices_action_mobile`*, `devices_action_chromeos`*, `devices_move_chromeos` |
| **Reports** | `reports_activities` (audit log), `reports_usage_user`, `reports_usage_customer` | — |
| **Group settings** | `groupsettings_get` | `groupsettings_update` |

\* Destructive — additionally requires `"confirm": true` in the call
(device tools only for wipe/deprovision actions).

List tools auto-paginate up to a `maxResults` cap, and `users_list` supports
the full Admin SDK search syntax (`orgUnitPath='/Sales'`, `isAdmin=true`,
`email:jdoe*`, ...).

## Requirements

- Node.js >= 20
- Super-admin access to a Google Workspace domain (to grant domain-wide
  delegation)
- A Google Cloud project (free — the Admin SDK has no usage cost)

## Google Cloud setup

You need a service account whose key the server uses to impersonate a
Workspace super-admin. Two paths:

### Path A — scripted (needs `gcloud`)

```bash
gcloud auth login admin@yourdomain.com
scripts/setup-service-account.sh admin@yourdomain.com your-project-id
```

The script creates/reuses the project, enables the Admin SDK + Groups
Settings APIs, creates the service account, writes the key and config to
`~/.config/gws-admin-mcp/`, and prints the client ID + scope string for the
final manual step (step 5 below — Google provides no API for that part).

### Path B — manual (Cloud console)

1. **Create a project** at [console.cloud.google.com](https://console.cloud.google.com)
   (or reuse one dedicated to admin tooling).
2. **Enable APIs**: *Admin SDK API* and *Groups Settings API*
   (APIs & Services → Library).
3. **Create a service account** (IAM & Admin → Service Accounts → Create).
   No project-level IAM roles are needed — its power comes entirely from the
   delegation grant in the next steps.
4. **Create a JSON key** for it (Keys tab → Add key → JSON) and save it as
   `~/.config/gws-admin-mcp/service-account.json` with `chmod 600`.
5. **Grant domain-wide delegation** — this is the step people miss:
   - Copy the service account's **OAuth 2 client ID** (a long number, shown on
     the service account details page).
   - In the **Admin console** ([admin.google.com](https://admin.google.com)):
     *Security → Access and data control → API controls → Domain-wide
     delegation → Add new*.
   - Paste the client ID, and paste this exact scope list as one
     comma-separated line:

```
https://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
```

6. **Tell the server which admin to impersonate.** Create
   `~/.config/gws-admin-mcp/config.json`:

```json
{
  "delegatedAdmin": "admin@yourdomain.com",
  "customerId": "my_customer"
}
```

`delegatedAdmin` must be a **super-admin** of the domain. `my_customer`
resolves to that admin's own organization.

Environment variables override the config files: `GOOGLE_SA_KEY` (key path),
`DELEGATED_ADMIN`, `CUSTOMER_ID`, `GWS_ADMIN_CONFIG_DIR` (alternate config
directory). See `.env.example`.

## Build and verify

```bash
npm install
npm run build
node dist/cli.js doctor
```

`doctor` checks the key, mints a delegated token, and runs sample reads
against users, domains, roles, and the audit reports API. All four should say
`PASS`. Then optionally:

```bash
npm run smoke   # spawns the real server over stdio, checks tool registration + live reads
```

## MCP client configuration

### Cursor (`~/.cursor/mcp.json`)

Read-only — the recommended default:

```json
{
  "mcpServers": {
    "gws-admin": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/gws-admin-mcp/dist/cli.js", "serve"]
    }
  }
}
```

Write-enabled (use deliberately, ideally as a second entry you toggle on):

```json
{
  "mcpServers": {
    "gws-admin-write": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/gws-admin-mcp/dist/cli.js", "serve", "--allow-write"]
    }
  }
}
```

### Claude Desktop (`claude_desktop_config.json`)

macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` ·
Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "gws-admin": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/TO/gws-admin-mcp/dist/cli.js", "serve"]
    }
  }
}
```

Restart the client after editing. You should see the `gws-admin` server with
17 tools (read-only) or 40 (write-enabled).

## Troubleshooting

| Symptom | Cause / fix |
|---------|-------------|
| `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. |
| `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. |
| `DELEGATED_ADMIN ... is not set` | Add `delegatedAdmin` to `config.json` or set the `DELEGATED_ADMIN` env var. |
| `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. |
| `404` from Groups Settings calls | The *Groups Settings API* isn't enabled in the project (it's separate from the Admin SDK). |
| Write tools don't appear in the client | Working as intended — start the server with `--allow-write` or `GWS_ADMIN_ALLOW_WRITE=1`. |
| A delete/wipe call returns `Refused: ... destructive/irreversible` | Working as intended — re-issue the call with `"confirm": true`. |
| 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. |

## Security notes

- The service-account key impersonates a **super-admin** with org-wide power.
  Treat `service-account.json` like a domain-admin password: keep it out of
  git (this repo's `.gitignore` already excludes key files, `.env`, and
  `config.json`), keep it `chmod 600`, and rotate it periodically.
- Prefer a dedicated Cloud project for this service account so the key is
  easy to audit and revoke.
- Keep the permanent instance read-only. Enable writes in a separate instance
  only when you actually intend to change things, and turn it off after.

## License & purchase

This repository is **source-available, not open source**: the code is public
so you can read and audit every line before trusting it with a super-admin
credential, but *using* it requires a license.

- **Buy a license ($34):**
  [antchoutine.gumroad.com/l/gws-admin-mcp](https://antchoutine.gumroad.com/l/gws-admin-mcp)
  — perpetual, includes the full write-enabled edition and updates.
- **Try it free:** the read-only edition (17 tools, no mutating code) is on
  npm as [`gws-admin-mcp`](https://www.npmjs.com/package/gws-admin-mcp).

See [LICENSE](LICENSE) for the exact terms (no redistribution, no offering
it as a hosted service).

