google-workspace-admin-mcp
Enables AI agents to safely provision new Google Workspace accounts for employee onboarding, with availability checks, account creation, and credential delivery, all behind OAuth and per-user allowlists.
README
google-workspace-admin-mcp
A create-only Google Workspace admin MCP server for employee onboarding — availability checks, account creation, and credentials delivery behind Google OAuth, a per-user allowlist, and keyless domain-wide delegation.
Overview
google-workspace-admin-mcp exposes a deliberately narrow slice of the Google Workspace Admin SDK as Model Context Protocol (MCP) tools, so an AI onboarding agent (e.g. Claude) can provision new-hire accounts without ever holding broad admin rights. The surface is create-only by design — there are no delete, suspend, or update tools — and temporary passwords are generated server-side and never appear in tool results or logs.
It is built with the official @modelcontextprotocol/sdk, runs as a stateless HTTP service on Cloud Run, restricts access to a configurable Google Workspace domain plus a per-user allowlist, and reaches the Admin SDK through keyless domain-wide delegation (no service-account key ever touches disk).
MCP Tools
| Tool | Description |
|---|---|
check_email_availability |
Verifies a proposed address is free in both Google Workspace and the full Slack member history (including deactivated members). Fails closed: no definitive Slack answer, no availability verdict. |
create_user |
Creates the Workspace account in the configured organizational unit with a server-side temporary password. Refuses any address that has ever been used, per the never-reuse rule. Capped at 3 creations per day. |
send_credentials_email |
Resets the account to a fresh temporary password and emails the credentials to the hire's personal address ahead of day one. |
The never-reuse rule
Google Workspace frees a deleted address after ~20 days, but Slack retains deactivated members forever — which makes Slack the durable source of truth for "has this address ever been used?". src/slackCheck.ts calls users.lookupByEmail with a bot token (users:read.email scope):
ok: truewithuser.deleted: true→ the address was used before (burned)users_not_found→ genuinely free
Fail closed: a missing token, missing scope, rate limit, or any HTTP error throws — availability is never vouched for without a successful Slack check.
Architecture
MCP client (e.g. Claude)
│ HTTPS + Bearer token (Google OAuth)
▼
Cloud Run service (google-workspace-admin-mcp)
┌─────────────────────────────────────────────┐
│ Express HTTP server │
│ ├── /health — health check │
│ ├── /.well-known/... — OAuth discovery │
│ ├── /register — dynamic client │
│ │ registration │
│ └── /mcp — MCP endpoint │
│ │ │
│ ├── verifyGoogleToken() │
│ │ • @ALLOWED_DOMAIN enforcement │
│ │ • ALLOWED_USERS allowlist │
│ │ │
│ ├── Zod input validation (schemas.ts) │
│ ├── Guards: target OU, daily create cap│
│ └── Audit log on every tool call │
└─────────────────────────────────────────────┘
│ keyless DWD (IAM Credentials signJwt)
▼
Google Admin SDK + Gmail API Slack Web API
(create user, send credentials) (never-reuse check)
Key design decisions:
- Create-only surface — the server cannot delete, suspend, or modify existing accounts. The blast radius of a compromised client is limited to creating (capped, audited) accounts.
- Keyless domain-wide delegation — the Cloud Run service account self-signs the delegation JWT via the IAM Credentials
signJwtAPI. No service-account key exists on disk or in the container image. The connecting user's OAuth token only proves identity; it never touches Workspace APIs. - Server-side temporary passwords — generated in
src/tempPassword.tsand delivered only via the credentials email. They never appear in MCP responses, logs, or error messages. - Fail-closed availability — the Slack never-reuse check throws on any non-definitive answer, so an outage can delay onboarding but never hand out a burned address.
- Guard rails — new users land in a configurable organizational unit, creations are capped per day, and Zod schemas validate every tool input at the MCP boundary.
- Rate limiting — 60 requests/min per user on the MCP endpoint; 512 KB JSON body limit.
- Audit logging — every tool call is logged with user, action, and outcome (Cloud Logging on Cloud Run).
Tech Stack
| Layer | Technology |
|---|---|
| Runtime | Node.js 22 (ESM) |
| Language | TypeScript 5 |
| MCP SDK | @modelcontextprotocol/sdk |
| HTTP server | Express 5 |
| Google APIs | googleapis + google-auth-library (keyless DWD) |
| Validation | Zod 4 |
| Tests | node:test (unit tests for every module) |
| Container | Docker (multi-stage) |
| CI | GitHub Actions (CodeQL) + Google Cloud Build (npm audit gate) |
| Hosting | Google Cloud Run |
Getting Started
Prerequisites
- Node.js 22+
- A Google Workspace domain with super-admin access (to configure domain-wide delegation)
- A GCP project with Cloud Run enabled and a Google OAuth 2.0 Web Application client
- A Slack app bot token with the
users:read.emailscope (for the never-reuse check)
Install
git clone https://github.com/micahyee415/google-workspace-admin-mcp
cd google-workspace-admin-mcp
npm install
Configuration
Copy .env.example to .env and fill in the values:
cp .env.example .env
| Variable | Required | Description |
|---|---|---|
ALLOWED_DOMAIN |
Yes | Only verified Google accounts at this domain may connect (default: example.com) |
ALLOWED_USERS |
No | Per-user allowlist on top of the domain check (comma-separated emails). Unset = domain check only. |
DWD_SERVICE_ACCOUNT |
Yes | Service account that self-signs the delegation JWT (keyless, via signJwt) |
GWS_ADMIN_SUBJECT |
Yes | Workspace admin user the DWD service account impersonates |
GOOGLE_CLIENT_ID |
Yes | GCP OAuth 2.0 client ID (per-user sign-in) |
GOOGLE_CLIENT_SECRET |
Yes | GCP OAuth 2.0 client secret |
SLACK_BOT_TOKEN |
Yes | Slack bot token for the never-reuse check (from Secret Manager on Cloud Run) |
TARGET_OU |
No | Organizational unit new users are created into (default: /Employees) |
COMPANY_NAME |
No | Display name used in the credentials email (default: Example Corp) |
CREDENTIALS_FROM |
No | From: address for the credentials email (default: it@<ALLOWED_DOMAIN>) |
PORT |
No | HTTP port (default: 8080; Cloud Run sets this automatically) |
Domain-wide delegation setup: in the Google Admin console, grant the DWD service account's client ID the scopes https://www.googleapis.com/auth/admin.directory.user and https://www.googleapis.com/auth/gmail.send. In GCP, grant the Cloud Run runtime service account roles/iam.serviceAccountTokenCreator on the DWD service account.
Send-as note: if CREDENTIALS_FROM is a group address (e.g. it@your-domain.com) rather than the impersonated admin's mailbox, configure a Gmail send-as alias for that address on the impersonated admin account first — Gmail silently rewrites the From: header otherwise.
Run locally
npm run build
npm start
Run the test suite:
npm test
Deploy to Cloud Run
gcloud builds submit --config cloudbuild.yaml --project your-gcp-project
Cloud Build will:
- Run
npm auditathighseverity — fails the build if high/critical CVEs are found. - Build and push the Docker image.
- Deploy to Cloud Run via
service.yaml(environment variables and theSLACK_BOT_TOKENSecret Manager reference are declared there). - Restore the public-invoker IAM binding —
gcloud run services replaceresets IAM on deploy (authentication is enforced in-app via Google OAuth).
Connecting an MCP Client
Point your MCP client at the Cloud Run service URL:
https://your-service.example.com/mcp
The server implements RFC 8414 OAuth authorization server metadata and RFC 7591 dynamic client registration, so MCP clients that support these standards can auto-discover OAuth settings.
When prompted, authenticate with a Google account in the ALLOWED_DOMAIN domain. If ALLOWED_USERS is set, your email must also be on the allowlist.
Security
- Authentication — every request requires a valid Google OAuth bearer token; only verified
@ALLOWED_DOMAINaccounts (and, if set,ALLOWED_USERSmembers) are accepted, with audience validation against the configured OAuth client. - Least privilege — create-only tool surface; delegation scopes limited to
admin.directory.user+gmail.send; no service-account keys anywhere. - Secret hygiene — temporary passwords are never returned, logged, or embedded in errors; the Slack token lives in Secret Manager, not in the image or env files.
- Guard rails — configurable target OU, daily creation cap, Zod validation at the MCP boundary, fail-closed availability checks, CRLF header-injection guard on personal emails.
- CORS — only
https://claude.aiandhttps://api.claude.aiare accepted as origins. - Dynamic client registration caveat —
/register(RFC 7591) returns the configured OAuth client credentials so MCP clients can complete the Google OAuth flow; Google's registered redirect-URI allowlist is the effective security boundary. Register only trusted callback URIs on the OAuth client, and treat the client as effectively public. - Rate limiting — 60 requests/min per user on the MCP endpoint.
- Security headers —
X-Content-Type-Options: nosniff,X-Frame-Options: DENY,Strict-Transport-Securityon all responses. - Audit logging — every tool call is logged with the calling user, action, and result.
- Dependency scanning —
npm audit --audit-level=highgates every Cloud Build deploy; Dependabot and CodeQL run on GitHub.
License
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。