Skip to main content
Glama
AngelN-Halo

Google Workspace Directory MCP

by AngelN-Halo

Google Workspace Directory MCP

Servicio MCP de solo lectura, orientado a producción, para consultas de usuarios de Google Workspace con un alcance restringido. Utiliza Python, FastMCP Streamable HTTP, la Google Admin SDK Directory API, una credencial JSON dedicada de cuenta de servicio, Domain-Wide Delegation (DWD) y un único sujeto administrador delegado fijo proveniente de la configuración del servidor.

El servicio solo realiza users.get y users.list. No puede crear, actualizar, suspender, archivar, renombrar, eliminar ni modificar usuarios de ninguna otra forma.

Arquitectura y límite de amenazas

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)

La puerta de enlace externa (gateway) autentica a la persona y debe inyectar un secreto de puerta de enlace compartido además de una identidad de llamante verificada. La aplicación verifica ambos, autoriza la identidad y la incluye, junto con un ID de solicitud generado, en cada evento de auditoría de herramienta. El secreto compartido demuestra que la solicitud llegó a través de la ruta de ingreso de confianza; no identifica a un individuo y no sustituye al aislamiento de red ni al TLS externo. NPM debe eliminar las copias de ambas cabeceras suministradas por el cliente antes de inyectar sus propios valores.

La aplicación se vincula a 0.0.0.0:8000 dentro del contenedor para que Docker y NPM puedan alcanzarla. Compose publica solo 127.0.0.1:8000:8000 en el host. El servicio de Compose utiliza una red externa dedicada de Docker llamada google-mcp-ingress; conecte únicamente NPM y este servicio a esa red. No utilice la red genérica proxy.

El proceso MCP valida la entrada y los dominios de correo permitidos, construye consultas acotadas de Google a partir de términos de búsqueda simples, limita la salida de la búsqueda, solicita campos de respuesta parciales, filtra los alias entre dominios, elimina los caracteres de control/formato del texto del directorio y devuelve esquemas estables y reducidos. El texto del directorio son datos no confiables y se marcan explícitamente como tales en las instrucciones del servidor/herramienta MCP; los clientes no deben tratar nombres, alias, rutas ni consultas como instrucciones. Este es un control de límite de confianza, no un sustituto de las defensas a nivel de sistema del cliente MCP contra la inyección de instrucciones (prompt injection).

DWD es potente: Google autoriza el cliente OAuth y los ámbitos (scopes), pero no impone la elección de sujeto fijo de esta aplicación. Quien posea la clave privada de la cuenta de servicio puede escribir otro código que elija otro sujeto permitido por DWD. Este servicio fija GOOGLE_DELEGATED_ADMIN en la configuración y nunca acepta el sujeto como argumento de herramienta, pero se trata de un control de la aplicación, no de una restricción de sujeto impuesta por Google.

Related MCP server: gwsadm-mcp

Herramientas de la fase uno

  • google_user_status(email)

  • google_user_search(query, limit=10); query es un fragmento simple de nombre/correo; máximo estricto 20

  • google_user_aliases(email)

  • google_user_summary(email)

Cada argumento de correo explícito debe pertenecer a uno de los dominios de GOOGLE_ALLOWED_DOMAINS, comparado sin distinguir entre mayúsculas y minúsculas. Las listas de alias devueltas contienen solo esos dominios. Los dominios secundarios de Workspace deben indicarse explícitamente. El servicio nunca sigue un alias hacia otro dominio.

Previsto, no implementado:

  • google_user_groups(email) requiere el ámbito adicional https://www.googleapis.com/auth/admin.directory.group.readonly.

En la fase uno no hay ningún ámbito de grupos ni operación de API de grupos.

Requisitos previos de Google

