# Which token scopes does the GitHub MCP server need?

Source: https://forum.codelifter.com/posts/which-token-scopes-does-the-github-mcp-server-need/
Site: CodeLifter Forum, category MCP and tools
Published: 2026-10-16. Updated: 2026-10-16. Replies: 0.

## Question by CodeLifter editors (staff), 2026-10-16

Only the scopes for the tools you turn on. With a classic token, repo covers most repository, issue and pull request tools; add workflow, gist, notifications or read:org only when you need those tools. GitHub recommends a fine-grained token limited to selected repositories instead, but the server then shows every tool and leaves enforcement to the API.

## How the server reacts to each kind of token

The official server behaves differently depending on how you sign in. Its [scope filtering document](https://github.com/github/github-mcp-server/blob/main/docs/scope-filtering.md) sets it out:

| Token type | Prefix | What the server does |
| --- | --- | --- |
| Classic personal access token | `ghp_` | Reads your scopes at startup and hides tools your token cannot use |
| OAuth (hosted server) | none to set | Shows all tools, then prompts you to grant a missing scope when a tool needs it |
| Fine-grained personal access token | `github_pat_` | No filtering: "all tools shown, API enforces permissions" |
| GitHub App installation token | `ghs_` | No filtering; permissions come from the app installation |

Two details catch people out. If the server cannot read your classic token's scopes (the document gives network issues or rate limiting as examples), it "logs a warning and continues without filtering." And read-only repository tools that only need `repo` or `public_repo` stay visible even without those scopes, because they work on public repositories.

## Scopes by job

The server's [README](https://github.com/github/github-mcp-server) lists the OAuth scopes each tool may ask for. The middle column below comes from that list. The right column gives the fine-grained permission named for the same resource in GitHub's [personal access token documentation](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens); that pairing is our reading, so confirm it against an API response (see the last section).

| What you want the assistant to do | Classic scope | Closest fine-grained permission |
| --- | --- | --- |
| Read files, commits, issues and pull requests in private repos | `repo` | Contents, Issues, Pull requests: read |
| Open issues and add comments (`issue_write`, `add_issue_comment`) | `repo` | Issues: write |
| Push files, open and merge pull requests (`push_files`, `create_pull_request`, `merge_pull_request`) | `repo` | Contents and Pull requests: write |
| Change a file under `.github/workflows/` | `repo` plus `workflow` | Workflows: write |
| List or trigger Actions runs, read job logs (`actions` toolset, off by default) | `repo` | Actions: read, or write to trigger |
| Code scanning and Dependabot alerts | `security_events` (included in `repo`) | Code scanning alerts, Dependabot alerts: read |
| Create or update gists | `gist` | Gists: write (account permission) |
| List or dismiss notifications | `notifications` | No notifications permission appears in GitHub's fine-grained list |
| Read teams and members (`get_teams`, `get_team_members`) | `read:org` | Members (organization permission): read |
| Delete a repository (`delete_repository`) | `delete_repo` plus `repo` | Do not grant it |

The scope filtering document notes that `workflow` is requested "only when the call changes a workflow file." That scope is worth keeping off unless you need it, because a workflow file decides what GitHub Actions runs in that repository.

The README's own "Token Security Best Practices" list `repo`, `read:packages` (for "Docker image access") and `read:org` as minimum scopes. The same README says the Docker image at `ghcr.io/github/github-mcp-server` is public, so test whether you need `read:packages` before you add it.

## Set up a fine-grained token for one project

1. On GitHub, open Settings, then Developer settings, then Personal access tokens, then Fine-grained tokens, and click Generate new token.
2. Set an expiration. GitHub's documentation says infinite lifetimes "may be blocked by a maximum lifetime policy" in some organisations, and recommends an expiry in any case.
3. Under Resource owner, pick your account or the organisation that owns the repository.
4. Under Repository access, choose Only select repositories and pick the ones the assistant should touch. GitHub notes that tokens "always include read-only access to all public repositories on GitHub."
5. Under Permissions, start with Contents: read, Issues: read and Pull requests: read. Add write permissions one at a time when a task fails for lack of them.
6. Generate the token and store it in an environment variable, not in a committed file. The server reads it from `GITHUB_PERSONAL_ACCESS_TOKEN`.

Because a fine-grained token disables the server's tool filtering, limit the tools on the server side too:

```bash
github-mcp-server stdio --toolsets=repos,issues,pull_requests --read-only
```

The [server configuration guide](https://github.com/github/github-mcp-server/blob/main/docs/server-configuration.md) says read-only mode disables write tools "even when explicitly requested," and that `--exclude-tools` removes listed tools "regardless of any other configuration." If you allow writes, exclude the riskiest tools by name, for example `--exclude-tools=merge_pull_request,delete_file`.

## When a classic token is the only option

GitHub's documentation lists cases fine-grained tokens do not cover yet, including contributing to public repositories where you are not a member, working as an outside collaborator, and accessing several organisations at once. In those cases a classic token is needed. Remember that a classic token "will grant access to all repositories within the organizations that you have access to, as well as all personal repositories," so pair it with `--read-only` or a short toolset list.

## Check what your token actually has

For a classic token, the scope filtering document gives this command:

```bash
curl -sI -H "Authorization: Bearer $GITHUB_PERSONAL_ACCESS_TOKEN" \
  https://api.github.com/user | grep -i x-oauth-scopes
```

For a fine-grained token, GitHub's REST documentation says responses carry an `X-Accepted-GitHub-Permissions` header naming the permissions an endpoint needs, which is the quickest way to settle a "Resource not accessible" error.

Scopes are only half of the picture; where the server runs is the other half. See [remote or local GitHub MCP server](/posts/remote-or-local-github-mcp-server-which-should-you-run/) for that choice, and [who is the author of a commit made through an MCP server](/posts/who-is-the-author-of-a-commit-made-through-an-mcp-server/) for what happens to authorship once you allow writes. The CodeLifter [GitHub MCP server page](https://codelifter.com/mcp/github/) lists every toolset and what it can change.

---
Cite as: CodeLifter Forum, "Which token scopes does the GitHub MCP server need?", https://forum.codelifter.com/posts/which-token-scopes-does-the-github-mcp-server-need/, accessed 2026-10-16.
