Skip to content

Commit f8d0e45

Browse files
Merge branch 'main' into fix-connectivity-panic
2 parents 7f90445 + c061804 commit f8d0e45

Some content is hidden

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

72 files changed

+6465
-2961
lines changed

.github/pull_request_template.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ Fixes #
3333
- [ ] Auth / permissions considered
3434
- [ ] Data exposure, filtering, or token/size limits considered
3535

36+
## Tool renaming
37+
- [ ] I am renaming tools as part of this PR (e.g. a part of a consolidation effort)
38+
- [ ] I have added the new tool aliases in `deprecated_tool_aliases.go`
39+
- [ ] I am not renaming tools as part of this PR
40+
41+
Note: if you're renaming tools, you *must* add the tool aliases. For more information on how to do so, please refer to the [official docs](https://github.com/github/github-mcp-server/blob/main/docs/tool-renaming.md).
42+
3643
## Lint & tests
3744
<!-- Check what you ran. If not run, explain briefly. -->
3845
- [ ] Linted locally with `./script/lint`

.github/workflows/code-scanning.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ env:
1414
jobs:
1515
analyze:
1616
name: Analyze (${{ matrix.language }})
17+
# Only run on the main repository, not on forks
18+
if: github.repository == 'github/github-mcp-server'
1719
runs-on: ${{ fromJSON(matrix.runner) }}
1820
permissions:
1921
actions: read

.github/workflows/docker-publish.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ jobs:
7070
# https://github.com/docker/metadata-action
7171
- name: Extract Docker metadata
7272
id: meta
73-
uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 # v5.9.0
73+
uses: docker/metadata-action@c299e40c65443455700f0fdfc63efafe5b349051 # v5.10.0
7474
with:
7575
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
7676
tags: |

.github/workflows/license-check.yml

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ jobs:
2525
steps:
2626
- name: Check out code
2727
uses: actions/checkout@v6
28-
with:
29-
ref: ${{ github.head_ref }}
28+
29+
# Check out the actual PR branch so we can push changes back if needed
30+
- name: Check out PR branch
31+
env:
32+
GH_TOKEN: ${{ github.token }}
33+
run: gh pr checkout ${{ github.event.pull_request.number }}
3034

