Skip to content

Commit 94b1f9f

Browse files
authored
Merge branch 'main' into add-agent-skills
2 parents 88f987c + 0e2fc38 commit 94b1f9f

30 files changed

Lines changed: 725 additions & 258 deletions

.github/workflows/docker-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ jobs:
106106
# https://github.com/docker/build-push-action
107107
- name: Build and push Docker image
108108
id: build-and-push
109-
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
109+
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0
110110
with:
111111
context: .
112112
push: ${{ github.event_name != 'pull_request' }}

.github/workflows/license-check.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
- name: Check if already commented
7878
if: steps.changes.outcome == 'failure' && steps.push.outcome == 'failure'
7979
id: check_comment
80-
uses: actions/github-script@v8
80+
uses: actions/github-script@v9
8181
with:
8282
script: |
8383
const { data: comments } = await github.rest.issues.listComments({
@@ -95,7 +95,7 @@ jobs:
9595
9696
- name: Comment with instructions if cannot push
9797
if: steps.changes.outcome == 'failure' && steps.push.outcome == 'failure' && steps.check_comment.outputs.already_commented == 'false'
98-
uses: actions/github-script@v8
98+
uses: actions/github-script@v9
9999
with:
100100
script: |
101101
await github.rest.issues.createComment({

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ COPY ui/ ./ui/
77
RUN mkdir -p ./pkg/github/ui_dist && \
88
cd ui && npm run build
99

10-
FROM golang:1.25.9-alpine@sha256:04d017a27c481185c169884328a5761d052910fdced8c3b8edd686474efdf59b AS build
10+
FROM golang:1.25.9-alpine@sha256:5caaf1cca9dc351e13deafbc3879fd4754801acba8653fa9540cea125d01a71f AS build
1111
ARG VERSION="dev"
1212

1313
# Set the working directory

docs/installation-guides/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This directory contains detailed installation instructions for the GitHub MCP Se
1313
- **[OpenAI Codex](install-codex.md)** - Installation guide for OpenAI Codex
1414
- **[Roo Code](install-roo-code.md)** - Installation guide for Roo Code
1515
- **[Windsurf](install-windsurf.md)** - Installation guide for Windsurf IDE
16+
- **[Xcode (Codex & Claude Agent)](install-xcode.md)** - Installation guide for Codex and Claude Agent within Xcode
1617

1718
## Support by Host Application
1819

@@ -32,6 +33,8 @@ This directory contains detailed installation instructions for the GitHub MCP Se
3233
| Windsurf || ✅ PAT + ❌ No OAuth | Docker or Go build, GitHub PAT | Easy |
3334
| Copilot in Xcode || ✅ Full (OAuth + PAT) | Local: Docker or Go build, GitHub PAT<br>Remote: Copilot for Xcode 0.41.0+ | Easy |
3435
| Copilot in Eclipse || ✅ Full (OAuth + PAT) | Local: Docker or Go build, GitHub PAT<br>Remote: Eclipse Plug-in for Copilot 0.10.0+ | Easy |
36+
| Xcode (Codex) || ✅ PAT + ❌ No OAuth | Local: Docker (full path required), GitHub PAT<br>Remote: GitHub PAT via `GITHUB_PAT_TOKEN` env var (`bearer_token_env_var`) | Easy |
37+
| Xcode (Claude Agent) || ✅ PAT + ❌ No OAuth | Local: Docker (full path required), GitHub PAT<br>Remote: GitHub PAT | Easy |
3538

3639
**Legend:**
3740
- ✅ = Fully supported

docs/installation-guides/install-claude.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,75 @@ Add this codeblock to your `claude_desktop_config.json`:
164164

165165
---
166166

167-
## Troubleshooting
167+
## Xcode (Claude Agent)
168+
169+
Xcode's Claude Agent uses the same `.claude.json` configuration format as the Claude Code CLI, but reads it from an Xcode-specific directory rather than the global config location.
170+
171+
### Configuration File Location
172+
173+
```
174+
~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude.json
175+
```
176+
177+
> Configurations placed here only affect Claude Agent when launched from Xcode. See [Apple's documentation](https://developer.apple.com/documentation/xcode/setting-up-coding-intelligence#Customize-the-Claude-Agent-and-Codex-environments) for more details.
178+
179+
### Remote Server Setup (Recommended)
180+
181+
Run the following command in Terminal to add the remote GitHub MCP server:
182+
183+
```bash
184+
claude mcp add-json github '{"type":"http","url":"https://api.githubcopilot.com/mcp/","headers":{"Authorization":"Bearer YOUR_GITHUB_PAT"}}' --config ~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude.json
185+
```
186+
187+
Or open the file in a text editor and add the `mcpServers` block manually:
188+
189+
```json
190+
{
191+
"mcpServers": {
192+
"github": {
193+
"type": "http",
194+
"url": "https://api.githubcopilot.com/mcp/",
195+
"headers": {
196+
"Authorization": "Bearer YOUR_GITHUB_PAT"
197+
}
198+
}
199+
}
200+
}
201+
```
202+
203+
### Local Server Setup (Docker)
204+
205+
> **macOS note**: Xcode runs with a minimal `PATH` that typically excludes `/usr/local/bin` (Intel) and `/opt/homebrew/bin` (Apple Silicon). Use the full path to `docker` to ensure it can be found. Run `which docker` in Terminal to find the correct path on your system.
206+
207+
```json
208+
{
209+
"mcpServers": {
210+
"github": {
211+
"command": "/usr/local/bin/docker",
212+
"args": [
213+
"run",
214+
"-i",
215+
"--rm",
216+
"-e",
217+
"GITHUB_PERSONAL_ACCESS_TOKEN",
218+
"ghcr.io/github/github-mcp-server"
219+
],
220+
"env": {
221+
"GITHUB_PERSONAL_ACCESS_TOKEN": "YOUR_GITHUB_PAT"
222+
}
223+
}
224+
}
225+
}
226+
```
227+
228+
### Setup Steps
229+
1. Create or open `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/.claude.json`
230+
2. Add the configuration block above
231+
3. Replace `YOUR_GITHUB_PAT` with your actual token
232+
4. Restart Xcode
233+
234+
---
235+
168236

169237
**Authentication Failed:**
170238
- Verify PAT has `repo` scope
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Install GitHub MCP Server in Xcode
2+
3+
Xcode currently supports two built-in coding agents: **Codex** (powered by OpenAI) and **Claude Agent** (powered by Anthropic). Follow the standard installation guide for each agent, with one important difference: Xcode uses its own isolated configuration directories for each agent, separate from your global config.
4+
5+
> Configurations placed in these directories only affect agents when launched from Xcode. See [Apple's documentation](https://developer.apple.com/documentation/xcode/setting-up-coding-intelligence#Customize-the-Claude-Agent-and-Codex-environments) for more details.
6+
7+
## Configuration Directories
8+
9+
| Agent | Configuration Directory |
10+
|-------|------------------------|
11+
| Codex | `~/Library/Developer/Xcode/CodingAssistant/codex/` |
12+
| Claude Agent | `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/` |
13+
14+
Place your MCP server configuration in the relevant directory above rather than the default location used by the standalone CLI.
15+
16+
## Setup Guides
17+
18+
- **[Codex](install-codex.md)** — configure `config.toml` inside `~/Library/Developer/Xcode/CodingAssistant/codex/`
19+
- **[Claude Agent](install-claude.md#xcode-claude-agent)** — configure `.claude.json` inside `~/Library/Developer/Xcode/CodingAssistant/ClaudeAgentConfig/`
20+
21+
## macOS Path Note
22+
23+
Xcode runs with a minimal `PATH` that typically excludes common binary locations. If you are using a local STDIO server (e.g. Docker or a pre-built binary), use the **full path** to the command in your config. Run `which docker` (or `which github-mcp-server`) in Terminal to find the correct path on your system. Common locations:
24+
25+
| Installation | Typical path |
26+
|---|---|
27+
| Docker (Intel Mac) | `/usr/local/bin/docker` |
28+
| Docker (Apple Silicon) | `/usr/local/bin/docker` |
29+
| Homebrew (Intel Mac) | `/usr/local/bin/` |
30+
| Homebrew (Apple Silicon) | `/opt/homebrew/bin/` |
31+
32+
## Troubleshooting
33+
34+
| Issue | Possible Cause | Fix |
35+
|-------|----------------|-----|
36+
| Tools not loading | Config placed in wrong directory | Ensure config is in the Xcode-specific path above, not `~/.codex/` or `~/.claude.json` |
37+
| Command not found (STDIO) | Xcode's PATH excludes binary location | Use the full path (e.g. `/usr/local/bin/docker` or `/opt/homebrew/bin/docker`); run `which docker` in Terminal to confirm |
38+
| Docker not found | Docker not running | Start Docker Desktop and restart Xcode |
39+
| Authentication failed | Invalid or expired PAT | Regenerate PAT and update config |
40+
41+
## References
42+
43+
- [Apple Developer Documentation — Setting up coding intelligence](https://developer.apple.com/documentation/xcode/setting-up-coding-intelligence#Customize-the-Claude-Agent-and-Codex-environments)
44+
- [Codex MCP documentation](https://developers.openai.com/codex/mcp)
45+
- Main project README: [Advanced configuration options](../../README.md)

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/josephburnett/jd/v2 v2.5.0
1111
github.com/lithammer/fuzzysearch v1.1.8
1212
github.com/microcosm-cc/bluemonday v1.0.27
13-
github.com/modelcontextprotocol/go-sdk v1.5.0
13+
github.com/modelcontextprotocol/go-sdk v1.5.1-0.20260403154220-27f29c1cef3b
1414
github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021
1515
github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7
1616
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8
3939
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
4040
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
4141
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
42-
github.com/modelcontextprotocol/go-sdk v1.5.0 h1:CHU0FIX9kpueNkxuYtfYQn1Z0slhFzBZuq+x6IiblIU=
43-
github.com/modelcontextprotocol/go-sdk v1.5.0/go.mod h1:gggDIhoemhWs3BGkGwd1umzEXCEMMvAnhTrnbXJKKKA=
42+
github.com/modelcontextprotocol/go-sdk v1.5.1-0.20260403154220-27f29c1cef3b h1:mB8zdpP8SX1TEqnEZpV2hHD30EQXivsZl4AP9hgm7F8=
43+
github.com/modelcontextprotocol/go-sdk v1.5.1-0.20260403154220-27f29c1cef3b/go.mod h1:gggDIhoemhWs3BGkGwd1umzEXCEMMvAnhTrnbXJKKKA=
4444
github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021 h1:31Y+Yu373ymebRdJN1cWLLooHH8xAr0MhKTEJGV/87g=
4545
github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021/go.mod h1:WERUkUryfUWlrHnFSO/BEUZ+7Ns8aZy7iVOGewxKzcc=
4646
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=

internal/ghmcp/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ func createGitHubClients(cfg github.MCPServerConfig, apiHost utils.APIHostResolv
9191
if cfg.RepoAccessTTL != nil {
9292
opts = append(opts, lockdown.WithTTL(*cfg.RepoAccessTTL))
9393
}
94-
repoAccessCache = lockdown.GetInstance(gqlClient, opts...)
94+
repoAccessCache = lockdown.GetInstance(gqlClient, restClient, opts...)
9595
}
9696

9797
return &githubClients{

pkg/github/dependabot.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func GetDependabotAlert(t translations.TranslationHelperFunc) inventory.ServerTo
6969
alert, resp, err := client.Dependabot.GetRepoAlert(ctx, owner, repo, alertNumber)
7070
if err != nil {
7171
return ghErrors.NewGitHubAPIErrorResponse(ctx,
72-
fmt.Sprintf("failed to get alert with number '%d'", alertNumber),
72+
dependabotErrMsg(fmt.Sprintf("failed to get alert with number '%d'", alertNumber), owner, repo, resp),
7373
resp,
7474
err,
7575
), nil, nil
@@ -160,7 +160,7 @@ func ListDependabotAlerts(t translations.TranslationHelperFunc) inventory.Server
160160
})
161161
if err != nil {
162162
return ghErrors.NewGitHubAPIErrorResponse(ctx,
163-
fmt.Sprintf("failed to list alerts for repository '%s/%s'", owner, repo),
163+
dependabotErrMsg(fmt.Sprintf("failed to list alerts for repository '%s/%s'", owner, repo), owner, repo, resp),
164164
resp,
165165
err,
166166
), nil, nil
@@ -184,3 +184,16 @@ func ListDependabotAlerts(t translations.TranslationHelperFunc) inventory.Server
184184
},
185185
)
186186
}
187+
188+
// dependabotErrMsg enhances error messages for dependabot API failures by
189+
// appending a hint about token permissions when the response indicates
190+
// the token may lack access to the repository (403 or 404).
191+
func dependabotErrMsg(base, owner, repo string, resp *github.Response) string {
192+
if resp != nil && (resp.StatusCode == http.StatusForbidden || resp.StatusCode == http.StatusNotFound) {
193+
return fmt.Sprintf("%s. Your token may not have access to Dependabot alerts on %s/%s. "+
194+
"To access Dependabot alerts, the token needs the 'security_events' scope or, for fine-grained tokens, "+
195+
"Dependabot alerts read permission for this specific repository.",
196+
base, owner, repo)
197+
}
198+
return base
199+
}

0 commit comments

Comments
 (0)