Skip to content

Consider workflow scope or user-escalation pattern for merging PRs that modify workflow files #1815

@SamMorrowDrums

Description

@SamMorrowDrums

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 EMPTY

Both 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:

  1. Intercept merge operations (merge_pull_request, create_or_update_file)
  2. Check if user has workflow scope - if yes, proceed normally
  3. If no workflow scope, fetch PR files via GET /repos/{owner}/{repo}/pulls/{pull_number}/files
  4. Check paths against .github/workflows/ and .github/workflows-lab/
  5. If workflow files detected → return 401 with scope challenge:
    WWW-Authenticate: Bearer resource="https://api.github.com", scope="workflow"
    
  6. Otherwise → proceed with normal merge

This is different from other scopes because:

  • Normal scopes: deterministic per-tool (create_issuerepo scope)
  • Workflow scope: content-sensitive (merge_pull_request → check files → maybe workflow scope)

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
  • workflow scope grants significant permissions (create/modify/delete workflows)
  • Common scenario: Dependabot bumping actions/checkout@v5v6

Affected Use Cases

  1. Merging Dependabot PRs for GitHub Actions updates
  2. Any PR that touches .github/workflows/*.yml files
  3. Users trying to batch-merge security updates

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions