diff --git a/cmd/github-mcp-server/main.go b/cmd/github-mcp-server/main.go index cad002666..1605f4523 100644 --- a/cmd/github-mcp-server/main.go +++ b/cmd/github-mcp-server/main.go @@ -52,6 +52,7 @@ var ( EnabledToolsets: enabledToolsets, DynamicToolsets: viper.GetBool("dynamic_toolsets"), ReadOnly: viper.GetBool("read-only"), + ToolPrefix: viper.GetString("tool-prefix"), ExportTranslations: viper.GetBool("export-translations"), EnableCommandLogging: viper.GetBool("enable-command-logging"), LogFilePath: viper.GetString("log-file"), @@ -71,6 +72,7 @@ func init() { rootCmd.PersistentFlags().StringSlice("toolsets", github.DefaultTools, "An optional comma separated list of groups of tools to allow, defaults to enabling all") 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("tool-prefix", "", "Optional prefix to add to all tool names (e.g. 'github_')") rootCmd.PersistentFlags().String("log-file", "", "Path to log file") rootCmd.PersistentFlags().Bool("enable-command-logging", false, "When enabled, the server will log all command requests and responses to the log file") rootCmd.PersistentFlags().Bool("export-translations", false, "Save translations to a JSON file") @@ -80,6 +82,7 @@ func init() { _ = viper.BindPFlag("toolsets", rootCmd.PersistentFlags().Lookup("toolsets")) _ = viper.BindPFlag("dynamic_toolsets", rootCmd.PersistentFlags().Lookup("dynamic-toolsets")) _ = viper.BindPFlag("read-only", rootCmd.PersistentFlags().Lookup("read-only")) + _ = viper.BindPFlag("tool-prefix", rootCmd.PersistentFlags().Lookup("tool-prefix")) _ = viper.BindPFlag("log-file", rootCmd.PersistentFlags().Lookup("log-file")) _ = viper.BindPFlag("enable-command-logging", rootCmd.PersistentFlags().Lookup("enable-command-logging")) _ = viper.BindPFlag("export-translations", rootCmd.PersistentFlags().Lookup("export-translations")) diff --git a/internal/ghmcp/server.go b/internal/ghmcp/server.go index 568af10d1..3c307b886 100644 --- a/internal/ghmcp/server.go +++ b/internal/ghmcp/server.go @@ -45,6 +45,9 @@ type MCPServerConfig struct { // ReadOnly indicates if we should only offer read-only tools ReadOnly bool + // ToolPrefix is an optional prefix to add to all tool names (e.g. "github_") + ToolPrefix string + // Translator provides translated text for the server tooling Translator translations.TranslationHelperFunc } @@ -138,11 +141,11 @@ func NewMCPServer(cfg MCPServerConfig) (*server.MCPServer, error) { } // Register all mcp functionality with the server - tsg.RegisterAll(ghServer) + tsg.RegisterAll(ghServer, cfg.ToolPrefix) if cfg.DynamicToolsets { dynamic := github.InitDynamicToolset(ghServer, tsg, cfg.Translator) - dynamic.RegisterTools(ghServer) + dynamic.RegisterTools(ghServer, cfg.ToolPrefix) } return ghServer, nil @@ -169,6 +172,9 @@ type StdioServerConfig struct { // ReadOnly indicates if we should only register read-only tools ReadOnly bool + // ToolPrefix is an optional prefix to add to all tool names (e.g. "github_") + ToolPrefix string + // ExportTranslations indicates if we should export translations // See: https://github.com/github/github-mcp-server?tab=readme-ov-file#i18n--overriding-descriptions ExportTranslations bool @@ -195,6 +201,7 @@ func RunStdioServer(cfg StdioServerConfig) error { EnabledToolsets: cfg.EnabledToolsets, DynamicToolsets: cfg.DynamicToolsets, ReadOnly: cfg.ReadOnly, + ToolPrefix: cfg.ToolPrefix, Translator: t, }) if err != nil { diff --git a/pkg/toolsets/toolsets.go b/pkg/toolsets/toolsets.go index 5d503b742..81dad9cab 100644 --- a/pkg/toolsets/toolsets.go +++ b/pkg/toolsets/toolsets.go @@ -91,16 +91,24 @@ func (t *Toolset) GetAvailableTools() []server.ServerTool { return append(t.readTools, t.writeTools...) } -func (t *Toolset) RegisterTools(s *server.MCPServer) { +func (t *Toolset) RegisterTools(s *server.MCPServer, prefix string) { if !t.Enabled { return } - for _, tool := range t.readTools { + registerToolWithPrefix := func(tool server.ServerTool) { + if prefix != "" { + // Create a new tool with the prefixed name + tool.Tool.Name = prefix + tool.Tool.Name + } s.AddTool(tool.Tool, tool.Handler) } + + for _, tool := range t.readTools { + registerToolWithPrefix(tool) + } if !t.readOnly { for _, tool := range t.writeTools { - s.AddTool(tool.Tool, tool.Handler) + registerToolWithPrefix(tool) } } } @@ -250,9 +258,9 @@ func (tg *ToolsetGroup) EnableToolset(name string) error { return nil } -func (tg *ToolsetGroup) RegisterAll(s *server.MCPServer) { +func (tg *ToolsetGroup) RegisterAll(s *server.MCPServer, prefix string) { for _, toolset := range tg.Toolsets { - toolset.RegisterTools(s) + toolset.RegisterTools(s, prefix) toolset.RegisterResourcesTemplates(s) toolset.RegisterPrompts(s) }