# Reported issues for Google Workspace Admin Security-Audit MCP

Pod holds 12 of 12 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to [Google Workspace Admin Security-Audit MCP](/mcp/google-workspace-admin-security-audit-mcp).

## Most discussed

### perf: daily_brief still exceeds the ~60s claude.ai gateway timeout on large tenants even after parallelization (#8)

## Problem

After #8 (parallel Reports-API fetches, released in **0.3.0**), `daily_brief` at its **default parameters** (`hours=24`, `max_pages=5`) still exceeds the claude.ai remote-MCP gateway's ~60s per-request timeout on a large tenant, so the call fails / the gateway falls back to invoking the sub-tools individually.

Confirmed the running server is the parallelized build, so this is a **scale limit, not a stale version**:

- `health_check` → `version: 0.3.0`, `status: healthy`, both domain

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/10) · 2026-07-10 · closed · 4 comments

### Add a per-user lookup (users.get) — account status is only reachable by enumerating the domain

## Problem

There is no way to ask about **one** user. To answer "is this address suspended?" the only
option today is `suspended_accounts`, which enumerates the whole domain and stops at
`max_pages`. On a large tenant that cap is hit long before the address of interest, so the
question comes back unanswerable — while the caller already knows the exact address.

Of the 13 tools, the only per-user one is `user_oauth_tokens(username)`, which covers OAuth
grants rather than account state. `login_au

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/68) · 2026-08-14 · closed · 1 comment

### Add group-membership lookup (list_group_members) so gmail_message_trace can resolve ML/Group addresses

## Problem

`gmail_message_trace` impersonates a recipient via domain-wide delegation
(DWD subject) to search that user's own mailbox. This only works for a
real individual mailbox — DWD `subject=` cannot impersonate a Google Group
/ mailing list, since there is no mailbox behind it.

In practice this surfaced as two different, confusing auth errors from
`find_message_by_id` depending on the address:

- A nonexistent address → `invalid_grant: Invalid email or User ID`
- A real Google Group addre

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/56) · 2026-08-06 · open · 1 comment

### perf: parallelize get_group/list_group_members in the list_group_members MCP tool

## Background

Raised by \`/code-review\` on PR #58: \`get_group()\` and \`list_group_members()\` are documented as fully independent calls under different DWD scopes (\`admin.directory.group.readonly\` vs \`admin.directory.group.member.readonly\`), and the \`list_group_members\` MCP tool already calls both unconditionally and degrades per-section — but it calls them **sequentially**, not in parallel.

\`gmail_message_trace\` elsewhere in this same file already parallelizes independent per-recip

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/59) · 2026-08-07 · open · 0 comments

### Add a live smoke test that exercises every registered tool

## Motivation

Unit tests check logic against fixtures. They cannot tell you that a tool users actually call has stopped returning real data — a tool that exists but does not work is worse than no tool.

This happened for real in `jquants-mcp`: the earnings-calendar tools returned well-formed **empty** results for every query while the whole suite stayed green (shigechika/jquants-mcp#523). A live smoke test was built there to close the gap, and on its first production run it found three defects,

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/35) · 2026-07-25 · closed · 0 comments

### feat: drive_doc_activity — per-document owner + ACL/event history for triaging external-sharing findings

## Motivation

`drive_external_sharing` / `daily_brief` surface findings like *\"external actor X bulk-granted N documents to external target Y\"*, but triaging such a finding requires answers the current tools cannot give:

1. **Who owns the document?** (individual user vs. a shared drive — completely changes the risk read)
2. **Full ACL/event history of the document** (when was it created, by whom, who was granted access over time)
3. **Shared-drive membership history** (when/by whom was the e

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/30) · 2026-07-24 · closed · 0 comments

### refactor: extract the HttpError/GoogleAuthError/transport error-mapping block shared by all API methods

From the PR #23 code review (finding 8/10).

The except-chain mapping `HttpError → GwsError` (with the two-step status extraction), `GoogleAuthError → GwsAuthError`, and `httplib2.HttpLib2Error/OSError → transport GwsError` now exists verbatim in three methods (`fetch_activities`, `list_suspended_users`, `list_user_oauth_tokens`), and `check()` repeats the status extraction a fourth time.

A fix to the status extraction, or handling for a newly discovered exception type (e.g. `ssl.SSLError` not 

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/25) · 2026-07-14 · open · 0 comments

### refactor: consolidate per-scope service builders into a scope-keyed registry

From the PR #23 code review (finding 7/10).

`_reports_service()`, `_directory_service()`, and `_directory_security_service()` are three near-verbatim copies of the same double-checked-lock credentials+build block, differing only in the scope constant and the two attribute names they cache into. Callers must also hand-pair the right service with the right creds attribute when calling `_new_http(...)`, and `_new_http`'s `creds = creds or self._creds` fallback silently signs with the REPORTS-scope

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/24) · 2026-07-14 · open · 0 comments

## Most recent

### suspended_accounts: default max_pages=20 (10k users) may truncate large suspended-alumni sets

Follow-up from the review of #17.

`suspended_accounts` defaults to `max_pages=20` → 500×20 = 10,000 accounts. A tenant with many years of suspended alumni can exceed that; the result is truncated with `capped=true`.

`capped` surfaces it, so this is not silent, but a caller that ignores `capped` would undercount. Consider documenting the recommended `max_pages` for reconciliation sweeps, or raising the default. Low priority.

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/21) · 2026-07-13 · open · 0 comments

### refactor: extract shared _build_service() for reports and directory clients

Follow-up from the review of #17.

`_directory_service()` is ~15 lines nearly identical to `_reports_service()` (credential load, `build()`, key-path-safe error mapping), differing only in scope/api/version. Consider extracting `_build_service(scope, api, version)` to remove the duplication. Low priority — the explicit style is readable as-is.

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/20) · 2026-07-13 · open · 0 comments

### test: assert suspended_accounts sends maxResults/projection/orderBy

Follow-up from the review of #17.

`test_list_suspended_users_paginates_and_passes_params` asserts `domain`, `query=isSuspended=true`, and `pageToken`, but not `maxResults=500`, `projection=basic`, or `orderBy=email`.

`projection=basic` is what makes `suspensionReason` / `lastLoginTime` / `orgUnitPath` available to `_suspended_entry`; a regression dropping it would pass the test yet return sparse records. Add assertions for these params.

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/19) · 2026-07-13 · open · 0 comments

### robustness: _new_http creds fallback can authorize a directory request with reports creds

Follow-up from the review of #17.

`_new_http(self, creds=None)` resolves `creds = creds or self._creds`. `list_suspended_users` calls `self._new_http(self._directory_creds)`. If `self._directory_creds` were ever `None` while the reports creds exist, the directory request would be authorized with the **reports-scoped** credentials (wrong scope).

Currently unreachable in production (`_directory_service()` always sets `self._directory_creds` before the `_new_http` call), so this is a latent footg

[Read the thread](https://github.com/shigechika/gwsadm-mcp/issues/18) · 2026-07-13 · open · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/shigechika/gwsadm-mcp/issues).
