Skip to content

Commit c2220f8

Browse files
committed
adding structs for toolset group metadata
1 parent bf4f6d8 commit c2220f8

File tree

2 files changed

+172
-20
lines changed

2 files changed

+172
-20
lines changed

cmd/github-mcp-server/main.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ var (
4545
return fmt.Errorf("failed to unmarshal toolsets: %w", err)
4646
}
4747

48+
if len(enabledToolsets) == 0 {
49+
enabledToolsets = github.GetDefaultToolsetIDs()
50+
}
51+
4852
stdioServerConfig := ghmcp.StdioServerConfig{
4953
Version: version,
5054
Host: viper.GetString("host"),
@@ -69,7 +73,7 @@ func init() {
6973
rootCmd.SetVersionTemplate("{{.Short}}\n{{.Version}}\n")
7074

7175
// Add global flags that will be shared by all commands
72-
rootCmd.PersistentFlags().StringSlice("toolsets", github.DefaultTools, "An optional comma separated list of groups of tools to allow, defaults to enabling all")
76+
rootCmd.PersistentFlags().StringSlice("toolsets", nil, github.GenerateToolsetsHelp())
7377
rootCmd.PersistentFlags().Bool("dynamic-toolsets", false, "Enable dynamic toolsets")
7478
rootCmd.PersistentFlags().Bool("read-only", false, "Restrict the server to read-only operations")
7579
rootCmd.PersistentFlags().String("log-file", "", "Path to log file")

pkg/github/tools.go

Lines changed: 167 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package github
22

33
import (
44
"context"
5+
"fmt"
6+
"strings"
57

68
"github.com/github/github-mcp-server/pkg/raw"
79
"github.com/github/github-mcp-server/pkg/toolsets"
@@ -14,14 +16,126 @@ import (
1416
type GetClientFn func(context.Context) (*github.Client, error)
1517
type GetGQLClientFn func(context.Context) (*githubv4.Client, error)
1618

17-
var DefaultTools = []string{"context", "repos", "issues", "pull_requests", "users"}
19+
// ToolsetMetadata holds metadata for a toolset including its ID and description
20+
type ToolsetMetadata struct {
21+
ID string
22+
Description string
23+
}
24+
25+
var (
26+
ToolsetMetadataContext = ToolsetMetadata{
27+
ID: "context",
28+
Description: "Tools that provide context about the current user and GitHub context you are operating in",
29+
}
30+
ToolsetMetadataRepos = ToolsetMetadata{
31+
ID: "repos",
32+
Description: "GitHub Repository related tools",
33+
}
34+
ToolsetMetadataIssues = ToolsetMetadata{
35+
ID: "issues",
36+
Description: "GitHub Issues related tools",
37+
}
38+
ToolsetMetadataPullRequests = ToolsetMetadata{
39+
ID: "pull_requests",
40+
Description: "GitHub Pull Request related tools",
41+
}
42+
ToolsetMetadataUsers = ToolsetMetadata{
43+
ID: "users",
44+
Description: "GitHub User related tools",
45+
}
46+
ToolsetMetadataOrgs = ToolsetMetadata{
47+
ID: "orgs",
48+
Description: "GitHub Organization related tools",
49+
}
50+
ToolsetMetadataActions = ToolsetMetadata{
51+
ID: "actions",
52+
Description: "GitHub Actions workflows and CI/CD operations",
53+
}
54+
ToolsetMetadataCodeSecurity = ToolsetMetadata{
55+
ID: "code_security",
56+
Description: "Code security related tools, such as GitHub Code Scanning",
57+
}
58+
ToolsetMetadataSecretProtection = ToolsetMetadata{
59+
ID: "secret_protection",
60+
Description: "Secret protection related tools, such as GitHub Secret Scanning",
61+
}
62+
ToolsetMetadataDependabot = ToolsetMetadata{
63+
ID: "dependabot",
64+
Description: "Dependabot tools",
65+
}
66+
ToolsetMetadataNotifications = ToolsetMetadata{
67+
ID: "notifications",
68+
Description: "GitHub Notifications related tools",
69+
}
70+
ToolsetMetadataExperiments = ToolsetMetadata{
71+
ID: "experiments",
72+
Description: "Experimental features that are not considered stable yet",
73+
}
74+
ToolsetMetadataDiscussions = ToolsetMetadata{
75+
ID: "discussions",
76+
Description: "GitHub Discussions related tools",
77+
}
78+
ToolsetMetadataGists = ToolsetMetadata{
79+
ID: "gists",
80+
Description: "GitHub Gist related tools",
81+
}
82+
ToolsetMetadataSecurityAdvisories = ToolsetMetadata{
83+
ID: "security_advisories",
84+
Description: "Security advisories related tools",
85+
}
86+
ToolsetMetadataProjects = ToolsetMetadata{
87+
ID: "projects",
88+
Description: "GitHub Projects related tools",
89+
}
90+
ToolsetMetadataStargazers = ToolsetMetadata{
91+
ID: "stargazers",
92+
Description: "GitHub Stargazers related tools",
93+
}
94+
ToolsetMetadataDynamic = ToolsetMetadata{
95+
ID: "dynamic",
96+
Description: "Discover GitHub MCP tools that can help achieve tasks by enabling additional sets of tools, you can control the enablement of any toolset to access its tools when this toolset is enabled.",
97+
}
98+
)
99+
100+
func AvailableTools() []ToolsetMetadata {
101+
return []ToolsetMetadata{
102+
ToolsetMetadataContext,
103+
ToolsetMetadataRepos,
104+
ToolsetMetadataIssues,
105+
ToolsetMetadataPullRequests,
106+
ToolsetMetadataUsers,
107+
ToolsetMetadataOrgs,
108+
ToolsetMetadataActions,
109+
ToolsetMetadataCodeSecurity,
110+
ToolsetMetadataSecretProtection,
111+
ToolsetMetadataDependabot,
112+
ToolsetMetadataNotifications,
113+
ToolsetMetadataExperiments,
114+
ToolsetMetadataDiscussions,
115+
ToolsetMetadataGists,
116+
ToolsetMetadataSecurityAdvisories,
117+
ToolsetMetadataProjects,
118+
ToolsetMetadataStargazers,
119+
ToolsetMetadataDynamic,
120+
}
121+
}
122+
123+
func GetDefaultToolsetIDs() []string {
124+
return []string{
125+
ToolsetMetadataContext.ID,
126+
ToolsetMetadataRepos.ID,
127+
ToolsetMetadataIssues.ID,
128+
ToolsetMetadataPullRequests.ID,
129+
ToolsetMetadataUsers.ID,
130+
}
131+
}
18132

19133
func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetGQLClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc, contentWindowSize int) *toolsets.ToolsetGroup {
20134
tsg := toolsets.NewToolsetGroup(readOnly)
21135

22136
// Define all available features with their default state (disabled)
23137
// Create toolsets
24-
repos := toolsets.NewToolset("repos", "GitHub Repository related tools").
138+
repos := toolsets.NewToolset(ToolsetMetadataRepos.ID, ToolsetMetadataRepos.Description).
25139
AddReadTools(
26140
toolsets.NewServerTool(SearchRepositories(getClient, t)),
27141
toolsets.NewServerTool(GetFileContents(getClient, getRawClient, t)),
@@ -50,7 +164,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
50164
toolsets.NewServerResourceTemplate(GetRepositoryResourceTagContent(getClient, getRawClient, t)),
51165
toolsets.NewServerResourceTemplate(GetRepositoryResourcePrContent(getClient, getRawClient, t)),
52166
)
53-
issues := toolsets.NewToolset("issues", "GitHub Issues related tools").
167+
issues := toolsets.NewToolset(ToolsetMetadataIssues.ID, ToolsetMetadataIssues.Description).
54168
AddReadTools(
55169
toolsets.NewServerTool(GetIssue(getClient, t)),
56170
toolsets.NewServerTool(SearchIssues(getClient, t)),
@@ -71,15 +185,15 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
71185
toolsets.NewServerPrompt(AssignCodingAgentPrompt(t)),
72186
toolsets.NewServerPrompt(IssueToFixWorkflowPrompt(t)),
73187
)
74-
users := toolsets.NewToolset("users", "GitHub User related tools").
188+
users := toolsets.NewToolset(ToolsetMetadataUsers.ID, ToolsetMetadataUsers.Description).
75189
AddReadTools(
76190
toolsets.NewServerTool(SearchUsers(getClient, t)),
77191
)
78-
orgs := toolsets.NewToolset("orgs", "GitHub Organization related tools").
192+
orgs := toolsets.NewToolset(ToolsetMetadataOrgs.ID, ToolsetMetadataOrgs.Description).
79193
AddReadTools(
80194
toolsets.NewServerTool(SearchOrgs(getClient, t)),
81195
)
82-
pullRequests := toolsets.NewToolset("pull_requests", "GitHub Pull Request related tools").
196+
pullRequests := toolsets.NewToolset(ToolsetMetadataPullRequests.ID, ToolsetMetadataPullRequests.Description).
83197
AddReadTools(
84198
toolsets.NewServerTool(GetPullRequest(getClient, t)),
85199
toolsets.NewServerTool(ListPullRequests(getClient, t)),
@@ -104,23 +218,23 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
104218
toolsets.NewServerTool(SubmitPendingPullRequestReview(getGQLClient, t)),
105219
toolsets.NewServerTool(DeletePendingPullRequestReview(getGQLClient, t)),
106220
)
107-
codeSecurity := toolsets.NewToolset("code_security", "Code security related tools, such as GitHub Code Scanning").
221+
codeSecurity := toolsets.NewToolset(ToolsetMetadataCodeSecurity.ID, ToolsetMetadataCodeSecurity.Description).
108222
AddReadTools(
109223
toolsets.NewServerTool(GetCodeScanningAlert(getClient, t)),
110224
toolsets.NewServerTool(ListCodeScanningAlerts(getClient, t)),
111225
)
112-
secretProtection := toolsets.NewToolset("secret_protection", "Secret protection related tools, such as GitHub Secret Scanning").
226+
secretProtection := toolsets.NewToolset(ToolsetMetadataSecretProtection.ID, ToolsetMetadataSecretProtection.Description).
113227
AddReadTools(
114228
toolsets.NewServerTool(GetSecretScanningAlert(getClient, t)),
115229
toolsets.NewServerTool(ListSecretScanningAlerts(getClient, t)),
116230
)
117-
dependabot := toolsets.NewToolset("dependabot", "Dependabot tools").
231+
dependabot := toolsets.NewToolset(ToolsetMetadataDependabot.ID, ToolsetMetadataDependabot.Description).
118232
AddReadTools(
119233
toolsets.NewServerTool(GetDependabotAlert(getClient, t)),
120234
toolsets.NewServerTool(ListDependabotAlerts(getClient, t)),
121235
)
122236

123-
notifications := toolsets.NewToolset("notifications", "GitHub Notifications related tools").
237+
notifications := toolsets.NewToolset(ToolsetMetadataNotifications.ID, ToolsetMetadataNotifications.Description).
124238
AddReadTools(
125239
toolsets.NewServerTool(ListNotifications(getClient, t)),
126240
toolsets.NewServerTool(GetNotificationDetails(getClient, t)),
@@ -132,15 +246,15 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
132246
toolsets.NewServerTool(ManageRepositoryNotificationSubscription(getClient, t)),
133247
)
134248

135-
discussions := toolsets.NewToolset("discussions", "GitHub Discussions related tools").
249+
discussions := toolsets.NewToolset(ToolsetMetadataDiscussions.ID, ToolsetMetadataDiscussions.Description).
136250
AddReadTools(
137251
toolsets.NewServerTool(ListDiscussions(getGQLClient, t)),
138252
toolsets.NewServerTool(GetDiscussion(getGQLClient, t)),
139253
toolsets.NewServerTool(GetDiscussionComments(getGQLClient, t)),
140254
toolsets.NewServerTool(ListDiscussionCategories(getGQLClient, t)),
141255
)
142256

143-
actions := toolsets.NewToolset("actions", "GitHub Actions workflows and CI/CD operations").
257+
actions := toolsets.NewToolset(ToolsetMetadataActions.ID, ToolsetMetadataActions.Description).
144258
AddReadTools(
145259
toolsets.NewServerTool(ListWorkflows(getClient, t)),
146260
toolsets.NewServerTool(ListWorkflowRuns(getClient, t)),
@@ -160,7 +274,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
160274
toolsets.NewServerTool(DeleteWorkflowRunLogs(getClient, t)),
161275
)
162276

163-
securityAdvisories := toolsets.NewToolset("security_advisories", "Security advisories related tools").
277+
securityAdvisories := toolsets.NewToolset(ToolsetMetadataSecurityAdvisories.ID, ToolsetMetadataSecurityAdvisories.Description).
164278
AddReadTools(
165279
toolsets.NewServerTool(ListGlobalSecurityAdvisories(getClient, t)),
166280
toolsets.NewServerTool(GetGlobalSecurityAdvisory(getClient, t)),
@@ -169,16 +283,16 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
169283
)
170284

171285
// Keep experiments alive so the system doesn't error out when it's always enabled
172-
experiments := toolsets.NewToolset("experiments", "Experimental features that are not considered stable yet")
286+
experiments := toolsets.NewToolset(ToolsetMetadataExperiments.ID, ToolsetMetadataExperiments.Description)
173287

174-
contextTools := toolsets.NewToolset("context", "Tools that provide context about the current user and GitHub context you are operating in").
288+
contextTools := toolsets.NewToolset(ToolsetMetadataContext.ID, ToolsetMetadataContext.Description).
175289
AddReadTools(
176290
toolsets.NewServerTool(GetMe(getClient, t)),
177291
toolsets.NewServerTool(GetTeams(getClient, getGQLClient, t)),
178292
toolsets.NewServerTool(GetTeamMembers(getGQLClient, t)),
179293
)
180294

181-
gists := toolsets.NewToolset("gists", "GitHub Gist related tools").
295+
gists := toolsets.NewToolset(ToolsetMetadataGists.ID, ToolsetMetadataGists.Description).
182296
AddReadTools(
183297
toolsets.NewServerTool(ListGists(getClient, t)),
184298
).
@@ -187,7 +301,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
187301
toolsets.NewServerTool(UpdateGist(getClient, t)),
188302
)
189303

190-
projects := toolsets.NewToolset("projects", "GitHub Projects related tools").
304+
projects := toolsets.NewToolset(ToolsetMetadataProjects.ID, ToolsetMetadataProjects.Description).
191305
AddReadTools(
192306
toolsets.NewServerTool(ListProjects(getClient, t)),
193307
toolsets.NewServerTool(GetProject(getClient, t)),
@@ -201,7 +315,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
201315
toolsets.NewServerTool(DeleteProjectItem(getClient, t)),
202316
toolsets.NewServerTool(UpdateProjectItem(getClient, t)),
203317
)
204-
stargazers := toolsets.NewToolset("stargazers", "GitHub Stargazers related tools").
318+
stargazers := toolsets.NewToolset(ToolsetMetadataStargazers.ID, ToolsetMetadataStargazers.Description).
205319
AddReadTools(
206320
toolsets.NewServerTool(ListStarredRepositories(getClient, t)),
207321
).
@@ -236,7 +350,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG
236350
func InitDynamicToolset(s *server.MCPServer, tsg *toolsets.ToolsetGroup, t translations.TranslationHelperFunc) *toolsets.Toolset {
237351
// Create a new dynamic toolset
238352
// Need to add the dynamic toolset last so it can be used to enable other toolsets
239-
dynamicToolSelection := toolsets.NewToolset("dynamic", "Discover GitHub MCP tools that can help achieve tasks by enabling additional sets of tools, you can control the enablement of any toolset to access its tools when this toolset is enabled.").
353+
dynamicToolSelection := toolsets.NewToolset(ToolsetMetadataDynamic.ID, ToolsetMetadataDynamic.Description).
240354
AddReadTools(
241355
toolsets.NewServerTool(ListAvailableToolsets(tsg, t)),
242356
toolsets.NewServerTool(GetToolsetsTools(tsg, t)),
@@ -260,3 +374,37 @@ func ToStringPtr(s string) *string {
260374
}
261375
return &s
262376
}
377+
378+
// GenerateToolsetsHelp generates the help text for the toolsets flag
379+
func GenerateToolsetsHelp() string {
380+
// Format default tools
381+
defaultTools := strings.Join(GetDefaultToolsetIDs(), ", ")
382+
383+
// Format available tools with line breaks for better readability
384+
allTools := AvailableTools()
385+
var availableToolsLines []string
386+
const maxLineLength = 70
387+
currentLine := ""
388+
389+
for i, tool := range allTools {
390+
if i == 0 {
391+
currentLine = tool.ID
392+
} else if len(currentLine)+len(tool.ID)+2 <= maxLineLength {
393+
currentLine += ", " + tool.ID
394+
} else {
395+
availableToolsLines = append(availableToolsLines, currentLine)
396+
currentLine = tool.ID
397+
}
398+
}
399+
if currentLine != "" {
400+
availableToolsLines = append(availableToolsLines, currentLine)
401+
}
402+
403+
availableTools := strings.Join(availableToolsLines, ",\n\t ")
404+
405+
toolsetsHelp := fmt.Sprintf("Comma-separated list of tool groups to enable (no spaces).\n"+
406+
"Default: %s\n"+
407+
"Available: %s\n", defaultTools, availableTools)+
408+
"To enable all tools, use \"all\"."
409+
return toolsetsHelp
410+
}

0 commit comments

Comments
 (0)