github-readonly-mcp
A 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.
README
github-readonly-mcp
A small, self-hosted MCP connector that gives Claude read-only access to your GitHub repos — including private ones. Which repos are reachable is determined entirely by the scope of the GitHub token you give it (see below), not by a list in the code. It exists because:
- Cowork's cloud sandbox blocks direct calls to
api.github.com(you'll get403 GitHub access to this repository is not enabled for this session). - GitHub's own official remote MCP server (
api.githubcopilot.com/mcp) needs a GitHub App OAuth flow that Claude's custom-connector UI doesn't support (it only takes an OAuth Client ID/Secret, not GitHub's flow). - Broader third-party connectors grant read and write access, which is more than this needs.
This connector is deliberately narrow: it runs on Cloudflare Workers (free tier is plenty), gates access behind a single shared password + OAuth 2.1, and exposes exactly 7 read-only tools. The reachable repos are whatever the GitHub token can read — scope the token, not the code. There is no write path in the code at all — no create/update/delete/merge function exists anywhere, so it can't modify GitHub no matter what a model asks it to do.
Tools it exposes: list_repos, list_commits, list_branches,
list_pull_requests, list_issues, get_file_contents, search_code.
Everything below has already been tested locally end-to-end (dynamic client registration → password-gated authorize → token exchange → authenticated MCP session → tools/list → tools/call, including a real 401 from GitHub with a placeholder token and a correctly-rejected malformed repo name). What's left is deploying it for real and connecting it to Claude.
1. Prerequisites
- Node.js 18+ and npm (already used to build this).
- A free Cloudflare account: https://dash.cloudflare.com/sign-up
- A GitHub fine-grained personal access token, read-only. This token is
the connector's only access boundary — it can read exactly the repos the
token can, so scope it deliberately:
https://github.com/settings/personal-access-tokens/new
- Repository access: "Only select repositories" → pick exactly the repos you want reachable (or "All repositories" if you truly want full read access).
- Permissions: Contents (Read-only), Metadata (Read-only), Pull requests (Read-only), Issues (Read-only). Don't grant anything else.
2. Install dependencies
cd github-readonly-mcp
npm install
3. Log in to Cloudflare
npx wrangler login
This opens a browser to authorize the Wrangler CLI against your Cloudflare account.
4. Create the KV namespace
@cloudflare/workers-oauth-provider needs a KV namespace to store OAuth
grants and token hashes (no secrets are stored in plaintext — just hashes).
npx wrangler kv namespace create OAUTH_KV
This prints something like:
[[kv_namespaces]]
binding = "OAUTH_KV"
id = "abcd1234...."
Copy that id value into wrangler.jsonc, replacing the placeholder:
"kv_namespaces": [
{ "binding": "OAUTH_KV", "id": "abcd1234...." } // <- your real id here
],
5. Set the two secrets
These are never written to wrangler.jsonc or committed anywhere — they live only in Cloudflare's encrypted secret store.
npx wrangler secret put GITHUB_PAT
# paste your fine-grained GitHub PAT when prompted
npx wrangler secret put CONNECTOR_PASSWORD
# choose a real password — this is the one gate between the internet and
# your GitHub read tools, so make it a proper passphrase, not "test123"
6. (No allow-list to configure)
There is no repo allow-list in this connector: it can read any repo the
GITHUB_PAT grants. The token you scoped in step 1 is the boundary —
if you want to narrow what's reachable, narrow the token's repository access,
then rotate it (step 5 / "Updating later"). The connector still validates that
each repo argument is a well-formed "owner/name" before calling GitHub, so
malformed values can't be used to reach unintended API paths.
7. Deploy
npm run deploy
Wrangler will print a URL like https://github-readonly-mcp.<your-subdomain>.workers.dev.
That's your connector's base URL — save it, you'll need it in the next step.
Sanity-check it:
curl https://github-readonly-mcp.<your-subdomain>.workers.dev/health
# -> "github-readonly-mcp is running. Connect it to Claude as a custom connector."
8. Add it to Claude as a custom connector
- In Claude, go to Settings → Connectors → Add custom connector.
- Name it something like "GitHub (read-only)".
- Remote MCP server URL:
https://github-readonly-mcp.<your-subdomain>.workers.dev/mcp - Save. Claude will kick off the OAuth flow: it hits
/registerautomatically, then opens the/authorizepage in step 9.
9. Authorize it
You'll land on a small dark-themed page titled "Authorize Claude." Enter the
CONNECTOR_PASSWORD you set in step 5 and submit. That's the only manual
gate — after this, Claude holds a scoped OAuth token and can call the 7
tools directly.
10. Verify it works
Ask Claude something like "using the GitHub read-only connector, list
recent commits on jpalvarezb/bonafe" and confirm it returns real commit
data (not a 401). You can also ask it to list_repos to see everything the
token can reach.
11. Tell me once it's connected
Once steps 1–10 are done, let me know — I'll delete and recreate the
"Daily Schedule Review (cloud)" scheduled task so its connector list picks
up this new one, then we'll run one more supervised test exercising
list_commits / list_pull_requests / list_issues against your real repos
with real credentials, to confirm the whole chain works end-to-end.
Updating later
Changed a tool, re-scoped the repos, or rotated the PAT? (Re-scoping the reachable repos now means issuing a new fine-grained token and rotating it — there's no list in the code to edit.)
npm run deploy # code/config changes
npx wrangler secret put GITHUB_PAT # to rotate the token
No need to touch the OAuth setup again — Claude's existing connection keeps working across redeploys as long as the KV namespace and secrets stay in place.
Security notes
- Read-only by construction, not by policy. There is no function in
src/github.ts(or anywhere else) that issues a POST/PATCH/PUT/DELETE to GitHub. A prompt injection or a misbehaving model can't make this connector write to GitHub — the code to do so doesn't exist. - The GitHub token is the access boundary. There is no repo allow-list;
the connector can read exactly what the
GITHUB_PATcan. Use a fine-grained, read-only token scoped to just the repos you want reachable. The connector does validate that eachrepoargument is a well-formed"owner/name"before calling GitHub, which prevents malformed values from being smuggled into unintended API paths — but that is an injection guard, not access control. Anyone who has the connector password can read every repo the token can, so keep both the token narrow and the password strong. - Secrets never touch source control.
GITHUB_PATandCONNECTOR_PASSWORDare Cloudflare secrets (wrangler secret put), notvarsin wrangler.jsonc, and.dev.varsis gitignored. - One shared password, by design. The
/authorizegate uses a single password rather than a full user-account system because this connector has exactly one legitimate caller — you, connecting your own Claude to your own GitHub data. If you ever want to share it with others, that authorize.ts gate is the one place to revisit.
Project layout
src/
index.ts OAuthProvider wiring: routes /authorize, /token, /register, /mcp
authorize.ts Password-gated consent page (the only manual step)
mcp-agent.ts MCP server: registers the 7 read-only tools
github.ts GitHub REST wrapper — GET-only, "owner/name" format-validated
env.d.ts Adds GITHUB_PAT/CONNECTOR_PASSWORD to wrangler's generated Env type
wrangler.jsonc Worker config: DO binding, KV binding
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。