Skip to content

Commit 48744ca

Browse files
Sort scope slices for deterministic output
Map iteration in Go is non-deterministic, which causes doc generation to produce different output on each run. Sort the scope slices in: - ScopeSet.ToSlice() - ScopeSet.ToStringSlice() - ExpandScopes()
1 parent cec5a1a commit 48744ca

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

README.md

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -602,14 +602,14 @@ The following sets of tools are available:
602602

603603
- **get_code_scanning_alert** - Get code scanning alert
604604
- **Required OAuth Scopes**: `security_events`
605-
- **Accepted OAuth Scopes**: `security_events`, `repo`
605+
- **Accepted OAuth Scopes**: `repo`, `security_events`
606606
- `alertNumber`: The number of the alert. (number, required)
607607
- `owner`: The owner of the repository. (string, required)
608608
- `repo`: The name of the repository. (string, required)
609609

610610
- **list_code_scanning_alerts** - List code scanning alerts
611611
- **Required OAuth Scopes**: `security_events`
612-
- **Accepted OAuth Scopes**: `security_events`, `repo`
612+
- **Accepted OAuth Scopes**: `repo`, `security_events`
613613
- `owner`: The owner of the repository. (string, required)
614614
- `ref`: The Git reference for the results you want to list. (string, optional)
615615
- `repo`: The name of the repository. (string, required)
@@ -628,13 +628,13 @@ The following sets of tools are available:
628628

629629
- **get_team_members** - Get team members
630630
- **Required OAuth Scopes**: `read:org`
631-
- **Accepted OAuth Scopes**: `read:org`, `admin:org`, `write:org`
631+
- **Accepted OAuth Scopes**: `admin:org`, `read:org`, `write:org`
632632
- `org`: Organization login (owner) that contains the team. (string, required)
633633
- `team_slug`: Team slug (string, required)
634634

635635
- **get_teams** - Get teams
636636
- **Required OAuth Scopes**: `read:org`
637-
- **Accepted OAuth Scopes**: `read:org`, `admin:org`, `write:org`
637+
- **Accepted OAuth Scopes**: `admin:org`, `read:org`, `write:org`
638638
- `user`: Username to get teams for. If not provided, uses the authenticated user. (string, optional)
639639

640640
</details>
@@ -645,7 +645,7 @@ The following sets of tools are available:
645645

646646
- **get_dependabot_alert** - Get dependabot alert
647647
- **Required OAuth Scopes**: `security_events`
648-
- **Accepted OAuth Scopes**: `security_events`, `repo`
648+
- **Accepted OAuth Scopes**: `repo`, `security_events`
649649
- `alertNumber`: The number of the alert. (number, required)
650650
- `owner`: The owner of the repository. (string, required)
651651
- `repo`: The name of the repository. (string, required)
@@ -798,7 +798,7 @@ The following sets of tools are available:
798798

799799
- **list_issue_types** - List available issue types
800800
- **Required OAuth Scopes**: `read:org`
801-
- **Accepted OAuth Scopes**: `read:org`, `admin:org`, `write:org`
801+
- **Accepted OAuth Scopes**: `admin:org`, `read:org`, `write:org`
802802
- `owner`: The organization owner of the repository (string, required)
803803

804804
- **list_issues** - List issues
@@ -916,7 +916,7 @@ The following sets of tools are available:
916916

917917
- **search_orgs** - Search organizations
918918
- **Required OAuth Scopes**: `read:org`
919-
- **Accepted OAuth Scopes**: `read:org`, `admin:org`, `write:org`
919+
- **Accepted OAuth Scopes**: `admin:org`, `read:org`, `write:org`
920920
- `order`: Sort order (string, optional)
921921
- `page`: Page number for pagination (min 1) (number, optional)
922922
- `perPage`: Results per page for pagination (min 1, max 100) (number, optional)
@@ -946,22 +946,22 @@ The following sets of tools are available:
946946

947947
- **get_project** - Get project
948948
- **Required OAuth Scopes**: `read:project`
949-
- **Accepted OAuth Scopes**: `read:project`, `project`
949+
- **Accepted OAuth Scopes**: `project`, `read:project`
950950
- `owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive. (string, required)
951951
- `owner_type`: Owner type (string, required)
952952
- `project_number`: The project's number (number, required)
953953

954954
- **get_project_field** - Get project field
955955
- **Required OAuth Scopes**: `read:project`
956-
- **Accepted OAuth Scopes**: `read:project`, `project`
956+
- **Accepted OAuth Scopes**: `project`, `read:project`
957957
- `field_id`: The field's id. (number, required)
958958
- `owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive. (string, required)
959959
- `owner_type`: Owner type (string, required)
960960
- `project_number`: The project's number. (number, required)
961961

962962
- **get_project_item** - Get project item
963963
- **Required OAuth Scopes**: `read:project`
964-
- **Accepted OAuth Scopes**: `read:project`, `project`
964+
- **Accepted OAuth Scopes**: `project`, `read:project`
965965
- `fields`: Specific list of field IDs to include in the response (e.g. ["102589", "985201", "169875"]). If not provided, only the title field is included. (string[], optional)
966966
- `item_id`: The item's ID. (number, required)
967967
- `owner`: If owner_type == user it is the handle for the GitHub user account. If owner_type == org it is the name of the organization. The name is not case sensitive. (string, required)
@@ -980,7 +980,7 @@ The following sets of tools are available:
980980