Estos son pasos manuales de administración de Google. Este repositorio no crea recursos en la nube ni credenciales.

  1. Cree un proyecto de Google Cloud dedicado para esta carga de trabajo.

  2. Habilite la Admin SDK API (admin.googleapis.com). La fase uno no requiere ninguna otra API de Google.

  3. Cree una cuenta de servicio dedicada y habilite la Domain-Wide Delegation para ella.

  4. Cree o seleccione un usuario administrador delegado dedicado de Workspace. Un rol de administrador personalizado con un alcance reducido debería conceder:

    • Admin API > Users > Read (USERS_RETRIEVE)

    • Admin API > Organizational Units > Read (ORGANIZATION_UNITS_RETRIEVE)

  5. Asigne ese rol en todas las unidades organizativas (OU) que el servicio debe consultar. No utilice una cuenta de superadministrador de uso diario.

  6. En la consola de administración, abra Security > Access and data control > API controls > Manage Domain Wide Delegation. Añada el ID de cliente OAuth numérico de la cuenta de servicio, no su dirección de correo.

  7. Autorice exactamente este ámbito de la fase uno:

    https://www.googleapis.com/auth/admin.directory.user.readonly
  8. Cree una clave JSON solo si no hay actualmente disponible un método de despliegue sin claves. Muévala de inmediato a un directorio controlado por el propietario raíz/de la implementación, fuera de este repositorio, establezca permisos de host como chmod 600, restrinja el recorrido de directorios y documente un propietario y un calendario de rotación. Revogue la clave anterior después de una rotación probada.

El mecanismo secrets de Compose monta el archivo del host en modo de solo lectura, pero no proporciona cifrado en reposo para ese archivo de origen. Siguen siendo necesarias las protecciones de almacenamiento del host, el control de acceso, la gestión de copias de seguridad, la respuesta a incidentes y la rotación. Nunca confirme la clave en un repositorio (commit), la envíe por correo, la pegue en los registros (logs) ni la incruste en una imagen.

Configuración

Variable

Requerida

Significado

GOOGLE_SERVICE_ACCOUNT_FILE

Ruta absoluta dentro del contenedor hasta la credencial JSON montada

GOOGLE_DELEGATED_ADMIN

Sujeto administrador delegado fijo de Workspace

GOOGLE_CUSTOMER_ID

sí en producción

Cliente de Directorio explícito; my_customer solo se permite en modo de prueba explícito

GOOGLE_ALLOWED_DOMAINS

Dominios de Workspace separados por comas aceptados para usuarios y alias

GOOGLE_MCP_TEST_MODE

no

Debe ser explícitamente true para la configuración unitaria/de prueba sin autenticación de puerta de enlace

GOOGLE_MCP_GATEWAY_SECRET

sí en producción

Secreto compartido aleatorio de la puerta de enlace de confianza; nunca un argumento de herramienta ni un valor de registro

GOOGLE_MCP_AUTHORIZED_USERS

sí en producción

Identidades humanas autorizadas separadas por comas

GOOGLE_MCP_GATEWAY_SECRET_HEADER

no

Nombre de la cabecera; por defecto X-MCP-Gateway-Secret

GOOGLE_MCP_IDENTITY_HEADER

no

Nombre de la cabecera; por defecto X-Authenticated-User

GOOGLE_MCP_CALLER_DOMAINS

no

Lista de permitidos opcional de dominios del llamante; de lo contrario, usa GOOGLE_ALLOWED_DOMAINS

GOOGLE_MCP_HOST

no

Dirección de escucha; por defecto 0.0.0.0 en el código

GOOGLE_MCP_PORT

no

Puerto de escucha; por defecto 8000

GOOGLE_MCP_LOG_LEVEL

no

CRITICAL, ERROR, WARNING, INFO o DEBUG

AUDIT_HASH_TARGETS

no

Seudonimiza los objetivos mediante HMAC cuando es true

AUDIT_HMAC_KEY

requerida para el hash

Al menos 32 caracteres; también seudonimiza a los llamantes cuando se establece

GOOGLE_EXPOSE_ADMIN_FLAGS

no

Por defecto false; los campos deshabilitados se devuelven como null

GOOGLE_EXPOSE_2SV_FLAGS

no

Por defecto true

GOOGLE_EXPOSE_LAST_LOGIN

no

Por defecto true

GOOGLE_EXPOSE_ORG_UNIT

no

Por defecto true

El arranque normal valida la configuración y la ruta del archivo de credenciales y, a continuación, construye las credenciales delegadas. Falla rápidamente con un error saneado si falla la configuración o la inicialización de las credenciales. Las importaciones y las pruebas unitarias no requieren credenciales.

