github-mcp-server. The agent sees familiar tools — create_pull_request, issue_write, get_file_contents — under the github alias, but every call is authorized, scoped, and attributed by the proxy, and GitHub credentials never enter the sandbox. This page covers the catalog, how the allowlist is computed, and the capability gates. Read it with the mounts reference, which owns the declaration syntax.
How access is provisioned
GitHub access is mount-backed. A session gets thegithub MCP server if and only if its agent has at least one kind: git mount with auth: { kind: githubApp } — the mounts are what the proxy mints tokens from. A kind: github tool declaration only tunes the tool list on top of that:
.auto/agents/pr-review.yaml
- Mounts, no
githubtool: the server is wired anyway with the default allowlist. githubtool, no githubApp mount: the tool is a silent no-op — no server is wired, because every call would be rejected.- The alias defaults to
github, so tools appear to the model asmcp__github__create_pull_requestand the other names models already know.
The credential model
The sandbox holds only a session-scoped bearer token for the proxy endpoint. Per request, the proxy:- Resolves the session’s githubApp mounts and rejects sessions that have none.
- Determines the target repository from the tool call’s arguments. The repo must be a mount or a repository the project is authorized to use — anything else is rejected with
repository is not authorized for this project. - Mints a fresh GitHub App installation token, down-scoped at mint time to the target repository and to the permission set derived from the mount’s capabilities.
- Forwards the single
tools/callupstream with the tool allowlist enforced. Theghs_token exists only between the proxy and the upstream server; it is never returned to the sandbox.
github-mcp-server v1.3.0) running the repos, issues, pull_requests, and actions toolsets, so the catalog below is stable rather than tracking upstream releases silently.
The catalog
An agent’skind: github tool may select from 49 names: 41 upstream tools plus 8 implemented by the proxy itself.
Upstream (41): actions_get, actions_list, actions_run_trigger, add_comment_to_pending_review, add_issue_comment, add_reply_to_pull_request_comment, create_branch, create_or_update_file, create_pull_request, create_repository, delete_file, fork_repository, get_commit, get_file_contents, get_job_logs, get_label, get_latest_release, get_release_by_tag, get_tag, issue_read, issue_write, list_branches, list_commits, list_issue_types, list_issues, list_pull_requests, list_releases, list_repository_collaborators, list_tags, merge_pull_request, pull_request_read, pull_request_review_write, push_files, search_code, search_commits, search_issues, search_pull_requests, search_repositories, sub_issue_write, update_pull_request, update_pull_request_branch.
Proxy-implemented (8): executed by auto itself with the same per-call minted token, injected into tools/list, never forwarded upstream:
The proxy also extends
pull_request_read with a labels sub-operation.
The default allowlist
Omittingtools: applies a curated 24-tool default: PR flow (create_pull_request, pull_request_read, update_pull_request, update_pull_request_branch, pull_request_review_write, add_comment_to_pending_review, add_reply_to_pull_request_comment), issue/comment flow (add_issue_comment, delete_issue_comment, upsert_issue_comment, download_comment_attachment, issue_read, issue_write), search (search_pull_requests, search_issues, search_code), repo content (get_file_contents, list_commits, create_branch, create_or_update_file, push_files), and Actions reads (actions_get, actions_list, get_job_logs).
Deliberately excluded by default — name them explicitly to opt in: create_repository, fork_repository, delete_file, actions_run_trigger, rerun_failed_jobs, rerun_failed_jobs_for_pr_head, list_repository_collaborators, sub_issue_write, release/tag/label reads, search_repositories, search_commits. Merge and secrets tools work differently: they follow the mount capability, not the tool list — a mount granting merge: write or secrets: adds them on top of the curated default automatically, and without the grant they stay invisible even when named explicitly (merging with no human in the loop is an opt-in, not a default).
Naming tools: replaces the default entirely — the effective list is exactly the names you give, still subject to the capability gates below.
Capability scoping from mounts
Each githubApp mount declares capability levels that become both the minted token’s GitHub permissions and the proxy’s gates:
Every minted token also carries
metadata: read. merge: write requires contents: write and pullRequests: write on the same mount — GitHub has no standalone merge permission, so an incoherent grant is rejected at apply time.
Two tool families are double-gated — invisible and uncallable unless granted, even when an agent names them explicitly:
- Merge tools (
merge_pull_request,enable_pull_request_auto_merge): visible only when some mount grantsmerge: write; per call, the target repository’s own mount must grant it. A merge-granted session still cannot merge on its other, non-granted repositories. - Secrets tools:
actions_secret_listneedssecrets: reador better,actions_secret_writeneedssecrets: write— same two-level model, session visibility from the maximum across mounts, per-repo re-check against the called repo’s mount.
actions: write, and the currently applied target mount must still grant actions: write when the token is minted. A later capability grant does not add the mutation to an already-running session, a later revocation stops the call, and broader bearer-token scopes cannot bypass either snapshot. Agents should use a rerun tool only with explicit human authority for the workflow run being rerun.
rerun_failed_jobs_for_pr_head adds a point-of-use fence: immediately before the mutation, the proxy requires the PR to be open, both the live PR and run heads to match the expected full SHA, the run’s current attempt to match the expected attempt, and that attempt to be completed with conclusion failure. GitHub’s failed-jobs rerun endpoint has no conditional head or attempt parameter, so the live reads and POST are not provider-atomic. The residual race can rerun only the old workflow; downstream orchestration must still verify the current PR head and evidence cycle and must never count a stale rerun as current evidence.
A called repository that is itself a mount uses that mount’s capabilities. A project-authorized repository that is not a mount gets the standard default capability set, with merge, secrets, and explicitly gated Actions mutations always denied.
Guardrails on write tools
Beyond scoping, the proxy enforces several invariants:- Visible attribution: covered write-tool bodies are stamped with an agent-attribution header derived from the session identity (never from tool arguments), linking back to the session page when project slugs resolve.
- Artifact attribution: successful write-tool calls are recorded as artifact attributions — this is how a PR an agent opens auto-binds to its session on
pull_request.opened(see triggers and sessions). - Commit-author verification at PR creation, so attributed authorship on PRs matches the platform’s records.
- Comment substance guard:
add_issue_commentrejects near-empty bodies before anything is minted or forwarded, so a stray placeholder can never land on an issue. - One
tools/callper request: batched calls are rejected outright rather than partially attributed. - A tool outside the session’s allowlist fails with a tool-level error (
unknown tool "…": not enabled for this session), which agents recover from far better than a transport error.
Example: a review agent’s GitHub surface
A PR-review agent that comments and manages checks but can never merge or push:.auto/agents/pr-review.yaml
contents: read, the minted tokens cannot push even through git; with no merge capability, merge tools do not exist for this session regardless of what any prompt asks for.