981981
- **list_project_items** - List project items
982982
- **Required OAuth Scopes**: `read:project`
983-
- **Accepted OAuth Scopes**: `read:project`, `project`
983+
- **Accepted OAuth Scopes**: `project`, `read:project`
984984
- `after`: Forward pagination cursor from previous pageInfo.nextCursor. (string, optional)
985985
- `before`: Backward pagination cursor from previous pageInfo.prevCursor (rare). (string, optional)
986986
- `fields`: Field IDs to include (e.g. ["102589", "985201"]). CRITICAL: Always provide to get field values. Without this, only titles returned. (string[], optional)
@@ -1265,14 +1265,14 @@ The following sets of tools are available:
12651265

12661266
- **get_secret_scanning_alert** - Get secret scanning alert
12671267
- **Required OAuth Scopes**: `security_events`
1268-
- **Accepted OAuth Scopes**: `security_events`, `repo`
1268+
- **Accepted OAuth Scopes**: `repo`, `security_events`
12691269
- `alertNumber`: The number of the alert. (number, required)
12701270
- `owner`: The owner of the repository. (string, required)
12711271
- `repo`: The name of the repository. (string, required)
12721272

12731273
- **list_secret_scanning_alerts** - List secret scanning alerts
12741274
- **Required OAuth Scopes**: `security_events`
1275-
- **Accepted OAuth Scopes**: `security_events`, `repo`
1275+
- **Accepted OAuth Scopes**: `repo`, `security_events`
12761276
- `owner`: The owner of the repository. (string, required)
12771277
- `repo`: The name of the repository. (string, required)
12781278
- `resolution`: Filter by resolution (string, optional)
@@ -1287,12 +1287,12 @@ The following sets of tools are available:
12871287

12881288
- **get_global_security_advisory** - Get a global security advisory
12891289
- **Required OAuth Scopes**: `security_events`
1290-
- **Accepted OAuth Scopes**: `security_events`, `repo`
1290+
- **Accepted OAuth Scopes**: `repo`, `security_events`
12911291
- `ghsaId`: GitHub Security Advisory ID (format: GHSA-xxxx-xxxx-xxxx). (string, required)
12921292

12931293
- **list_global_security_advisories** - List global security advisories
12941294
- **Required OAuth Scopes**: `security_events`
1295-
- **Accepted OAuth Scopes**: `security_events`, `repo`
1295+
- **Accepted OAuth Scopes**: `repo`, `security_events`
12961296
- `affects`: Filter advisories by affected package or version (e.g. "package1,[email protected]"). (string, optional)
12971297
- `cveId`: Filter by CVE ID. (string, optional)
12981298
- `cwes`: Filter by Common Weakness Enumeration IDs (e.g. ["79", "284", "22"]). (string[], optional)
@@ -1315,7 +1315,7 @@ The following sets of tools are available:
13151315

13161316
- **list_repository_security_advisories** - List repository security advisories
13171317
- **Required OAuth Scopes**: `security_events`
1318-
- **Accepted OAuth Scopes**: `security_events`, `repo`
1318+
- **Accepted OAuth Scopes**: `repo`, `security_events`
13191319
- `direction`: Sort direction. (string, optional)
13201320
- `owner`: The owner of the repository. (string, required)
13211321
- `repo`: The name of the repository. (string, required)

pkg/scopes/scopes.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package scopes
22

3+
import "sort"
4+
35
// Scope represents a GitHub OAuth scope.
46
// These constants define all OAuth scopes used by the GitHub MCP server tools.
57
// See https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps
@@ -85,15 +87,21 @@ func (s ScopeSet) ToSlice() []Scope {
8587
for scope := range s {
8688
scopes = append(scopes, scope)
8789
}
90+
// Sort for deterministic output
91+
sort.Slice(scopes, func(i, j int) bool {
92+
return scopes[i] < scopes[j]
93+
})
8894
return scopes
8995
}
9096

9197
// ToStringSlice converts a ScopeSet to a slice of string values.
98+
// The returned slice is sorted for deterministic output.
9299
func (s ScopeSet) ToStringSlice() []string {
93100
scopes := make([]string, 0, len(s))
94101
for scope := range s {
95102
scopes = append(scopes, string(scope))
96103
}
104+
sort.Strings(scopes)
97105
return scopes
98106
}
99107

@@ -110,6 +118,7 @@ func ToStringSlice(scopes ...Scope) []string {
110118
// including parent scopes from the hierarchy.
111119
// For example, if "public_repo" is required, "repo" is also accepted since
112120
// having the "repo" scope grants access to "public_repo".
121+
// The returned slice is sorted for deterministic output.
113122
func ExpandScopes(required ...Scope) []string {
114123
if len(required) == 0 {
115124
return nil
@@ -131,10 +140,11 @@ func ExpandScopes(required ...Scope) []string {
131140
}
132141
}
133142

134-
// Convert to slice
143+
// Convert to slice and sort for deterministic output
135144
result := make([]string, 0, len(accepted))
136145
for scope := range accepted {
137146
result = append(result, scope)
138147
}
148+
sort.Strings(result)
139149
return result
140150
}

0 commit comments

Comments
 (0)