Compilación y ejecución

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

El punto de conexión local es http://127.0.0.1:8000/mcp; NPM debe usar http://google-mcp:8000/mcp a través de la red de ingreso dedicada. Inspeccione el arranque sin exponer secretos:

docker compose ps
docker compose logs --tail=100 google-mcp

NPM está fuera de este repositorio y no ha sido modificado. Añada la siguiente red a su proyecto de Compose, conecte app a ella y cree la red antes de iniciar ambos proyectos:

services:
  app:
    networks:
      - proxy
      - google-mcp-ingress

networks:
  google-mcp-ingress:
    external: true
    name: google-mcp-ingress

A continuación, cree un Proxy Host autenticado de NPM que reenvíe al hostname google-mcp, puerto 8000 y ruta /mcp. Streamable HTTP requiere reenviar tanto POST como GET, conservando la ruta /mcp sin reescribirla, deshabilitando el almacenamiento en búfer de la respuesta y usando tiempos de espera de lectura/envío suficientemente largos. Ejemplo de configuración avanzada de NPM, usando solo marcadores de posición:

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 debe sobrescribir estas cabeceras, no reenviar los valores del cliente. Si el mecanismo de autenticación de NPM seleccionado no rellena $remote_user, use un proxy de SSO/autenticación que suministre una cabecera de identidad verificada; no trate el secreto compartido de la puerta de enlace como la identidad individual del llamante. No habilite un CORS permisivo.

Si la red dedicada aún no existe, créela antes de iniciar cualquiera de los dos proyectos de Compose:

docker network create google-mcp-ingress

Detenga y elimine el contenedor/la red conservando el archivo de credenciales externo:

docker compose down

Hay un ejemplo de cliente MCP en examples/mcp-client.json. Su URL, hostname y token son marcadores de posición. Adapte la forma al cliente y a la puerta de enlace de autenticación específicos.

Pruebas

Las pruebas unitarias simulan (mock) la API de Directorio y nunca contactan con Google:

cd google-mcp
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -r requirements-dev.txt
pytest -q

La ruta de pruebas en contenedor evita suposiciones sobre las dependencias de Python del host:

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

El script de prueba de humo (smoke test) en vivo solo se ejecuta cuando se invoca explícitamente. Use variables ficticias a continuación como marcadores de posición y establezca las direcciones de prueba reales solo en el shell, nunca en archivos:

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

Confirma la lista exacta de herramientas de la fase uno, exige que el usuario conocido devuelva ACTIVE, exige opcionalmente que el usuario inexistente devuelva NOT_FOUND, e imprime solo estados—no registros completos de usuario.

Esquemas de respuesta estables

google_user_status devuelve exactamente estos campos de estado. Un 404 genuino de la API de Directorio es la única condición de NOT_FOUND. ARCHIVED tiene prioridad sobre SUSPENDED; todos los demás usuarios existentes son ACTIVE. El valor de epoch/sentinel del último inicio de sesión de Google se convierte en null, junto con never_logged_in: true. Los campos opcionales permanecen presentes como null cuando están deshabilitados. Los indicadores de administrador tienen por defecto null a menos que se expongan explícitamente; los campos de 2SV, último inicio de sesión y OU están expuestos por defecto.

{
  "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
}

Para NOT_FOUND, los campos booleanos son false, los campos anulables son null, y never_logged_in es false porque no existe ninguna cuenta de la que inferir el historial de inicio de sesión.

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 incluye todos los campos de estado más requested_email, display_name, given_name, family_name, aliases y non_editable_aliases. Utiliza una llamada users.get.

google_user_search acepta un fragmento simple introducido por una persona, no la sintaxis de consulta de Google Directory. Construye de forma segura una consulta de prefijo de correo/prefijo de nombre o una consulta exacta de correo de dominio permitido.

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"
    }
  ]
}

