shared-skill-mcp
shared-skill-mcp
一个为 claude.ai 自定义连接器(custom connectors)设计的、托管在 AWS 上的 MCP 服务器,其设计目标是在后续持续容纳更多工具,而不只是最初那个 Google Sheets 查询工具。架构为:一个共享的 Cognito 认证层(Google 登录)+ 一个 Bedrock AgentCore Gateway(真正的 MCP 服务器)+ 每个工具一个 Lambda。
最初 query_sheet 工具的完整规格、架构图和分阶段演进历史,请见:Reel AI Workers/skills-spec/sheet-gviz/sheet-gviz.md。
状态(2026-08-24)
已上线并端到端验证可用,包括一个真实的 claude.ai 连接器完成 Google 登录并调用该工具——而不只是 curl 验证。
项目 | 值 |
MCP 服务器 URL(Gateway) |
|
Cognito 域名 |
|
用户池 ID |
|
AWS 账户 |
|
随时获取当前值(包括密钥):
AWS_PROFILE=<your profile> terraform -chdir=terraform output
AWS_PROFILE=<your profile> terraform -chdir=terraform output -raw cognito_client_secret当前对外暴露的工具:query_sheet —— 对一个 Google Sheet 执行
gviz
查询(类 SQL:select/where/group by/pivot/order by)。
Related MCP server: Google Workspace MCP
架构
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这里存在两个必须保持区分的 Google OAuth 客户端:一个供 Cognito 登录使用(联合身份),另一个供 gviz.js 读取 Sheet(服务凭证,基于刷新令牌,绝不进行交互式使用)。刻意避免让两者复用同一个客户端——见规格文档中对“两个身份”的框架说明。
这个仓库的由来(在改认证配置前值得先读)
第一个可用的版本是把手写的 Lambda Function URL 当作 MCP 服务器,由 Lambda 自身校验 Cognito JWT,并手工提供 OAuth discovery 元数据(RFC 9728 / RFC 8414)。它通过了 curl 和手动 Postman OAuth 流程——完整往返链路、真实 Google 登录、真实 Sheet 数据——但 claude.ai 的实际连接器客户端每次都会静默失败(Couldn't connect / Authorization failed),且完全看不出原因:Lambda 日志显示 claude.ai 拉取了一次 discovery 元数据之后就再无动静——没有 token 交换,没有报错,什么都没有。
当时的工作假说:Cognito 的 access token 不携带 aud 声明(这是真实存在的 Cognito 限制——解码真实 token 后确认过),而 MCP 规范期望客户端发送的 resource 参数能反映到该声明中。生态中别处近期出现的、看似可信的证据似乎也印证这一点。结果证明这是个误导性线索——来自另一个独立项目(同一个人,不同仓库)的一个可用参考实现证明,Cognito + claude.ai 连接器完全可以正常工作,只需要在 Cognito 前面放 Bedrock AgentCore Gateway,而不是手写服务器;该 Gateway 的 CUSTOM_JWT 授权器按 allowed_clients(即 Cognito 的 client_id)而不是 aud 进行匹配。原先失败真正的根因始终没有被一锤定音地定位——最有可能还是手写 JSON-RPC/discovery 实现中某些细节与 claude.ai 客户端期望不完全吻合,尽管它通过了所有手动测试。
下一次的教训: 一个看起来完全符合规范、能通过 curl 和 Postman 测试的手写 MCP 服务器,并不能证明它对 claude.ai 的真实连接器客户端可用——两者可能在零错误信号的情况下出现差异。优先使用 AWS 自己的 MCP 服务器实现(AgentCore Gateway),而不是手工重新实现 MCP + OAuth discovery,尽管这意味着要多了解一项 AWS 服务,并且当前 Terraform provider 的坑相对更多(见下文)。
在 Gateway 确认可用后,手写的 Function URL 服务器(sheets-gviz-mcp Lambda、modules/mcp-lambda、src/lambda-handler.mjs、src/auth.mjs)随之退役——通过 Terraform 拆除(对仍然活跃的 Cognito User Pool / domain / app client 零影响,Gateway 路径原样复用它)并将其从仓库移除。如果以后还要用到相关设计思路或代码,它完整保留在 Git 历史中。
途中踩到的坑(已在代码中修复,再次动这里之前值得了解)
Sheets/gviz 层(src/gviz.js):
OAuth token 需要同时包含
.../auth/spreadsheets和.../auth/spreadsheets.readonly两个 scope —— 仅readonly会得到 401,且响应看起来像 HTML 登录页,而不是清晰的错误。即使使用 OAuth bearer token,gviz 的
/tq端点也需要带/a/<domain>/路径段,如:docs.google.com/a/google.com/spreadsheets/d/<id>/gviz/tq。如果google.com不适用于你的账号域,可通过GVIZ_DOMAIN_SEGMENT配置。始终传入
headers=1(已在querySheet中硬编码)。如果不传,gviz 对表头行的自动检测可能出错,并把真实数据行静默折叠进cols[].label成一个巨大字符串,导致数据全部丢失。
AWS/Terraform 层:
4. IAM 身份策略变更可能需要几十秒到几分钟才能真正生效,即使 aws iam simulate-principal-policy 立即确认策略正确。因此刚授予新权限后立刻做一次全新的 plan/apply 而遇到 403 是完全正常的——不必紧张,等一小段时间后重试即可。
5. ESM .js 文件在打包 zip 时,如果不带上仓库根目录的 package.json,那么需要有自己独立的 package.json({"type": "module"})——gviz.js 使用了 export/import,它之所以能被解析为 ESM,正是因为它在每个 Lambda 的 zip 中都与 src/package.json 放在一起。
6. aws_bedrock-agentcore_* 是较新的 Terraform 资源,仍在不断演化——请依据 provider 自带的 schema 来确认实际的参数结构(terraform providers schema -json),不要只相信更新滞后的文档或博客。需要 provider 版本 >= 6.0。
7. AgentCore Gateway 的 CUSTOM_JWT 授权器按 allowed_clients(即 Cognito 的 client_id)匹配调用方,而不是 allowed_audience——这正是它能在不用额外 token 中间层分发的情况下,与 Cognito 的非标准(无 aud)access token 搭配工作的原因。
8. 把在线的 Terraform 资源重构进 module 容易误删它们。无论是最初的 Phase 4→module 重构,还是后来解除 Function URL,都在每次 apply 前使用了 terraform state mv 和真实的 plan 检查(预期保留的资源销毁数必须为 0)——claude.ai 已经拿到凭据的 app client 就是这样被移动了两次,期间从未被销毁或重建。
设置
1. 单独验证 Sheets 凭据可用(无需 AWS)
cp .env.example .env # fill in GOOGLE_CLIENT_ID/SECRET/REFRESH_TOKEN, SPREADSHEET_ID
node scripts/phase1-test.mjs "select *"完成判定: 对真实查询输出 {columns, rows}。这个阶段的失败基本是 Google 侧的问题(scope、共享权限、Sheets API 未启用)——这是联系 AWS 之前排查问题边界最低成本的时机。
2. 部署 Cognito + Gateway + 工具 Lambda
需要具备 terraform/iam-policy.json 中列出权限的 AWS 凭据,以及一个 第二个 Google OAuth 客户端(Web 应用,必须区别于读取 Sheet 用的那个),供 Cognito 登录使用。它的 redirect URI 需要 Cognito 的域,而该域当时还不存在,需要先用一次部分 apply 才能解开这个鸡生蛋的循环:
scripts/tf.sh apply -target=module.auth.aws_cognito_user_pool.this \
-target=module.auth.aws_cognito_user_pool_domain.this创建 Google OAuth 客户端,redirect URI 填写 https://<domain 输出>/oauth2/idpresponse,在 .env 中填好
GOOGLE_LOGIN_CLIENT_ID / GOOGLE_LOGIN_CLIENT_SECRET,然后:
scripts/tf.sh applyCLAUDE_OAUTH_REDIRECT_URI 不需要专门设置——默认为 https://claude.ai/api/mcp/auth_callback,并且已确认可用,针对真实连接器工作正常。
3. 把它添加为 claude.ai 连接器
设置 → 连接器 → 添加自定义连接器:
服务器 URL:取
gateway_url输出高级设置 → OAuth 客户端 ID / 密钥:取
cognito_client_id/cognito_client_secret输出
之后应会通过 Cognito 的 Hosted UI 触发一次真实的 Google 登录,系统随后即可让 Claude 调用 query_sheet(在聊天窗口可见为 tool-use 块)。
添加新工具
使用 AgentCore 约定编写 Lambda 处理器——扁平式的
event就是工具参数,不再有 JSON-RPC 包裹(Gateway 负责 MCP 帧格式)。遵循src/gateway-tool-handler.mjs的写法。在
main.tf里加一个module "..." { source = "./spell/modules/gateway-tool-lambda" ... }块。为工具添加
aws_bedrockagentcore_gateway_target资源——可以扩展modules/agentcore-gateway使其支持一个 targets 列表,也可以直接在main.tf中添加资源并指向module.gateway.gateway_id。
不需要新的 Google OAuth 客户端、新的 Cognito 域名或新的 Gateway——module.auth 和 module.gateway 里的所有内容都是共享的。
目录结构
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.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 gradedqualityBmaintenanceMCP 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).521MIT
- FlicenseNot gradedqualityDmaintenanceEnables interaction with Google Sheets, Docs, Slides, and Drive through a remote MCP server hosted on Cloudflare Workers, with OAuth authentication and Claude-native connect.
- FlicenseNot gradedqualityDmaintenanceMCP 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.
- AlicenseBqualityCmaintenanceMCP server that gives Claude full read-write access to Google Drive, Docs, Sheets, and Slides using your own Google OAuth credentials and hosted server.25MIT
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
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/amar-p6/shared-skill-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server