github-readonly-mcp
Provides read-only access to GitHub repositories, including private ones, with tools for listing repos, commits, branches, pull requests, issues, file contents, and searching code, scoped by a GitHub personal access token.
Click on "Install 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-readonly-mcplist pull requests in myorg/myrepo"
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-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.
Related MCP server: Vindata MCP Server
2. Install dependencies
cd github-readonly-mcp
npm install3. Log in to Cloudflare
npx wrangler loginThis 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_KVThis 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 deployWrangler 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/mcpSave. 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 tokenNo 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 bindingThis 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.
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/jpalvarezb/claude-github-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server