Skip to content

Commit e973978

Browse files
authored
Merge branch 'main' into dependabot/go_modules/github.com/go-viper/mapstructure/v2-2.5.0
2 parents a2b1379 + 7c053f1 commit e973978

File tree

127 files changed

+3094
-1849
lines changed

Some content is hidden

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

127 files changed

+3094
-1849
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"

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ The following sets of tools are available:
752752
- **assign_copilot_to_issue** - Assign Copilot to issue
753753
- **Required OAuth Scopes**: `repo`
754754
- `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)
755+
- `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)
755756
- `issue_number`: Issue number (number, required)
756757
- `owner`: Repository owner (string, required)
757758
- `repo`: Repository name (string, required)

cmd/github-mcp-server/generate_docs.go

Lines changed: 4 additions & 2 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,7 +342,8 @@ 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")

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 & 0 deletions
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

internal/ghmcp/server.go

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ type MCPServerConfig struct {
6464
// LockdownMode indicates if we should enable lockdown mode
6565
LockdownMode bool
6666

67+
// Insider indicates if we should enable experimental features
68+
InsiderMode bool
69+
6770
// Logger is used for logging within the server
6871
Logger *slog.Logger
6972
// RepoAccessTTL overrides the default TTL for repository access cache entries.
@@ -96,8 +99,10 @@ func createGitHubClients(cfg MCPServerConfig, apiHost apiHost) (*githubClients,
9699
// We use NewEnterpriseClient unconditionally since we already parsed the API host
97100
gqlHTTPClient := &http.Client{
98101
Transport: &bearerAuthTransport{
99-
transport: http.DefaultTransport,
100-
token: cfg.Token,
102+
transport: &github.GraphQLFeaturesTransport{
103+
Transport: http.DefaultTransport,
104+
},
105+
token: cfg.Token,
101106
},
102107
}
103108
gqlClient := githubv4.NewEnterpriseClient(apiHost.graphqlURL.String(), gqlHTTPClient)
@@ -198,15 +203,22 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) {
198203
ghServer.AddReceivingMiddleware(addGitHubAPIErrorToContext)
199204
ghServer.AddReceivingMiddleware(addUserAgentsMiddleware(cfg, clients.rest, clients.gqlHTTP))
200205

206+
// Create feature checker
207+
featureChecker := createFeatureChecker(cfg.EnabledFeatures)
208+
201209
// Create dependencies for tool handlers
202210
deps := github.NewBaseDeps(
203211
clients.rest,
204212
clients.gql,
205213
clients.raw,
206214
clients.repoAccess,
207215
cfg.Translator,
208-
github.FeatureFlags{LockdownMode: cfg.LockdownMode},
216+
github.FeatureFlags{
217+
LockdownMode: cfg.LockdownMode,
218+
InsiderMode: cfg.InsiderMode,
219+
},
209220
cfg.ContentWindowSize,
221+
featureChecker,
210222
)
211223

212224
// Inject dependencies into context for all tool handlers
@@ -221,15 +233,18 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) {
221233
WithDeprecatedAliases(github.DeprecatedToolAliases).
222234
WithReadOnly(cfg.ReadOnly).
223235
WithToolsets(enabledToolsets).
224-
WithTools(github.CleanTools(cfg.EnabledTools)).
225-
WithFeatureChecker(createFeatureChecker(cfg.EnabledFeatures))
226-
236+
WithTools(cfg.EnabledTools).
237+
WithFeatureChecker(featureChecker)
238+
227239
// Apply token scope filtering if scopes are known (for PAT filtering)
228240
if cfg.TokenScopes != nil {
229241
inventoryBuilder = inventoryBuilder.WithFilter(github.CreateToolScopeFilter(cfg.TokenScopes))
230242
}
231243

232-
inventory := inventoryBuilder.Build()
244+
inventory, err := inventoryBuilder.Build()
245+
if err != nil {
246+
return nil, fmt.Errorf("failed to build inventory: %w", err)
247+
}
233248

234249
if unrecognized := inventory.UnrecognizedToolsets(); len(unrecognized) > 0 {
235250
fmt.Fprintf(os.Stderr, "Warning: unrecognized toolsets ignored: %s\n", strings.Join(unrecognized, ", "))
@@ -322,6 +337,9 @@ type StdioServerConfig struct {
322337
// LockdownMode indicates if we should enable lockdown mode
323338
LockdownMode bool
324339

340+
// InsiderMode indicates if we should enable experimental features
341+
InsiderMode bool
342+
325343
// RepoAccessCacheTTL overrides the default TTL for repository access cache entries.
326344
RepoAccessCacheTTL *time.Duration
327345
}
@@ -378,6 +396,7 @@ func RunStdioServer(cfg StdioServerConfig) error {
378396
Translator: t,
379397
ContentWindowSize: cfg.ContentWindowSize,
380398
LockdownMode: cfg.LockdownMode,
399+
InsiderMode: cfg.InsiderMode,
381400
Logger: logger,
382401
RepoAccessTTL: cfg.RepoAccessCacheTTL,
383402
TokenScopes: tokenScopes,
@@ -622,12 +641,6 @@ type bearerAuthTransport struct {
622641
func (t *bearerAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
623642
req = req.Clone(req.Context())
624643
req.Header.Set("Authorization", "Bearer "+t.token)
625-
626-
// Check for GraphQL-Features in context and add header if present
627-
if features := github.GetGraphQLFeatures(req.Context()); len(features) > 0 {
628-
req.Header.Set("GraphQL-Features", strings.Join(features, ", "))
629-
}
630-
631644
return t.transport.RoundTrip(req)
632645
}
633646

internal/ghmcp/server_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ func TestNewMCPServer_CreatesSuccessfully(t *testing.T) {
2323
Translator: translations.NullTranslationHelper,
2424
ContentWindowSize: 5000,
2525
LockdownMode: false,
26+
InsiderMode: false,
2627
}
2728

2829
// Create the server

internal/toolsnaps/toolsnaps.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,35 @@ func Test(toolName string, tool any) error {
6767
}
6868

6969
func writeSnap(snapPath string, contents []byte) error {
70+
// Sort the JSON keys recursively to ensure consistent output.
71+
// We do this by unmarshaling and remarshaling, which ensures Go's JSON encoder
72+
// sorts all map keys alphabetically at every level.
73+
sortedJSON, err := sortJSONKeys(contents)
74+
if err != nil {
75+
return fmt.Errorf("failed to sort JSON keys: %w", err)
76+
}
77+
7078
// Ensure the directory exists
7179
if err := os.MkdirAll(filepath.Dir(snapPath), 0700); err != nil {
7280
return fmt.Errorf("failed to create snapshot directory: %w", err)
7381
}
7482

7583
// Write the snapshot file
76-
if err := os.WriteFile(snapPath, contents, 0600); err != nil {
84+
if err := os.WriteFile(snapPath, sortedJSON, 0600); err != nil {
7785
return fmt.Errorf("failed to write snapshot file: %w", err)
7886
}
7987

8088
return nil
8189
}
90+
91+
// sortJSONKeys recursively sorts all object keys in a JSON byte array by
92+
// unmarshaling to map[string]any and remarshaling. Go's JSON encoder
93+
// automatically sorts map keys alphabetically.
94+
func sortJSONKeys(jsonData []byte) ([]byte, error) {
95+
var data any
96+
if err := json.Unmarshal(jsonData, &data); err != nil {
97+
return nil, err
98+
}
99+
100+
return json.MarshalIndent(data, "", " ")
101+
}

0 commit comments

Comments
 (0)