Skip to main content
Glama
darl33

github-universal-mcp

by darl33

github-universal-mcp

Self-hosted remote MCP server that gives any MCP client read-only tools for private GitHub repos. Runs on Cloudflare Workers. It speaks standard MCP (Streamable HTTP) and the MCP authorization spec (OAuth 2.1 with PKCE, dynamic client registration, protected resource metadata), so it works with any client that supports remote servers with OAuth, hosted or local. Towards GitHub it uses a GitHub App user token. Only allowlisted GitHub logins can finish sign-in.

Derived from nemolize/remote-mcp-github (MIT, see LICENSE). Kept: the workers-oauth-provider wiring and src/workers-oauth-utils.ts (consent page, CSRF and state binding). Changed: GitHub App flow instead of OAuth App scopes, login allowlist, stateless Streamable HTTP at /mcp (no Durable Object, no SSE), tool surface.

Status

Minimal build: one tool, github_whoami, to prove a client can connect and call tools before adding more.

Related MCP server: GitHub Read MCP Server

Endpoints

Path

Purpose

/mcp

MCP endpoint (Streamable HTTP, JSON responses). Requires a Bearer token.

/authorize, /token, /register

OAuth server used by MCP clients (dynamic client registration).

/callback

GitHub App redirect target.

/.well-known/oauth-authorization-server, /.well-known/oauth-protected-resource/mcp

Discovery metadata.

Deploy

Needs Node.js 22+, a Cloudflare account and a GitHub account. Commands assume a bash shell (WSL or Fedora).

  1. Set ALLOWED_GITHUB_LOGINS in wrangler.jsonc to your GitHub login, then install and log in to Cloudflare:

    git clone https://github.com/darl33/github-universal-mcp
    cd github-universal-mcp
    npm ci
    npx wrangler login
    npx wrangler whoami   # note your workers.dev subdomain

    The Worker URL will be https://github-mcp.<subdomain>.workers.dev.

  2. Create the KV namespace and paste the printed id into wrangler.jsonc (kv_namespaces[0].id):

    npx wrangler kv namespace create OAUTH_KV
  3. Create the GitHub App at https://github.com/settings/apps/new:

    Field

    Value

    Homepage URL

    https://github-mcp.<subdomain>.workers.dev

    Callback URL

    https://github-mcp.<subdomain>.workers.dev/callback

    Expire user authorization tokens

    On (tokens last 8 h, refresh tokens 6 months)

    Request user authorization (OAuth) during installation

    Off

    Enable Device Flow

    Off

    Webhook > Active

    Off

    Repository permissions

    Contents: Read, Metadata: Read, Pull requests: Read, Issues: Read

    Account permissions

    None

    Where can this GitHub App be installed?

    Only on this account

    Then: generate a client secret, and use Install App to install it on Only select repositories. A GitHub App user token can only reach repos that are both installed and visible to the user, so the install list is the access boundary.

  4. Set secrets and deploy:

    npx wrangler secret put GITHUB_CLIENT_ID       # App "Client ID" (starts with Iv)
    npx wrangler secret put GITHUB_CLIENT_SECRET
    openssl rand -hex 32 | npx wrangler secret put COOKIE_ENCRYPTION_KEY
    npm run deploy
    curl -s https://github-mcp.<subdomain>.workers.dev/.well-known/oauth-authorization-server
  5. Connect a client. Point any MCP client that supports remote servers with OAuth at:

    https://github-mcp.<subdomain>.workers.dev/mcp

    Leave any OAuth client ID and secret fields empty; the client registers itself. The client opens a browser to the consent page, then GitHub; sign in with an allowlisted account. Local clients that use a http://localhost or http://127.0.0.1 redirect work too, since the registration accepts loopback redirect URIs.

    Client guides: Claude, Codex.

    To debug without a client, use MCP Inspector (npx @modelcontextprotocol/inspector) with transport "Streamable HTTP" and the URL above.

Smoke test

  1. Ask the client (or Inspector) to call github_whoami. Expect your own login.

  2. Sign-in as any other GitHub account must end on a 403 page.

  3. curl -i -X POST https://github-mcp.<subdomain>.workers.dev/mcp must return 401 with a WWW-Authenticate header pointing at the resource metadata.

Troubleshooting

  • Logs: npx wrangler tail. If a client says sign-in succeeded but calls fail, check whether its requests to /mcp carry an Authorization: Bearer header.

  • If a client shows the server as connected but never offers its tools, test with MCP Inspector first. If Inspector works, the problem is on the client side.

  • Some clients refuse to add a second server with the same URL. Remove the old entry before re-adding.

  • whoami failing with 401 about 8 hours after connecting is expected in this build: token refresh is the next step. Reconnect the server in your client as a workaround.

Security notes

  • Tokens: the GitHub access and refresh tokens live in the grant props, which workers-oauth-provider encrypts before writing to KV. The key is derived from the MCP access token held by the client, so KV contents alone cannot be decrypted.

  • Allowlist: ALLOWED_GITHUB_LOGINS in wrangler.jsonc. It matches login, which GitHub lets users rename; the numeric user id is stored in props if a stricter id check is wanted later.

  • The server is never authless: /mcp returns 401 without a valid token issued after the allowlist check.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Connects Claude to GitHub via OAuth and proxies official GitHub MCP tools, allowing each end user to interact with GitHub as themselves.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables self-hosted, read-only remote interaction with GitHub repositories, allowing listing repositories, searching code, and inspecting commits, pull requests, issues, and diffs via authenticated MCP clients.
    94 npm
    MIT