# OAuth Authentication Flow for the Remote GitHub MCP Server: Complete Guide

> Master the OAuth authentication flow for the remote GitHub MCP server. Learn about Authorization Code flow, PKCE, and dynamic scope challenges. Get started now.

- Repository: [GitHub/github-mcp-server](https://github.com/github/github-mcp-server)
- Tags: how-to-guide
- Published: 2026-02-16

---

**The remote GitHub MCP server implements an OAuth 2.0 Authorization Code flow with optional PKCE support and a custom scope-challenge mechanism that dynamically requests additional GitHub permissions when tools require scopes beyond those initially granted.**

The `github/github-mcp-server` supports remote deployment scenarios where clients authenticate via OAuth 2.0 rather than personal access tokens. Understanding the OAuth authentication flow for the remote MCP server is essential for developers building integrations that interact with GitHub's API through the Model Context Protocol. This guide breaks down the complete authorization sequence—from initial app registration through dynamic scope challenges—based on the actual implementation in the repository source code.

## OAuth 2.0 Authorization Code Flow with PKCE

The server follows the **OAuth 2.0 Authorization Code flow** with optional **PKCE** (Proof Key for Code Exchange) to prevent authorization code interception attacks. The implementation defines supported GitHub scopes in [`pkg/http/oauth/oauth.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/oauth/oauth.go) within the `SupportedScopes` slice, which enumerates all available permissions the MCP server can request during authorization.

## Step-by-Step Authentication Process

### Register the OAuth Application

Before initiating authentication, you must register a GitHub OAuth App or GitHub App in your organization or user settings. This registration provides the **client_id** and **client_secret** required for the flow. For remote MCP server deployments, the redirect URI must point to your local or hosted callback endpoint capable of receiving the authorization code. Refer to [`docs/host-integration.md`](https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md) for detailed registration requirements.

### Initiate Authorization with PKCE

Generate a PKCE code verifier and challenge to secure the authorization request. The client opens GitHub's authorization endpoint at `https://github.com/login/oauth/authorize`—defined as `DefaultAuthorizationServer` in [`pkg/http/oauth/oauth.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/oauth/oauth.go)—including the challenge and requested scopes.

```bash

# Generate PKCE verifier and challenge

CODE_VERIFIER=$(openssl rand -base64 32 | tr -d '=+/')
CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl sha256 -binary | openssl base64 | tr -d '=+/')

# Open authorization URL (macOS)

open "https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8080/callback&scope=repo%20read:user&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256"

```

After user consent, GitHub redirects to your callback URL with a `code` parameter.

### Exchange Code for Access Token

Exchange the temporary authorization code for a **Bearer token** (prefixed with `gho_`) by posting to GitHub's token endpoint. The client performs this exchange—not the MCP server—using the client credentials and PKCE verifier.

```bash
curl -X POST https://github.com/login/oauth/access_token \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d code=AUTH_CODE \
  -d redirect_uri=http://localhost:8080/callback \
  -d code_verifier=$CODE_VERIFIER \
  -H "Accept: application/json"

```

The JSON response contains the `access_token` (e.g., `gho_xxxxxxxx`), `token_type` (Bearer), and granted `scope`.

### Authenticate MCP Requests

Include the Bearer token in the `Authorization` header for every MCP JSON-RPC request. The server extracts and validates these tokens using middleware defined in [`pkg/http/middleware/token.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/token.go).

```bash
curl -X POST https://api.githubcopilot.com/mcp/x/repos \
  -H "Authorization: Bearer gho_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"repo_get","arguments":{"owner":"octocat","repo":"Hello-World"}}}'

```

## Dynamic Scope Challenges

The remote MCP server implements a **scope-challenge** mechanism that requests additional permissions when tools require GitHub scopes not present in the current token.

### How Scope Challenges Work

When an MCP tool invocation requires additional scopes, the `WithScopeChallenge` middleware in [`pkg/http/middleware/scope_challenge.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/scope_challenge.go) intercepts the request. It returns a **403 Forbidden** response with a `WWW-Authenticate` header containing `error="insufficient_scope"` and the missing permissions.

The middleware fetches the token's current scopes using `scopeFetcher.FetchTokenScopes`, then constructs the challenge header including:
- `error="insufficient_scope"`
- `scope` parameter listing current plus required scopes
- `resource_metadata` URL pointing to the OAuth protected resource endpoint
- `error_description` explaining the missing permissions

### OAuth Protected Resource Metadata

The server advertises its OAuth configuration via the well-known endpoint `/.well-known/oauth-protected-resource`, implemented by the `metadataHandler()` function in [`pkg/http/oauth/oauth.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/oauth/oauth.go). This endpoint returns a JSON document containing:
- `resource`: The full URL of the MCP server
- `authorization_servers`: Array containing GitHub's OAuth URL (`https://github.com/login/oauth`)
- `scopes_supported`: Complete list from the `SupportedScopes` configuration in [`pkg/http/oauth/oauth.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/oauth/oauth.go)

### Handling Insufficient Scopes

When receiving a 403 scope challenge, clients must:
1. Parse the `WWW-Authenticate` header to extract the `scope` parameter showing required permissions
2. Extract the `resource_metadata` URL to confirm the server identity
3. Re-initiate the OAuth flow requesting the additional scopes listed in the challenge
4. Retry the original MCP request with the new token containing the expanded permissions

```bash

# Example: Handling a scope challenge response

# Server returns 403 with header:

# WWW-Authenticate: Bearer error="insufficient_scope", scope="repo read:user workflow", resource_metadata="https://api.githubcopilot.com/.well-known/oauth-protected-resource", error_description="Additional scopes required: workflow"

# Re-authorize with the additional workflow scope

open "https://github.com/login/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=http://localhost:8080/callback&scope=repo%20read:user%20workflow&code_challenge=$CODE_CHALLENGE&code_challenge_method=S256"

```

## Key Implementation Files

The OAuth authentication system is implemented across these critical files in the `github/github-mcp-server` repository:

- **[`pkg/http/oauth/oauth.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/oauth/oauth.go)**: Defines `DefaultAuthorizationServer`, `SupportedScopes`, and the `metadataHandler()` function for the OAuth protected resource endpoint.

- **[`pkg/http/middleware/scope_challenge.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/scope_challenge.go)**: Implements the `WithScopeChallenge` middleware that handles insufficient scope errors and constructs `WWW-Authenticate` challenge headers.

- **[`pkg/http/middleware/token.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/token.go)**: Handles extraction and validation of Bearer tokens from incoming requests, containing the OAuth protected resource metadata URL configuration.

- **[`docs/host-integration.md`](https://github.com/github/github-mcp-server/blob/main/docs/host-integration.md)**: Documentation for registering OAuth applications and host integration requirements.

- **[`docs/scope-filtering.md`](https://github.com/github/github-mcp-server/blob/main/docs/scope-filtering.md)**: Detailed explanation of scope challenges and dynamic permission requests.

- **[`docs/remote-server.md`](https://github.com/github/github-mcp-server/blob/main/docs/remote-server.md)**: Overview of remote server deployment and OAuth metadata endpoint specifications.

## Summary

- The remote GitHub MCP server implements **OAuth 2.0 Authorization Code flow** with optional PKCE support for secure token exchange.
- Authentication requires registering a GitHub OAuth App to obtain `client_id` and `client_secret` before initiating the authorization sequence.
- The server validates **Bearer tokens** (prefixed `gho_`) via middleware in [`pkg/http/middleware/token.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/token.go) on every MCP JSON-RPC request.
- A **scope-challenge mechanism** in [`pkg/http/middleware/scope_challenge.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/scope_challenge.go) enables dynamic permission requests when tools require additional GitHub scopes.
- The **OAuth protected resource metadata endpoint** at `/.well-known/oauth-protected-resource` advertises supported scopes and authorization server details.

## Frequently Asked Questions

### What OAuth flow does the remote GitHub MCP server use?

The server uses the **OAuth 2.0 Authorization Code flow** with optional **PKCE** (Proof Key for Code Exchange) support. This implementation is defined in [`pkg/http/oauth/oauth.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/oauth/oauth.go) through the `DefaultAuthorizationServer` configuration, requiring clients to exchange a temporary authorization code for a Bearer token via GitHub's standard token endpoint at `https://github.com/login/oauth/access_token`.

### How does the scope challenge mechanism work?

When an MCP tool requires GitHub scopes not present in the current token, the `WithScopeChallenge` middleware in [`pkg/http/middleware/scope_challenge.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/scope_challenge.go) returns a **403 Forbidden** response with a `WWW-Authenticate` header containing `error="insufficient_scope"`. The header includes a `scope` parameter listing the required permissions and a `resource_metadata` URL pointing to the OAuth protected resource endpoint, enabling clients to re-authenticate with elevated permissions.

### Where is the OAuth protected resource metadata endpoint located?

The metadata endpoint is located at `/.well-known/oauth-protected-resource` relative to the MCP server base URL. Implemented by the `metadataHandler()` function in [`pkg/http/oauth/oauth.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/oauth/oauth.go), this endpoint returns a JSON document containing the `resource` identifier, `authorization_servers` array (pointing to GitHub's OAuth endpoint), and `scopes_supported` list from the `SupportedScopes` configuration.

### What token format does GitHub return for MCP authentication?

GitHub returns **Bearer tokens** prefixed with `gho_` (representing GitHub OAuth tokens). Clients must include these tokens in the `Authorization: Bearer <token>` header for every MCP JSON-RPC request. The server extracts and validates these tokens using the middleware defined in [`pkg/http/middleware/token.go`](https://github.com/github/github-mcp-server/blob/main/pkg/http/middleware/token.go) before processing tool invocations.