From a372e2811ec8890216ac9abafacb3dc80ee8afbf Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Fri, 16 Jan 2026 12:02:39 +0100 Subject: [PATCH 1/3] feat: mark copilot toolset as default The copilot toolset contains important tools like `create_pull_request_with_copilot` and `get_copilot_job_status` that should be available by default in the remote MCP server. By setting `Default: true` on the toolset metadata in OSS, the remote server automatically picks it up without needing any special handling. Even though no tools in OSS use this toolset, having the metadata here allows consistent behavior when the remote server loads defaults. This is a cleaner approach than having the remote server maintain its own list of additional default toolsets. --- pkg/github/tools.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/github/tools.go b/pkg/github/tools.go index 4384b730d..dfb60d36f 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -133,6 +133,7 @@ var ( ToolsetMetadataCopilot = inventory.ToolsetMetadata{ ID: "copilot", Description: "Copilot related tools", + Default: true, Icon: "copilot", } ToolsetMetadataCopilotSpaces = inventory.ToolsetMetadata{ From db6cb9da1ff41599c48baa29c1157c382859279d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:24:00 +0000 Subject: [PATCH 2/3] feat: support standalone toolset metadata in inventory builder - Added `toolsetMetadata` field to Builder for registering standalone toolset metadata - Added `SetToolsetMetadata()` method to Builder for setting standalone metadata - Updated `processToolsets()` to include standalone metadata in default toolsets - Updated `NewInventory()` to register remote-only toolset metadata - Updated test expectations to include `copilot` in defaults This change enables toolset metadata with `Default: true` to control whether tools in that toolset are included by default, even if no tools in the OSS repo use that toolset. The remote server can now register tools in the `copilot` toolset and they will automatically be included in defaults. Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com> --- internal/ghmcp/server.go | 4 ++-- pkg/github/inventory.go | 3 ++- pkg/github/tools_test.go | 3 +++ pkg/inventory/builder.go | 22 ++++++++++++++++++++++ 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/internal/ghmcp/server.go b/internal/ghmcp/server.go index 6090063f1..9e7dafcae 100644 --- a/internal/ghmcp/server.go +++ b/internal/ghmcp/server.go @@ -215,7 +215,7 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) { cfg.Translator, github.FeatureFlags{ LockdownMode: cfg.LockdownMode, - InsiderMode: cfg.InsiderMode, + InsiderMode: cfg.InsiderMode, }, cfg.ContentWindowSize, featureChecker, @@ -235,7 +235,7 @@ func NewMCPServer(cfg MCPServerConfig) (*mcp.Server, error) { WithToolsets(enabledToolsets). WithTools(cfg.EnabledTools). WithFeatureChecker(featureChecker) - + // Apply token scope filtering if scopes are known (for PAT filtering) if cfg.TokenScopes != nil { inventoryBuilder = inventoryBuilder.WithFilter(github.CreateToolScopeFilter(cfg.TokenScopes)) diff --git a/pkg/github/inventory.go b/pkg/github/inventory.go index 38c936d86..31a3be0df 100644 --- a/pkg/github/inventory.go +++ b/pkg/github/inventory.go @@ -14,5 +14,6 @@ func NewInventory(t translations.TranslationHelperFunc) *inventory.Builder { return inventory.NewBuilder(). SetTools(AllTools(t)). SetResources(AllResources(t)). - SetPrompts(AllPrompts(t)) + SetPrompts(AllPrompts(t)). + SetToolsetMetadata(RemoteOnlyToolsets()) } diff --git a/pkg/github/tools_test.go b/pkg/github/tools_test.go index 80270d2bc..2bcd2d525 100644 --- a/pkg/github/tools_test.go +++ b/pkg/github/tools_test.go @@ -23,6 +23,7 @@ func TestAddDefaultToolset(t *testing.T) { input: []string{"default"}, expected: []string{ "context", + "copilot", "repos", "issues", "pull_requests", @@ -36,6 +37,7 @@ func TestAddDefaultToolset(t *testing.T) { "actions", "gists", "context", + "copilot", "repos", "issues", "pull_requests", @@ -47,6 +49,7 @@ func TestAddDefaultToolset(t *testing.T) { input: []string{"default", "context", "repos"}, expected: []string{ "context", + "copilot", "repos", "issues", "pull_requests", diff --git a/pkg/inventory/builder.go b/pkg/inventory/builder.go index 58abb8ad1..5524debce 100644 --- a/pkg/inventory/builder.go +++ b/pkg/inventory/builder.go @@ -32,6 +32,7 @@ type Builder struct { resourceTemplates []ServerResourceTemplate prompts []ServerPrompt deprecatedAliases map[string]string + toolsetMetadata []ToolsetMetadata // standalone toolset metadata // Configuration options (processed at Build time) readOnly bool @@ -68,6 +69,16 @@ func (b *Builder) SetPrompts(prompts []ServerPrompt) *Builder { return b } +// SetToolsetMetadata sets standalone toolset metadata for the inventory. +// This is used for toolsets that may not have tools registered in this build +// but should still be recognized (e.g., remote-only toolsets). +// Toolsets with Default: true will be included in default toolsets even if +// no tools use them. Returns self for chaining. +func (b *Builder) SetToolsetMetadata(metadata []ToolsetMetadata) *Builder { + b.toolsetMetadata = metadata + return b +} + // WithDeprecatedAliases adds deprecated tool name aliases that map to canonical names. // Returns self for chaining. func (b *Builder) WithDeprecatedAliases(aliases map[string]string) *Builder { @@ -248,6 +259,17 @@ func (b *Builder) processToolsets() (map[ToolsetID]bool, []string, []ToolsetID, descriptions[p.Toolset.ID] = p.Toolset.Description } } + // Process standalone toolset metadata + for i := range b.toolsetMetadata { + m := &b.toolsetMetadata[i] + validIDs[m.ID] = true + if m.Default { + defaultIDs[m.ID] = true + } + if m.Description != "" { + descriptions[m.ID] = m.Description + } + } // Build sorted slices from the collected maps allToolsetIDs := make([]ToolsetID, 0, len(validIDs)) From 21a7eec6e71f7176fa9adda657e328b6978a95d7 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 11:26:03 +0000 Subject: [PATCH 3/3] docs: improve comments for standalone toolset metadata - Enhanced field comment to clarify use case - Added note about additive behavior to SetToolsetMetadata docstring Co-authored-by: SamMorrowDrums <4811358+SamMorrowDrums@users.noreply.github.com> --- pkg/inventory/builder.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/inventory/builder.go b/pkg/inventory/builder.go index 5524debce..c7abb3c93 100644 --- a/pkg/inventory/builder.go +++ b/pkg/inventory/builder.go @@ -32,7 +32,7 @@ type Builder struct { resourceTemplates []ServerResourceTemplate prompts []ServerPrompt deprecatedAliases map[string]string - toolsetMetadata []ToolsetMetadata // standalone toolset metadata + toolsetMetadata []ToolsetMetadata // standalone toolset metadata for toolsets without registered tools (e.g., remote-only toolsets) // Configuration options (processed at Build time) readOnly bool @@ -72,6 +72,7 @@ func (b *Builder) SetPrompts(prompts []ServerPrompt) *Builder { // SetToolsetMetadata sets standalone toolset metadata for the inventory. // This is used for toolsets that may not have tools registered in this build // but should still be recognized (e.g., remote-only toolsets). +// Any metadata provided here is added to metadata derived from registered tools/resources/prompts. // Toolsets with Default: true will be included in default toolsets even if // no tools use them. Returns self for chaining. func (b *Builder) SetToolsetMetadata(metadata []ToolsetMetadata) *Builder {