ChatGPT Local Agent MCP uses two completely separate OAuth layers that serve different purposes and use different credentials. The first layer uses GitHub as an identity provider — it answers the question “who is logging in?” The second layer runs a local OAuth server that acts as the authorization server for the ChatGPT connector — it answers the question “does ChatGPT have a valid token to callDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/XxYouDeaDPunKxX/chatgpt-local-agent-mcp/llms.txt
Use this file to discover all available pages before exploring further.
/mcp?” Mixing up these two layers is the most common configuration mistake, so understanding them separately is the first step.
Layer 1: GitHub OAuth App → MCP Server
Purpose
Verify the identity of the person authorizing the connection. GitHub is the identity provider — the MCP server uses it to confirm your login before issuing a local authorization code.
Callback URL
Your GitHub OAuth App must have this exact callback URL registered:
https://your-public-host.example/callbackHow the GitHub layer works
When ChatGPT triggers the authorization flow, the MCP server redirects your browser to GitHub for login. GitHub sends the result back to/callback on your public hostname. The server then:
- Exchanges the GitHub code for a GitHub access token
- Fetches your GitHub username from
https://api.github.com/user - Checks whether your login is in
ALLOWED_GITHUB_LOGINS - Issues a local MCP authorization code (not a GitHub token) if the check passes
- Redirects ChatGPT’s OAuth client to the redirect URI with that local code
GitHub layer .env variables
ALLOWED_GITHUB_LOGINS is a comma-separated list of lowercase GitHub usernames. Only logins on this list can complete the authorization flow and receive an access token for the MCP server. Everyone else receives access_denied.Layer 2: ChatGPT Connector → MCP Server
Purpose
Authorize ChatGPT itself as an OAuth client. ChatGPT uses your local OAuth server to obtain Bearer tokens for calling
/mcp.These are NOT GitHub credentials
OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET are values you choose when configuring the ChatGPT connector. They have nothing to do with your GitHub OAuth App.How the local OAuth layer works
The MCP server implements a standard OAuth 2.0 authorization server. ChatGPT’s connector uses it to:- Discover endpoints via
/.well-known/oauth-authorization-server - Direct your browser to
/authorize(which triggers the GitHub flow above) - Exchange the returned authorization code at
/tokenfor a Bearer access token - Include that Bearer token on every request to
/mcp
ChatGPT connector .env variables
OAuth Metadata Endpoints
The MCP server exposes two standard discovery endpoints that ChatGPT uses automatically:| Endpoint | Purpose |
|---|---|
GET /.well-known/oauth-protected-resource | Declares the resource URI, supported scopes, and authorization server location |
GET /.well-known/oauth-authorization-server | Declares the authorization endpoint, token endpoint, supported grant types, PKCE methods, and scopes |
The Full Authorization Flow
ChatGPT initiates authorization
ChatGPT’s connector sends your browser to
/authorize with its client_id, redirect_uri, resource, state, and PKCE code_challenge.Server validates and redirects to GitHub
The MCP server validates the client credentials and PKCE parameters, stores a pending authorization record, then redirects to
https://github.com/login/oauth/authorize.You log in to GitHub
GitHub authenticates you and redirects back to
/callback on your public hostname with a GitHub authorization code.Server checks the allowlist and issues a local code
The server exchanges the GitHub code, fetches your username, checks
ALLOWED_GITHUB_LOGINS, and issues a short-lived local MCP authorization code (valid for 5 minutes). Your browser is redirected to ChatGPT’s redirect_uri with this code.ChatGPT exchanges the code at /token
ChatGPT’s connector POSTs to
/token with its client credentials, the authorization code, and the PKCE code_verifier. The server validates everything and returns a Bearer access token.PKCE
PKCE (Proof Key for Code Exchange) is required by default (AUTH_REQUIRE_PKCE=true). Only the S256 method is supported. This prevents authorization code interception attacks and is the correct setting for any remote connector.
Disabling Authentication
AUTH_REQUIRED=false bypasses the entire OAuth flow and is intended only for localhost-only smoke testing before OAuth is configured. The server enforces several guards when this is set:
- The server must bind to
127.0.0.1,localhost, or::1only PUBLIC_BASE_URLmust not usehttps://CLOUDFLARE_TUNNEL_ENABLEDmust befalseNODE_ENVmust be unset ordevelopment