github-mcp-worker
Provides tools for interacting with the GitHub REST and GraphQL APIs, enabling repository, file, branch, commit, issue, pull request, Actions/CI, release, tag, and notification operations. Supports reads and first-class writes such as multi-file commits, PR creation/review/merge, and workflow dispatch/rerun.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@github-mcp-workercreate a pull request from feature/login to main in acme/web"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
github-mcp-worker
A self-hosted GitHub MCP server on Cloudflare Workers. It exposes the GitHub REST / GraphQL API as 51 gh_* tools over Streamable HTTP, and uses Cloudflare Access Managed OAuth for sign-in — so you can add it to claude.ai as a custom connector with a normal "Sign in" flow, without writing any OAuth code or putting a secret in the URL.
MCP client (claude.ai custom connector, Claude Code, ...)
→ https://github-mcp.example.com/mcp
Cloudflare Access application (Managed OAuth, your allow policy)
unauthenticated → 401 + WWW-Authenticate (resource_metadata) → client registers (DCR) → Access login → consent → token
authenticated → request forwarded with Cf-Access-Jwt-Assertion
→ Worker verifies the JWT (signature / aud / iss / exp) → calls api.github.com with your GITHUB_TOKENWhy this instead of a hosted GitHub connector:
Output is trimmed to what a model needs; large bodies are cut at
max_chars(default 60,000) withtruncated: true.Writes are first-class: multi-file commits in one call (
gh_push_files), PR create / review / merge, Actions rerun / dispatch.Escape hatches:
gh_api(any REST path) andgh_graphqlfor anything not covered.You own it: one Worker, one PAT, access decided by your own Access policy.
Tools
Area | Tools |
Status / generic |
|
Repos / contents |
|
Branches / commits |
|
Issues |
|
Pull requests |
|
CI / Actions |
|
Releases / misc |
|
Until GITHUB_TOKEN is set, only gh_status is listed and it returns setup steps.
Related MCP server: epik-gh
Requirements
A Cloudflare account with a zone (domain) on it — Access protects a hostname, so
workers.devalone is not enoughCloudflare Zero Trust (the free plan is fine) with at least one login method (e.g. One-time PIN, Google, GitHub)
A GitHub personal access token
Node.js 22.6+ (for the tests)
Setup
1. GitHub token
Create a fine-grained personal access token for the repositories you want to use:
Permission | Access |
Contents, Issues, Pull requests, Actions, Workflows, Commit statuses | Read and write |
Administration | Read and write (only if you want |
Metadata | Read |
Fine-grained tokens cannot read check runs or notifications. gh_checks falls back to Actions workflow runs for the same commit; gh_notifications_list returns 403. If you need those, use a classic token with repo, workflow, read:org, notifications — but note that a classic token reaches every repository your account can.
2. Access application with Managed OAuth
Create a self-hosted Access application for the hostname you will serve the Worker on, with Managed OAuth and Dynamic Client Registration enabled. The dashboard does not expose every OAuth field, so the API is easiest (the token needs Access: Apps and Policies Edit):
ACCOUNT_ID=<your account id>
HOST=github-mcp.example.com
curl -s https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/access/apps \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json" \
-d @- <<JSON
{
"type": "self_hosted",
"name": "github-mcp",
"domain": "$HOST",
"destinations": [{ "type": "public", "uri": "$HOST" }],
"app_launcher_visible": false,
"session_duration": "24h",
"policies": [{
"name": "Allow me",
"decision": "allow",
"include": [{ "email": { "email": "you@example.com" } }]
}],
"oauth_configuration": {
"enabled": true,
"grant": { "session_duration": "720h", "access_token_lifetime": "15m" },
"dynamic_client_registration": {
"enabled": true,
"allowed_uris": [
"https://claude.ai/api/mcp/auth_callback",
"https://claude.com/api/mcp/auth_callback"
],
"allow_any_on_localhost": true,
"allow_any_on_loopback": true
}
}
}
JSONFrom the response, note result.aud (the Application Audience tag). Your team domain is https://<team>.cloudflareaccess.com (Zero Trust → Settings).
grant.session_durationis how long a client stays connected before signing in again. The dashboard only offers up to one month; longer values can be set through the API, and the dashboard will then show the field as empty. Change such an app through the API (PUT with the full object) rather than saving it in the dashboard.Add other MCP clients' callback URLs to
allowed_urisif you use them. Loopback / localhost cover Claude Code and local testing.Who can connect is decided only by the Access policy. Anyone allowed there uses your GitHub token.
See Cloudflare's Managed OAuth docs for details.
3. Deploy the Worker
Edit the TODO values in wrangler.jsonc (routes, ACCESS_TEAM_DOMAIN, ACCESS_AUD, optionally DEFAULT_OWNER), then:
npm install
npm run typecheck
npm test # unit tests (no network)
npx wrangler secret put GITHUB_TOKEN # paste the token from step 1
npm run deployCheck that an unauthenticated request is stopped by Access:
curl -si -X POST https://github-mcp.example.com/mcp -d '{}' | grep -i -E '^HTTP|www-authenticate'
# HTTP/2 401
# www-authenticate: Bearer ... resource_metadata="https://github-mcp.example.com/.well-known/oauth-protected-resource..."If you get 403 or error 1010 instead, a zone security feature (Bot Fight Mode, WAF) is blocking non-browser clients on that hostname.
4. Connect a client
claude.ai — Settings → Connectors → Add custom connector → URL https://github-mcp.example.com/mcp → Add → Connect. Sign in through Access and allow the consent screen. Claude Code can then use the connector as well when you are logged in with the same claude.ai account.
Claude Code (direct):
claude mcp add --transport http github https://github-mcp.example.com/mcpThen run /mcp in Claude Code and authenticate.
How it works
Stateless: no
Mcp-Session-Id, no SSE; each POST is an independent JSON-RPC request (batches supported).Fail closed:
/mcpreturns 500 ifACCESS_TEAM_DOMAIN/ACCESS_AUDare missing, and 403 if the Access JWT is absent or invalid. The JWT is verified against the team's public keys (/cdn-cgi/access/certs, cached for an hour, refetched on an unknownkid).Token containment:
gh_apiaccepts full URLs only on theGITHUB_APIorigin, so the PAT is never sent elsewhere. Redirects (e.g. Actions logs on blob storage) are followed without the Authorization header.Logs:
gh_actions_job_logs/gh_actions_run_logs_failedsupportgrepandtail_linesso a model doesn't pull megabytes of logs.
Operations
Task | How |
Logs |
|
Rotate the GitHub token |
|
Allow more people | Add them to the Access policy. They all act as the token's owner on GitHub |
Disconnect all clients | Access application → Revoke existing tokens; clients reconnect with Connect |
Recreated the Access app | The AUD changes; update |
Smoke test |
|
Costs: the Worker fits the Workers free plan for personal use, Access is within the Zero Trust free plan (up to 50 users), and the GitHub API is free (5,000 requests/hour per token).
Limitations
Single GitHub identity: every allowed user acts through one token. For per-user GitHub identities you would need a GitHub App or GitHub OAuth instead.
gh_checkscannot show check-run details with a fine-grained token (see step 1).
License
MIT
This server cannot be deployed
Maintenance
Related MCP Connectors
GitHub MCP — wraps the GitHub public REST API (no auth required for public endpoints)
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Zero-setup MCP gateway securely connecting AI to your tools with authentication and workflows
Access the GitHub API, enabling file operations, repository management, search functionality, and…
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables remote MCP connections with GitHub OAuth authentication, providing tools like add, userInfoOctokit, and image generation (restricted) deployed on Cloudflare Workers.25 npmMIT
- FlicenseNot gradedqualityAmaintenanceA GitHub MCP server that wraps the gh CLI to expose GitHub operations like issues, pull requests, branches, labels, repositories, CI actions, and Projects V2 as tools for MCP clients.-
- AlicenseNot gradedqualityBmaintenanceMCP server providing maximum practical control over GitHub via REST and GraphQL APIs, exposing 22 tools for repository management, file operations, issues, PRs, Actions, and more.MIT
- FlicenseNot gradedqualityBmaintenanceA read-only MCP server for GitHub that exposes 7 tools (list repos, commits, branches, pull requests, issues, file contents, search) via a Cloudflare Worker, using a single password for authorization and a fine-grained GitHub token for access control.-