Google Workspace Directory MCP
Google Workspace Directory MCP
面向生产环境、只读的 MCP 服务,用于范围受限的 Google Workspace 用户查询。它使用 Python、FastMCP Streamable HTTP、Google Admin SDK Directory API、专用服务账号 JSON 凭据、域级委派(DWD)以及来自服务器配置的一个固定委派管理员主体。
该服务仅执行 users.get 和 users.list。它不能创建、更新、暂停、归档、重命名、删除或以其他方式修改用户。
架构与威胁边界
MCP client
-> external TLS and human authentication at Nginx Proxy Manager
-> dedicated ingress network + gateway secret and verified identity headers
-> FastMCP /mcp on 0.0.0.0:8000
-> fixed-subject DWD credential provider
-> Google Admin SDK Directory API (read-only users scope)外部网关对人员进行身份验证,并且必须注入共享网关密钥以及经过验证的调用者身份。应用会验证两者,对身份进行授权,并在每次工具审计事件中将其与生成的请求 ID 一起包含。共享密钥证明请求来自可信的入口路径;它不标识个人,也不能替代网络隔离或外部 TLS。NPM 必须在注入自己的值之前移除客户端提供的这两个请求头副本。
应用在容器内绑定到 0.0.0.0:8000,以便 Docker 和 NPM 可以访问它。Compose 仅在主机上发布 127.0.0.1:8000:8000。Compose 服务使用名为 google-mcp-ingress 的专用外部 Docker 网络;只将 NPM 和此服务附加到该网络。不要使用通用 proxy 网络。
MCP 进程验证输入和允许的电子邮件域,从普通搜索词构造有界的 Google 查询,限制搜索输出,请求部分响应字段,过滤跨域别名,从目录文本中移除控制/格式字符,并返回窄而稳定的模式。目录文本是不可信数据,并在 MCP 服务器/工具指令中明确标记为不可信;客户端不得将名称、别名、路径或查询视为指令。这是信任边界控制,不能替代 MCP 客户端系统级的提示注入防御。
DWD 功能强大:Google 授权 OAuth 客户端和范围,但不强制执行此应用的固定主体选择。持有服务账号私钥的人可以编写不同的代码,选择 DWD 允许的另一个主体。此服务在配置中固定 GOOGLE_DELEGATED_ADMIN,并且绝不接受主体作为工具参数,但这是应用控制,而不是 Google 强制的主体限制。
Related MCP server: gwsadm-mcp
第一阶段工具
google_user_status(email)google_user_search(query, limit=10);query是普通名称/电子邮件片段,硬性上限20google_user_aliases(email)google_user_summary(email)
每个显式电子邮件参数必须属于 GOOGLE_ALLOWED_DOMAINS 之一,不区分大小写比较。返回的别名列表仅包含这些域。辅助 Workspace 域必须显式列出。该服务绝不跟随别名进入另一个域。
已计划但未实现:
google_user_groups(email)需要额外的范围https://www.googleapis.com/auth/admin.directory.group.readonly。
第一阶段不包含任何组范围或组 API 操作。
Google 前置条件
这些是手动的 Google 管理步骤。本仓库不创建云资源或凭据。
为此工作负载创建专用的 Google Cloud 项目。
启用 Admin SDK API(
admin.googleapis.com)。第一阶段不需要其他 Google API。创建专用服务账号并为其启用域委派。
创建或选择专用的 Workspace 委派管理员用户。范围狭窄的自定义管理员角色应授予:
Admin API > Users > Read(
USERS_RETRIEVE)Admin API > Organizational Units > Read(
ORGANIZATION_UNITS_RETRIEVE)
在服务要查询的每个 OU 中分配该角色。不要使用日常超级管理员账号。
在 Admin 控制台中,打开 Security > Access and data control > API controls > Manage Domain Wide Delegation。添加服务账号的 数字 OAuth 客户端 ID,而不是其电子邮件地址。
仅授权此第一阶段范围:
https://www.googleapis.com/auth/admin.directory.user.readonly仅当当前没有无密钥部署方法时才创建 JSON 密钥。立即将其移动到本仓库之外的根/部署所有者控制的目录,设置主机权限(如
chmod 600),限制目录遍历,并记录所有者和轮换计划。经过测试的轮换后撤销旧密钥。
Compose secrets 机制以只读方式挂载主机文件,但不为该源文件提供静态加密。主机存储保护、访问控制、备份处理、事件响应和轮换仍然是必要的。切勿提交、通过电子邮件发送、粘贴到日志中或将密钥烘焙到镜像中。
配置
变量 | 必需 | 含义 |
| 是 | 容器内挂载的 JSON 凭据的绝对路径 |
| 是 | 固定的委派 Workspace 管理员主体 |
| 生产环境中是 | 显式 Directory 客户; |
| 是 | 逗号分隔的 Workspace 域,接受用户和别名 |
| 否 | 必须显式为 |
| 生产环境中是 | 来自可信网关的随机共享密钥;绝不可作为工具参数或日志值 |
| 生产环境中是 | 逗号分隔的授权人员身份 |
| 否 | 标头名称;默认为 |
| 否 | 标头名称;默认为 |
| 否 | 可选的调用者域允许列表;否则使用 |
| 否 | 监听地址;代码中默认为 |
| 否 | 监听端口;默认为 |
| 否 |
|
| 否 | 为 true 时对目标进行 HMAC 假名化 |
| 哈希必需 | 至少 32 个字符;设置时也会对调用者进行假名化 |
| 否 | 默认为 |
| 否 | 默认为 |
| 否 | 默认为 |
| 否 | 默认为 |
正常启动会验证配置和凭据文件路径,然后构造委派凭据。如果配置或凭据初始化失败,它会快速失败并返回经过清理的错误。导入和单元测试不需要凭据。
构建和运行
cd google-mcp
cp .env.example .env
chmod 600 .env
# Edit .env; the host credential path must remain outside this repository.
docker compose config
docker compose build
docker compose up -d本地端点为 http://127.0.0.1:8000/mcp;NPM 应通过专用入口网络使用 http://google-mcp:8000/mcp。在不暴露机密的情况下检查启动:
docker compose ps
docker compose logs --tail=100 google-mcpNPM 位于本仓库之外,未被修改。将以下网络添加到其 Compose 项目中,将 app 附加到它,并在启动两个项目之前创建网络:
services:
app:
networks:
- proxy
- google-mcp-ingress
networks:
google-mcp-ingress:
external: true
name: google-mcp-ingress然后创建一个经过身份验证的 NPM 代理主机,转发到主机名 google-mcp、端口 8000 和路径 /mcp。Streamable HTTP 需要同时转发 POST 和 GET,保留 /mcp 路径而不重写,禁用响应缓冲,并使用足够长的读取/发送超时。示例 NPM 高级配置,仅使用占位符:
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_set_header Connection "";
proxy_set_header X-MCP-Gateway-Secret "REPLACE_WITH_SECRET_FROM_NPM_SECRET_STORE";
proxy_set_header X-Authenticated-User $remote_user;NPM 必须覆盖这些标头,而不是传递客户端值。如果选定的 NPM 认证机制不填充 $remote_user,请使用提供已验证身份标头的 SSO/认证代理;不要将共享网关密钥视为个人调用者身份。不要启用宽松的 CORS。
如果专用网络尚不存在,请在启动任一 Compose 项目之前创建它:
docker network create google-mcp-ingress停止并移除容器/网络,同时保留外部凭据文件:
docker compose downMCP 客户端示例位于 examples/mcp-client.json。其 URL、主机名和令牌是占位符。根据特定客户端和认证网关调整形状。
测试
单元测试模拟 Directory API,绝不联系 Google:
cd google-mcp
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements-dev.txt
pytest -q容器化测试路径避免主机 Python 依赖假设:
docker build --target test -t google-mcp:test .
docker run --rm --user "$(id -u):$(id -g)" --read-only --tmpfs /tmp:size=16m \
-v "$PWD/tests:/app/tests:ro" \
google-mcp:test pytest -q -p no:cacheprovider实时冒烟脚本仅在显式调用时运行。使用以下虚构变量作为占位符,并仅在 shell 中设置真实测试地址,绝不在文件中设置:
export GOOGLE_TEST_USER='known-active-user@example.test'
export GOOGLE_TEST_MISSING_USER='known-missing-user@example.test' # optional
export GOOGLE_TEST_GATEWAY_SECRET='set-only in the shell; never in a file' # required outside test mode
export GOOGLE_TEST_CALLER='agent1@example.org' # required outside test mode
python tests/smoke_mcp.py http://127.0.0.1:8000/mcp它确认精确的第一阶段工具列表,要求已知用户返回 ACTIVE,可选地要求缺失用户返回 NOT_FOUND,并且仅打印状态——不打印完整的用户记录。
稳定的响应模式
google_user_status 仅返回这些状态字段。真正的 Directory API 404 是唯一的 NOT_FOUND 条件。ARCHIVED 优先于 SUSPENDED;所有其他现有用户均为 ACTIVE。Google 的纪元/哨兵最后登录值变为 null 加上 never_logged_in: true。可选字段在禁用时保持为 null。管理员标志默认为 null,除非显式暴露;2SV、最后登录和 OU 字段默认为暴露。
{
"email": "alex.rivera@example.test",
"state": "ACTIVE",
"suspended": false,
"archived": false,
"last_login_time": "2026-08-01T13:45:00.000Z",
"never_logged_in": false,
"org_unit_path": "/Staff/Campus-A",
"is_admin": null,
"is_delegated_admin": null,
"is_enrolled_in_2sv": true,
"is_enforced_in_2sv": true
}对于 NOT_FOUND,布尔字段为 false,可空字段为 null,never_logged_in 为 false,因为不存在可以推断登录历史的账号。
google_user_aliases:
{
"email": "alex.rivera@example.test",
"state": "ACTIVE",
"primary_email": "alex.rivera@example.test",
"aliases": ["a.rivera@example.test"],
"non_editable_aliases": ["alex@example.test"]
}google_user_summary 包含所有状态字段加上 requested_email、display_name、given_name、family_name、aliases 和 non_editable_aliases。它使用一次 users.get 调用。
google_user_search 接受普通人工输入的片段,而不是 Google Directory 查询语法。它安全地构造电子邮件前缀/名称前缀查询或精确的允许域电子邮件查询。
google_user_search:
{
"query": "Alex Rivera",
"limit": 10,
"count": 1,
"truncated": false,
"next_page_available": false,
"users": [
{
"email": "alex.rivera@example.test",
"display_name": "Alex Rivera",
"state": "ACTIVE",
"suspended": false,
"archived": false,
"last_login_time": "2026-08-01T13:45:00.000Z",
"never_logged_in": false,
"org_unit_path": "/Staff/Campus-A"
}
]
}始终使用配置的客户 ID。允许域之外的结果被省略,并使 truncated 为 true。上游页面令牌永远不会暴露;当 truncated 或 next_page_available 为 true 时,调用者应缩小搜索词。搜索词必须为 3..128 个字符,并且不包含控制/格式字符或原始查询语法。超出 1..20 的限制被拒绝,并且只请求一个上游页面。
日志记录和失败行为
每次工具调用都会发出一个结构化的 JSON 审计事件,其中包含 UTC 时间戳、生成的请求 ID、已验证的调用者身份(或 HMAC 假名)、工具、被掩蔽或经 HMAC 假名化的目标、结果状态/计数、延迟以及经过清理的错误类别。该服务不会记录网关机密、访问令牌、凭据内容或路径、私钥、完整的 Google 记录、原始提示、别名、姓名、电话/个人资料数据或 Google 原始错误正文。
只有 HTTP 404 映射为 NOT_FOUND。HTTP 401/403 变为 AUTHORIZATION;429 和符合条件的 5xx(500、502、503、504)最多总共尝试四次,并采用指数退避和抖动。超时和瞬时传输故障同样有界。其他格式错误或上游故障仍保留为明确的清洗后错误。
故障排查
invalid_grant:验证被委派的主体是否存在、未被暂停、位于同一 Workspace 租户中,并且服务器时钟与 NTP 同步。同时验证该凭据是否属于已启用 DWD 的服务账号。unauthorized_client:在 DWD 中使用服务账号的数字 OAuth 客户端 ID,并授权上面显示的确切范围。DWD 更改可能需要一段时间才能生效。403/AUTHORIZATION:验证用户读取和组织单位读取权限、OU 分配范围、API 访问控制、被委派的主体以及 Admin SDK API。仅凭有效的密钥是不够的。缺少范围:将 DWD 条目与
https://www.googleapis.com/auth/admin.directory.user.readonly逐字符比对。第一阶段有意不请求任何群组、云端硬盘、Gmail、日历、角色管理或安全管理范围。被委派主体错误:更正
GOOGLE_DELEGATED_ADMIN;它必须是专用的委派管理员,其角色覆盖所查询的 OU。MCP 调用者无法覆盖它。时钟偏差:同步 Docker 主机时钟。签名的 JWT 断言对时间敏感。
意外出现
NOT_FOUND:确认请求的电子邮件使用配置的允许域,并且是当前未删除的 Directory 用户。授权和速率限制失败绝不会变为NOT_FOUND。
紧急撤销
如果怀疑网关、服务账号或委派身份遭到入侵:
禁用或移除 NPM 路由。
停止 MCP 容器。
如果怀疑入侵,请移除 DWD 客户端条目。
禁用或删除服务账号密钥。
如有需要,禁用委派管理员。
保留并审查网关、应用程序和 Google 审计日志。
WIF 迁移说明
凭据接口是隔离的,因此以后可以添加其他提供商,但此版本仅实现并测试了挂载的服务账号 JSON 密钥。Workload Identity Federation 不被声称受支持。对于 DWD,WIF 不一定是 JSON 密钥的直接替代品:生成 DWD JWT 断言可能需要 IAM Credentials signJwt 权限以及显式的签名/交换逻辑。在移除 JSON 密钥提供商之前,请设计并测试该路径。
google-mcp
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceRead-only MCP server for Google Merchant Center, Google Search Console, Google Drive, Gmail, Calendar, and People API.MIT
- AlicenseAqualityAmaintenanceGoogle Workspace security-audit MCP server — read-only visibility into account locks, suspicious logins, and external file sharing, built on the Admin SDK Reports API (audit activities).14MIT
- AlicenseNot gradedqualityCmaintenanceAn admin-oriented Model Context Protocol server for Google Workspace that lets LLMs perform directory and user lifecycle operations with safety guardrails and audit logging.MIT
- AlicenseNot gradedqualityBmaintenanceSecure, read-only Google Search Console MCP server with exact property allowlists and a hardened TypeScript runtime.12MIT
Related MCP Connectors
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
Federated commerce search across independent WooCommerce merchants. Keyless, read-only MCP server.
Identity resolution MCP server for phone/email lookups across 31+ services. Global + India coverage.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/AngelN-Halo/google-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server