Skip to content

ci: restore the Claude Code workflow and .mcp.json, lost in the v2 tree swap - #1869

Merged
cliffhall merged 2 commits into
v2/mainfrom
v2/ci/restore-claude-workflow
Aug 1, 2026
Merged

ci: restore the Claude Code workflow and .mcp.json, lost in the v2 tree swap#1869
cliffhall merged 2 commits into
v2/mainfrom
v2/ci/restore-claude-workflow

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes #1850.

Recreated from #1851, which GitHub auto-closed when its head branch was renamed ci/restore-claude-workflowv2/ci/restore-claude-workflow to satisfy the version-prefix branch convention. Same commits, same content; #1851 could not be reopened because its original head ref no longer exists.

Same regression class as #1843 (SECURITY.md): the v2 tree swap replaced the default branch's tree, and neither .github/workflows/claude.yml nor .mcp.json existed in the v2 tree, so both were silently dropped.

Impact

issue_comment / pull_request_review_comment / issues events always run workflows from the default branch, so losing the workflow disabled @claude repo-wide — including on PRs targeting v2/main.

Found the hard way: two @claude review comments on #1847 (19:08 and 19:10 UTC) produced no bot reply and no workflow run.

Evidence

Check Result
actions/workflows/173749385 state deleted
Last 3 runs (issue_comment, latest 03:10 UTC today) all skipped
.github/workflows/ on main only main.yml
ac3c1a12 (last commit carrying the file) not an ancestor of current main

The change

Two files, both restored byte-for-byte, both verified after the copy:

File Source sha256 Bytes
.github/workflows/claude.yml ac3c1a12 1c44f2d9d51c936adb40c9acefd4b44628fe7810360e2f8196034347f9d2602d 3592
.mcp.json 47f92841 (v1/main) b0f0b8ea0d6c6e4bd9d19270db8c4ed13a951c6a7d8fa9a7b76d0d12ddd2491f 123

