From bf4f6d814f2d7ac543ce4ee8177626927b784b92 Mon Sep 17 00:00:00 2001 From: tonytrg Date: Tue, 30 Sep 2025 12:47:09 +0200 Subject: [PATCH 1/5] adding default toolset group, splitting up stargazers from repos --- README.md | 37 ++++++++++++++++++++++--------------- docs/remote-server.md | 1 + pkg/github/tools.go | 14 ++++++++++---- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index bd0963abf..7722e394f 100644 --- a/README.md +++ b/README.md @@ -293,6 +293,7 @@ The following sets of tools are available (all are on by default): | `repos` | GitHub Repository related tools | | `secret_protection` | Secret protection related tools, such as GitHub Secret Scanning | | `security_advisories` | Security advisories related tools | +| `stargazers` | GitHub Stargazers related tools | | `users` | GitHub User related tools | @@ -940,13 +941,6 @@ The following sets of tools are available (all are on by default): - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - `repo`: Repository name (string, required) -- **list_starred_repositories** - List starred repositories - - `direction`: The direction to sort the results by. (string, optional) - - `page`: Page number for pagination (min 1) (number, optional) - - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - - `sort`: How to sort the results. Can be either 'created' (when the repository was starred) or 'updated' (when the repository was last pushed to). (string, optional) - - `username`: Username to list starred repositories for. Defaults to the authenticated user. (string, optional) - - **list_tags** - List tags - `owner`: Repository owner (string, required) - `page`: Page number for pagination (min 1) (number, optional) @@ -973,14 +967,6 @@ The following sets of tools are available (all are on by default): - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) - `query`: Repository search query. Examples: 'machine learning in:name stars:>1000 language:python', 'topic:react', 'user:facebook'. Supports advanced search syntax for precise filtering. (string, required) -- **star_repository** - Star repository - - `owner`: Repository owner (string, required) - - `repo`: Repository name (string, required) - -- **unstar_repository** - Unstar repository - - `owner`: Repository owner (string, required) - - `repo`: Repository name (string, required) -
@@ -1038,6 +1024,27 @@ The following sets of tools are available (all are on by default):
+Stargazers + +- **list_starred_repositories** - List starred repositories + - `direction`: The direction to sort the results by. (string, optional) + - `page`: Page number for pagination (min 1) (number, optional) + - `perPage`: Results per page for pagination (min 1, max 100) (number, optional) + - `sort`: How to sort the results. Can be either 'created' (when the repository was starred) or 'updated' (when the repository was last pushed to). (string, optional) + - `username`: Username to list starred repositories for. Defaults to the authenticated user. (string, optional) + +- **star_repository** - Star repository + - `owner`: Repository owner (string, required) + - `repo`: Repository name (string, required) + +- **unstar_repository** - Unstar repository + - `owner`: Repository owner (string, required) + - `repo`: Repository name (string, required) + +
+ +
+ Users - **search_users** - Search users diff --git a/docs/remote-server.md b/docs/remote-server.md index 7be9d83bb..da82e846d 100644 --- a/docs/remote-server.md +++ b/docs/remote-server.md @@ -34,6 +34,7 @@ Below is a table of available toolsets for the remote GitHub MCP Server. Each to | Repositories | GitHub Repository related tools | https://api.githubcopilot.com/mcp/x/repos | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-repos&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Frepos%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/repos/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-repos&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Frepos%2Freadonly%22%7D) | | Secret Protection | Secret protection related tools, such as GitHub Secret Scanning | https://api.githubcopilot.com/mcp/x/secret_protection | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-secret_protection&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecret_protection%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/secret_protection/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-secret_protection&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecret_protection%2Freadonly%22%7D) | | Security Advisories | Security advisories related tools | https://api.githubcopilot.com/mcp/x/security_advisories | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-security_advisories&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecurity_advisories%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/security_advisories/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-security_advisories&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fsecurity_advisories%2Freadonly%22%7D) | +| Stargazers | GitHub Stargazers related tools | https://api.githubcopilot.com/mcp/x/stargazers | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-stargazers&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fstargazers%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/stargazers/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-stargazers&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fstargazers%2Freadonly%22%7D) | | Users | GitHub User related tools | https://api.githubcopilot.com/mcp/x/users | [Install](https://insiders.vscode.dev/redirect/mcp/install?name=gh-users&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fusers%22%7D) | [read-only](https://api.githubcopilot.com/mcp/x/users/readonly) | [Install read-only](https://insiders.vscode.dev/redirect/mcp/install?name=gh-users&config=%7B%22type%22%3A%20%22http%22%2C%22url%22%3A%20%22https%3A%2F%2Fapi.githubcopilot.com%2Fmcp%2Fx%2Fusers%2Freadonly%22%7D) | diff --git a/pkg/github/tools.go b/pkg/github/tools.go index dec0a9e37..6663f8187 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -14,7 +14,7 @@ import ( type GetClientFn func(context.Context) (*github.Client, error) type GetGQLClientFn func(context.Context) (*githubv4.Client, error) -var DefaultTools = []string{"all"} +var DefaultTools = []string{"context", "repos", "issues", "pull_requests", "users"} func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetGQLClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc, contentWindowSize int) *toolsets.ToolsetGroup { tsg := toolsets.NewToolsetGroup(readOnly) @@ -34,7 +34,6 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(ListReleases(getClient, t)), toolsets.NewServerTool(GetLatestRelease(getClient, t)), toolsets.NewServerTool(GetReleaseByTag(getClient, t)), - toolsets.NewServerTool(ListStarredRepositories(getClient, t)), ). AddWriteTools( toolsets.NewServerTool(CreateOrUpdateFile(getClient, t)), @@ -43,8 +42,6 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(CreateBranch(getClient, t)), toolsets.NewServerTool(PushFiles(getClient, t)), toolsets.NewServerTool(DeleteFile(getClient, t)), - toolsets.NewServerTool(StarRepository(getClient, t)), - toolsets.NewServerTool(UnstarRepository(getClient, t)), ). AddResourceTemplates( toolsets.NewServerResourceTemplate(GetRepositoryResourceContent(getClient, getRawClient, t)), @@ -204,6 +201,14 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(DeleteProjectItem(getClient, t)), toolsets.NewServerTool(UpdateProjectItem(getClient, t)), ) + stargazers := toolsets.NewToolset("stargazers", "GitHub Stargazers related tools"). + AddReadTools( + toolsets.NewServerTool(ListStarredRepositories(getClient, t)), + ). + AddWriteTools( + toolsets.NewServerTool(StarRepository(getClient, t)), + toolsets.NewServerTool(UnstarRepository(getClient, t)), + ) // Add toolsets to the group tsg.AddToolset(contextTools) @@ -222,6 +227,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG tsg.AddToolset(gists) tsg.AddToolset(securityAdvisories) tsg.AddToolset(projects) + tsg.AddToolset(stargazers) return tsg } From c2220f81ba4d8963d5293d4d34e3668a5b67cf9f Mon Sep 17 00:00:00 2001 From: tonytrg Date: Tue, 30 Sep 2025 19:53:31 +0200 Subject: [PATCH 2/5] adding structs for toolset group metadata --- cmd/github-mcp-server/main.go | 6 +- pkg/github/tools.go | 186 ++++++++++++++++++++++++++++++---- 2 files changed, 172 insertions(+), 20 deletions(-) diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go index 0a4545835..a0e225293 100644 --- a/cmd/github-mcp-server/main.go +++ b/cmd/github-mcp-server/main.go @@ -45,6 +45,10 @@ var ( return fmt.Errorf("failed to unmarshal toolsets: %w", err) } + if len(enabledToolsets) == 0 { + enabledToolsets = github.GetDefaultToolsetIDs() + } + stdioServerConfig := ghmcp.StdioServerConfig{ Version: version, Host: viper.GetString("host"), @@ -69,7 +73,7 @@ func init() { rootCmd.SetVersionTemplate("{{.Short}}\n{{.Version}}\n") // Add global flags that will be shared by all commands - rootCmd.PersistentFlags().StringSlice("toolsets", github.DefaultTools, "An optional comma separated list of groups of tools to allow, defaults to enabling all") + rootCmd.PersistentFlags().StringSlice("toolsets", nil, github.GenerateToolsetsHelp()) rootCmd.PersistentFlags().Bool("dynamic-toolsets", false, "Enable dynamic toolsets") rootCmd.PersistentFlags().Bool("read-only", false, "Restrict the server to read-only operations") rootCmd.PersistentFlags().String("log-file", "", "Path to log file") diff --git a/pkg/github/tools.go b/pkg/github/tools.go index 6663f8187..835df975c 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -2,6 +2,8 @@ package github import ( "context" + "fmt" + "strings" "github.com/github/github-mcp-server/pkg/raw" "github.com/github/github-mcp-server/pkg/toolsets" @@ -14,14 +16,126 @@ import ( type GetClientFn func(context.Context) (*github.Client, error) type GetGQLClientFn func(context.Context) (*githubv4.Client, error) -var DefaultTools = []string{"context", "repos", "issues", "pull_requests", "users"} +// ToolsetMetadata holds metadata for a toolset including its ID and description +type ToolsetMetadata struct { + ID string + Description string +} + +var ( + ToolsetMetadataContext = ToolsetMetadata{ + ID: "context", + Description: "Tools that provide context about the current user and GitHub context you are operating in", + } + ToolsetMetadataRepos = ToolsetMetadata{ + ID: "repos", + Description: "GitHub Repository related tools", + } + ToolsetMetadataIssues = ToolsetMetadata{ + ID: "issues", + Description: "GitHub Issues related tools", + } + ToolsetMetadataPullRequests = ToolsetMetadata{ + ID: "pull_requests", + Description: "GitHub Pull Request related tools", + } + ToolsetMetadataUsers = ToolsetMetadata{ + ID: "users", + Description: "GitHub User related tools", + } + ToolsetMetadataOrgs = ToolsetMetadata{ + ID: "orgs", + Description: "GitHub Organization related tools", + } + ToolsetMetadataActions = ToolsetMetadata{ + ID: "actions", + Description: "GitHub Actions workflows and CI/CD operations", + } + ToolsetMetadataCodeSecurity = ToolsetMetadata{ + ID: "code_security", + Description: "Code security related tools, such as GitHub Code Scanning", + } + ToolsetMetadataSecretProtection = ToolsetMetadata{ + ID: "secret_protection", + Description: "Secret protection related tools, such as GitHub Secret Scanning", + } + ToolsetMetadataDependabot = ToolsetMetadata{ + ID: "dependabot", + Description: "Dependabot tools", + } + ToolsetMetadataNotifications = ToolsetMetadata{ + ID: "notifications", + Description: "GitHub Notifications related tools", + } + ToolsetMetadataExperiments = ToolsetMetadata{ + ID: "experiments", + Description: "Experimental features that are not considered stable yet", + } + ToolsetMetadataDiscussions = ToolsetMetadata{ + ID: "discussions", + Description: "GitHub Discussions related tools", + } + ToolsetMetadataGists = ToolsetMetadata{ + ID: "gists", + Description: "GitHub Gist related tools", + } + ToolsetMetadataSecurityAdvisories = ToolsetMetadata{ + ID: "security_advisories", + Description: "Security advisories related tools", + } + ToolsetMetadataProjects = ToolsetMetadata{ + ID: "projects", + Description: "GitHub Projects related tools", + } + ToolsetMetadataStargazers = ToolsetMetadata{ + ID: "stargazers", + Description: "GitHub Stargazers related tools", + } + ToolsetMetadataDynamic = ToolsetMetadata{ + ID: "dynamic", + 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.", + } +) + +func AvailableTools() []ToolsetMetadata { + return []ToolsetMetadata{ + ToolsetMetadataContext, + ToolsetMetadataRepos, + ToolsetMetadataIssues, + ToolsetMetadataPullRequests, + ToolsetMetadataUsers, + ToolsetMetadataOrgs, + ToolsetMetadataActions, + ToolsetMetadataCodeSecurity, + ToolsetMetadataSecretProtection, + ToolsetMetadataDependabot, + ToolsetMetadataNotifications, + ToolsetMetadataExperiments, + ToolsetMetadataDiscussions, + ToolsetMetadataGists, + ToolsetMetadataSecurityAdvisories, + ToolsetMetadataProjects, + ToolsetMetadataStargazers, + ToolsetMetadataDynamic, + } +} + +func GetDefaultToolsetIDs() []string { + return []string{ + ToolsetMetadataContext.ID, + ToolsetMetadataRepos.ID, + ToolsetMetadataIssues.ID, + ToolsetMetadataPullRequests.ID, + ToolsetMetadataUsers.ID, + } +} func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetGQLClientFn, getRawClient raw.GetRawClientFn, t translations.TranslationHelperFunc, contentWindowSize int) *toolsets.ToolsetGroup { tsg := toolsets.NewToolsetGroup(readOnly) // Define all available features with their default state (disabled) // Create toolsets - repos := toolsets.NewToolset("repos", "GitHub Repository related tools"). + repos := toolsets.NewToolset(ToolsetMetadataRepos.ID, ToolsetMetadataRepos.Description). AddReadTools( toolsets.NewServerTool(SearchRepositories(getClient, t)), toolsets.NewServerTool(GetFileContents(getClient, getRawClient, t)), @@ -50,7 +164,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerResourceTemplate(GetRepositoryResourceTagContent(getClient, getRawClient, t)), toolsets.NewServerResourceTemplate(GetRepositoryResourcePrContent(getClient, getRawClient, t)), ) - issues := toolsets.NewToolset("issues", "GitHub Issues related tools"). + issues := toolsets.NewToolset(ToolsetMetadataIssues.ID, ToolsetMetadataIssues.Description). AddReadTools( toolsets.NewServerTool(GetIssue(getClient, t)), toolsets.NewServerTool(SearchIssues(getClient, t)), @@ -71,15 +185,15 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerPrompt(AssignCodingAgentPrompt(t)), toolsets.NewServerPrompt(IssueToFixWorkflowPrompt(t)), ) - users := toolsets.NewToolset("users", "GitHub User related tools"). + users := toolsets.NewToolset(ToolsetMetadataUsers.ID, ToolsetMetadataUsers.Description). AddReadTools( toolsets.NewServerTool(SearchUsers(getClient, t)), ) - orgs := toolsets.NewToolset("orgs", "GitHub Organization related tools"). + orgs := toolsets.NewToolset(ToolsetMetadataOrgs.ID, ToolsetMetadataOrgs.Description). AddReadTools( toolsets.NewServerTool(SearchOrgs(getClient, t)), ) - pullRequests := toolsets.NewToolset("pull_requests", "GitHub Pull Request related tools"). + pullRequests := toolsets.NewToolset(ToolsetMetadataPullRequests.ID, ToolsetMetadataPullRequests.Description). AddReadTools( toolsets.NewServerTool(GetPullRequest(getClient, t)), toolsets.NewServerTool(ListPullRequests(getClient, t)), @@ -104,23 +218,23 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(SubmitPendingPullRequestReview(getGQLClient, t)), toolsets.NewServerTool(DeletePendingPullRequestReview(getGQLClient, t)), ) - codeSecurity := toolsets.NewToolset("code_security", "Code security related tools, such as GitHub Code Scanning"). + codeSecurity := toolsets.NewToolset(ToolsetMetadataCodeSecurity.ID, ToolsetMetadataCodeSecurity.Description). AddReadTools( toolsets.NewServerTool(GetCodeScanningAlert(getClient, t)), toolsets.NewServerTool(ListCodeScanningAlerts(getClient, t)), ) - secretProtection := toolsets.NewToolset("secret_protection", "Secret protection related tools, such as GitHub Secret Scanning"). + secretProtection := toolsets.NewToolset(ToolsetMetadataSecretProtection.ID, ToolsetMetadataSecretProtection.Description). AddReadTools( toolsets.NewServerTool(GetSecretScanningAlert(getClient, t)), toolsets.NewServerTool(ListSecretScanningAlerts(getClient, t)), ) - dependabot := toolsets.NewToolset("dependabot", "Dependabot tools"). + dependabot := toolsets.NewToolset(ToolsetMetadataDependabot.ID, ToolsetMetadataDependabot.Description). AddReadTools( toolsets.NewServerTool(GetDependabotAlert(getClient, t)), toolsets.NewServerTool(ListDependabotAlerts(getClient, t)), ) - notifications := toolsets.NewToolset("notifications", "GitHub Notifications related tools"). + notifications := toolsets.NewToolset(ToolsetMetadataNotifications.ID, ToolsetMetadataNotifications.Description). AddReadTools( toolsets.NewServerTool(ListNotifications(getClient, t)), toolsets.NewServerTool(GetNotificationDetails(getClient, t)), @@ -132,7 +246,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(ManageRepositoryNotificationSubscription(getClient, t)), ) - discussions := toolsets.NewToolset("discussions", "GitHub Discussions related tools"). + discussions := toolsets.NewToolset(ToolsetMetadataDiscussions.ID, ToolsetMetadataDiscussions.Description). AddReadTools( toolsets.NewServerTool(ListDiscussions(getGQLClient, t)), toolsets.NewServerTool(GetDiscussion(getGQLClient, t)), @@ -140,7 +254,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(ListDiscussionCategories(getGQLClient, t)), ) - actions := toolsets.NewToolset("actions", "GitHub Actions workflows and CI/CD operations"). + actions := toolsets.NewToolset(ToolsetMetadataActions.ID, ToolsetMetadataActions.Description). AddReadTools( toolsets.NewServerTool(ListWorkflows(getClient, t)), toolsets.NewServerTool(ListWorkflowRuns(getClient, t)), @@ -160,7 +274,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(DeleteWorkflowRunLogs(getClient, t)), ) - securityAdvisories := toolsets.NewToolset("security_advisories", "Security advisories related tools"). + securityAdvisories := toolsets.NewToolset(ToolsetMetadataSecurityAdvisories.ID, ToolsetMetadataSecurityAdvisories.Description). AddReadTools( toolsets.NewServerTool(ListGlobalSecurityAdvisories(getClient, t)), toolsets.NewServerTool(GetGlobalSecurityAdvisory(getClient, t)), @@ -169,16 +283,16 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG ) // Keep experiments alive so the system doesn't error out when it's always enabled - experiments := toolsets.NewToolset("experiments", "Experimental features that are not considered stable yet") + experiments := toolsets.NewToolset(ToolsetMetadataExperiments.ID, ToolsetMetadataExperiments.Description) - contextTools := toolsets.NewToolset("context", "Tools that provide context about the current user and GitHub context you are operating in"). + contextTools := toolsets.NewToolset(ToolsetMetadataContext.ID, ToolsetMetadataContext.Description). AddReadTools( toolsets.NewServerTool(GetMe(getClient, t)), toolsets.NewServerTool(GetTeams(getClient, getGQLClient, t)), toolsets.NewServerTool(GetTeamMembers(getGQLClient, t)), ) - gists := toolsets.NewToolset("gists", "GitHub Gist related tools"). + gists := toolsets.NewToolset(ToolsetMetadataGists.ID, ToolsetMetadataGists.Description). AddReadTools( toolsets.NewServerTool(ListGists(getClient, t)), ). @@ -187,7 +301,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(UpdateGist(getClient, t)), ) - projects := toolsets.NewToolset("projects", "GitHub Projects related tools"). + projects := toolsets.NewToolset(ToolsetMetadataProjects.ID, ToolsetMetadataProjects.Description). AddReadTools( toolsets.NewServerTool(ListProjects(getClient, t)), toolsets.NewServerTool(GetProject(getClient, t)), @@ -201,7 +315,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG toolsets.NewServerTool(DeleteProjectItem(getClient, t)), toolsets.NewServerTool(UpdateProjectItem(getClient, t)), ) - stargazers := toolsets.NewToolset("stargazers", "GitHub Stargazers related tools"). + stargazers := toolsets.NewToolset(ToolsetMetadataStargazers.ID, ToolsetMetadataStargazers.Description). AddReadTools( toolsets.NewServerTool(ListStarredRepositories(getClient, t)), ). @@ -236,7 +350,7 @@ func DefaultToolsetGroup(readOnly bool, getClient GetClientFn, getGQLClient GetG func InitDynamicToolset(s *server.MCPServer, tsg *toolsets.ToolsetGroup, t translations.TranslationHelperFunc) *toolsets.Toolset { // Create a new dynamic toolset // Need to add the dynamic toolset last so it can be used to enable other toolsets - 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."). + dynamicToolSelection := toolsets.NewToolset(ToolsetMetadataDynamic.ID, ToolsetMetadataDynamic.Description). AddReadTools( toolsets.NewServerTool(ListAvailableToolsets(tsg, t)), toolsets.NewServerTool(GetToolsetsTools(tsg, t)), @@ -260,3 +374,37 @@ func ToStringPtr(s string) *string { } return &s } + +// GenerateToolsetsHelp generates the help text for the toolsets flag +func GenerateToolsetsHelp() string { + // Format default tools + defaultTools := strings.Join(GetDefaultToolsetIDs(), ", ") + + // Format available tools with line breaks for better readability + allTools := AvailableTools() + var availableToolsLines []string + const maxLineLength = 70 + currentLine := "" + + for i, tool := range allTools { + if i == 0 { + currentLine = tool.ID + } else if len(currentLine)+len(tool.ID)+2 <= maxLineLength { + currentLine += ", " + tool.ID + } else { + availableToolsLines = append(availableToolsLines, currentLine) + currentLine = tool.ID + } + } + if currentLine != "" { + availableToolsLines = append(availableToolsLines, currentLine) + } + + availableTools := strings.Join(availableToolsLines, ",\n\t ") + + toolsetsHelp := fmt.Sprintf("Comma-separated list of tool groups to enable (no spaces).\n"+ + "Default: %s\n"+ + "Available: %s\n", defaultTools, availableTools)+ + "To enable all tools, use \"all\"." + return toolsetsHelp +} From ab06f3922e291779151a8fab5f3926eb595d8e44 Mon Sep 17 00:00:00 2001 From: tonytrg Date: Tue, 30 Sep 2025 19:59:17 +0200 Subject: [PATCH 3/5] update readme --- README.md | 7 +++++++ pkg/github/tools.go | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7722e394f..3f277f2d0 100644 --- a/README.md +++ b/README.md @@ -1100,6 +1100,13 @@ To specify toolsets you want available to the LLM, you can pass an allow-list in The environment variable `GITHUB_TOOLSETS` takes precedence over the command line argument if both are provided. +The default configuration is: +- context +- repos +- issues +- pull_requests +- users + ### Using Toolsets With Docker When using Docker, you can pass the toolsets as environment variables: diff --git a/pkg/github/tools.go b/pkg/github/tools.go index 835df975c..2a9439efa 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -404,7 +404,7 @@ func GenerateToolsetsHelp() string { toolsetsHelp := fmt.Sprintf("Comma-separated list of tool groups to enable (no spaces).\n"+ "Default: %s\n"+ - "Available: %s\n", defaultTools, availableTools)+ + "Available: %s\n", defaultTools, availableTools) + "To enable all tools, use \"all\"." return toolsetsHelp } From 9573d4d34842d28d851b73abafc6653e4aa3c163 Mon Sep 17 00:00:00 2001 From: tonytrg Date: Tue, 30 Sep 2025 20:19:21 +0200 Subject: [PATCH 4/5] refactor the readme --- README.md | 106 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 3f277f2d0..f03e54b9a 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,17 @@ Alternatively, to manually configure VS Code, choose the appropriate JSON block > **Note:** Each MCP host application needs to configure a GitHub App or OAuth App to support remote access via OAuth. Any host application that supports remote MCP servers should support the remote GitHub server with PAT authentication. Configuration details and support levels vary by host. Make sure to refer to the host application's documentation for more info. ### Configuration -See [Remote Server Documentation](/docs/remote-server.md) on how to pass additional configuration settings to the remote GitHub MCP Server. + +#### Default toolset configuration + +The default configuration is: +- context +- repos +- issues +- pull_requests +- users + +See [Remote Server Documentation](docs/remote-server.md) for full details on remote server configuration, toolsets, headers, and advanced usage. This file provides comprehensive instructions and examples for connecting, customizing, and installing the remote GitHub MCP Server in VS Code and other MCP hosts. --- @@ -271,6 +281,50 @@ The GitHub MCP Server supports enabling or disabling specific groups of function _Toolsets are not limited to Tools. Relevant MCP Resources and Prompts are also included where applicable._ +The Local GitHub MCP Server follows the same [default toolset configuration](#default-toolset-configuration) as the remote version. + +#### Specifying Toolsets + +To specify toolsets you want available to the LLM, you can pass an allow-list in two ways: + +1. **Using Command Line Argument**: + + ```bash + github-mcp-server --toolsets repos,issues,pull_requests,actions,code_security + ``` + +2. **Using Environment Variable**: + ```bash + GITHUB_TOOLSETS="repos,issues,pull_requests,actions,code_security" ./github-mcp-server + ``` + +The environment variable `GITHUB_TOOLSETS` takes precedence over the command line argument if both are provided. + +### Using Toolsets With Docker + +When using Docker, you can pass the toolsets as environment variables: + +```bash +docker run -i --rm \ + -e GITHUB_PERSONAL_ACCESS_TOKEN= \ + -e GITHUB_TOOLSETS="repos,issues,pull_requests,actions,code_security,experiments" \ + ghcr.io/github/github-mcp-server +``` + +### The "all" Toolset + +The special toolset `all` can be provided to enable all available toolsets regardless of any other configuration: + +```bash +./github-mcp-server --toolsets all +``` + +Or using the environment variable: + +```bash +GITHUB_TOOLSETS="all" ./github-mcp-server +``` + ### Available Toolsets The following sets of tools are available (all are on by default): @@ -299,7 +353,6 @@ The following sets of tools are available (all are on by default): ## Tools -
@@ -1083,55 +1136,6 @@ The following sets of tools are available (all are on by default): - **list_copilot_spaces** - List Copilot Spaces
-#### Specifying Toolsets - -To specify toolsets you want available to the LLM, you can pass an allow-list in two ways: - -1. **Using Command Line Argument**: - - ```bash - github-mcp-server --toolsets repos,issues,pull_requests,actions,code_security - ``` - -2. **Using Environment Variable**: - ```bash - GITHUB_TOOLSETS="repos,issues,pull_requests,actions,code_security" ./github-mcp-server - ``` - -The environment variable `GITHUB_TOOLSETS` takes precedence over the command line argument if both are provided. - -The default configuration is: -- context -- repos -- issues -- pull_requests -- users - -### Using Toolsets With Docker - -When using Docker, you can pass the toolsets as environment variables: - -```bash -docker run -i --rm \ - -e GITHUB_PERSONAL_ACCESS_TOKEN= \ - -e GITHUB_TOOLSETS="repos,issues,pull_requests,actions,code_security,experiments" \ - ghcr.io/github/github-mcp-server -``` - -### The "all" Toolset - -The special toolset `all` can be provided to enable all available toolsets regardless of any other configuration: - -```bash -./github-mcp-server --toolsets all -``` - -Or using the environment variable: - -```bash -GITHUB_TOOLSETS="all" ./github-mcp-server -``` - ## Dynamic Tool Discovery **Note**: This feature is currently in beta and may not be available in all environments. Please test it out and let us know if you encounter any issues. From ea275ce9535802d2107787cba7e3c8c779fa4c49 Mon Sep 17 00:00:00 2001 From: tonytrg Date: Wed, 1 Oct 2025 10:02:00 +0200 Subject: [PATCH 5/5] fix lint --- pkg/github/tools.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/github/tools.go b/pkg/github/tools.go index 2a9439efa..cdb7ce8a2 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -387,11 +387,12 @@ func GenerateToolsetsHelp() string { currentLine := "" for i, tool := range allTools { - if i == 0 { + switch { + case i == 0: currentLine = tool.ID - } else if len(currentLine)+len(tool.ID)+2 <= maxLineLength { + case len(currentLine)+len(tool.ID)+2 <= maxLineLength: currentLine += ", " + tool.ID - } else { + default: availableToolsLines = append(availableToolsLines, currentLine) currentLine = tool.ID }