Skip to main content
Glama
amar-p6

shared-skill-mcp

by amar-p6

shared-skill-mcp

Un servidor MCP alojado en AWS para conectores personalizados de claude.ai, pensado para albergar más de una herramienta con el tiempo: no se limita a la herramienta de consulta de Google Sheets con la que empezó. Una capa de autenticación Cognito compartida (inicio de sesión con Google) + una puerta de enlace de Bedrock AgentCore Gateway (el servidor MCP real) + una Lambda por herramienta.

Especificación completa, diagrama de arquitectura e historia por fases de la herramienta original query_sheet: Reel AI Workers''/skills-spec/sheet-gviz/sheet-gviz.md`.

Estado (2026-08-24)

Operativo y confirmado end-to-end, incluido un conector real de claude.ai que completa el inicio de sesión con Google y llama a la herramienta — no solo curl.

Elemento

Valor

URL del servidor MCP (Gateway)

https://sheets-gviz-gateway-63psdjvcgs.gateway.bedrock-agentcore.eu-west-1.amazonaws.com/mcp

Dominio Cognito

sheets-gviz-b24dc744.auth.eu-west-1.amazoncognito.com

ID del User Pool

eu-west-1_sfGqYcC0a

Cuenta de AWS

423566941862, eu-west-1

Obtén los valores actuales (incluidos los secretos) en cualquier momento:

AWS_PROFILE=<your profile> terraform -chdir=terraform output
AWS_PROFILE=<your profile> terraform -chdir=terraform output -raw cognito_client_secret

Herramientas expuestas hoy: query_sheet — ejecuta una consulta de [gviz](https://console.cloud.google.com/chart-interactive/querylanguage) (tipo SQL: select/where/group by/pivot/order by`) contra una hoja de cálculo de Google.

Related MCP server: Google Workspace MCP

Arquitectura