No content changes to either. The @claude trigger remains gated to OWNER / MEMBER / COLLABORATOR author associations, which is the behavior we want under the issues-only contribution model (#1820).

Why .mcp.json is in the same PR

The workflow runs with --mcp-config .mcp.json and --allowedTools "Bash,mcp__mcp-docs". .mcp.json registers the mcp-docs HTTP server (https://modelcontextprotocol.io/mcp) and was lost in the same swap — it survives only on v1/main:

git ls-tree --name-only origin/main .mcp.json     # (empty)
git ls-tree --name-only origin/v2/main .mcp.json  # (empty)
git ls-tree --name-only origin/v1/main .mcp.json  # .mcp.json

Restoring the workflow without it would register no MCP server, so the mcp__mcp-docs tools would not resolve and the protocol-documentation lookups that --append-system-prompt explicitly directs it to make would silently do nothing. Shipping them together avoids a window where the workflow is on v2/main pointing at a file that isn't.

Why this targets v2/main and not main

This work originally targeted main. It now targets v2/main, the develop branch that merges into main at milestone releases. Landing on v2/main is what makes the fix durable: restoring only to main would be undone by the next milestone merge, which is precisely how these files were lost.

Correction to #1851's description. It claimed main and v2/main share no common git ancestor and that this is why the PR read as conflicted across a dozen untouched files. That is wrong — the claim came from running git merge-base in a shallow clone, which truncates history so the base isn't reachable. The branches do share a base, 4d30d1cd, established by the go-live merge (#1830); after git fetch --unshallow it resolves normally. The rebuild onto v2/main was still the right move, and the diff here is the two files above and nothing else.

Verifying after merge

@claude cannot work until this reaches main, which happens at the next milestone merge — a workflow on a non-default branch is not consulted for issue_comment events. After that, comment @claude review on any open PR; claude[bot] should reply within ~20s (it took 19s on #1825). If it's needed before the milestone, that wants a separate direct-to-main PR in addition to this one.

Testing

No source files are touched, so nothing in validate or coverage measures this change — the format globs cover core/, scripts/, the shared surface, and each client's scope, none of which reach a workflow YAML or a root-level JSON. npx prettier --check .mcp.json passes.

Note

SECURITY.md (#1843, plus #1864/#1867 for the v2/main half), claude.yml, and .mcp.json are three instances of one pattern, and none was caught by CI. A sweep for anything else the swap dropped is worth doing separately — and, contrary to #1851's closing note, git can surface these directly, since the branches share history: git diff --stat origin/main origin/v2/main lists the divergence.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU

cliffhall and others added 2 commits July 31, 2026 13:40
Closes #1850.

Restored byte-for-byte from ac3c1a1 (sha256
1c44f2d9d51c936adb40c9acefd4b44628fe7810360e2f8196034347f9d2602d,
3592 bytes). No content changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
The restored workflow runs with `--mcp-config .mcp.json` and
`--allowedTools "Bash,mcp__mcp-docs"`, so without this file the mcp-docs
server never registers and those tools do not resolve.

Lost in the same tree swap: .mcp.json survives only on v1/main, and is
absent from both main and v2/main. Restored byte-for-byte from 47f9284
(sha256 b0f0b8ea0d6c6e4bd9d19270db8c4ed13a951c6a7d8fa9a7b76d0d12ddd2491f,
123 bytes). No content changes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Restores the repository’s Claude Code GitHub Actions workflow and its .mcp.json MCP-server configuration, which were dropped during the v2 tree swap, to re-enable @claude-triggered automation once the changes reach the default branch.

Changes:

  • Re-add .github/workflows/claude.yml to handle @claude triggers on issue/PR events.
  • Re-add .mcp.json defining the mcp-docs HTTP MCP server used by the workflow.
  • Ensure the workflow continues to invoke Claude Code with the MCP config and allowed tools.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/workflows/claude.yml Restores the Claude Code workflow that reacts to @claude across issue/PR-related events.
.mcp.json Restores MCP server configuration (mcp-docs) used by the Claude workflow.
Suppressed comments (1)

.github/workflows/claude.yml:80

  • If the PR is from a fork (or PR metadata lookup fails), the workflow falls back to checking out the base repository but will still run Claude. That can lead to commenting based on the wrong code (default branch) and still consumes secrets/time. Gate the Claude step so it only runs for same-repo PRs, while still allowing non-PR issue/issue_comment triggers.
      - name: Run Claude Code
        id: claude
        uses: anthropics/claude-code-action@v1
        with:

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +32 to +36
contents: read
pull-requests: read
issues: read
id-token: write
actions: read

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • >

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not taking this one — the premise is factually incorrect, and acting on it would weaken the workflow's security posture for no gain.

anthropics/claude-code-action does not post through GITHUB_TOKEN. It exchanges the OIDC token granted by id-token: write (present on line 35) for a Claude Code GitHub App installation token, and that app token carries its own write scopes. The permissions: block on lines 31-36 scopes GITHUB_TOKEN only, so read-only grants there do not gate comment or review posting.

Verified empirically rather than by reading docs:

  • ac3c1a12, the commit this file is restored byte-for-byte from, is dated 2026-07-17 and is the last commit that touched claude.yml.
  • claude[bot] posted on docs: refresh V2 board Status option IDs in AGENTS.md (#1823) #1825 on 2026-07-27 — ten days later, so this exact permissions block was live — twice, at 23:45:01Z and 23:47:53Z, each ~20s after a @claude review comment.

So @claude demonstrably replied under issues: read / pull-requests: read. The failure this PR fixes was the workflow file being absent from the default branch after the v2 tree swap (actions/workflows/173749385 is in state deleted), not a permissions problem.

Widening these to write would hand a broader GITHUB_TOKEN to a job that runs a tool-enabled agent with Bash allowed, which is exactly the grant worth keeping minimal. Leaving them read-only.

core.setOutput('repo', pr.data.head.repo.full_name);

- name: Checkout PR branch
if: steps.pr.outcome == 'success'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legitimate class of concern, and I'm not dismissing it — but deferring it to its own PR rather than folding it in here. Tracked as #1882 (on the v2 board), which also captures your suppressed comment about the fallback branch reviewing the base tree while still spending secrets.

Two reasons it isn't changing in this PR:

1. This PR's contract is a byte-for-byte restore. Both files are restored unmodified from the commits that last carried them (claude.yml from ac3c1a12, sha256 1c44f2d9…2602d, 3592 bytes; .mcp.json from 47f92841, sha256 b0f0b8ea…491f, 123 bytes). The value of that is that the restored workflow is a known-working artifact — it was live and answering @claude through 2026-07-27. Mixing a behavior change into the restore means a post-merge failure has two candidate causes instead of zero, and this workflow can only be exercised from the default branch, so it isn't testable until after it lands.

2. The exposure is already structurally mitigated here.

  • Every trigger arm requires contains(fromJSON('["OWNER", "MEMBER", "COLLABORATOR"]'), …author_association), so an outside contributor cannot self-trigger the workflow on their own PR. That gate is intentional under the issues-only contribution model (go-live 6/9: restrict PRs to collaborators; CONTRIBUTORS.md + SECURITY.md #1820) and is staying.
  • The repo's pull_request_creation_policy is collaborators_only (confirmed via gh api repos/modelcontextprotocol/inspector), so PRs from non-collaborators cannot be opened at all.

The residual path is a maintainer deliberately invoking @claude on a collaborator's fork branch — and collaborators already hold repo access, so the marginal exposure over the status quo is small. Real, worth closing, not urgent enough to compromise the restore.

#1882 carries the candidate fixes: gating the head checkout on head.repo.full_name == github.repository, and/or gating the Run Claude Code step itself on same-repo so the fallback can't review the wrong tree.

@cliffhall
cliffhall merged commit ee707db into v2/main Aug 1, 2026
14 checks passed
@cliffhall
cliffhall deleted the v2/ci/restore-claude-workflow branch August 1, 2026 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Claude Code workflow (.github/workflows/claude.yml) and .mcp.json lost in the v2 tree swap — @claude no longer triggers

3 participants