Skip to content

Commit 3704533

Browse files
tadasantclaude
andauthored
Restrict @claude bot to mcp org only, fix fork behavior (#819)
Written by Claude Code, reviewed by me. ## Summary Fixes `@claude` to work on external fork PRs by: 1. Restricting triggers to modelcontextprotocol org members only 2. Properly checking out fork PR code via `refs/pull/N/head` ## Background The `@claude` GitHub app was failing on external forks ([example](https://github.com/modelcontextprotocol/registry/actions/runs/19938435814/job/57169634431)) because the action tried to fetch branches by name, which doesn't work for forks. ## Changes ### Org membership check - Fetches the member list from [`modelcontextprotocol/access`](https://github.com/modelcontextprotocol/access) repo's `users.ts` - Only org members can trigger `@claude` (prevents strangers from using it) - Uses `github.triggering_actor` so the person commenting must be an org member ### Fork PR checkout fix - Detects when a comment is on a fork PR - Uses `refs/pull/{number}/head` to checkout fork code (instead of branch name) - This works because GitHub exposes all PRs via special refs on the base repo ## How it works 1. Org member comments `@claude` on a fork PR 2. Workflow checks if commenter is in the `modelcontextprotocol/access` member list 3. Workflow detects it's a fork PR and checks out via `refs/pull/N/head` 4. Claude runs with access to the fork's code 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude <[email protected]>
1 parent 8b861e5 commit 3704533

File tree

1 file changed

+33
-0
lines changed

1 file changed

+33
-0
lines changed

.github/workflows/claude.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,43 @@ jobs:
2525
id-token: write
2626
actions: read
2727
steps:
28+
# Only allow modelcontextprotocol org members to trigger @claude
29+
# This enables @claude to work on external fork PRs when triggered by org members
30+
# Members list is fetched from modelcontextprotocol/access repo
31+
- name: Check if org member
32+
run: |
33+
ACTOR="${{ github.triggering_actor }}"
34+
USERS_URL="https://raw.githubusercontent.com/modelcontextprotocol/access/main/src/config/users.ts"
35+
36+
# Fetch users.ts and extract GitHub usernames
37+
MEMBERS=$(curl -fsSL "$USERS_URL" | grep -oE 'github:\s*"[^"]+"' | sed 's/github:\s*"//;s/"$//')
38+
39+
if echo "$MEMBERS" | grep -qxF "$ACTOR"; then
40+
echo "User $ACTOR is a member of modelcontextprotocol org"
41+
else
42+
echo "::error::User $ACTOR is not a member of the modelcontextprotocol org. Only org members can trigger @claude."
43+
exit 1
44+
fi
45+
46+
# For PR comments, get PR details to checkout the correct branch (including forks)
47+
- name: Get PR details
48+
id: pr
49+
if: github.event.issue.pull_request
50+
env:
51+
GH_TOKEN: ${{ github.token }}
52+
run: |
53+
PR_DATA=$(gh api ${{ github.event.issue.pull_request.url }})
54+
echo "number=$(echo "$PR_DATA" | jq -r '.number')" >> $GITHUB_OUTPUT
55+
echo "head_ref=$(echo "$PR_DATA" | jq -r '.head.ref')" >> $GITHUB_OUTPUT
56+
echo "head_repo=$(echo "$PR_DATA" | jq -r '.head.repo.full_name')" >> $GITHUB_OUTPUT
57+
echo "is_fork=$(echo "$PR_DATA" | jq -r '.head.repo.fork')" >> $GITHUB_OUTPUT
58+
2859
- name: Checkout repository
2960
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd
3061
with:
3162
fetch-depth: 1
63+
# For fork PRs, checkout via PR ref; otherwise use the branch directly
64+
ref: ${{ steps.pr.outputs.is_fork == 'true' && format('refs/pull/{0}/head', steps.pr.outputs.number) || steps.pr.outputs.head_ref || github.ref }}
3265

3366
- name: Run Claude Code
3467
id: claude

0 commit comments

Comments
 (0)