claude.ai connector
      │  OAuth 2.1 (real Google login, via Cognito's Hosted UI)
      ▼
Cognito User Pool ──federates to──> Google (login only)
      │  issues an access token (no "aud" claim — see gotcha below)
      ▼
AgentCore Gateway (CUSTOM_JWT authorizer, matches by client_id)
      │  invokes under its own service role
      ▼
Lambda tool target (gateway-tool-handler.mjs) ──> gviz.js ──> Google Sheets API

Existen dos clientes OAuth de Google y deben seguir siendo distintos: uno que Cognito usa para el inicio de sesión (identidad federada) y otro que gviz.js usa para leer hojas de cálculo (una credencial de servicio, basada en token de refresco, nunca usada de forma interactiva). Se evitó deliberadamente reutilizar uno para ambas cosas; véase el enfoque de "dos identidades" del documento de especificación.

Cómo llegó este repositorio a su estado actual (leer antes de cambiar la configuración de autenticación)

La primera versión funcional usaba un servidor HTTP de URL de Función Lambda hecho a mano como servidor MCP, con la propia Lambda que verificaba los JWTS de Cognito y servía manualmente la metadata de descubrimiento OAuth (RFC 9728 y RFC 8414). Funcionaba con curl y un flujo de OAuth de Postman — ronda completa, inicio de sesión real de Google, datos reales de usuarios — pero el conector real de claude.ai fallaba en silencio cada vez (Couldn't connect / Authorization failed), sin ninguna señal de por qué: los registros de Lambda mostraban que claude.ai obtenía una vez la metadata de descubrimiento y luego se quedaba en silencio — sin intercambio de tokens, sin error, nada.

La teoría de trabajo era que los tokens de acceso de Cognito no incluyen la reclamación procesable aud (una limitación conocida y real de Cognito) que muestra la la especificación MCP espera que el parámetro resource que envía el cliente se refleje en esa reclamación tendría el resultado esperado. Poco después, evidencia reciente y con datos de otro lugar del ecosistema parecía confirmarla como la respuesta. Resultó ser una falso rastro: una referencia de proyecto distinto (misma persona, otro repositorio) demostró que los conectores Cognito + claude.ai funcionan bien, usando Bedrock Core Gateway delante de Cognito como capa intermedia en lugar de un servidor hecho a mano, con el autorizador CUSTOM_JWT que identifica por allowed_clients (según el client_id de Cognito) y no por aud. La causa real original de la falla nunca se determinó con total certeza — probablemente algo en la implementación hecha a mano de JSON-RPC / descubrimiento que no encajaba exactamente con lo que espera el cliente de claude.ai, a pesar de pasar todas las pruebas manuales hechas.

Lección para la próxima vez: una servidor MCP escrito a mano que sea conforme a la especificación y que pase las pruebas curl y Postman no es una prueba de que funciona con el cliente real de claude.ai — los dos pueden divergir de forma que no generan ninguna señal de error. Mejor prefijos la implementación propia AWS de servidor MCP (AgentCore Gateway) que reimplementar MCP + descubrimiento OAuth a manos, aunque eso implante un servicio AWS más que aprender y una superficie de proveedor Terraform hoy más tosca (consulta "contratiempos" más abajo).

El servidor MCP de URL de Función Lambda hecho a mano (sheets-gviz-mcp Lambda, módulos/mcp-lambda, src/lambda-handler.mjs, src/auth.mjs) fue dado de baja una vez que Gateway se confirmó funcionando — se eliminó con Terraform (sin impacto en el User Pool/dominio/cliente de aplicación Cognito que siguen vivos y que la ruta Gateway reúsa tal cual) y se eliminó del repositorio. Queda en historial de git por si el razonamiento o el código vuelven a ser útiles.

Contratiempos encontrados en el camino (corregidos en el código; conviene saberlo antes de tocar esto de nuevo)

Capa de Sheets/gviz (src/gviz.js):

  1. El token OAuth necesita .. tanto los scoping gviz .../auth/spreadsheetscomo.../auth/spreadsheets.readonly; con solo readonlyobtienes un401` que se ve como página HTML de login, no como un error claro.

  2. El endpoint /tq de gviz necesita el segmento /a/<domain>/ incluso con autenticación OAuth docs.google.com/a/google.com/spreadsheets/d/<id>/gviz/tq. Configurable con GVIZ_DOMAIN_SEGMENT si google.com no funciona para el dominio de tu cuenta.

  3. Pasa siempre headers=1 (hardcodeado en querySheets). Sin él, la auto-detección de la fila de cabecera puede fallar y silenciar/doblar filas de datos reales en cols[].label como una sola cadena enorme, perdiéndolas por completo.

Capa AWS/Terraform:

4. Los cambios de políticas IAM de identidad pueden tardar decenas de segundos o varios minutos en aplicarse de verdad, incluso después de que PICAR y simulate-principal-policy los confirmen correctos de inmediato. No es esperar que un plan/apply recién ejecutado devuelva un 403 justo después de dar un nuevo permiso — no es señal de error, solo vuelve a intentarlo tras a little.

5. Los archivos ESM .js necesitan su propio package.json ({"type": "module"}) si se comprimen sin la raíz del "root" del repositorio — gviz.js usa export/imports y solo se resuelve como ESM porque ese archivo está junto a él en el zip de cada Lambda (src/package.json).

6. Los recursos aws_bedrockagentcore_* de Terraform son recientes y están todavía evolucionando - comprueba la estructura real de los argumentos contra el esquema del propio proveedor (terraform providers schema -json) más que confiar en documentación o posts de blogs, que siempre van retrasaturados. Requiere proveedor >= 6.0. 7. El autorizador CUSTOM_JWT de AgentCore Gateway identifica a los llamadores mediante allowed_clients (el client_id de Cognito), no mediante allowed_audience — esto es lo que lo hace funcionar con los tokens de acceso no estándar (sin aud) de Cognito sin ninguna capa adicional de acuñación de tokens.

Configuración

1. Verificar que la credencial de Sheets funciona (standalone, sin AWS)

cp .env.example .env   # fill in GOOGLE_CLIENT_ID/SECRET/REFRESH_TOKEN, SPREADSHEET_ID
node scripts/phase1-test.mjs "select *"

Se sabe que funciona cuando: imprime {colunas, filas} para una consulta real. Si falla, el problema es del lado de Google (alces, compartir, API no habilitada) — la forma más barata de detectarlo antes de tocar AWS.

2. Desplegar Cognito + Gateway + la Lambda de la herramienta

Necesita credenciales AWS con los permisos de terraform/iam-policy.json, además de un segundo cliente OAuth de Google (aplicación Web, separado del que lee Sheets) para el inicio de sesión Cognito. Su URI de redirección necesita el dominio de Cognito, que aún no existe — quiere romper ese círculo con un primer despliegue parcial:

scripts/tf.sh apply -target=module.auth.aws_cognito_user_pool.this \
  -target=module.auth.aws_cognito_user_pool_domain.this

Crea el cliente OAuth de Google con el redirect URI https://<esa-salida-dominio>/oauth2/idpresponse, completa GOOGLE_LOGIN_CLIENT_ID / GOOGLE_LOGIN_CLIENT_SECRET en .env, y luego:

scripts/tf.sh apply

CLAUDE_OAUTH_REDIRECT_URI no necesita configurarse — por defecto es https://claude.ai/api/mcp/auth_callback, confirmado como funciona con conectores reales.

3. Añadir como conector en claude.ai

Configuración → Connectors → Add custom connector:

  • Server URL: la salida gateway_url

  • Advanced settings → OAuth Client ID/Secret: las salidas cognito_client_id / cognito_client_secret

Debe activar un inicio de sesión real de Google through la UI de ofrecida de Cognito (Hosted UI), y después dejar que Claude llame query_sheet (visible en el chat como bloque de herramientas).

Añadir una nueva herramienta

  1. Escribe un handler Lambda que use el contrato de Lambda "objetivo" de AgentCore — event plano = los argumentos de la herramienta, sin envoltura JSON-RPC (Gateway gestiona el contexto MCP). Vea el patrón en src/gateway-tool-handler.mjs.

  2. Añade un bloque module "..." { source = "./modules/gateway-tool-lambda" ... } en main.tf.

  3. Añade un bloque aws_bedrockagentcore_gateway_target para él — ya sea extiende modules/agentcore-gateway para que acepte una lista de targets, o añade el recurso directo en main.tf apuntado a module.gateway.gateway_id.

No hace falta nuevo cliente OAuth, nuevo dominio Cognito, ni nueva Gateway — todo lo que hay en module.auth y module.gateway es compartido.

Estructura

src/
  gviz.js                  Sheets-reading logic — token refresh, gviz query, response
                            parsing. Host-agnostic; used by gateway-tool-handler.mjs.
  gateway-tool-handler.mjs AgentCore Gateway Lambda-target contract for query_sheet —
                            flat event-in/JSON-out, no JSON-RPC framing (Gateway
                            handles MCP protocol translation itself).
  package.json              {"type": "module"} — required for gviz.js's ESM syntax to
                            resolve once zipped alone, without the repo root's
                            package.json alongside it.
scripts/
  phase1-test.mjs           Standalone local proof the Sheets credential + gviz query
                            round-trip works, no AWS involved.
  tf.sh                     Wraps `terraform` with GOOGLE_*/Cognito vars sourced from
                            .env — use this instead of calling terraform directly.
terraform/
  main.tf                   Root — provider, variables, the shared auth module, the
                            claude.ai connector's Cognito app client, the Gateway, and
                            the query_sheet tool Lambda.
  modules/mcp-auth/         Cognito User Pool + Google identity provider + Hosted UI
                            domain. Shared — instantiate once per AWS account.
  modules/agentcore-gateway/ The Gateway (CUSTOM_JWT authorizer) + the query_sheet
                            Gateway Target. Extend for more targets, or add more
                            gateways for a genuinely separate trust boundary.
  modules/gateway-tool-lambda/ A standalone tool Lambda for a Gateway target — no
                            Function URL, no public permissions, no own Cognito
                            client. Gateway is the only caller, via its service role.
  iam-policy.json            Deploy-time IAM policy for whatever AWS identity runs
                            scripts/tf.sh. Broad on bedrock-agentcore:* deliberately —
                            that service/provider surface is new and evolving.
F
license - not found
Not graded
quality - not tested
B
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

  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for Google Drive, Docs, and Sheets — built for Claude Code. Gives Claude Code direct read/write access to Google Sheets (cell-level edits, formatting, structure), Google Docs (insert, replace, append), and Drive (search).
    52
    1
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    MCP server for Claude Desktop that provides tools to read/write Google Sheets, manage Gmail, schedule Google Calendar events, and run queries on Neon Postgres databases.

View all related MCP servers

Related MCP Connectors

  • Hosted Amazon Seller Central and Amazon Ads MCP server for Claude, ChatGPT, Cursor, and agents.

  • Hosted Amazon Seller and Vendor MCP server for Claude, ChatGPT, Cursor, Codex, Gemini, Copilot.

  • Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer

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/amar-p6/shared-skill-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server