-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Description
Problem
When merging PRs that modify .github/workflows/ files, the GitHub API requires the workflow OAuth scope. Without it, merge attempts fail with HTTP 403:
Resource not accessible by integration
The GitHub MCP Server currently doesn't have the workflow scope, causing silent failures when users try to merge Dependabot PRs that update GitHub Actions versions.
Investigation Findings
1. x-accepted-oauth-scopes Header Does NOT Help
Tested via curl on PR #605 (modifies 4 workflow files) vs PR #609 (no workflow files):
# PR with workflow changes
curl -s -I "https://api.github.com/repos/.../pulls/605/merge"
x-accepted-oauth-scopes: # EMPTY
# PR without workflow changes
curl -s -I "https://api.github.com/repos/.../pulls/609/merge"
x-accepted-oauth-scopes: # ALSO EMPTYBoth return empty x-accepted-oauth-scopes - GitHub doesn't advertise the workflow scope requirement in advance via headers.
2. Scope Enforcement is Content-Sensitive
The workflow scope is enforced at merge time based on what files are being changed, not declared in API metadata. The enforcement logic is roughly:
protected_dirs = [".github/workflows/", ".github/workflows-lab/"]
if user is authenticating via OAuth app
and token does NOT have "workflow" scope
and any changed file starts with protected_dirs:
reject with 403
3. No Pre-flight Detection Possible via Headers
The only reliable way to detect this requirement is to inspect PR files before merge.
Proposed Solutions
Option A: Add workflow scope to GitHub MCP Server OAuth
- Pros: Cleanest fix, full functionality
- Cons: This is a powerful scope (can create/modify/delete workflows) - probably shouldn't be on by default
Option B: Pre-flight file inspection in scope challenge middleware (Recommended)
Since the workflow scope is unique (content-sensitive rather than tool-based), add special handling in the scope challenge middleware:
- Intercept merge operations (
merge_pull_request,create_or_update_file) - Check if user has
workflowscope - if yes, proceed normally - If no
workflowscope, fetch PR files viaGET /repos/{owner}/{repo}/pulls/{pull_number}/files - Check paths against
.github/workflows/and.github/workflows-lab/ - If workflow files detected → return 401 with scope challenge:
WWW-Authenticate: Bearer resource="https://api.github.com", scope="workflow" - Otherwise → proceed with normal merge
This is different from other scopes because:
- Normal scopes: deterministic per-tool (
create_issue→reposcope) - Workflow scope: content-sensitive (
merge_pull_request→ check files → maybeworkflowscope)
Option C: Better error handling (Minimum viable)
- Detect the 403 error pattern
- Surface a clear message explaining why and how to resolve
Technical Context
- MCP uses SSE streams - can't do OAuth re-auth mid-stream
workflowscope grants significant permissions (create/modify/delete workflows)- Common scenario: Dependabot bumping
actions/checkout@v5→v6
Affected Use Cases
- Merging Dependabot PRs for GitHub Actions updates
- Any PR that touches
.github/workflows/*.ymlfiles - Users trying to batch-merge security updates
References
- GitHub OAuth Scopes
- RFC 9728: OAuth 2.0 Protected Resource Metadata