3135
- name: Set up Go
3236
uses: actions/setup-go@v6
@@ -57,15 +61,13 @@ jobs:
5761
git config user.name "github-actions[bot]"
5862
git config user.email "github-actions[bot]@users.noreply.github.com"
5963
git add third-party-licenses.*.md third-party/
60-
git commit -m "chore: regenerate license files
61-
62-
Auto-generated by license-check workflow"
64+
git commit -m "chore: regenerate license files" -m "Auto-generated by license-check workflow"
6365
git push
6466
6567
- name: Check if already commented
6668
if: steps.changes.outcome == 'failure' && steps.push.outcome == 'failure'
6769
id: check_comment
68-
uses: actions/github-script@v7
70+
uses: actions/github-script@v8
6971
with:
7072
script: |
7173
const { data: comments } = await github.rest.issues.listComments({
@@ -83,26 +85,26 @@ Auto-generated by license-check workflow"
8385
8486
- name: Comment with instructions if cannot push
8587
if: steps.changes.outcome == 'failure' && steps.push.outcome == 'failure' && steps.check_comment.outputs.already_commented == 'false'
86-
uses: actions/github-script@v7
88+
uses: actions/github-script@v8
8789
with:
8890
script: |
8991
await github.rest.issues.createComment({
9092
owner: context.repo.owner,
9193
repo: context.repo.repo,
9294
issue_number: context.issue.number,
9395
body: `## ⚠️ License files need updating
94-
95-
The license files are out of date. I tried to fix them automatically but don't have permission to push to this branch.
96-
97-
**Please run:**
98-
\`\`\`bash
99-
script/licenses
100-
git add third-party-licenses.*.md third-party/
101-
git commit -m "chore: regenerate license files"
102-
git push
103-
\`\`\`
104-
105-
Alternatively, enable "Allow edits by maintainers" in the PR settings so I can fix it automatically.`
96+
97+
The license files are out of date. I tried to fix them automatically but don't have permission to push to this branch.
98+
99+
**Please run:**
100+
\`\`\`bash
101+
script/licenses
102+
git add third-party-licenses.*.md third-party/
103+
git commit -m "chore: regenerate license files"
104+
git push
105+
\`\`\`
106+
107+
Alternatively, enable "Allow edits by maintainers" in the PR settings so I can fix it automatically.`
106108
});
107109
108110
- name: Fail check if changes needed

README.md

Lines changed: 117 additions & 46 deletions
Large diffs are not rendered by default.

cmd/github-mcp-server/generate_docs.go

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package main
22

33
import (
4+
"context"
45
"fmt"
56
"net/url"
67
"os"
@@ -11,7 +12,6 @@ import (
1112
"github.com/github/github-mcp-server/pkg/inventory"
1213
"github.com/github/github-mcp-server/pkg/translations"
1314
"github.com/google/jsonschema-go/jsonschema"
14-
"github.com/modelcontextprotocol/go-sdk/mcp"
1515
"github.com/spf13/cobra"
1616
)
1717

@@ -50,8 +50,8 @@ func generateReadmeDocs(readmePath string) error {
5050
// Create translation helper
5151
t, _ := translations.TranslationHelper()
5252

53-
// Build inventory - stateless, no dependencies needed for doc generation
54-
r := github.NewInventory(t).Build()
53+
// (not available to regular users) while including tools with FeatureFlagDisable.
54+
r := github.NewInventory(t).WithToolsets([]string{"all"}).Build()
5555

5656
// Generate toolsets documentation
5757
toolsetsDoc := generateToolsetsDoc(r)
@@ -153,9 +153,7 @@ func generateToolsetsDoc(i *inventory.Inventory) string {
153153
}
154154

155155
func generateToolsDoc(r *inventory.Inventory) string {
156-
// AllTools() returns tools sorted by toolset ID then tool name.
157-
// We iterate once, grouping by toolset as we encounter them.
158-
tools := r.AllTools()
156+
tools := r.AvailableTools(context.Background())
159157
if len(tools) == 0 {
160158
return ""
161159
}
@@ -190,7 +188,7 @@ func generateToolsDoc(r *inventory.Inventory) string {
190188
currentToolsetID = tool.Toolset.ID
191189
currentToolsetIcon = tool.Toolset.Icon
192190
}
193-
writeToolDoc(&toolBuf, tool.Tool)
191+
writeToolDoc(&toolBuf, tool)
194192
toolBuf.WriteString("\n\n")
195193
}
196194

@@ -200,40 +198,26 @@ func generateToolsDoc(r *inventory.Inventory) string {
200198
return buf.String()
201199
}
202200

203-
func formatToolsetName(name string) string {
204-
switch name {
205-
case "pull_requests":
206-
return "Pull Requests"
207-
case "repos":
208-
return "Repositories"
209-
case "code_security":
210-
return "Code Security"
211-
case "secret_protection":
212-
return "Secret Protection"
213-
case "orgs":
214-
return "Organizations"
215-
default:
216-
// Fallback: capitalize first letter and replace underscores with spaces
217-
parts := strings.Split(name, "_")
218-
for i, part := range parts {
219-
if len(part) > 0 {
220-
parts[i] = strings.ToUpper(string(part[0])) + part[1:]
221-
}
201+
func writeToolDoc(buf *strings.Builder, tool inventory.ServerTool) {
202+
// Tool name (no icon - section header already has the toolset icon)
203+
fmt.Fprintf(buf, "- **%s** - %s\n", tool.Tool.Name, tool.Tool.Annotations.Title)
204+
205+
// OAuth scopes if present
206+
if len(tool.RequiredScopes) > 0 {
207+
fmt.Fprintf(buf, " - **Required OAuth Scopes**: `%s`\n", strings.Join(tool.RequiredScopes, "`, `"))
208+
209+
// Only show accepted scopes if they differ from required scopes
210+
if len(tool.AcceptedScopes) > 0 && !scopesEqual(tool.RequiredScopes, tool.AcceptedScopes) {
211+
fmt.Fprintf(buf, " - **Accepted OAuth Scopes**: `%s`\n", strings.Join(tool.AcceptedScopes, "`, `"))
222212
}
223-
return strings.Join(parts, " ")
224213
}
225-
}
226-
227-
func writeToolDoc(buf *strings.Builder, tool mcp.Tool) {
228-
// Tool name (no icon - section header already has the toolset icon)
229-
fmt.Fprintf(buf, "- **%s** - %s\n", tool.Name, tool.Annotations.Title)
230214

231215
// Parameters
232-
if tool.InputSchema == nil {
216+
if tool.Tool.InputSchema == nil {
233217
buf.WriteString(" - No parameters required")
234218
return
235219
}
236-
schema, ok := tool.InputSchema.(*jsonschema.Schema)
220+
schema, ok := tool.Tool.InputSchema.(*jsonschema.Schema)
237221
if !ok || schema == nil {
238222
buf.WriteString(" - No parameters required")
239223
return
@@ -282,6 +266,28 @@ func writeToolDoc(buf *strings.Builder, tool mcp.Tool) {
282266
}
283267
}
284268

269+
// scopesEqual checks if two scope slices contain the same elements (order-independent)
270+
func scopesEqual(a, b []string) bool {
271+
if len(a) != len(b) {
272+
return false
273+
}
274+
275+
// Create a map for quick lookup
276+
aMap := make(map[string]bool, len(a))
277+
for _, scope := range a {
278+
aMap[scope] = true
279+
}
280+
281+
// Check if all elements in b are in a
282+
for _, scope := range b {
283+
if !aMap[scope] {
284+
return false
285+
}
286+
}
287+
288+
return true
289+
}
290+
285291
func contains(slice []string, item string) bool {
286292
for _, s := range slice {
287293
if s == item {

cmd/github-mcp-server/helpers.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package main
2+
3+
import "strings"
4+
5+
// formatToolsetName converts a toolset ID to a human-readable name.
6+
// Used by both generate_docs.go and list_scopes.go for consistent formatting.
7+
func formatToolsetName(name string) string {
8+
switch name {
9+
case "pull_requests":
10+
return "Pull Requests"
11+
case "repos":
12+
return "Repositories"
13+
case "code_security":
14+
return "Code Security"
15+
case "secret_protection":
16+
return "Secret Protection"
17+
case "orgs":
18+
return "Organizations"
19+
default:
20+
// Fallback: capitalize first letter and replace underscores with spaces
21+
parts := strings.Split(name, "_")
22+
for i, part := range parts {
23+
if len(part) > 0 {
24+
parts[i] = strings.ToUpper(string(part[0])) + part[1:]
25+
}
26+
}
27+
return strings.Join(parts, " ")
28+
}
29+
}

0 commit comments

Comments
 (0)