Skip to main content
ClaudeWave

MCP server for Google Workspace security auditing — login audit, external sharing, daily brief

MCP ServersOfficial Registry0 stars0 forks● PythonMITUpdated today
ClaudeWave Trust Score
87/100
✓ Trusted
Passed
  • ✓Open-source license (MIT)
  • ✓Actively maintained (<30d)
  • ✓Clear description
  • ✓Documented (README)
Last scanned: 10/17/2026
Install in Claude Code / Claude Desktop
Method: UVX (Python) · gwsadm-mcp
Claude Code CLI
claude mcp add gwsadm-mcp -- uvx gwsadm-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "gwsadm-mcp": {
      "command": "uvx",
      "args": ["gwsadm-mcp"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
💡 Package name inferred from the repository name. Verify it exists on PyPI, or clone https://github.com/shigechika/gwsadm-mcp and follow its README.
Use cases

MCP Servers overview

<!-- mcp-name: io.github.shigechika/gwsadm-mcp -->

# gwsadm-mcp

English | [日本語](README.ja.md)

Google Workspace **security-audit** MCP (Model Context Protocol) server —
read-only visibility into account locks, suspicious logins, and external file
sharing, built on the Admin SDK Reports API (audit activities).

Named after the admin-console viewpoint (`gwsadm` = Google Workspace admin),
sibling of [`boxadm-mcp`](https://github.com/shigechika/boxadm-mcp). This is
**not** a general-purpose Workspace MCP: it surfaces risk, it never mutates
anything.

## Features

| Tool | Description |
|------|-------------|
| `health_check` | Server version, config path, and per-domain auth probe — call at session start or after a timeout |
| `login_audit` | Reports API `login` — accounts **auto-disabled by Google** (`account_disabled_*`: leaked password, hijacked, spamming), suspicious logins, failure top-N |
| `gmail_usage_report` | Reports API `customerUsageReports` — daily Gmail send/receive counts per domain, one date at a time, ending yesterday (the API's own UTC-8:00/PST date anchor). Requires the separate `admin.reports.usage.readonly` DWD scope (see Auth model below) — a DIFFERENT grant from `admin.reports.audit.readonly` even though both are Reports API |
| `suspended_accounts` | Directory API — current snapshot of **suspended** accounts (`isSuspended=true`); cross-reference against a downstream IdP (e.g. KeyCloak) to find suspended-but-still-enabled accounts |
| `get_user` | Directory API `users().get` — **one named account's** current state: `suspended` (with reason and time), `archived`, `last_login`, 2SV enrolled/enforced, org unit, creation time, pending password change. The "why can't this person sign in" lookup: one request, no pagination, for an address you already know — unlike `suspended_accounts`, which lists only accounts that ARE suspended, so it can never confirm that a given address is *not* suspended (and once that list exceeds its page cap, absence stops being evidence either way). Needs no scope beyond the one `suspended_accounts` already uses |
| `user_oauth_tokens` | Directory API `tokens().list` — third-party OAuth app grants for **one user**; a compromise vector `login_audit` is blind to, since a previously-granted token needs no fresh login. Domain resolved from the username's suffix, with an optional `domain` override for alias/secondary-domain addresses |
| `user_activity` | Reports API `activities().list` with `userKey=<username>` — everything **one account** did in a window, merged across applications (login, token, user_accounts, drive, groups, calendar, chat, meet, saml by default) newest first. `flags` surfaces the events that change the account's security posture regardless of volume — 2SV enrolled/disabled, recovery email/phone changed, password changed, outbound forwarding, Google's `risky_sensitive_action_*` / `suspicious_login` verdicts, every OAuth `authorize` with client and scopes — because a second factor the attacker enrolled survives a password reset; `ips` lists the distinct source addresses with first/last seen. Google's own `account_disabled_*` / `suspicious_login` verdicts are not served under the account's `userKey` (their actor is Google), so they are fetched the way `login_audit` does and reported under the synthetic application `login_verdicts`. The post-compromise question `login_audit` cannot answer: it sees only the events Google itself raised, domain-wide |
| `ip_activity` | Reports API `activities().list` with `actorIpAddress=<ip>` — every account **one source address** acted as, per domain and application, with the same `flags`. The follow-through after `user_activity` names an attacker's address: did the same source reach other accounts? A spray shows up as `login_failure` counts before it ever succeeds |
| `compromise_sweep` | The Google-side follow-through after **one account** is confirmed compromised, in one call: `activity` (`user_activity`, flags first), `state` / `grants` (`get_user`; OAuth grants with mail / Drive / contacts / admin scopes called out as `risky`), `ips` (`ip_activity` across every domain for the attacker's addresses — given, or taken from the account's own flags — with the account itself excluded), and `gmail`: the settings an attacker leaves behind to keep reading mail (auto-forwarding, forwarding addresses, filters that forward / delete / archive, delegates, send-as and reply-to) plus what the mailbox sent in the window as counts and recipient domains — never a subject or body. `gmail.kind` says whether it could be read at all: `ok` / `partial` (one settings section or the sent summary failed; the rest stands) / `api_disabled` (the Gmail API is off in the service account's own Cloud project) / `no_grant` / `error` — a failure is reported, never read as "nothing found". `highlights` lists the facts to act on, `checklist` what remains to do by hand. Shares `gmail_message_trace`'s `gmail.readonly` DWD scope (every settings read, `delegates.list` included, is served by it — verified live) |
| `drive_external_sharing` | Reports API `drive` — ACL **grants** to external addresses or domains (revocations reported separately) and visibility **transitions** into link/public exposure |
| `drive_doc_activity` | Reports API `drive` with a server-side `doc_id` filter — **one document's** owner, ACL changes, and lifecycle events. Triage companion to `drive_external_sharing`: the owner (an individual vs. a shared drive's name) disambiguates the shared-drive false-positive class, where files created inside a shared drive propagate member ACLs and read as bulk external sharing |
| `shared_drive_membership_changes` | Reports API `drive` (`shared_drive_membership_change`) — who added/removed/re-roled shared-drive members and when, with external classification of the affected member and a client-side drive-name filter |
| `gmail_message_trace` | Gmail API — did a **known** Message-ID reach **specific** mailboxes, and where (inbox/spam/trash/archived)? For each recipient it impersonates that user via DWD and searches their own mailbox. Requires the separate `gmail.readonly` DWD scope (see Auth model below); a domain missing that grant reports a per-recipient error, never a false "not found" |
| `dmarc_rua_summary` | Gmail API — DMARC aggregate (RUA) report pass/fail summary and top reject-candidate source IPs, per domain. Impersonates the domain's configured `dmarc_rua_mailbox` (a real user; default `postmaster@<domain>`), searches it for mail addressed to `dmarc_rua_recipient` (the published `rua=` address, e.g. `postmaster+rua@`; default: the mailbox) and reads the compressed report attachments those messages carry. Shares `gmail_message_trace`'s `gmail.readonly` DWD scope, but unlike that tool this one DOES read attachment content (the report XML), not just metadata — see Auth model below |
| `group_delivery_policy` | Groups Settings API — a Google Group's own posting/delivery policy (`who_can_post`, `allow_external_members`, moderation levels). A group's access control sits **in front of** Gmail delivery: a domain-only posting policy silently drops an external sender's mail before it generates any Gmail delivery event at all, indistinguishable from a delivery failure without reading the policy directly. Requires the separate `apps.groups.settings` DWD scope (see Auth model below) |
| `list_group_members` | Directory API — a Google Group's basic metadata and member roster, resolved directly rather than inferred from who happened to receive one particular message. Requires the separate `admin.directory.group.readonly` and `admin.directory.group.member.readonly` DWD scopes (see Auth model below) |
| `daily_brief` | One-call summary across all configured domains |
| `daily_brief_start` / `daily_brief_result` | Same as `daily_brief`, run in the background: `start` returns a `job_id` immediately, then poll `result(job_id)` until `done`. Use on large tenants where the synchronous call risks the client's ~60s tool-call timeout |

Planned: `dlp_events` (Reports `rules`; requires a Workspace edition with DLP),
`token_events`, `admin_events`.

## Auth model

Service account with **domain-wide delegation (DWD)** impersonating an
audit-capable admin. Fully non-interactive — no browser, no token refresh
rotation — so the server runs unattended (cron, MCP gateway, CI).

Grant **all** of the following DWD scopes on the same service-account client
ID up front, in one setup pass. Adding them one at a time as each tool gets
built is how a scope goes missing until the one tool that needed it starts
degrading — one place, one pass, avoids the trap:

| Scope | Needed by | Missing it |
|-------|-----------|------------|
| `https://www.googleapis.com/auth/admin.reports.audit.readonly` | `login_audit`, `user_activity`, `ip_activity`, `drive_external_sharing`, `drive_doc_activity`, `shared_drive_membership_changes`, `daily_brief*` | those tools degrade to a per-domain error |
| `https://www.googleapis.com/auth/admin.directory.user.readonly` | `suspended_accounts`, `get_user` | those two tools degrade to an error (per-domain for `suspended_accounts`); everything else keeps working |
| `https://www.googleapis.com/auth/admin.directory.user.security` | `user_oauth_tokens` | that tool degrades to a per-domain error; everything else keeps working |

`health_check` needs no scope at all to respond: it is the tool to call when
a grant might be missing — it probes each domain and reports the failing
auth in a structured per-domain result instead of failing itself.

`gmail_usage_report` needs its own separate scope too, despite living under
the same Admin SDK Reports API as the base pass above — the "Usage report"
family (`customerUsageReports`) and the "Audit" activity stream
(`activities().list`, everything else in the base pass) are gated by two
different scopes, and having one does not imply the other:

| Scope | Needed by | Missing it |
|-------|-----------|------------|
| `https://ww

What people ask about gwsadm-mcp

What is shigechika/gwsadm-mcp?

+

shigechika/gwsadm-mcp is mcp servers for the Claude AI ecosystem. MCP server for Google Workspace security auditing — login audit, external sharing, daily brief It has 0 GitHub stars and its last recorded update is dated 2026-10-17.

How do I install gwsadm-mcp?

+

You can install gwsadm-mcp by cloning the repository (https://github.com/shigechika/gwsadm-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is shigechika/gwsadm-mcp safe to use?

+

Our security agent has analyzed shigechika/gwsadm-mcp and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.

Who maintains shigechika/gwsadm-mcp?

+

shigechika/gwsadm-mcp is maintained by shigechika. The last recorded GitHub activity is dated 2026-10-17, with 10 open issues.

Are there alternatives to gwsadm-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy gwsadm-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: shigechika/gwsadm-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/shigechika-gwsadm-mcp)](https://claudewave.com/repo/shigechika-gwsadm-mcp)
<a href="https://claudewave.com/repo/shigechika-gwsadm-mcp"><img src="https://claudewave.com/api/badge/shigechika-gwsadm-mcp" alt="Featured on ClaudeWave: shigechika/gwsadm-mcp" width="320" height="64" /></a>

More MCP Servers

gwsadm-mcp alternatives