El ID de cliente configurado se usa siempre. Los resultados fuera de los dominios permitidos se omiten y hacen que truncated sea true. El token de página ascendente nunca se expone; los llamantes deben acotar el término cuando truncated o next_page_available sea true. Los términos deben tener entre 3 y 128 caracteres y no contener caracteres de control/formato ni sintaxis de consulta sin procesar. Los límites fuera de 1..20 se rechazan, y solo se solicita una página ascendente.

Registro y comportamiento ante fallos

Cada llamada a herramienta emite un evento de auditoría JSON estructurado que contiene la marca de tiempo UTC, el ID de solicitud generado, la identidad del llamante verificada (o seudónimo HMAC), la herramienta, el objetivo enmascarado o seudonimizado con HMAC, el estado/recuento del resultado, la latencia y la categoría de error saneada. El servicio no registra secretos de puerta de enlace, tokens de acceso, contenidos o rutas de credenciales, claves privadas, registros completos de Google, prompts sin procesar, alias, nombres, datos de teléfono/perfil ni cuerpos de error sin procesar de Google.

Solo el HTTP 404 se asigna a NOT_FOUND. Los HTTP 401/403 se convierten en AUTHORIZATION; el 429 y los 5xx elegibles (500, 502, 503, 504) reciben como máximo cuatro intentos en total con retroceso exponencial y fluctuación. Los tiempos de espera y los fallos transitorios de transporte también están limitados. Otros errores malformados o de origen ascendente permanecen como errores saneados explícitos.

Solución de problemas

  • invalid_grant: verifica que el sujeto delegado exista, no esté suspendido, esté en el mismo inquilino de Workspace y que el reloj del servidor esté sincronizado con NTP. También verifica que la credencial pertenezca a la cuenta de servicio habilitada para DWD.

  • unauthorized_client: usa el ID de cliente OAuth numérico de la cuenta de servicio en DWD y autoriza el alcance exacto mostrado arriba. Los cambios en DWD pueden tardar en propagarse.

  • 403 / AUTHORIZATION: verifica los privilegios de Lectura de usuarios y Lectura de unidades organizativas, el alcance de asignación de OU, los controles de acceso a la API, el sujeto delegado y la API de Admin SDK. Una clave válida por sí sola no es suficiente.

  • Alcance faltante: compara la entrada de DWD carácter por carácter con https://www.googleapis.com/auth/admin.directory.user.readonly. La fase uno solicita intencionalmente ningún alcance de grupos, Drive, Gmail, Calendar, gestión de roles o gestión de seguridad.

  • Sujeto delegado incorrecto: corrige GOOGLE_DELEGATED_ADMIN; debe ser el administrador delegado dedicado cuyo rol cubra las OU consultadas. El llamante de MCP no puede anularlo.

  • Desfase de reloj: sincroniza el reloj del host de Docker. Las aserciones JWT firmadas son sensibles al tiempo.

  • NOT_FOUND inesperado: confirma que el correo solicitado use el dominio permitido configurado y sea un usuario de Directory actual y no eliminado. Los fallos de autorización y de límite de velocidad nunca se convierten en NOT_FOUND.

Revocación de emergencia

Si se sospecha que la puerta de enlace, la cuenta de servicio o la identidad delegada están comprometidas:

  1. Deshabilita o elimina la ruta de NPM.

  2. Detén el contenedor de MCP.

  3. Elimina la entrada de cliente DWD si se sospecha compromiso.

  4. Deshabilita o elimina la clave de la cuenta de servicio.

  5. Deshabilita el administrador delegado si es necesario.

  6. Conserva y revisa los registros de auditoría de la puerta de enlace, la aplicación y Google.

Nota sobre la migración a WIF

La interfaz de credenciales está aislada para que se pueda agregar otro proveedor más adelante, pero esta versión implementa y prueba solo una clave JSON de cuenta de servicio montada. Workload Identity Federation no se declara como compatible. Para DWD, WIF no es necesariamente un reemplazo directo de una clave JSON: generar la aserción JWT de DWD puede requerir permisos de signJwt de IAM Credentials y lógica explícita de firma/intercambio. Diseña y prueba esa ruta antes de eliminar el proveedor de clave JSON.

google-mcp

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

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

View all related MCP servers

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.

View all MCP Connectors

Latest Blog Posts

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