Skip to main content

Documentation 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.

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 call /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/callback

How 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:
  1. Exchanges the GitHub code for a GitHub access token
  2. Fetches your GitHub username from https://api.github.com/user
  3. Checks whether your login is in ALLOWED_GITHUB_LOGINS
  4. Issues a local MCP authorization code (not a GitHub token) if the check passes
  5. Redirects ChatGPT’s OAuth client to the redirect URI with that local code
The GitHub access token is used only for identity — it is not stored or forwarded anywhere.

GitHub layer .env variables

GITHUB_CLIENT_ID=your_github_oauth_app_client_id
GITHUB_CLIENT_SECRET=your_github_oauth_app_client_secret
ALLOWED_GITHUB_LOGINS=your-github-username
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:
  1. Discover endpoints via /.well-known/oauth-authorization-server
  2. Direct your browser to /authorize (which triggers the GitHub flow above)
  3. Exchange the returned authorization code at /token for a Bearer access token
  4. Include that Bearer token on every request to /mcp
Access tokens are valid for 3600 seconds (1 hour) and are stored in memory only — they do not survive a server restart.

ChatGPT connector .env variables

OAUTH_CLIENT_ID=choose_a_client_id_for_chatgpt
OAUTH_CLIENT_SECRET=choose_a_strong_secret_for_chatgpt
OAUTH_REDIRECT_URIS=https://chatgpt.com/aip/g-.../ (provided by ChatGPT connector)
If you delete and recreate the ChatGPT connector, OpenAI may assign a new redirect URI. Update OAUTH_REDIRECT_URIS in your .env and restart the server when this happens.

OAuth Metadata Endpoints

The MCP server exposes two standard discovery endpoints that ChatGPT uses automatically:
EndpointPurpose
GET /.well-known/oauth-protected-resourceDeclares the resource URI, supported scopes, and authorization server location
GET /.well-known/oauth-authorization-serverDeclares the authorization endpoint, token endpoint, supported grant types, PKCE methods, and scopes
These endpoints are public and unauthenticated by design — they allow ChatGPT to discover the OAuth configuration without any prior credentials.

The Full Authorization Flow

1

ChatGPT initiates authorization

ChatGPT’s connector sends your browser to /authorize with its client_id, redirect_uri, resource, state, and PKCE code_challenge.
2

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.
3

You log in to GitHub

GitHub authenticates you and redirects back to /callback on your public hostname with a GitHub authorization code.
4

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.
5

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.
6

ChatGPT calls /mcp with the Bearer token

All subsequent MCP requests from ChatGPT include Authorization: Bearer <token>. Tokens expire after 1 hour; ChatGPT will restart the flow when they expire.

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.
AUTH_REQUIRE_PKCE=true

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 ::1 only
  • PUBLIC_BASE_URL must not use https://
  • CLOUDFLARE_TUNNEL_ENABLED must be false
  • NODE_ENV must be unset or development
# Safe local-only smoke test — NO tunnel, NO public URL
PUBLIC_BASE_URL=http://127.0.0.1:8789
CLOUDFLARE_TUNNEL_ENABLED=false
AUTH_REQUIRED=false
Never set AUTH_REQUIRED=false with a public URL, public hostname, or tunnel. Doing so exposes your entire local tool surface — filesystem, shell, browser, and desktop — to anyone who can reach the endpoint without any credential check. The server will refuse to start if it detects an unsafe combination, but your configuration still matters.
For the full remote connector setup, see the Path B setup guide.

Build docs developers (and LLMs) love