Connect Codex to GitHub
Published Jul 16, 2026 · Checked against the official docs
Connect Codex to GitHub and it can read a PR diff or trigger an Actions workflow, straight from a prompt. GitHub wrote the setup doc itself, so wiring it up is quick. What that doc doesn't say: remote and Docker each want the token in a different env var, and if your config still points at the old npm server, it's archived and nobody's patching it.
What you get
GitHub maintains this server itself and ships an install doc written for Codex specifically. Point Codex at it and you get tool access to repos, issues, pull requests, Actions runs, and gists, grouped into “toolsets” that GitHub turns on or off.
The default toolset, what loads if you configure nothing, is context, repos, issues, pull_requests, and users, per the github-mcp-server README. The full local catalog runs to twenty toolsets, adding actions, code_quality, code_security, copilot, dependabot, discussions, gists, git, labels, notifications, orgs, projects, secret_protection, security_advisories, and stargazers. The remote hosted server carries two the local image doesn’t have: copilot_spaces and github_support_docs_search.
In practice Codex can list your repos, comment on issues and PRs, read a PR diff, trigger an Actions workflow, and create a gist, all from a prompt. GitHub’s install doc gives these as test prompts: “List my GitHub repositories”, “Show me the diff for PR #123”, “Trigger the ‘deploy’ workflow in [owner/repo]”.
Setup
Two ways in: a server GitHub hosts, and a local Docker image. GitHub’s doc covers the remote path first, under its “Remote Configuration” heading, and that’s the one to start with. There’s no daemon to run and no image to pull.
1. Get a token. Create a GitHub Personal Access Token. GitHub’s scope guidance is repo for general repository operations, then workflow for Actions access, read:org for org-level resources, project for classic project boards, and gist for gist tools. The doc’s stated rule is least privilege: add a scope only when a tool call fails on a missing permission.
2. Remote. Add this to ~/.codex/config.toml (%USERPROFILE%\.codex\config.toml on Windows):
[mcp_servers.github]
url = "https://api.githubcopilot.com/mcp/"
bearer_token_env_var = "GITHUB_PAT_TOKEN"
Watch the trailing slash: /mcp/, not /mcp. That’s the exact path in GitHub’s doc. bearer_token_env_var holds the name of an environment variable, not the token itself, so the token never sits in the TOML file. Set it before launching Codex:
export GITHUB_PAT_TOKEN=ghp_your_token_here
Or let the CLI write the block for you:
codex mcp add github --url https://api.githubcopilot.com/mcp/ --bearer-token-env-var GITHUB_PAT_TOKEN
Those two flags landed in openai/codex #4904, merged 2025-10-08. Codex’s own MCP docs only show the stdio form of codex mcp add, so if your version rejects the flags, write the TOML block by hand instead.
You can use OAuth on the remote server rather than a PAT with codex mcp login github, per the general auth flow on Connect an MCP server.
3. Docker (self-hosted alternative). If policy keeps tokens off GitHub’s hosted endpoint, run the image locally. GitHub’s doc gives two auth modes.
OAuth, browser login on first use, no token needed up front:
[mcp_servers.github]
command = "docker"
args = ["run", "-i", "--rm", "-p", "127.0.0.1:8085:8085", "-e", "GITHUB_OAUTH_CALLBACK_PORT", "ghcr.io/github/github-mcp-server"]
[mcp_servers.github.env]
GITHUB_OAUTH_CALLBACK_PORT = "8085"
Personal Access Token, which GitHub’s doc says takes precedence over OAuth:
[mcp_servers.github]
command = "docker"
args = ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", "ghcr.io/github/github-mcp-server"]
[mcp_servers.github.env]
GITHUB_PERSONAL_ACCESS_TOKEN = "ghp_your_token_here"
GitHub’s doc writes that env table inline (env = { ... }). Same TOML either way.
Put the real value in your shell environment or an untracked .env, per mcp_servers.config.toml you might commit.
The blocks above are alternatives, so pick one. Two [mcp_servers.github] tables in the same file is a duplicate key and TOML won’t parse it.
4. Confirm it. Run codex mcp list and check github shows initialized. GitHub’s doc says to run /mcp in the TUI or open the IDE MCP panel and confirm github shows tools. Then ask it something real: “List my GitHub repositories”.
5. Clamp the toolset. Twenty toolsets is a lot for Codex to sort through on every turn. Two levers stack here. The Docker image reads GITHUB_TOOLSETS to decide what it registers at all, and the README documents --toolsets repos,issues,pull_requests as the equivalent flag, with the env var winning if you set both. Codex’s own enabled_tools and disabled_tools then filter what Codex sees, on either transport:
[mcp_servers.github]
url = "https://api.githubcopilot.com/mcp/"
bearer_token_env_var = "GITHUB_PAT_TOKEN"
enabled_tools = ["get_file_contents", "issue_read", "create_pull_request", "get_gist"]
Full detail on that key is on Connect an MCP server.
Gotchas
Two env vars, two different jobs. bearer_token_env_var = "GITHUB_PAT_TOKEN" is the remote server’s slot. It names the variable Codex reads to build the Authorization: Bearer header for the hosted endpoint. GITHUB_PERSONAL_ACCESS_TOKEN is the Docker server’s slot, the literal variable name the container itself expects, passed through in Codex’s env table. Setting one does nothing for the other.
JSON isn’t TOML, and GitHub ships a third shape. GitHub’s README installs into VS Code with its own JSON:
{
"servers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/"
}
}
}
That’s neither Codex’s TOML nor Claude Desktop’s mcpServers shape. Translate it the same way: servers.github becomes [mcp_servers.github], url carries over as-is, and type drops out, since Codex infers HTTP from the presence of url. Full table on Connect an MCP server.
A cold Docker pull can blow the startup window. The image has to download before the container can answer the MCP handshake, and startup_timeout_sec (default 10) doesn’t care why the process is slow to respond. This is the same pattern a cold npx hits. If codex mcp list shows a timeout on first use, raise startup_timeout_sec or run docker pull ghcr.io/github/github-mcp-server before you add the server. Detail on mcp_servers.
Retire the archived package. If an old config still points npx at @modelcontextprotocol/server-github, that’s the early reference implementation. It now lives in modelcontextprotocol/servers-archived, which the GitHub API reported as archived: true when we checked on 2026-07-16, described as “Reference MCP servers that are no longer maintained”. Its README says outright: “NO SECURITY GUARANTEES ARE PROVIDED FOR THESE ARCHIVED SERVERS.” Swap it for the remote endpoint or the ghcr.io/github/github-mcp-server image above.
Related
- Connect an MCP server: the general TOML shape and the JSON-to-TOML table
- mcp_servers.
.startup_timeout_sec : raising the launch window for a slow Docker pull - mcp_servers.
.env : keeping the token out of a committed file - How to install Codex: if Codex itself isn’t set up yet
Sources
- GitHub: Install GitHub MCP Server in OpenAI Codex (official)
- GitHub: github-mcp-server README (toolsets, Docker, default toolset)
- openai/codex #4904: adds --url and --bearer-token-env-var to codex mcp add (merged 2025-10-08)
- OpenAI Codex: official MCP docs (codex mcp add, login, list)
- modelcontextprotocol/servers-archived: archive notice for the old @modelcontextprotocol/server-github