Skip to content

Commit bd214f9

Browse files
Merge branch 'main' into fix-connectivity-panic
2 parents f8d0e45 + e81f120 commit bd214f9

File tree

143 files changed

+3985
-1951
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

143 files changed

+3985
-1951
lines changed

.github/workflows/ai-issue-assessment.yml

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ on:
66

77
jobs:
88
ai-issue-assessment:
9-
if: >
10-
(github.event.action == 'opened' && github.event.issue.labels[0] == null) ||
11-
(github.event.action == 'labeled' && github.event.label.name == 'bug')
129
runs-on: ubuntu-latest
1310
permissions:
1411
issues: write
@@ -23,8 +20,8 @@ jobs:
2320
uses: github/ai-assessment-comment-labeler@e3bedc38cfffa9179fe4cee8f7ecc93bffb3fee7 # v1.0.1
2421
with:
2522
token: ${{ secrets.GITHUB_TOKEN }}
26-
ai_review_label: 'bug, enhancement'
23+
ai_review_label: "request ai review"
2724
issue_number: ${{ github.event.issue.number }}
2825
issue_body: ${{ github.event.issue.body }}
29-
prompts_directory: '.github/prompts'
30-
labels_to_prompts_mapping: 'bug,bug-report-review.prompt.yml|default,default-issue-review.prompt.yml'
26+
prompts_directory: ".github/prompts"
27+
labels_to_prompts_mapping: "bug,bug-report-review.prompt.yml|default,default-issue-review.prompt.yml"
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
name: Label issues for AI review
2+
on:
3+
issues:
4+
types:
5+
- reopened
6+
- opened
7+
jobs:
8+
label_issues:
9+
runs-on: ubuntu-latest
10+
permissions:
11+
issues: write
12+
steps:
13+
- name: Add AI review label to issue
14+
run: gh issue edit "$NUMBER" --add-label "$LABELS"
15+
env:
16+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17+
GH_REPO: ${{ github.repository }}
18+
NUMBER: ${{ github.event.issue.number }}
19+
LABELS: "request ai review"

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ bin/
1818

1919
# binary
2020
github-mcp-server
21+
mcpcurl
22+
e2e.test
2123

2224
.history
2325
conformance-report/

README.md

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Alternatively, to manually configure VS Code, choose the appropriate JSON block
8080
</table>
8181

