github-mcp-gateway
github-mcp-gateway
一个远程 MCP 服务器,通过真正的 OAuth 2.1 握手,在 Cloudflare Workers 上为任何 MCP 客户端提供经过认证的 GitHub 访问——仓库、议题、拉取请求、文件内容和搜索。
兼容 Claude Code、Claude.ai / Cowork 以及任何符合规范的 MCP 客户端。认证采用 GitHub App 的用户到服务器(user-to-server)流程,所以它能访问的仓库,是你自己在 GitHub 安装界面中勾选的那些——而不是你账号能看到的全部。
这是你要自己运行的源码,而不是注册即用的服务。 没有共享实例。你要针对自己的 GitHub App 部署自己的 Worker,你的凭据永远不会离开你的账号——参见设计限制。搭建只需一个脚本,大约十分钟:
git clone https://github.com/mazze93/github-mcp-gateway cd github-mcp-gateway && ./scripts/setup.sh <your-github-login>
你将获得
21 个工具 | 仓库(6)、议题(5)、拉取请求(5)、文件内容(3)、代码与议题搜索(2)——所有列表工具均支持分页 |
真正的 OAuth 2.1 | PKCE、动态客户端注册和客户端 ID 元数据文档,通过 Cloudflare 自家的 |
可自动续期的令牌 | 8 小时的 GitHub 访问令牌依据 6 个月的刷新令牌进行透明刷新;MCP 客户端对两者都不可见 |
加固的发布版本 | 多架构工具链镜像、非 root 且 distroless、使用 cosign 进行无密钥签名、发布时附带 SBOM 与 SLSA 出处信息 |
针对真实运行时测试 | 通过 |
Related MCP server: Cloudflare GitHub OAuth MCP Server
它为什么存在,以及它的形态
MCP 客户端无法直接使用你的凭据与 GitHub 的 API 通信——它需要一个中间层来(a)证明请求者是谁,(b)持有真正的 GitHub 令牌,并且(c)把工具调用转成 GitHub API 请求。这个 Worker 就是那个中间层,而且它同时扮演两个 OAuth 角色:
面向 GitHub 的 OAuth 客户端(上游)——它会将你引导至 GitHub 自己的授权页面,并用返回的授权码换取令牌。
面向 MCP 客户端的 OAuth 服务器(下游)——客户端永远看不到你的 GitHub 令牌。它从这个 Worker 获取自己的令牌,且该令牌只对此 Worker 有效。
@cloudflare/workers-oauth-provider(Cloudflare 自家的库)实现了下游这一半:OAuth 2.1、PKCE 和动态客户端注册(DCR)——尤其是 DCR,它让客户端在首次连接时自行注册,而无需你手动为它创建凭据。
MCP client ──OAuth (DCR, PKCE)──▶ this Worker ──OAuth (GitHub App)──▶ GitHub
│
▼
Workers KV (OAUTH_KV)
state · refresh tokens · approved clients为什么用 GitHub App 而不是经典 OAuth App
Cloudflare 自己的模板用的是经典 OAuth App,它更简单,但仓库权限要么全有要么全无,而且令牌不会过期,除非你自己实现过期逻辑。本构建改用 GitHub App 的*用户到服务器(user-to-server)*令牌流程:
安装时按仓库授权——你可以精确选择这个服务器能访问哪些仓库(使用 GitHub 自带的安装选择器),而不是“该账号能看到的全部”。
令牌真正会过期并自动续期——开启“Expire user authorization tokens”后,GitHub 会返回一个 8 小时的访问令牌外加一个 6 个月的刷新令牌,使用刷新令牌会重新生成一对新令牌。只要你每 6 个月至少使用一次这个服务器,它就永远不会失效,你也无需手动生成新令牌。
这个刷新周期由 src/github-client.ts 处理,与 Cowork 同这个 Worker 之间的会话相互独立——参见下文令牌生命周期。
1. 创建 GitHub App
前往 github.com/settings/apps/new(个人账号)或 github.com/organizations/<org>/settings/apps/new(组织所有——如果你想让它归属于组织而不是个人账号,请使用这个)。
字段 | 值 |
GitHub App 名称 |
|
主页 URL |
|
回调 URL |
|
Webhook | 取消勾选“Active”——这个服务器不使用 webhook |
仓库权限 → Contents | 读取与写入 |
仓库权限 → Issues | 读取与写入 |
仓库权限 → Pull requests | 读取与写入 |
仓库权限 → Metadata | 读取(必选,自动选中) |
这个 GitHub App 可以安装在哪里? | 仅限此账号 |
创建完成后:
记下应用设置页面顶部的 Client ID。
点击 Generate a new client secret——立即复制,它只显示一次。
在 Optional features 下找到 User-to-server token expiration 并点击 Opt-in。正是这个选项让刷新令牌得以存在——跳过它的话,服务器会在回调步骤失败并给出明确错误,提示你回来完成这一步。
前往左侧边栏的 Install App,将其安装到你的账号,选择 Only select repositories——挑出你希望这个服务器访问的仓库(之后你还可以在同一个界面中添加更多)。
如果你打算在部署前用 wrangler dev 在本地反复调试,那么你还需要第二个 GitHub App,配置完全相同,只是回调 URL 改为 http://localhost:8788/callback。
2. 创建 KV 命名空间
最快路径——./scripts/setup.sh <your-github-login>:安装依赖、创建命名空间,并把你的命名空间 ID 和允许列表写回 wrangler.jsonc。然后跳到第 3 步。
手动操作:
cd github-mcp-gateway
npm ci
npx wrangler kv namespace create OAUTH_KV把返回的 id 复制到 wrangler.jsonc 中的 kv_namespaces[0].id 下,替换掉已提交的值。那个值是维护者的线上命名空间,不是占位符——这个仓库既是模板,也是一套正在运行的部署,所以检入的配置是真实的。它是一个标识符,不是凭据:它不会给 fork 授予任何权限,但保留不动的话,你的 Worker 启动时就会指向一个你的账号无法访问的命名空间。
3. 设置 secret 和允许列表变量
npx wrangler secret put GITHUB_APP_CLIENT_ID
npx wrangler secret put GITHUB_APP_CLIENT_SECRET
openssl rand -hex 32 | npx wrangler secret put COOKIE_ENCRYPTION_KEYALLOWED_GITHUB_LOGINS 是普通变量(var),不是 secret——将它添加到 wrangler.jsonc 的顶层 "vars" 块中:
"vars": {
"ALLOWED_GITHUB_LOGINS": "your-github-login"
}这是一个纵深防御式的允许列表,会在 OAuth 回调时检查:尽管只有你本人能为自己的账号完成 GitHub 的授权页面,但它让“门禁”在代码中显式存在,而不是隐式地寄托在“只要能通过认证就行”上。未设置或为空的值会拒绝所有人——它按“失败即关闭”(fail closed)的方式运作,所以漏掉一步会把你锁在外面,而不是把服务器开放。
4. 部署
npx wrangler deploy5. 连接客户端
把任何 MCP 客户端指向:
https://github-mcp-gateway.<your-subdomain>.workers.dev/mcpClaude Code:
claude mcp add --transport http github-mcp-gateway <url>**Claude.ai / Cowork:**使用该 URL 添加一个自定义 MCP 连接器。
客户端通过 DCR 自行注册,将你重定向到这个服务器的授权页面,接着是 GitHub 的授权页面,最后回到这里,工具即可用。
本地开发
cp .dev.vars.example .dev.vars # fill in the *local* GitHub App's credentials
npx wrangler devwrangler dev 在 http://localhost:8788 提供服务——把 MCP 客户端(例如 MCP Inspector)指向 http://localhost:8788/mcp。
令牌生命周期
存在两条相互独立的令牌关系,遵循不同的时钟:
Cowork ↔ 本 Worker。 由
workers-oauth-provider签发的标准 OAuth 2.1 访问/刷新令牌。Cowork 会按照 MCP 规范自行、自动地刷新这些令牌——这里无需管理任何内容。本 Worker ↔ GitHub。 一个 8 小时的访问令牌 + 一个 6 个月的刷新令牌。
src/github-client.ts会在每次调用 GitHub API 前检查过期时间,并在距过期不足 5 分钟时透明地刷新,把轮换后的新令牌对持久化到OAUTH_KV中github:tokens:{your-login}键下。这一步刻意不接入workers-oauth-provider的tokenExchangeCallback钩子——该机制有一个未修复的上游 bug(刷新后 props 过期会触发重新认证循环;参见 References)——所以改为直接在工具层处理,这样更容易推理和测试。
如果 GitHub 的刷新令牌本身过期(连续 6 个月以上未使用),或者你撤消了应用的访问权限,下一次工具调用就会失败,并给出明确的 ReauthorizationRequiredError 消息,指示你在 Cowork 中断开连接后重新连接。这里没有静默失败模式——要么它在后台安静地正常工作,要么它明确告诉你该怎么做。
工具
模块 | 工具 |
|
|
|
|
|
|
|
|
|
|
所有列表工具都接受 per_page 和 page 参数进行分页。
github_merge_pull_request 和 github_delete_file 是两个破坏性操作——一旦调用,就无法通过工具本身撤销。客户端在调用其中任何一个之前,都应先征求你的确认。
github_update_repo (description, homepage, topics) 需要 GitHub App 拥有 Administration 仓库权限。当前配置的 App(Contents/Issues/PRs/Metadata)不包含该权限——请在 App 设置中添加该权限并重新批准安装以启用此工具,或者改用 gh CLI 进行这些编辑。
设计限制(有意为之)
在采用之前请先阅读——这些是决策,而非疏漏。
每个部署一个操作者
此服务器在设计上就是单租户。ALLOWED_GITHUB_LOGINS 控制 OAuth 回调的准入;虽然它接受逗号分隔的列表,且令牌存储已按登录名分键(github:tokens:{login}),但预期的形态是每人一个部署。
这是一个威胁模型决策。共享部署意味着一个操作者的 KV 命名空间会持有他人的 GitHub 刷新令牌——这些是有效期为六个月、拥有仓库写权限的凭据。这使得操作者成为负有数据泄露通知义务的凭据保管者,而所在的基础设施并不提供此类保障。自托管让每个凭据都留在其所属的账户中,这正是该设计的全部意义所在。
因此:请 fork 并自行运行。 ./scripts/setup.sh 正是为此而存在。搭建大约需要十分钟,Cloudflare 免费套餐足以满足个人使用。
仓库范围在安装时设定,而非由本服务器决定
由于这是 GitHub App 而非经典 OAuth App,通过它可访问的仓库就是你在 GitHub 自己的安装界面上选择的那些。本服务器无法扩大该范围,也没有任何工具调用可以越出该范围。若要更改范围,请更改安装。
github_update_repo 需要一个该 App 并未内置的权限
它需要 Administration 仓库权限。请在 App 设置中添加该权限并重新批准安装,或使用 gh CLI 编辑描述和主题。
并非托管服务
没有可供客户端指向的公共实例。你在此仓库(deploy.yml、SECURITY.md 或 Dockerfile 头部)中找到的任何 workers.dev URL 都是维护者自己的部署,其允许列表会拒绝你。这是需要你自行运行的源码,而非注册即用的服务。
安全说明 / 本构建应对的已知上游问题
CSRF、状态重放、会话固定 — 在
src/oauth/workers-oauth-utils.ts中通过同意表单上的 CSRF 令牌 + Cookie 对、基于 KV 的一次性状态(10 分钟 TTL)以及会话绑定 Cookie(状态令牌的 SHA-256 哈希,用于证明完成 GitHub 回调的浏览器与发起流程的是同一个)来处理。workers-oauth-providerIssue #133 — 受众校验中的路径处理 bug 在某些版本中专门破坏了 Claude.ai/Cowork 连接。作为已记录的规避方案,本构建避免向任何资源指示器添加路径组件(/mcp和/sse路由注册在apiHandlers的根级别,而非嵌套在更长的路径下)。如果 Cowork 的首次连接尝试在令牌交换步骤失败,这是上游要首先检查的地方。Issue #108(RFC 8707 带路径的受众校验) — 与上述相同的根本原因;相同的缓解措施。
Issue #29(生产环境中的重定向 URI 不匹配) — 据报告,对于某些客户端,DCR 注册的重定向 URI 在生产环境与
wrangler dev中的行为不同。如果 Cowork 的重定向仅在部署后失败(本地正常),那么这就是已知的嫌疑对象。全程采用
__Host-Cookie 前缀 — 保证(由浏览器强制执行)Cookie 只能由该确切来源在 HTTPS 下设置,且没有可能扩大其作用范围的Domain属性。
参考
Cloudflare Agents — 构建远程 MCP 服务器
cloudflare/workers-oauth-provider— 本构建所依赖的下游 OAuth 2.1 实现GitHub 文档 — 刷新用户访问令牌
workers-oauth-providerIssue #133(Claude.ai 连接失败)以及 Issue #108(RFC 8707 路径受众 bug)
This server cannot be installed
Maintenance
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Cloudflare Workers-deployed MCP server that provides secure remote access to MCP tools through GitHub OAuth authentication. Includes example tools for basic math operations, user info retrieval, and image generation with configurable user access controls.241Apache 2.0
- FlicenseNot gradedqualityDmaintenanceA reference MCP server for Cloudflare Workers that provides remote connection support with integrated GitHub OAuth authentication. It enables developers to build and deploy authenticated remote tools with user-specific access controls and persistent state management.
- FlicenseNot gradedqualityCmaintenanceA remote MCP server for Cloudflare Workers featuring built-in GitHub OAuth for secure user authentication and identity-based access control to tools. It provides a reference implementation for managing remote MCP connections with persistent state and OAuth provider integration.1
- AlicenseNot gradedqualityBmaintenanceEnables remote MCP connections with GitHub OAuth authentication, providing tools like add, userInfoOctokit, and image generation (restricted) deployed on Cloudflare Workers.11MIT
Related MCP Connectors
An MCP server that gives your AI access to the source code and docs of all public github repos
Hosted remote MCP server for YNAB on Cloudflare Workers with OAuth
Search your AI chat history (ChatGPT, Claude, Codex) from any MCP client. Remote, private, read-only
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/mazze93/github-mcp-gateway'
If you have feedback or need assistance with the MCP directory API, please join our Discord server