8282
### Install in other MCP hosts
83+
8384
- **[GitHub Copilot in other IDEs](/docs/installation-guides/install-other-copilot-ides.md)** - Installation for JetBrains, Visual Studio, Eclipse, and Xcode with GitHub Copilot
8485
- **[Claude Applications](/docs/installation-guides/install-claude.md)** - Installation guide for Claude Desktop and Claude Code CLI
8586
- **[Codex](/docs/installation-guides/install-codex.md)** - Installation guide for Open AI Codex
@@ -104,6 +105,7 @@ When no toolsets are specified, [default toolsets](#default-toolset) are used.
104105
GitHub Enterprise Cloud can also make use of the remote server.
105106

106107
Example for `https://octocorp.ghe.com` with GitHub PAT token:
108+
107109
```
108110
{
109111
...
@@ -140,24 +142,30 @@ The MCP server can use many of the GitHub APIs, so enable the permissions that y
140142
<details><summary><b>Handling PATs Securely</b></summary>
141143

142144
### Environment Variables (Recommended)
145+
143146
To keep your GitHub PAT secure and reusable across different MCP hosts:
144147

145148
1. **Store your PAT in environment variables**
149+
146150
```bash
147151
export GITHUB_PAT=your_token_here
148152
```
153+
149154
Or create a `.env` file:
155+
150156
```env
151157
GITHUB_PAT=your_token_here
152158
```
153159

154160
2. **Protect your `.env` file**
161+
155162
```bash
156163
# Add to .gitignore to prevent accidental commits
157164
echo ".env" >> .gitignore
158165
```
159166

160167
3. **Reference the token in configurations**
168+
161169
```bash
162170
# CLI usage
163171
claude mcp update github -e GITHUB_PERSONAL_ACCESS_TOKEN=$GITHUB_PAT
@@ -180,6 +188,7 @@ To keep your GitHub PAT secure and reusable across different MCP hosts:
180188
- **Regular rotation**: Update tokens periodically
181189
- **Never commit**: Keep tokens out of version control
182190
- **File permissions**: Restrict access to config files containing tokens
191+
183192
```bash
184193
chmod 600 ~/.your-app/config.json
185194
```
@@ -193,6 +202,7 @@ the hostname for GitHub Enterprise Server or GitHub Enterprise Cloud with data r
193202

194203
- For GitHub Enterprise Server, prefix the hostname with the `https://` URI scheme, as it otherwise defaults to `http://`, which GitHub Enterprise Server does not support.
195204
- For GitHub Enterprise Cloud with data residency, use `https://YOURSUBDOMAIN.ghe.com` as the hostname.
205+
196206
``` json
197207
"github": {
198208
"command": "docker",
@@ -328,6 +338,18 @@ If you don't have Docker, you can use `go build` to build the binary in the
328338
}
329339
```
330340

341+
### CLI utilities
342+
343+
The `github-mcp-server` binary includes a few CLI subcommands that are helpful for debugging and exploring the server.
344+
345+
- `github-mcp-server tool-search "<query>"` searches tools by name, description, and input parameter names. Use `--max-results` to return more matches.
346+
Example:
347+
348+
```bash
349+
docker run -i --rm ghcr.io/github/github-mcp-server tool-search "issue" --max-results 5
350+
github-mcp-server tool-search "issue" --max-results 5
351+
```
352+
331353
## Tool Configuration
332354

333355
The GitHub MCP Server supports enabling or disabling specific groups of functionalities via the `--toolsets` flag. This allows you to control which GitHub API capabilities are available to your AI tools. Enabling only the toolsets that you need can help the LLM with tool choice and reduce the context size.
@@ -349,6 +371,7 @@ To specify toolsets you want available to the LLM, you can pass an allow-list in
349371
```
350372

351373
2. **Using Environment Variable**:
374+
352375
```bash
353376
GITHUB_TOOLSETS="repos,issues,pull_requests,actions,code_security" ./github-mcp-server
354377
```
@@ -366,23 +389,29 @@ You can also configure specific tools using the `--tools` flag. Tools can be use
366389
```
367390

368391
2. **Using Environment Variable**:
392+
369393
```bash
370394
GITHUB_TOOLS="get_file_contents,issue_read,create_pull_request" ./github-mcp-server
371395
```
372396

373397
3. **Combining with Toolsets** (additive):
398+
374399
```bash
375400
github-mcp-server --toolsets repos,issues --tools get_gist
376401
```
402+
377403
This registers all tools from `repos` and `issues` toolsets, plus `get_gist`.
378404

379405
4. **Combining with Dynamic Toolsets** (additive):
406+
380407
```bash
381408
github-mcp-server --tools get_file_contents --dynamic-toolsets
382409
```
410+
383411
This registers `get_file_contents` plus the dynamic toolset tools (`enable_toolset`, `list_available_toolsets`, `get_toolset_tools`).
384412

385413
**Important Notes:**
414+
386415
- Tools, toolsets, and dynamic toolsets can all be used together
387416
- Read-only mode takes priority: write tools are skipped if `--read-only` is set, even if explicitly requested via `--tools`
388417
- Tool names must match exactly (e.g., `get_file_contents`, not `getFileContents`). Invalid tool names will cause the server to fail at startup with an error message
@@ -435,9 +464,11 @@ GITHUB_TOOLSETS="all" ./github-mcp-server
435464
```
436465

437466
#### "default" toolset
467+
438468
The default toolset `default` is the configuration that gets passed to the server if no toolsets are specified.
439469

440470
The default configuration is:
471+
441472
- context
442473
- repos
443474
- issues
@@ -751,6 +782,8 @@ The following sets of tools are available:
751782

752783
- **assign_copilot_to_issue** - Assign Copilot to issue
753784
- **Required OAuth Scopes**: `repo`
785+
- `base_ref`: Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch (string, optional)
786+
- `custom_instructions`: Optional custom instructions to guide the agent beyond the issue body. Use this to provide additional context, constraints, or guidance that is not captured in the issue description (string, optional)
754787
- `issue_number`: Issue number (number, required)
755788
- `owner`: Repository owner (string, required)
756789
- `repo`: Repository name (string, required)
@@ -1369,32 +1402,34 @@ The following sets of tools are available:
13691402

13701403
<summary>Copilot</summary>
13711404

1372-
- **create_pull_request_with_copilot** - Perform task with GitHub Copilot coding agent
1373-
- `owner`: Repository owner. You can guess the owner, but confirm it with the user before proceeding. (string, required)
1374-
- `repo`: Repository name. You can guess the repository name, but confirm it with the user before proceeding. (string, required)
1375-
- `problem_statement`: Detailed description of the task to be performed (e.g., 'Implement a feature that does X', 'Fix bug Y', etc.) (string, required)
1376-
- `title`: Title for the pull request that will be created (string, required)
1377-
- `base_ref`: Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch (string, optional)
1405+
- **create_pull_request_with_copilot** - Perform task with GitHub Copilot coding agent
1406+
- `owner`: Repository owner. You can guess the owner, but confirm it with the user before proceeding. (string, required)
1407+
- `repo`: Repository name. You can guess the repository name, but confirm it with the user before proceeding. (string, required)
1408+
- `problem_statement`: Detailed description of the task to be performed (e.g., 'Implement a feature that does X', 'Fix bug Y', etc.) (string, required)
1409+
- `title`: Title for the pull request that will be created (string, required)
1410+
- `base_ref`: Git reference (e.g., branch) that the agent will start its work from. If not specified, defaults to the repository's default branch (string, optional)
13781411

13791412
</details>
13801413

13811414
<details>
13821415

13831416
<summary>Copilot Spaces</summary>
13841417

1385-
- **get_copilot_space** - Get Copilot Space
1386-
- `owner`: The owner of the space. (string, required)
1387-
- `name`: The name of the space. (string, required)
1418+
- **get_copilot_space** - Get Copilot Space
1419+
- `owner`: The owner of the space. (string, required)
1420+
- `name`: The name of the space. (string, required)
1421+
1422+
- **list_copilot_spaces** - List Copilot Spaces
13881423

1389-
- **list_copilot_spaces** - List Copilot Spaces
13901424
</details>
13911425

13921426
<details>
13931427

13941428
<summary>GitHub Support Docs Search</summary>
13951429

1396-
- **github_support_docs_search** - Retrieve documentation relevant to answer GitHub product and support questions. Support topics include: GitHub Actions Workflows, Authentication, GitHub Support Inquiries, Pull Request Practices, Repository Maintenance, GitHub Pages, GitHub Packages, GitHub Discussions, Copilot Spaces
1397-
- `query`: Input from the user about the question they need answered. This is the latest raw unedited user message. You should ALWAYS leave the user message as it is, you should never modify it. (string, required)
1430+
- **github_support_docs_search** - Retrieve documentation relevant to answer GitHub product and support questions. Support topics include: GitHub Actions Workflows, Authentication, GitHub Support Inquiries, Pull Request Practices, Repository Maintenance, GitHub Pages, GitHub Packages, GitHub Discussions, Copilot Spaces
1431+
- `query`: Input from the user about the question they need answered. This is the latest raw unedited user message. You should ALWAYS leave the user message as it is, you should never modify it. (string, required)
1432+
13981433
</details>
13991434

14001435
## Dynamic Tool Discovery

cmd/github-mcp-server/generate_docs.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ func generateReadmeDocs(readmePath string) error {
5151
t, _ := translations.TranslationHelper()
5252

5353
// (not available to regular users) while including tools with FeatureFlagDisable.
54-
r := github.NewInventory(t).WithToolsets([]string{"all"}).Build()
54+
// Build() can only fail if WithTools specifies invalid tools - not used here
55+
r, _ := github.NewInventory(t).WithToolsets([]string{"all"}).Build()
5556

5657
// Generate toolsets documentation
5758
toolsetsDoc := generateToolsetsDoc(r)
@@ -341,22 +342,22 @@ func generateRemoteToolsetsDoc() string {
341342
t, _ := translations.TranslationHelper()
342343

343344
// Build inventory - stateless
344-
r := github.NewInventory(t).Build()
345+
// Build() can only fail if WithTools specifies invalid tools - not used here
346+
r, _ := github.NewInventory(t).Build()
345347

346348
// Generate table header (icon is combined with Name column)
347349
buf.WriteString("| Name | Description | API URL | 1-Click Install (VS Code) | Read-only Link | 1-Click Read-only Install (VS Code) |\n")
348350
buf.WriteString("| ---- | ----------- | ------- | ------------------------- | -------------- | ----------------------------------- |\n")
349351

350352
// Add "all" toolset first (special case)
351353
allIcon := octiconImg("apps", "../")
352-
fmt.Fprintf(&buf, "| %s<br>all | All available GitHub MCP tools | https://api.githubcopilot.com/mcp/ | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=github&config=%%7B%%22type%%22%%3A%%20%%22http%%22%%2C%%22url%%22%%3A%%20%%22https%%3A%%2F%%2Fapi.githubcopilot.com%%2Fmcp%%2F%%22%%7D) | [read-only](https://api.githubcopilot.com/mcp/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=github&config=%%7B%%22type%%22%%3A%%20%%22http%%22%%2C%%22url%%22%%3A%%20%%22https%%3A%%2F%%2Fapi.githubcopilot.com%%2Fmcp%%2Freadonly%%22%%7D) |\n", allIcon)
354+
fmt.Fprintf(&buf, "| %s<br>`all` | All available GitHub MCP tools | https://api.githubcopilot.com/mcp/ | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=github&config=%%7B%%22type%%22%%3A%%20%%22http%%22%%2C%%22url%%22%%3A%%20%%22https%%3A%%2F%%2Fapi.githubcopilot.com%%2Fmcp%%2F%%22%%7D) | [read-only](https://api.githubcopilot.com/mcp/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=github&config=%%7B%%22type%%22%%3A%%20%%22http%%22%%2C%%22url%%22%%3A%%20%%22https%%3A%%2F%%2Fapi.githubcopilot.com%%2Fmcp%%2Freadonly%%22%%7D) |\n", allIcon)
353355

354356
// AvailableToolsets() returns toolsets that have tools, sorted by ID
355357
// Exclude context (handled separately) and dynamic (internal only)
356358
for _, ts := range r.AvailableToolsets("context", "dynamic") {
357359
idStr := string(ts.ID)
358360

359-
formattedName := formatToolsetName(idStr)
360361
apiURL := fmt.Sprintf("https://api.githubcopilot.com/mcp/x/%s", idStr)
361362
readonlyURL := fmt.Sprintf("https://api.githubcopilot.com/mcp/x/%s/readonly", idStr)
362363

@@ -372,9 +373,9 @@ func generateRemoteToolsetsDoc() string {
372373
readonlyInstallLink := fmt.Sprintf("[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-%s&config=%s)", idStr, readonlyConfig)
373374

374375
icon := octiconImg(ts.Icon, "../")
375-
fmt.Fprintf(&buf, "| %s<br>%s | %s | %s | %s | [read-only](%s) | %s |\n",
376+
fmt.Fprintf(&buf, "| %s<br>`%s` | %s | %s | %s | [read-only](%s) | %s |\n",
376377
icon,
377-
formattedName,
378+
idStr,
378379
ts.Description,
379380
apiURL,
380381
installLink,
@@ -397,7 +398,6 @@ func generateRemoteOnlyToolsetsDoc() string {
397398
for _, ts := range github.RemoteOnlyToolsets() {
398399
idStr := string(ts.ID)
399400

400-
formattedName := formatToolsetName(idStr)
401401
apiURL := fmt.Sprintf("https://api.githubcopilot.com/mcp/x/%s", idStr)
402402
readonlyURL := fmt.Sprintf("https://api.githubcopilot.com/mcp/x/%s/readonly", idStr)
403403

@@ -413,9 +413,9 @@ func generateRemoteOnlyToolsetsDoc() string {
413413
readonlyInstallLink := fmt.Sprintf("[Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-%s&config=%s)", idStr, readonlyConfig)
414414

415415
icon := octiconImg(ts.Icon, "../")
416-
fmt.Fprintf(&buf, "| %s<br>%s | %s | %s | %s | [read-only](%s) | %s |\n",
416+
fmt.Fprintf(&buf, "| %s<br>`%s` | %s | %s | %s | [read-only](%s) | %s |\n",
417417
icon,
418-
formattedName,
418+
idStr,
419419
ts.Description,
420420
apiURL,
421421
installLink,

cmd/github-mcp-server/list_scopes.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,10 @@ func runListScopes() error {
121121
inventoryBuilder = inventoryBuilder.WithTools(enabledTools)
122122
}
123123

124-
inv := inventoryBuilder.Build()
124+
inv, err := inventoryBuilder.Build()
125+
if err != nil {
126+
return fmt.Errorf("failed to build inventory: %w", err)
127+
}
125128

126129
// Collect all tools and their scopes
127130
output := collectToolScopes(inv, readOnly)

cmd/github-mcp-server/main.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ var (
8383
LogFilePath: viper.GetString("log-file"),
8484
ContentWindowSize: viper.GetInt("content-window-size"),
8585
LockdownMode: viper.GetBool("lockdown-mode"),
86+
InsiderMode: viper.GetBool("insider-mode"),
8687
RepoAccessCacheTTL: &ttl,
8788
}
8889
return ghmcp.RunStdioServer(stdioServerConfig)
@@ -108,6 +109,7 @@ func init() {
108109
rootCmd.PersistentFlags().String("gh-host", "", "Specify the GitHub hostname (for GitHub Enterprise etc.)")
109110
rootCmd.PersistentFlags().Int("content-window-size", 5000, "Specify the content window size")
110111
rootCmd.PersistentFlags().Bool("lockdown-mode", false, "Enable lockdown mode")
112+
rootCmd.PersistentFlags().Bool("insider-mode", false, "Enable insider features")
111113
rootCmd.PersistentFlags().Duration("repo-access-cache-ttl", 5*time.Minute, "Override the repo access cache TTL (e.g. 1m, 0s to disable)")
112114

113115
// Bind flag to viper
@@ -122,6 +124,7 @@ func init() {
122124
_ = viper.BindPFlag("host", rootCmd.PersistentFlags().Lookup("gh-host"))
123125
_ = viper.BindPFlag("content-window-size", rootCmd.PersistentFlags().Lookup("content-window-size"))
124126
_ = viper.BindPFlag("lockdown-mode", rootCmd.PersistentFlags().Lookup("lockdown-mode"))
127+
_ = viper.BindPFlag("insider-mode", rootCmd.PersistentFlags().Lookup("insider-mode"))
125128
_ = viper.BindPFlag("repo-access-cache-ttl", rootCmd.PersistentFlags().Lookup("repo-access-cache-ttl"))
126129

127130
// Add subcommands
@@ -133,7 +136,6 @@ func initConfig() {
133136
viper.SetEnvPrefix("github")
134137
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
135138
viper.AutomaticEnv()
136-
137139
}
138140

139141
func main() {

cmd/mcpcurl/mcpcurl

-6.41 MB
Binary file not shown.

e2e.test

-15.2 MB
Binary file not shown.

go.mod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module github.com/github/github-mcp-server
33
go 1.24.0
44

55
require (
6+
github.com/fatih/color v1.18.0
67
github.com/google/go-github/v79 v79.0.0
78
github.com/google/jsonschema-go v0.4.2
89
github.com/josephburnett/jd v1.9.2
@@ -20,6 +21,8 @@ require (
2021
github.com/gorilla/css v1.0.1 // indirect
2122
github.com/josharian/intern v1.0.0 // indirect
2223
github.com/mailru/easyjson v0.7.7 // indirect
24+
github.com/mattn/go-colorable v0.1.13 // indirect
25+
github.com/mattn/go-isatty v0.0.20 // indirect
2326
github.com/stretchr/objx v0.5.2 // indirect
2427
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
2528
go.yaml.in/yaml/v3 v3.0.4 // indirect
@@ -31,9 +34,10 @@ require (
3134
require (
3235
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
3336
github.com/fsnotify/fsnotify v1.9.0 // indirect
34-
github.com/go-viper/mapstructure/v2 v2.4.0
37+
github.com/go-viper/mapstructure/v2 v2.5.0
3538
github.com/google/go-querystring v1.1.0 // indirect
3639
github.com/inconshreveable/mousetrap v1.1.0 // indirect
40+
github.com/lithammer/fuzzysearch v1.1.8
3741
github.com/modelcontextprotocol/go-sdk v1.2.0
3842
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
3943
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect

0 commit comments

Comments
 (0)