From 65f31c88723bd42d15d2e25e2ecf71339f2cd000 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 17:43:32 +0000 Subject: [PATCH 01/17] build(deps): bump distroless/base-debian12 from `937c7ea` to `9dce90e` Bumps distroless/base-debian12 from `937c7ea` to `9dce90e`. --- updated-dependencies: - dependency-name: distroless/base-debian12 dependency-version: 9dce90e688a57e59ce473ff7bc4c80bc8fe52d2303b4d99b44f297310bbd2210 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index b13ae62d17..68aaf0dc9f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -30,7 +30,7 @@ RUN --mount=type=cache,target=/go/pkg/mod \ -o /bin/github-mcp-server ./cmd/github-mcp-server # Make a stage to run the app -FROM gcr.io/distroless/base-debian12@sha256:937c7eaaf6f3f2d38a1f8c4aeff326f0c56e4593ea152e9e8f74d976dde52f56 +FROM gcr.io/distroless/base-debian12@sha256:9dce90e688a57e59ce473ff7bc4c80bc8fe52d2303b4d99b44f297310bbd2210 # Add required MCP server annotation LABEL io.modelcontextprotocol.server.name="io.github.github/github-mcp-server" From 3cf4124dcf01d31f4737bc38b2ee3e407a98deee Mon Sep 17 00:00:00 2001 From: Matt Holloway Date: Wed, 15 Apr 2026 12:44:37 +0100 Subject: [PATCH 02/17] feat(http): implement HeaderAllowedFeatureFlags for X-MCP-Features header validation --- pkg/github/tools.go | 10 ++++++++++ pkg/http/server.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/github/tools.go b/pkg/github/tools.go index e5e9502800..a63f7460d9 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -145,7 +145,17 @@ var ( // When active, consolidated tools are replaced by single-purpose granular tools. FeatureFlagIssuesGranular = "issues_granular" FeatureFlagPullRequestsGranular = "pull_requests_granular" +) + +// HeaderAllowedFeatureFlags are the feature flags that clients may enable via the +// X-MCP-Features header. Only these flags are accepted from headers; unknown flags +// are silently ignored. +var HeaderAllowedFeatureFlags = []string{ + FeatureFlagIssuesGranular, + FeatureFlagPullRequestsGranular, +} +var ( // Remote-only toolsets - these are only available in the remote MCP server // but are documented here for consistency and to enable automated documentation. ToolsetMetadataCopilotSpaces = inventory.ToolsetMetadata{ diff --git a/pkg/http/server.go b/pkg/http/server.go index 38ea0de301..47533bc9af 100644 --- a/pkg/http/server.go +++ b/pkg/http/server.go @@ -27,7 +27,7 @@ import ( // knownFeatureFlags are the feature flags that can be enabled via X-MCP-Features header. // Only these flags are accepted from headers. -var knownFeatureFlags = []string{} +var knownFeatureFlags = github.HeaderAllowedFeatureFlags type ServerConfig struct { // Version of the server From 7894292b6592a86892acda35f2eb99bd001305cd Mon Sep 17 00:00:00 2001 From: Matt Holloway Date: Wed, 15 Apr 2026 12:58:31 +0100 Subject: [PATCH 03/17] Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- pkg/github/tools.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/github/tools.go b/pkg/github/tools.go index a63f7460d9..72c48aaa63 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -147,14 +147,19 @@ var ( FeatureFlagPullRequestsGranular = "pull_requests_granular" ) -// HeaderAllowedFeatureFlags are the feature flags that clients may enable via the +// headerAllowedFeatureFlags are the feature flags that clients may enable via the // X-MCP-Features header. Only these flags are accepted from headers; unknown flags // are silently ignored. -var HeaderAllowedFeatureFlags = []string{ +var headerAllowedFeatureFlags = []string{ FeatureFlagIssuesGranular, FeatureFlagPullRequestsGranular, } +// HeaderAllowedFeatureFlags returns the feature flags that clients may enable via +// the X-MCP-Features header. +func HeaderAllowedFeatureFlags() []string { + return slices.Clone(headerAllowedFeatureFlags) +} var ( // Remote-only toolsets - these are only available in the remote MCP server // but are documented here for consistency and to enable automated documentation. From efcaead5b5df81380cfde12a906c9d4c037cd26e Mon Sep 17 00:00:00 2001 From: Matt Holloway Date: Wed, 15 Apr 2026 13:00:52 +0100 Subject: [PATCH 04/17] feat(http): update knownFeatureFlags to use HeaderAllowedFeatureFlags() and add tests for feature flag validation --- pkg/github/tools.go | 1 + pkg/http/server.go | 2 +- pkg/http/server_test.go | 86 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 pkg/http/server_test.go diff --git a/pkg/github/tools.go b/pkg/github/tools.go index 72c48aaa63..02b86a9d9a 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -160,6 +160,7 @@ var headerAllowedFeatureFlags = []string{ func HeaderAllowedFeatureFlags() []string { return slices.Clone(headerAllowedFeatureFlags) } + var ( // Remote-only toolsets - these are only available in the remote MCP server // but are documented here for consistency and to enable automated documentation. diff --git a/pkg/http/server.go b/pkg/http/server.go index 47533bc9af..83586509bc 100644 --- a/pkg/http/server.go +++ b/pkg/http/server.go @@ -27,7 +27,7 @@ import ( // knownFeatureFlags are the feature flags that can be enabled via X-MCP-Features header. // Only these flags are accepted from headers. -var knownFeatureFlags = github.HeaderAllowedFeatureFlags +var knownFeatureFlags = github.HeaderAllowedFeatureFlags() type ServerConfig struct { // Version of the server diff --git a/pkg/http/server_test.go b/pkg/http/server_test.go new file mode 100644 index 0000000000..7aeabc5823 --- /dev/null +++ b/pkg/http/server_test.go @@ -0,0 +1,86 @@ +package http + +import ( + "context" + "testing" + + ghcontext "github.com/github/github-mcp-server/pkg/context" + "github.com/github/github-mcp-server/pkg/github" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestCreateHTTPFeatureChecker_Whitelist(t *testing.T) { + checker := createHTTPFeatureChecker() + + tests := []struct { + name string + flagName string + headerFeatures []string + wantEnabled bool + }{ + { + name: "whitelisted issues_granular flag accepted from header", + flagName: github.FeatureFlagIssuesGranular, + headerFeatures: []string{github.FeatureFlagIssuesGranular}, + wantEnabled: true, + }, + { + name: "whitelisted pull_requests_granular flag accepted from header", + flagName: github.FeatureFlagPullRequestsGranular, + headerFeatures: []string{github.FeatureFlagPullRequestsGranular}, + wantEnabled: true, + }, + { + name: "unknown flag in header is ignored", + flagName: "unknown_flag", + headerFeatures: []string{"unknown_flag"}, + wantEnabled: false, + }, + { + name: "whitelisted flag not in header returns false", + flagName: github.FeatureFlagIssuesGranular, + headerFeatures: nil, + wantEnabled: false, + }, + { + name: "whitelisted flag with different flag in header returns false", + flagName: github.FeatureFlagIssuesGranular, + headerFeatures: []string{github.FeatureFlagPullRequestsGranular}, + wantEnabled: false, + }, + { + name: "multiple whitelisted flags in header", + flagName: github.FeatureFlagIssuesGranular, + headerFeatures: []string{github.FeatureFlagIssuesGranular, github.FeatureFlagPullRequestsGranular}, + wantEnabled: true, + }, + { + name: "empty header features", + flagName: github.FeatureFlagIssuesGranular, + headerFeatures: []string{}, + wantEnabled: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.Background() + if len(tt.headerFeatures) > 0 { + ctx = ghcontext.WithHeaderFeatures(ctx, tt.headerFeatures) + } + + enabled, err := checker(ctx, tt.flagName) + require.NoError(t, err) + assert.Equal(t, tt.wantEnabled, enabled) + }) + } +} + +func TestKnownFeatureFlagsMatchesHeaderAllowed(t *testing.T) { + // Ensure knownFeatureFlags stays in sync with HeaderAllowedFeatureFlags + allowed := github.HeaderAllowedFeatureFlags() + assert.Equal(t, allowed, knownFeatureFlags, + "knownFeatureFlags should match github.HeaderAllowedFeatureFlags()") + assert.NotEmpty(t, knownFeatureFlags, "knownFeatureFlags should not be empty") +} From b5284544658360345a1551caea439696e64e048d Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Thu, 16 Apr 2026 00:47:26 +0200 Subject: [PATCH 05/17] deps: upgrade modelcontextprotocol/go-sdk to v1.5.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Upgrade the MCP Go SDK from v1.3.1-0.20260220105450-b17143f71798 (pseudo-version) to v1.5.0 (latest stable). This also resolves #2333, as the SDK now correctly handles Content-Type headers with MIME parameters (e.g. charset=utf-8) via mime.ParseMediaType in StreamableHTTPHandler (added in v1.4.1). Transitive dependency updates: - go directive: 1.24.0 → 1.25.0 (required by SDK) - golang.org/x/oauth2: v0.34.0 → v0.35.0 - golang.org/x/sys: v0.40.0 → v0.41.0 - segmentio/encoding: v0.5.3 → v0.5.4 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go.mod | 10 +++++----- go.sum | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index 2bacfe7593..9426da242f 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/github/github-mcp-server -go 1.24.0 +go 1.25.0 require ( github.com/go-chi/chi/v5 v5.2.5 @@ -10,7 +10,7 @@ require ( github.com/josephburnett/jd/v2 v2.4.0 github.com/lithammer/fuzzysearch v1.1.8 github.com/microcosm-cc/bluemonday v1.0.27 - github.com/modelcontextprotocol/go-sdk v1.3.1-0.20260220105450-b17143f71798 + github.com/modelcontextprotocol/go-sdk v1.5.0 github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021 github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7 github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 @@ -36,7 +36,7 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect github.com/segmentio/asm v1.1.3 // indirect - github.com/segmentio/encoding v0.5.3 // indirect + github.com/segmentio/encoding v0.5.4 // indirect github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect github.com/spf13/afero v1.15.0 // indirect github.com/spf13/cast v1.10.0 // indirect @@ -45,8 +45,8 @@ require ( go.yaml.in/yaml/v3 v3.0.4 // indirect golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect golang.org/x/net v0.38.0 // indirect - golang.org/x/oauth2 v0.34.0 // indirect - golang.org/x/sys v0.40.0 // indirect + golang.org/x/oauth2 v0.35.0 // indirect + golang.org/x/sys v0.41.0 // indirect golang.org/x/text v0.28.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 80f153a82f..3939ae177d 100644 --- a/go.sum +++ b/go.sum @@ -15,8 +15,8 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= -github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= +github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= @@ -44,8 +44,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= -github.com/modelcontextprotocol/go-sdk v1.3.1-0.20260220105450-b17143f71798 h1:ogb5ErmcnxZgfaTeVZnKEMrwdHDpJ3yln5EhCIPcTlY= -github.com/modelcontextprotocol/go-sdk v1.3.1-0.20260220105450-b17143f71798/go.mod h1:Nxc2n+n/GdCebUaqCOhTetptS17SXXNu9IfNTaLDi1E= +github.com/modelcontextprotocol/go-sdk v1.5.0 h1:CHU0FIX9kpueNkxuYtfYQn1Z0slhFzBZuq+x6IiblIU= +github.com/modelcontextprotocol/go-sdk v1.5.0/go.mod h1:gggDIhoemhWs3BGkGwd1umzEXCEMMvAnhTrnbXJKKKA= github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021 h1:31Y+Yu373ymebRdJN1cWLLooHH8xAr0MhKTEJGV/87g= github.com/muesli/cache2go v0.0.0-20221011235721-518229cd8021/go.mod h1:WERUkUryfUWlrHnFSO/BEUZ+7Ns8aZy7iVOGewxKzcc= github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= @@ -59,8 +59,8 @@ github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDc github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc= github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg= -github.com/segmentio/encoding v0.5.3 h1:OjMgICtcSFuNvQCdwqMCv9Tg7lEOXGwm1J5RPQccx6w= -github.com/segmentio/encoding v0.5.3/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= +github.com/segmentio/encoding v0.5.4 h1:OW1VRern8Nw6ITAtwSZ7Idrl3MXCFwXHPgqESYfvNt0= +github.com/segmentio/encoding v0.5.4/go.mod h1:HS1ZKa3kSN32ZHVZ7ZLPLXWvOVIiZtyJnO1gPH1sKt0= github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7 h1:cYCy18SHPKRkvclm+pWm1Lk4YrREb4IOIb/YdFO0p2M= github.com/shurcooL/githubv4 v0.0.0-20240727222349-48295856cce7/go.mod h1:zqMwyHmnN/eDOZOdiTohqIUKUrTFX62PNlu7IJdu0q8= github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0= @@ -101,8 +101,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= -golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw= -golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= +golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -112,8 +112,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -128,8 +128,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= +golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= +golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= From d330b4fb24861c35f2eab96b31d801678cad67ec Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 15 Apr 2026 22:50:07 +0000 Subject: [PATCH 06/17] chore: regenerate license files Auto-generated by license-check workflow --- third-party-licenses.darwin.md | 9 +++++---- third-party-licenses.linux.md | 9 +++++---- third-party-licenses.windows.md | 9 +++++---- third-party/golang.org/x/oauth2/LICENSE | 27 +++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 12 deletions(-) create mode 100644 third-party/golang.org/x/oauth2/LICENSE diff --git a/third-party-licenses.darwin.md b/third-party-licenses.darwin.md index b62febda3c..821219df08 100644 --- a/third-party-licenses.darwin.md +++ b/third-party-licenses.darwin.md @@ -28,13 +28,13 @@ The following packages are included for the amd64, arm64 architectures. - [github.com/lithammer/fuzzysearch/fuzzy](https://pkg.go.dev/github.com/lithammer/fuzzysearch/fuzzy) ([MIT](https://github.com/lithammer/fuzzysearch/blob/v1.1.8/LICENSE)) - [github.com/mailru/easyjson](https://pkg.go.dev/github.com/mailru/easyjson) ([MIT](https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE)) - [github.com/microcosm-cc/bluemonday](https://pkg.go.dev/github.com/microcosm-cc/bluemonday) ([BSD-3-Clause](https://github.com/microcosm-cc/bluemonday/blob/v1.0.27/LICENSE.md)) - - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/b17143f71798/LICENSE)) - - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/b17143f71798/LICENSE)) + - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) + - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) - [github.com/muesli/cache2go](https://pkg.go.dev/github.com/muesli/cache2go) ([BSD-3-Clause](https://github.com/muesli/cache2go/blob/518229cd8021/LICENSE.txt)) - [github.com/pelletier/go-toml/v2](https://pkg.go.dev/github.com/pelletier/go-toml/v2) ([MIT](https://github.com/pelletier/go-toml/blob/v2.2.4/LICENSE)) - [github.com/sagikazarmark/locafero](https://pkg.go.dev/github.com/sagikazarmark/locafero) ([MIT](https://github.com/sagikazarmark/locafero/blob/v0.11.0/LICENSE)) - [github.com/segmentio/asm](https://pkg.go.dev/github.com/segmentio/asm) ([MIT](https://github.com/segmentio/asm/blob/v1.1.3/LICENSE)) - - [github.com/segmentio/encoding](https://pkg.go.dev/github.com/segmentio/encoding) ([MIT](https://github.com/segmentio/encoding/blob/v0.5.3/LICENSE)) + - [github.com/segmentio/encoding](https://pkg.go.dev/github.com/segmentio/encoding) ([MIT](https://github.com/segmentio/encoding/blob/v0.5.4/LICENSE)) - [github.com/shurcooL/githubv4](https://pkg.go.dev/github.com/shurcooL/githubv4) ([MIT](https://github.com/shurcooL/githubv4/blob/48295856cce7/LICENSE)) - [github.com/shurcooL/graphql](https://pkg.go.dev/github.com/shurcooL/graphql) ([MIT](https://github.com/shurcooL/graphql/blob/ed46e5a46466/LICENSE)) - [github.com/sourcegraph/conc](https://pkg.go.dev/github.com/sourcegraph/conc) ([MIT](https://github.com/sourcegraph/conc/blob/5f936abd7ae8/LICENSE)) @@ -48,7 +48,8 @@ The following packages are included for the amd64, arm64 architectures. - [go.yaml.in/yaml/v3](https://pkg.go.dev/go.yaml.in/yaml/v3) ([MIT](https://github.com/yaml/go-yaml/blob/v3.0.4/LICENSE)) - [golang.org/x/exp/slices](https://pkg.go.dev/golang.org/x/exp/slices) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/054e65f0:LICENSE)) - [golang.org/x/net/html](https://pkg.go.dev/golang.org/x/net/html) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.40.0:LICENSE)) + - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.35.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.41.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.28.0:LICENSE)) - [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) ([MIT](https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE)) diff --git a/third-party-licenses.linux.md b/third-party-licenses.linux.md index 825c1ed6a3..50451d71fe 100644 --- a/third-party-licenses.linux.md +++ b/third-party-licenses.linux.md @@ -28,13 +28,13 @@ The following packages are included for the 386, amd64, arm64 architectures. - [github.com/lithammer/fuzzysearch/fuzzy](https://pkg.go.dev/github.com/lithammer/fuzzysearch/fuzzy) ([MIT](https://github.com/lithammer/fuzzysearch/blob/v1.1.8/LICENSE)) - [github.com/mailru/easyjson](https://pkg.go.dev/github.com/mailru/easyjson) ([MIT](https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE)) - [github.com/microcosm-cc/bluemonday](https://pkg.go.dev/github.com/microcosm-cc/bluemonday) ([BSD-3-Clause](https://github.com/microcosm-cc/bluemonday/blob/v1.0.27/LICENSE.md)) - - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/b17143f71798/LICENSE)) - - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/b17143f71798/LICENSE)) + - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) + - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) - [github.com/muesli/cache2go](https://pkg.go.dev/github.com/muesli/cache2go) ([BSD-3-Clause](https://github.com/muesli/cache2go/blob/518229cd8021/LICENSE.txt)) - [github.com/pelletier/go-toml/v2](https://pkg.go.dev/github.com/pelletier/go-toml/v2) ([MIT](https://github.com/pelletier/go-toml/blob/v2.2.4/LICENSE)) - [github.com/sagikazarmark/locafero](https://pkg.go.dev/github.com/sagikazarmark/locafero) ([MIT](https://github.com/sagikazarmark/locafero/blob/v0.11.0/LICENSE)) - [github.com/segmentio/asm](https://pkg.go.dev/github.com/segmentio/asm) ([MIT](https://github.com/segmentio/asm/blob/v1.1.3/LICENSE)) - - [github.com/segmentio/encoding](https://pkg.go.dev/github.com/segmentio/encoding) ([MIT](https://github.com/segmentio/encoding/blob/v0.5.3/LICENSE)) + - [github.com/segmentio/encoding](https://pkg.go.dev/github.com/segmentio/encoding) ([MIT](https://github.com/segmentio/encoding/blob/v0.5.4/LICENSE)) - [github.com/shurcooL/githubv4](https://pkg.go.dev/github.com/shurcooL/githubv4) ([MIT](https://github.com/shurcooL/githubv4/blob/48295856cce7/LICENSE)) - [github.com/shurcooL/graphql](https://pkg.go.dev/github.com/shurcooL/graphql) ([MIT](https://github.com/shurcooL/graphql/blob/ed46e5a46466/LICENSE)) - [github.com/sourcegraph/conc](https://pkg.go.dev/github.com/sourcegraph/conc) ([MIT](https://github.com/sourcegraph/conc/blob/5f936abd7ae8/LICENSE)) @@ -48,7 +48,8 @@ The following packages are included for the 386, amd64, arm64 architectures. - [go.yaml.in/yaml/v3](https://pkg.go.dev/go.yaml.in/yaml/v3) ([MIT](https://github.com/yaml/go-yaml/blob/v3.0.4/LICENSE)) - [golang.org/x/exp/slices](https://pkg.go.dev/golang.org/x/exp/slices) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/054e65f0:LICENSE)) - [golang.org/x/net/html](https://pkg.go.dev/golang.org/x/net/html) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.40.0:LICENSE)) + - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.35.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.41.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.28.0:LICENSE)) - [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) ([MIT](https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE)) diff --git a/third-party-licenses.windows.md b/third-party-licenses.windows.md index d45aa33e07..453582834d 100644 --- a/third-party-licenses.windows.md +++ b/third-party-licenses.windows.md @@ -29,13 +29,13 @@ The following packages are included for the 386, amd64, arm64 architectures. - [github.com/lithammer/fuzzysearch/fuzzy](https://pkg.go.dev/github.com/lithammer/fuzzysearch/fuzzy) ([MIT](https://github.com/lithammer/fuzzysearch/blob/v1.1.8/LICENSE)) - [github.com/mailru/easyjson](https://pkg.go.dev/github.com/mailru/easyjson) ([MIT](https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE)) - [github.com/microcosm-cc/bluemonday](https://pkg.go.dev/github.com/microcosm-cc/bluemonday) ([BSD-3-Clause](https://github.com/microcosm-cc/bluemonday/blob/v1.0.27/LICENSE.md)) - - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/b17143f71798/LICENSE)) - - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/b17143f71798/LICENSE)) + - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) + - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) - [github.com/muesli/cache2go](https://pkg.go.dev/github.com/muesli/cache2go) ([BSD-3-Clause](https://github.com/muesli/cache2go/blob/518229cd8021/LICENSE.txt)) - [github.com/pelletier/go-toml/v2](https://pkg.go.dev/github.com/pelletier/go-toml/v2) ([MIT](https://github.com/pelletier/go-toml/blob/v2.2.4/LICENSE)) - [github.com/sagikazarmark/locafero](https://pkg.go.dev/github.com/sagikazarmark/locafero) ([MIT](https://github.com/sagikazarmark/locafero/blob/v0.11.0/LICENSE)) - [github.com/segmentio/asm](https://pkg.go.dev/github.com/segmentio/asm) ([MIT](https://github.com/segmentio/asm/blob/v1.1.3/LICENSE)) - - [github.com/segmentio/encoding](https://pkg.go.dev/github.com/segmentio/encoding) ([MIT](https://github.com/segmentio/encoding/blob/v0.5.3/LICENSE)) + - [github.com/segmentio/encoding](https://pkg.go.dev/github.com/segmentio/encoding) ([MIT](https://github.com/segmentio/encoding/blob/v0.5.4/LICENSE)) - [github.com/shurcooL/githubv4](https://pkg.go.dev/github.com/shurcooL/githubv4) ([MIT](https://github.com/shurcooL/githubv4/blob/48295856cce7/LICENSE)) - [github.com/shurcooL/graphql](https://pkg.go.dev/github.com/shurcooL/graphql) ([MIT](https://github.com/shurcooL/graphql/blob/ed46e5a46466/LICENSE)) - [github.com/sourcegraph/conc](https://pkg.go.dev/github.com/sourcegraph/conc) ([MIT](https://github.com/sourcegraph/conc/blob/5f936abd7ae8/LICENSE)) @@ -49,7 +49,8 @@ The following packages are included for the 386, amd64, arm64 architectures. - [go.yaml.in/yaml/v3](https://pkg.go.dev/go.yaml.in/yaml/v3) ([MIT](https://github.com/yaml/go-yaml/blob/v3.0.4/LICENSE)) - [golang.org/x/exp/slices](https://pkg.go.dev/golang.org/x/exp/slices) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/054e65f0:LICENSE)) - [golang.org/x/net/html](https://pkg.go.dev/golang.org/x/net/html) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE)) - - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.40.0:LICENSE)) + - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.35.0:LICENSE)) + - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.41.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.28.0:LICENSE)) - [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) ([MIT](https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE)) diff --git a/third-party/golang.org/x/oauth2/LICENSE b/third-party/golang.org/x/oauth2/LICENSE new file mode 100644 index 0000000000..2a7cf70da6 --- /dev/null +++ b/third-party/golang.org/x/oauth2/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. From 76d68b476eb551f977ab911ecf0e69d80754148a Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Thu, 16 Apr 2026 01:01:15 +0200 Subject: [PATCH 07/17] docs: fix stale Dockerfile Go version in copilot-instructions.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index f1b4cf9cb6..e0d6873d10 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -94,7 +94,7 @@ go test ./pkg/github -run TestGetMe - **go.mod / go.sum:** Go module dependencies (Go 1.24.0+) - **.golangci.yml:** Linter configuration (v2 format, ~15 linters enabled) -- **Dockerfile:** Multi-stage build (golang:1.25.3-alpine → distroless) +- **Dockerfile:** Multi-stage build (golang:1.25.8-alpine → distroless) - **server.json:** MCP server metadata for registry - **.goreleaser.yaml:** Release automation config - **.gitignore:** Excludes bin/, dist/, vendor/, *.DS_Store, github-mcp-server binary From f21d66269f47e011c028716c7bf9f8b84220e135 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2026 17:02:46 +0000 Subject: [PATCH 08/17] build(deps): bump docker/login-action from 3.7.0 to 4.0.0 Bumps [docker/login-action](https://github.com/docker/login-action) from 3.7.0 to 4.0.0. - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/c94ce9fb468520275223c153574b00df6fe4bcc9...b45d80f862d83dbcd57f89517bcf500b2ab88fb2) --- updated-dependencies: - dependency-name: docker/login-action dependency-version: 4.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 4ce7356f37..4ed39bcc57 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -60,7 +60,7 @@ jobs: # https://github.com/docker/login-action - name: Log into registry ${{ env.REGISTRY }} if: github.event_name != 'pull_request' - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 + uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} From 6996ac4a3e04a5638ba1e0664b71e01872ce1549 Mon Sep 17 00:00:00 2001 From: marcelsafin <179933638+marcelsafin@users.noreply.github.com> Date: Sun, 12 Apr 2026 18:37:08 +0200 Subject: [PATCH 09/17] docs: fix broken link to tool renaming guide in README The README references docs/deprecated-tool-aliases.md which does not exist. The correct file is docs/tool-renaming.md. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 419f892979..5f9baa780e 100644 --- a/README.md +++ b/README.md @@ -459,7 +459,7 @@ You can also configure specific tools using the `--tools` flag. Tools can be use - Tools, toolsets, and dynamic toolsets can all be used together - Read-only mode takes priority: write tools are skipped if `--read-only` is set, even if explicitly requested via `--tools` - Tool names must match exactly (e.g., `get_file_contents`, not `getFileContents`). Invalid tool names will cause the server to fail at startup with an error message -- When tools are renamed, old names are preserved as aliases for backward compatibility. See [Deprecated Tool Aliases](docs/deprecated-tool-aliases.md) for details. +- When tools are renamed, old names are preserved as aliases for backward compatibility. See [Tool Renaming](docs/tool-renaming.md) for details. ### Using Toolsets With Docker From 68e7371fe866d713a8eae25f4f371da3e280ed1e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Mar 2026 17:02:36 +0000 Subject: [PATCH 10/17] build(deps): bump docker/setup-buildx-action from 3.12.0 to 4.0.0 Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3.12.0 to 4.0.0. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/8d2750c68a42422c14e847fe6c8ac0403b4cbd6f...4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-version: 4.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/docker-publish.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index 4ed39bcc57..c0a7407c59 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -54,7 +54,7 @@ jobs: # multi-platform images and export cache # https://github.com/docker/setup-buildx-action - name: Set up Docker Buildx - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 # Login against a Docker registry except on PR # https://github.com/docker/login-action From 8f0e0601e399c2376b8ff4ec9a20666de98d253a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 18:19:26 +0000 Subject: [PATCH 11/17] build(deps): bump github.com/josephburnett/jd/v2 from 2.4.0 to 2.5.0 Bumps [github.com/josephburnett/jd/v2](https://github.com/josephburnett/jd) from 2.4.0 to 2.5.0. - [Release notes](https://github.com/josephburnett/jd/releases) - [Changelog](https://github.com/josephburnett/jd/blob/master/RELEASE_NOTES.md) - [Commits](https://github.com/josephburnett/jd/compare/v2.4.0...v2.5.0) --- updated-dependencies: - dependency-name: github.com/josephburnett/jd/v2 dependency-version: 2.5.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 8 ++------ go.sum | 21 +++++++-------------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/go.mod b/go.mod index 9426da242f..4440a03eaa 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/go-viper/mapstructure/v2 v2.5.0 github.com/google/go-github/v82 v82.0.0 github.com/google/jsonschema-go v0.4.2 - github.com/josephburnett/jd/v2 v2.4.0 + github.com/josephburnett/jd/v2 v2.5.0 github.com/lithammer/fuzzysearch v1.1.8 github.com/microcosm-cc/bluemonday v1.0.27 github.com/modelcontextprotocol/go-sdk v1.5.0 @@ -25,13 +25,9 @@ require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/go-openapi/jsonpointer v0.21.0 // indirect - github.com/go-openapi/swag v0.23.0 // indirect github.com/google/go-querystring v1.2.0 // indirect github.com/gorilla/css v1.0.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/sagikazarmark/locafero v0.11.0 // indirect @@ -43,10 +39,10 @@ require ( github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 // indirect golang.org/x/net v0.38.0 // indirect golang.org/x/oauth2 v0.35.0 // indirect golang.org/x/sys v0.41.0 // indirect golang.org/x/text v0.28.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 3939ae177d..2d66c84ed7 100644 --- a/go.sum +++ b/go.sum @@ -9,10 +9,6 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= -github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= -github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= -github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY= @@ -30,18 +26,17 @@ github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/josephburnett/jd/v2 v2.4.0 h1:8MDRpbs/CATx4FR6Px8YMSp6NPGtI8pUWtDrgqI74tI= -github.com/josephburnett/jd/v2 v2.4.0/go.mod h1:0I5+gbo7y8diuajJjm79AF44eqTheSJy1K7DSbIUFAQ= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/josephburnett/jd/v2 v2.5.0 h1:c1G9TXeozJINRGZDeN2Z000Ok2Z8+0h0rbBRSdF79CY= +github.com/josephburnett/jd/v2 v2.5.0/go.mod h1:G6F+v/jcqS0b0d6LIyi1xC+wLleSKN8HvrqBhmBC8b8= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/modelcontextprotocol/go-sdk v1.5.0 h1:CHU0FIX9kpueNkxuYtfYQn1Z0slhFzBZuq+x6IiblIU= @@ -52,8 +47,8 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= @@ -91,8 +86,6 @@ go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394 h1:nDVHiLt8aIbd/VzvPWN6kSOPE7+F/fNFDSXLVYkE/Iw= -golang.org/x/exp v0.0.0-20250305212735-054e65f0b394/go.mod h1:sIifuuw/Yco/y6yb6+bDNfyeQ/MdPUy/hKEMYQV17cM= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= From bef626a717a321a2c1f404544246ac172f8fc169 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Feb 2026 18:21:02 +0000 Subject: [PATCH 12/17] chore: regenerate license files Auto-generated by license-check workflow --- third-party-licenses.darwin.md | 8 +- third-party-licenses.linux.md | 8 +- third-party-licenses.windows.md | 8 +- .../github.com/go-openapi/jsonpointer/LICENSE | 202 ------------------ .../github.com/go-openapi/swag/LICENSE | 202 ------------------ .../github.com/josharian/intern/license.md | 21 -- .../github.com/mailru/easyjson/LICENSE | 7 - third-party/golang.org/x/exp/slices/LICENSE | 27 --- third-party/gopkg.in/yaml.v3/LICENSE | 50 ----- third-party/gopkg.in/yaml.v3/NOTICE | 13 -- 10 files changed, 3 insertions(+), 543 deletions(-) delete mode 100644 third-party/github.com/go-openapi/jsonpointer/LICENSE delete mode 100644 third-party/github.com/go-openapi/swag/LICENSE delete mode 100644 third-party/github.com/josharian/intern/license.md delete mode 100644 third-party/github.com/mailru/easyjson/LICENSE delete mode 100644 third-party/golang.org/x/exp/slices/LICENSE delete mode 100644 third-party/gopkg.in/yaml.v3/LICENSE delete mode 100644 third-party/gopkg.in/yaml.v3/NOTICE diff --git a/third-party-licenses.darwin.md b/third-party-licenses.darwin.md index 821219df08..e8d9822218 100644 --- a/third-party-licenses.darwin.md +++ b/third-party-licenses.darwin.md @@ -16,17 +16,13 @@ The following packages are included for the amd64, arm64 architectures. - [github.com/fsnotify/fsnotify](https://pkg.go.dev/github.com/fsnotify/fsnotify) ([BSD-3-Clause](https://github.com/fsnotify/fsnotify/blob/v1.9.0/LICENSE)) - [github.com/github/github-mcp-server](https://pkg.go.dev/github.com/github/github-mcp-server) ([MIT](https://github.com/github/github-mcp-server/blob/HEAD/LICENSE)) - [github.com/go-chi/chi/v5](https://pkg.go.dev/github.com/go-chi/chi/v5) ([MIT](https://github.com/go-chi/chi/blob/v5.2.5/LICENSE)) - - [github.com/go-openapi/jsonpointer](https://pkg.go.dev/github.com/go-openapi/jsonpointer) ([Apache-2.0](https://github.com/go-openapi/jsonpointer/blob/v0.21.0/LICENSE)) - - [github.com/go-openapi/swag](https://pkg.go.dev/github.com/go-openapi/swag) ([Apache-2.0](https://github.com/go-openapi/swag/blob/v0.23.0/LICENSE)) - [github.com/go-viper/mapstructure/v2](https://pkg.go.dev/github.com/go-viper/mapstructure/v2) ([MIT](https://github.com/go-viper/mapstructure/blob/v2.5.0/LICENSE)) - [github.com/google/go-github/v82/github](https://pkg.go.dev/github.com/google/go-github/v82/github) ([BSD-3-Clause](https://github.com/google/go-github/blob/v82.0.0/LICENSE)) - [github.com/google/go-querystring/query](https://pkg.go.dev/github.com/google/go-querystring/query) ([BSD-3-Clause](https://github.com/google/go-querystring/blob/v1.2.0/LICENSE)) - [github.com/google/jsonschema-go/jsonschema](https://pkg.go.dev/github.com/google/jsonschema-go/jsonschema) ([MIT](https://github.com/google/jsonschema-go/blob/v0.4.2/LICENSE)) - [github.com/gorilla/css/scanner](https://pkg.go.dev/github.com/gorilla/css/scanner) ([BSD-3-Clause](https://github.com/gorilla/css/blob/v1.0.1/LICENSE)) - - [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.4.0/v2/LICENSE)) - - [github.com/josharian/intern](https://pkg.go.dev/github.com/josharian/intern) ([MIT](https://github.com/josharian/intern/blob/v1.0.0/license.md)) + - [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/v2/LICENSE)) - [github.com/lithammer/fuzzysearch/fuzzy](https://pkg.go.dev/github.com/lithammer/fuzzysearch/fuzzy) ([MIT](https://github.com/lithammer/fuzzysearch/blob/v1.1.8/LICENSE)) - - [github.com/mailru/easyjson](https://pkg.go.dev/github.com/mailru/easyjson) ([MIT](https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE)) - [github.com/microcosm-cc/bluemonday](https://pkg.go.dev/github.com/microcosm-cc/bluemonday) ([BSD-3-Clause](https://github.com/microcosm-cc/bluemonday/blob/v1.0.27/LICENSE.md)) - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) @@ -46,11 +42,9 @@ The following packages are included for the amd64, arm64 architectures. - [github.com/subosito/gotenv](https://pkg.go.dev/github.com/subosito/gotenv) ([MIT](https://github.com/subosito/gotenv/blob/v1.6.0/LICENSE)) - [github.com/yosida95/uritemplate/v3](https://pkg.go.dev/github.com/yosida95/uritemplate/v3) ([BSD-3-Clause](https://github.com/yosida95/uritemplate/blob/v3.0.2/LICENSE)) - [go.yaml.in/yaml/v3](https://pkg.go.dev/go.yaml.in/yaml/v3) ([MIT](https://github.com/yaml/go-yaml/blob/v3.0.4/LICENSE)) - - [golang.org/x/exp/slices](https://pkg.go.dev/golang.org/x/exp/slices) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/054e65f0:LICENSE)) - [golang.org/x/net/html](https://pkg.go.dev/golang.org/x/net/html) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE)) - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.35.0:LICENSE)) - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.41.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.28.0:LICENSE)) - - [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) ([MIT](https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE)) [github/github-mcp-server]: https://github.com/github/github-mcp-server diff --git a/third-party-licenses.linux.md b/third-party-licenses.linux.md index 50451d71fe..c4474fced3 100644 --- a/third-party-licenses.linux.md +++ b/third-party-licenses.linux.md @@ -16,17 +16,13 @@ The following packages are included for the 386, amd64, arm64 architectures. - [github.com/fsnotify/fsnotify](https://pkg.go.dev/github.com/fsnotify/fsnotify) ([BSD-3-Clause](https://github.com/fsnotify/fsnotify/blob/v1.9.0/LICENSE)) - [github.com/github/github-mcp-server](https://pkg.go.dev/github.com/github/github-mcp-server) ([MIT](https://github.com/github/github-mcp-server/blob/HEAD/LICENSE)) - [github.com/go-chi/chi/v5](https://pkg.go.dev/github.com/go-chi/chi/v5) ([MIT](https://github.com/go-chi/chi/blob/v5.2.5/LICENSE)) - - [github.com/go-openapi/jsonpointer](https://pkg.go.dev/github.com/go-openapi/jsonpointer) ([Apache-2.0](https://github.com/go-openapi/jsonpointer/blob/v0.21.0/LICENSE)) - - [github.com/go-openapi/swag](https://pkg.go.dev/github.com/go-openapi/swag) ([Apache-2.0](https://github.com/go-openapi/swag/blob/v0.23.0/LICENSE)) - [github.com/go-viper/mapstructure/v2](https://pkg.go.dev/github.com/go-viper/mapstructure/v2) ([MIT](https://github.com/go-viper/mapstructure/blob/v2.5.0/LICENSE)) - [github.com/google/go-github/v82/github](https://pkg.go.dev/github.com/google/go-github/v82/github) ([BSD-3-Clause](https://github.com/google/go-github/blob/v82.0.0/LICENSE)) - [github.com/google/go-querystring/query](https://pkg.go.dev/github.com/google/go-querystring/query) ([BSD-3-Clause](https://github.com/google/go-querystring/blob/v1.2.0/LICENSE)) - [github.com/google/jsonschema-go/jsonschema](https://pkg.go.dev/github.com/google/jsonschema-go/jsonschema) ([MIT](https://github.com/google/jsonschema-go/blob/v0.4.2/LICENSE)) - [github.com/gorilla/css/scanner](https://pkg.go.dev/github.com/gorilla/css/scanner) ([BSD-3-Clause](https://github.com/gorilla/css/blob/v1.0.1/LICENSE)) - - [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.4.0/v2/LICENSE)) - - [github.com/josharian/intern](https://pkg.go.dev/github.com/josharian/intern) ([MIT](https://github.com/josharian/intern/blob/v1.0.0/license.md)) + - [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/v2/LICENSE)) - [github.com/lithammer/fuzzysearch/fuzzy](https://pkg.go.dev/github.com/lithammer/fuzzysearch/fuzzy) ([MIT](https://github.com/lithammer/fuzzysearch/blob/v1.1.8/LICENSE)) - - [github.com/mailru/easyjson](https://pkg.go.dev/github.com/mailru/easyjson) ([MIT](https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE)) - [github.com/microcosm-cc/bluemonday](https://pkg.go.dev/github.com/microcosm-cc/bluemonday) ([BSD-3-Clause](https://github.com/microcosm-cc/bluemonday/blob/v1.0.27/LICENSE.md)) - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) @@ -46,11 +42,9 @@ The following packages are included for the 386, amd64, arm64 architectures. - [github.com/subosito/gotenv](https://pkg.go.dev/github.com/subosito/gotenv) ([MIT](https://github.com/subosito/gotenv/blob/v1.6.0/LICENSE)) - [github.com/yosida95/uritemplate/v3](https://pkg.go.dev/github.com/yosida95/uritemplate/v3) ([BSD-3-Clause](https://github.com/yosida95/uritemplate/blob/v3.0.2/LICENSE)) - [go.yaml.in/yaml/v3](https://pkg.go.dev/go.yaml.in/yaml/v3) ([MIT](https://github.com/yaml/go-yaml/blob/v3.0.4/LICENSE)) - - [golang.org/x/exp/slices](https://pkg.go.dev/golang.org/x/exp/slices) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/054e65f0:LICENSE)) - [golang.org/x/net/html](https://pkg.go.dev/golang.org/x/net/html) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE)) - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.35.0:LICENSE)) - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.41.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.28.0:LICENSE)) - - [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) ([MIT](https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE)) [github/github-mcp-server]: https://github.com/github/github-mcp-server diff --git a/third-party-licenses.windows.md b/third-party-licenses.windows.md index 453582834d..3f36d5127c 100644 --- a/third-party-licenses.windows.md +++ b/third-party-licenses.windows.md @@ -16,18 +16,14 @@ The following packages are included for the 386, amd64, arm64 architectures. - [github.com/fsnotify/fsnotify](https://pkg.go.dev/github.com/fsnotify/fsnotify) ([BSD-3-Clause](https://github.com/fsnotify/fsnotify/blob/v1.9.0/LICENSE)) - [github.com/github/github-mcp-server](https://pkg.go.dev/github.com/github/github-mcp-server) ([MIT](https://github.com/github/github-mcp-server/blob/HEAD/LICENSE)) - [github.com/go-chi/chi/v5](https://pkg.go.dev/github.com/go-chi/chi/v5) ([MIT](https://github.com/go-chi/chi/blob/v5.2.5/LICENSE)) - - [github.com/go-openapi/jsonpointer](https://pkg.go.dev/github.com/go-openapi/jsonpointer) ([Apache-2.0](https://github.com/go-openapi/jsonpointer/blob/v0.21.0/LICENSE)) - - [github.com/go-openapi/swag](https://pkg.go.dev/github.com/go-openapi/swag) ([Apache-2.0](https://github.com/go-openapi/swag/blob/v0.23.0/LICENSE)) - [github.com/go-viper/mapstructure/v2](https://pkg.go.dev/github.com/go-viper/mapstructure/v2) ([MIT](https://github.com/go-viper/mapstructure/blob/v2.5.0/LICENSE)) - [github.com/google/go-github/v82/github](https://pkg.go.dev/github.com/google/go-github/v82/github) ([BSD-3-Clause](https://github.com/google/go-github/blob/v82.0.0/LICENSE)) - [github.com/google/go-querystring/query](https://pkg.go.dev/github.com/google/go-querystring/query) ([BSD-3-Clause](https://github.com/google/go-querystring/blob/v1.2.0/LICENSE)) - [github.com/google/jsonschema-go/jsonschema](https://pkg.go.dev/github.com/google/jsonschema-go/jsonschema) ([MIT](https://github.com/google/jsonschema-go/blob/v0.4.2/LICENSE)) - [github.com/gorilla/css/scanner](https://pkg.go.dev/github.com/gorilla/css/scanner) ([BSD-3-Clause](https://github.com/gorilla/css/blob/v1.0.1/LICENSE)) - [github.com/inconshreveable/mousetrap](https://pkg.go.dev/github.com/inconshreveable/mousetrap) ([Apache-2.0](https://github.com/inconshreveable/mousetrap/blob/v1.1.0/LICENSE)) - - [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.4.0/v2/LICENSE)) - - [github.com/josharian/intern](https://pkg.go.dev/github.com/josharian/intern) ([MIT](https://github.com/josharian/intern/blob/v1.0.0/license.md)) + - [github.com/josephburnett/jd/v2](https://pkg.go.dev/github.com/josephburnett/jd/v2) ([MIT](https://github.com/josephburnett/jd/blob/v2.5.0/v2/LICENSE)) - [github.com/lithammer/fuzzysearch/fuzzy](https://pkg.go.dev/github.com/lithammer/fuzzysearch/fuzzy) ([MIT](https://github.com/lithammer/fuzzysearch/blob/v1.1.8/LICENSE)) - - [github.com/mailru/easyjson](https://pkg.go.dev/github.com/mailru/easyjson) ([MIT](https://github.com/mailru/easyjson/blob/v0.7.7/LICENSE)) - [github.com/microcosm-cc/bluemonday](https://pkg.go.dev/github.com/microcosm-cc/bluemonday) ([BSD-3-Clause](https://github.com/microcosm-cc/bluemonday/blob/v1.0.27/LICENSE.md)) - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([Apache-2.0](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) - [github.com/modelcontextprotocol/go-sdk](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) ([MIT](https://github.com/modelcontextprotocol/go-sdk/blob/v1.5.0/LICENSE)) @@ -47,11 +43,9 @@ The following packages are included for the 386, amd64, arm64 architectures. - [github.com/subosito/gotenv](https://pkg.go.dev/github.com/subosito/gotenv) ([MIT](https://github.com/subosito/gotenv/blob/v1.6.0/LICENSE)) - [github.com/yosida95/uritemplate/v3](https://pkg.go.dev/github.com/yosida95/uritemplate/v3) ([BSD-3-Clause](https://github.com/yosida95/uritemplate/blob/v3.0.2/LICENSE)) - [go.yaml.in/yaml/v3](https://pkg.go.dev/go.yaml.in/yaml/v3) ([MIT](https://github.com/yaml/go-yaml/blob/v3.0.4/LICENSE)) - - [golang.org/x/exp/slices](https://pkg.go.dev/golang.org/x/exp/slices) ([BSD-3-Clause](https://cs.opensource.google/go/x/exp/+/054e65f0:LICENSE)) - [golang.org/x/net/html](https://pkg.go.dev/golang.org/x/net/html) ([BSD-3-Clause](https://cs.opensource.google/go/x/net/+/v0.38.0:LICENSE)) - [golang.org/x/oauth2](https://pkg.go.dev/golang.org/x/oauth2) ([BSD-3-Clause](https://cs.opensource.google/go/x/oauth2/+/v0.35.0:LICENSE)) - [golang.org/x/sys](https://pkg.go.dev/golang.org/x/sys) ([BSD-3-Clause](https://cs.opensource.google/go/x/sys/+/v0.41.0:LICENSE)) - [golang.org/x/text](https://pkg.go.dev/golang.org/x/text) ([BSD-3-Clause](https://cs.opensource.google/go/x/text/+/v0.28.0:LICENSE)) - - [gopkg.in/yaml.v3](https://pkg.go.dev/gopkg.in/yaml.v3) ([MIT](https://github.com/go-yaml/yaml/blob/v3.0.1/LICENSE)) [github/github-mcp-server]: https://github.com/github/github-mcp-server diff --git a/third-party/github.com/go-openapi/jsonpointer/LICENSE b/third-party/github.com/go-openapi/jsonpointer/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/third-party/github.com/go-openapi/jsonpointer/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/third-party/github.com/go-openapi/swag/LICENSE b/third-party/github.com/go-openapi/swag/LICENSE deleted file mode 100644 index d645695673..0000000000 --- a/third-party/github.com/go-openapi/swag/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/third-party/github.com/josharian/intern/license.md b/third-party/github.com/josharian/intern/license.md deleted file mode 100644 index 353d3055f0..0000000000 --- a/third-party/github.com/josharian/intern/license.md +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Josh Bleecher Snyder - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/third-party/github.com/mailru/easyjson/LICENSE b/third-party/github.com/mailru/easyjson/LICENSE deleted file mode 100644 index fbff658f70..0000000000 --- a/third-party/github.com/mailru/easyjson/LICENSE +++ /dev/null @@ -1,7 +0,0 @@ -Copyright (c) 2016 Mail.Ru Group - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/third-party/golang.org/x/exp/slices/LICENSE b/third-party/golang.org/x/exp/slices/LICENSE deleted file mode 100644 index 2a7cf70da6..0000000000 --- a/third-party/golang.org/x/exp/slices/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright 2009 The Go Authors. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google LLC nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/third-party/gopkg.in/yaml.v3/LICENSE b/third-party/gopkg.in/yaml.v3/LICENSE deleted file mode 100644 index 2683e4bb1f..0000000000 --- a/third-party/gopkg.in/yaml.v3/LICENSE +++ /dev/null @@ -1,50 +0,0 @@ - -This project is covered by two different licenses: MIT and Apache. - -#### MIT License #### - -The following files were ported to Go from C files of libyaml, and thus -are still covered by their original MIT license, with the additional -copyright staring in 2011 when the project was ported over: - - apic.go emitterc.go parserc.go readerc.go scannerc.go - writerc.go yamlh.go yamlprivateh.go - -Copyright (c) 2006-2010 Kirill Simonov -Copyright (c) 2006-2011 Kirill Simonov - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -### Apache License ### - -All the remaining project files are covered by the Apache license: - -Copyright (c) 2011-2019 Canonical Ltd - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/third-party/gopkg.in/yaml.v3/NOTICE b/third-party/gopkg.in/yaml.v3/NOTICE deleted file mode 100644 index 866d74a7ad..0000000000 --- a/third-party/gopkg.in/yaml.v3/NOTICE +++ /dev/null @@ -1,13 +0,0 @@ -Copyright 2011-2016 Canonical Ltd. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. From 7e7fb96e279eae213753c7fc1c742927c39ae956 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Apr 2026 07:41:05 +0000 Subject: [PATCH 13/17] build(deps): bump golang from 1.25.8-alpine to 1.25.9-alpine Bumps golang from 1.25.8-alpine to 1.25.9-alpine. --- updated-dependencies: - dependency-name: golang dependency-version: 1.25.9-alpine dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 68aaf0dc9f..f62b6d3594 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ COPY ui/ ./ui/ RUN mkdir -p ./pkg/github/ui_dist && \ cd ui && npm run build -FROM golang:1.25.8-alpine@sha256:8e02eb337d9e0ea459e041f1ee5eece41cbb61f1d83e7d883a3e2fb4862063fa AS build +FROM golang:1.25.9-alpine@sha256:04d017a27c481185c169884328a5761d052910fdced8c3b8edd686474efdf59b AS build ARG VERSION="dev" # Set the working directory From a24c0be254cd72f80aa76b2a90395f2ce155dd94 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Wed, 15 Apr 2026 17:54:19 +0200 Subject: [PATCH 14/17] refactor: migrate MCP Apps from insiders mode to feature flag Rebase PR #2282 onto main (post-#2332) and unify feature flag allowlists into a single source of truth. - Add MCPAppsFeatureFlag, AllowedFeatureFlags, InsidersFeatureFlags, and ResolveFeatureFlags in feature_flags.go - AllowedFeatureFlags includes all user-controllable flags (MCP Apps + granular), InsidersFeatureFlags only includes MCPAppsFeatureFlag - HeaderAllowedFeatureFlags() now delegates to AllowedFeatureFlags - Builder uses feature checker instead of insidersMode bool - Remove InsidersOnly field from ServerTool and WithInsidersMode from Builder - HTTP feature checker uses ResolveFeatureFlags for per-request resolution with insiders expansion - Tool handlers check MCPAppsFeatureFlag via IsFeatureEnabled instead of InsidersMode Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- internal/ghmcp/server.go | 31 ++++---- pkg/github/feature_flags.go | 49 +++++++++++++ pkg/github/feature_flags_test.go | 64 ++++++++++++++++ pkg/github/tools.go | 13 +--- pkg/http/handler.go | 12 +-- pkg/http/handler_test.go | 6 +- pkg/http/server.go | 24 ++---- pkg/http/server_test.go | 44 ++++++++--- pkg/inventory/builder.go | 78 ++++++++++---------- pkg/inventory/registry_test.go | 122 +++++++++++-------------------- pkg/inventory/server_tool.go | 4 - 11 files changed, 258 insertions(+), 189 deletions(-) diff --git a/internal/ghmcp/server.go b/internal/ghmcp/server.go index 5dfaf596c6..3f81ac3f78 100644 --- a/internal/ghmcp/server.go +++ b/internal/ghmcp/server.go @@ -114,8 +114,8 @@ func NewStdioMCPServer(ctx context.Context, cfg github.MCPServerConfig) (*mcp.Se return nil, fmt.Errorf("failed to create GitHub clients: %w", err) } - // Create feature checker - featureChecker := createFeatureChecker(cfg.EnabledFeatures) + // Create feature checker — resolves explicit features + insiders expansion + featureChecker := createFeatureChecker(cfg.EnabledFeatures, cfg.InsidersMode) // Create dependencies for tool handlers obs, err := observability.NewExporters(cfg.Logger, metrics.NewNoopMetrics()) @@ -144,8 +144,7 @@ func NewStdioMCPServer(ctx context.Context, cfg github.MCPServerConfig) (*mcp.Se WithTools(github.CleanTools(cfg.EnabledTools)). WithExcludeTools(cfg.ExcludeTools). WithServerInstructions(). - WithFeatureChecker(featureChecker). - WithInsidersMode(cfg.InsidersMode) + WithFeatureChecker(featureChecker) // Apply token scope filtering if scopes are known (for PAT filtering) if cfg.TokenScopes != nil { @@ -162,10 +161,12 @@ func NewStdioMCPServer(ctx context.Context, cfg github.MCPServerConfig) (*mcp.Se return nil, fmt.Errorf("failed to create GitHub MCP server: %w", err) } - // Register MCP App UI resources if available (requires running script/build-ui). - // We check availability to allow Insiders mode to work for non-UI features - // even when UI assets haven't been built. - if cfg.InsidersMode && github.UIAssetsAvailable() { + // Register MCP App UI resources if the remote_mcp_ui_apps feature flag is enabled + // and UI assets are available (requires running script/build-ui). + // We check availability to allow the feature flag to be enabled without + // requiring a UI build (graceful degradation). + mcpAppsEnabled, _ := featureChecker(context.Background(), github.MCPAppsFeatureFlag) + if mcpAppsEnabled && github.UIAssetsAvailable() { github.RegisterUIResources(ghServer) } @@ -334,15 +335,11 @@ func RunStdioServer(cfg StdioServerConfig) error { return nil } -// createFeatureChecker returns a FeatureFlagChecker that checks if a flag name -// is present in the provided list of enabled features. For the local server, -// this is populated from the --features CLI flag. -func createFeatureChecker(enabledFeatures []string) inventory.FeatureFlagChecker { - // Build a set for O(1) lookup - featureSet := make(map[string]bool, len(enabledFeatures)) - for _, f := range enabledFeatures { - featureSet[f] = true - } +// createFeatureChecker returns a FeatureFlagChecker that resolves features +// using the centralized ResolveFeatureFlags function. For the local server, +// features are resolved once at startup from --features CLI flag + insiders mode. +func createFeatureChecker(enabledFeatures []string, insidersMode bool) inventory.FeatureFlagChecker { + featureSet := github.ResolveFeatureFlags(enabledFeatures, insidersMode) return func(_ context.Context, flagName string) (bool, error) { return featureSet[flagName], nil } diff --git a/pkg/github/feature_flags.go b/pkg/github/feature_flags.go index fd06a659be..3f3d7bf976 100644 --- a/pkg/github/feature_flags.go +++ b/pkg/github/feature_flags.go @@ -1,7 +1,56 @@ package github +// MCPAppsFeatureFlag is the feature flag name for MCP Apps (interactive UI forms). +const MCPAppsFeatureFlag = "remote_mcp_ui_apps" + +// AllowedFeatureFlags is the allowlist of feature flags that can be enabled +// by users via --features CLI flag or X-MCP-Features HTTP header. +// Only flags in this list are accepted; unknown flags are silently ignored. +// This is the single source of truth for which flags are user-controllable. +var AllowedFeatureFlags = []string{ + MCPAppsFeatureFlag, + FeatureFlagIssuesGranular, + FeatureFlagPullRequestsGranular, +} + +// InsidersFeatureFlags is the list of feature flags that insiders mode enables. +// When insiders mode is active, all flags in this list are treated as enabled. +// This is the single source of truth for what "insiders" means in terms of +// feature flag expansion. +var InsidersFeatureFlags = []string{ + MCPAppsFeatureFlag, +} + // FeatureFlags defines runtime feature toggles that adjust tool behavior. type FeatureFlags struct { LockdownMode bool InsidersMode bool } + +// ResolveFeatureFlags computes the effective set of enabled feature flags by: +// 1. Taking explicitly enabled features (from CLI flags or HTTP headers) +// 2. Adding insiders-expanded features when insiders mode is active +// 3. Validating all features against the AllowedFeatureFlags allowlist +// +// Returns a set (map) for O(1) lookup by the feature checker. +func ResolveFeatureFlags(enabledFeatures []string, insidersMode bool) map[string]bool { + allowed := make(map[string]bool, len(AllowedFeatureFlags)) + for _, f := range AllowedFeatureFlags { + allowed[f] = true + } + + effective := make(map[string]bool) + for _, f := range enabledFeatures { + if allowed[f] { + effective[f] = true + } + } + if insidersMode { + for _, f := range InsidersFeatureFlags { + if allowed[f] { + effective[f] = true + } + } + } + return effective +} diff --git a/pkg/github/feature_flags_test.go b/pkg/github/feature_flags_test.go index 0f08c4f12f..b0c1a4305c 100644 --- a/pkg/github/feature_flags_test.go +++ b/pkg/github/feature_flags_test.go @@ -136,6 +136,70 @@ func TestHelloWorld_ConditionalBehavior_Featureflag(t *testing.T) { } } +func TestResolveFeatureFlags(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + enabledFeatures []string + insidersMode bool + expectedFlags []string + unexpectedFlags []string + }{ + { + name: "no features, no insiders", + enabledFeatures: nil, + insidersMode: false, + expectedFlags: nil, + unexpectedFlags: []string{MCPAppsFeatureFlag}, + }, + { + name: "explicit feature enabled", + enabledFeatures: []string{MCPAppsFeatureFlag}, + insidersMode: false, + expectedFlags: []string{MCPAppsFeatureFlag}, + }, + { + name: "insiders mode enables insiders flags", + enabledFeatures: nil, + insidersMode: true, + expectedFlags: InsidersFeatureFlags, + }, + { + name: "unknown flags are filtered out", + enabledFeatures: []string{"unknown_flag", "another_unknown"}, + insidersMode: false, + unexpectedFlags: []string{"unknown_flag", "another_unknown"}, + }, + { + name: "mix of known and unknown flags", + enabledFeatures: []string{MCPAppsFeatureFlag, "unknown_flag"}, + insidersMode: false, + expectedFlags: []string{MCPAppsFeatureFlag}, + unexpectedFlags: []string{"unknown_flag"}, + }, + { + name: "explicit plus insiders deduplicates", + enabledFeatures: []string{MCPAppsFeatureFlag}, + insidersMode: true, + expectedFlags: []string{MCPAppsFeatureFlag}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + result := ResolveFeatureFlags(tt.enabledFeatures, tt.insidersMode) + for _, flag := range tt.expectedFlags { + assert.True(t, result[flag], "expected flag %q to be enabled", flag) + } + for _, flag := range tt.unexpectedFlags { + assert.False(t, result[flag], "expected flag %q to not be enabled", flag) + } + }) + } +} + func TestHelloWorld_ConditionalBehavior_Config(t *testing.T) { t.Parallel() diff --git a/pkg/github/tools.go b/pkg/github/tools.go index 02b86a9d9a..cdb07beecb 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -147,18 +147,11 @@ var ( FeatureFlagPullRequestsGranular = "pull_requests_granular" ) -// headerAllowedFeatureFlags are the feature flags that clients may enable via the -// X-MCP-Features header. Only these flags are accepted from headers; unknown flags -// are silently ignored. -var headerAllowedFeatureFlags = []string{ - FeatureFlagIssuesGranular, - FeatureFlagPullRequestsGranular, -} - // HeaderAllowedFeatureFlags returns the feature flags that clients may enable via -// the X-MCP-Features header. +// the X-MCP-Features header. It delegates to AllowedFeatureFlags as the single +// source of truth. func HeaderAllowedFeatureFlags() []string { - return slices.Clone(headerAllowedFeatureFlags) + return slices.Clone(AllowedFeatureFlags) } var ( diff --git a/pkg/http/handler.go b/pkg/http/handler.go index 37906a03e6..d55d7c53d7 100644 --- a/pkg/http/handler.go +++ b/pkg/http/handler.go @@ -275,11 +275,6 @@ func DefaultInventoryFactory(cfg *ServerConfig, t translations.TranslationHelper b = b.WithReadOnly(true) } - // Static insiders mode — enforce before request filters - if cfg.InsidersMode { - b = b.WithInsidersMode(true) - } - // Filter request tool names to only those in the static universe, // so requests for statically-excluded tools degrade gracefully. if hasStaticFilters { @@ -336,8 +331,7 @@ func buildStaticInventory(cfg *ServerConfig, t translations.TranslationHelperFun b := github.NewInventory(t). WithFeatureChecker(featureChecker). WithReadOnly(cfg.ReadOnly). - WithToolsets(github.ResolvedEnabledToolsets(cfg.DynamicToolsets, cfg.EnabledToolsets, cfg.EnabledTools)). - WithInsidersMode(cfg.InsidersMode) + WithToolsets(github.ResolvedEnabledToolsets(cfg.DynamicToolsets, cfg.EnabledToolsets, cfg.EnabledTools)) if len(cfg.EnabledTools) > 0 { b = b.WithTools(github.CleanTools(cfg.EnabledTools)) @@ -359,7 +353,9 @@ func buildStaticInventory(cfg *ServerConfig, t translations.TranslationHelperFun } // InventoryFiltersForRequest applies filters to the inventory builder -// based on the request context and headers +// based on the request context and headers. +// MCP Apps UI metadata is handled by the builder via the feature checker — +// no need to check headers here. func InventoryFiltersForRequest(r *http.Request, builder *inventory.Builder) *inventory.Builder { ctx := r.Context() diff --git a/pkg/http/handler_test.go b/pkg/http/handler_test.go index ee465c174e..5c8543c852 100644 --- a/pkg/http/handler_test.go +++ b/pkg/http/handler_test.go @@ -576,9 +576,6 @@ func TestStaticConfigEnforcement(t *testing.T) { if tt.config.ReadOnly { builder = builder.WithReadOnly(true) } - if tt.config.InsidersMode { - builder = builder.WithInsidersMode(true) - } if hasStatic { r = filterRequestTools(r, validToolNames) @@ -645,8 +642,7 @@ func buildStaticInventoryFromTools(cfg *ServerConfig, tools []inventory.ServerTo SetTools(tools). WithFeatureChecker(featureChecker). WithReadOnly(cfg.ReadOnly). - WithToolsets(github.ResolvedEnabledToolsets(cfg.DynamicToolsets, cfg.EnabledToolsets, cfg.EnabledTools)). - WithInsidersMode(cfg.InsidersMode) + WithToolsets(github.ResolvedEnabledToolsets(cfg.DynamicToolsets, cfg.EnabledToolsets, cfg.EnabledTools)) if len(cfg.EnabledTools) > 0 { b = b.WithTools(github.CleanTools(cfg.EnabledTools)) diff --git a/pkg/http/server.go b/pkg/http/server.go index 83586509bc..d1e8192ba4 100644 --- a/pkg/http/server.go +++ b/pkg/http/server.go @@ -8,7 +8,6 @@ import ( "net/http" "os" "os/signal" - "slices" "syscall" "time" @@ -25,10 +24,6 @@ import ( "github.com/go-chi/chi/v5" ) -// knownFeatureFlags are the feature flags that can be enabled via X-MCP-Features header. -// Only these flags are accepted from headers. -var knownFeatureFlags = github.HeaderAllowedFeatureFlags() - type ServerConfig struct { // Version of the server Version string @@ -233,19 +228,14 @@ func initGlobalToolScopeMap(t translations.TranslationHelperFunc) error { return nil } -// createHTTPFeatureChecker creates a feature checker that reads header features from context -// and validates them against the knownFeatureFlags whitelist +// createHTTPFeatureChecker creates a feature checker that resolves features +// per-request by reading header features and insiders mode from context, +// then validating against the centralized AllowedFeatureFlags allowlist. func createHTTPFeatureChecker() inventory.FeatureFlagChecker { - // Pre-compute whitelist as set for O(1) lookup - knownSet := make(map[string]bool, len(knownFeatureFlags)) - for _, f := range knownFeatureFlags { - knownSet[f] = true - } - return func(ctx context.Context, flag string) (bool, error) { - if knownSet[flag] && slices.Contains(ghcontext.GetHeaderFeatures(ctx), flag) { - return true, nil - } - return false, nil + headerFeatures := ghcontext.GetHeaderFeatures(ctx) + insidersMode := ghcontext.IsInsidersMode(ctx) + effective := github.ResolveFeatureFlags(headerFeatures, insidersMode) + return effective[flag], nil } } diff --git a/pkg/http/server_test.go b/pkg/http/server_test.go index 7aeabc5823..23c82d0486 100644 --- a/pkg/http/server_test.go +++ b/pkg/http/server_test.go @@ -10,27 +10,34 @@ import ( "github.com/stretchr/testify/require" ) -func TestCreateHTTPFeatureChecker_Whitelist(t *testing.T) { +func TestCreateHTTPFeatureChecker(t *testing.T) { checker := createHTTPFeatureChecker() tests := []struct { name string flagName string headerFeatures []string + insidersMode bool wantEnabled bool }{ { - name: "whitelisted issues_granular flag accepted from header", + name: "allowed issues_granular flag accepted from header", flagName: github.FeatureFlagIssuesGranular, headerFeatures: []string{github.FeatureFlagIssuesGranular}, wantEnabled: true, }, { - name: "whitelisted pull_requests_granular flag accepted from header", + name: "allowed pull_requests_granular flag accepted from header", flagName: github.FeatureFlagPullRequestsGranular, headerFeatures: []string{github.FeatureFlagPullRequestsGranular}, wantEnabled: true, }, + { + name: "MCP Apps flag accepted from header", + flagName: github.MCPAppsFeatureFlag, + headerFeatures: []string{github.MCPAppsFeatureFlag}, + wantEnabled: true, + }, { name: "unknown flag in header is ignored", flagName: "unknown_flag", @@ -38,19 +45,19 @@ func TestCreateHTTPFeatureChecker_Whitelist(t *testing.T) { wantEnabled: false, }, { - name: "whitelisted flag not in header returns false", + name: "allowed flag not in header returns false", flagName: github.FeatureFlagIssuesGranular, headerFeatures: nil, wantEnabled: false, }, { - name: "whitelisted flag with different flag in header returns false", + name: "allowed flag with different flag in header returns false", flagName: github.FeatureFlagIssuesGranular, headerFeatures: []string{github.FeatureFlagPullRequestsGranular}, wantEnabled: false, }, { - name: "multiple whitelisted flags in header", + name: "multiple allowed flags in header", flagName: github.FeatureFlagIssuesGranular, headerFeatures: []string{github.FeatureFlagIssuesGranular, github.FeatureFlagPullRequestsGranular}, wantEnabled: true, @@ -61,6 +68,18 @@ func TestCreateHTTPFeatureChecker_Whitelist(t *testing.T) { headerFeatures: []string{}, wantEnabled: false, }, + { + name: "insiders mode enables MCP Apps without header", + flagName: github.MCPAppsFeatureFlag, + insidersMode: true, + wantEnabled: true, + }, + { + name: "insiders mode does not enable granular flags", + flagName: github.FeatureFlagIssuesGranular, + insidersMode: true, + wantEnabled: false, + }, } for _, tt := range tests { @@ -69,6 +88,9 @@ func TestCreateHTTPFeatureChecker_Whitelist(t *testing.T) { if len(tt.headerFeatures) > 0 { ctx = ghcontext.WithHeaderFeatures(ctx, tt.headerFeatures) } + if tt.insidersMode { + ctx = ghcontext.WithInsidersMode(ctx, true) + } enabled, err := checker(ctx, tt.flagName) require.NoError(t, err) @@ -77,10 +99,10 @@ func TestCreateHTTPFeatureChecker_Whitelist(t *testing.T) { } } -func TestKnownFeatureFlagsMatchesHeaderAllowed(t *testing.T) { - // Ensure knownFeatureFlags stays in sync with HeaderAllowedFeatureFlags +func TestHeaderAllowedFeatureFlagsMatchesAllowed(t *testing.T) { + // Ensure HeaderAllowedFeatureFlags delegates to AllowedFeatureFlags allowed := github.HeaderAllowedFeatureFlags() - assert.Equal(t, allowed, knownFeatureFlags, - "knownFeatureFlags should match github.HeaderAllowedFeatureFlags()") - assert.NotEmpty(t, knownFeatureFlags, "knownFeatureFlags should not be empty") + assert.Equal(t, github.AllowedFeatureFlags, allowed, + "HeaderAllowedFeatureFlags() should match AllowedFeatureFlags") + assert.NotEmpty(t, allowed, "AllowedFeatureFlags should not be empty") } diff --git a/pkg/inventory/builder.go b/pkg/inventory/builder.go index d492e69b5a..b9a0d8548b 100644 --- a/pkg/inventory/builder.go +++ b/pkg/inventory/builder.go @@ -14,6 +14,11 @@ var ( ErrUnknownTools = errors.New("unknown tools specified in WithTools") ) +// mcpAppsFeatureFlag is the feature flag name that controls MCP Apps UI metadata. +// This is defined here to avoid importing pkg/github (which imports pkg/inventory). +// The value must match github.MCPAppsFeatureFlag. +const mcpAppsFeatureFlag = "remote_mcp_ui_apps" + // ToolFilter is a function that determines if a tool should be included. // Returns true if the tool should be included, false to exclude it. type ToolFilter func(ctx context.Context, tool *ServerTool) (bool, error) @@ -48,7 +53,6 @@ type Builder struct { featureChecker FeatureFlagChecker filters []ToolFilter // filters to apply to all tools generateInstructions bool - insidersMode bool } // NewBuilder creates a new Builder. @@ -154,15 +158,6 @@ func (b *Builder) WithExcludeTools(toolNames []string) *Builder { return b } -// WithInsidersMode enables or disables insiders mode features. -// When insiders mode is disabled (default), UI metadata is removed from tools -// so clients won't attempt to load UI resources. -// Returns self for chaining. -func (b *Builder) WithInsidersMode(enabled bool) *Builder { - b.insidersMode = enabled - return b -} - // CreateExcludeToolsFilter creates a ToolFilter that excludes tools by name. // Any tool whose name appears in the excluded list will be filtered out. // The input slice should already be cleaned (trimmed, deduplicated). @@ -195,6 +190,19 @@ func cleanTools(tools []string) []string { return cleaned } +// checkFeatureFlag checks a feature flag at build time using the builder's feature checker. +// Returns false if no checker is configured or the flag is not enabled. +func (b *Builder) checkFeatureFlag(flag string) bool { + if b.featureChecker == nil { + return false + } + enabled, err := b.featureChecker(context.Background(), flag) + if err != nil { + return false + } + return enabled +} + // Build creates the final Inventory with all configuration applied. // This processes toolset filtering, tool name resolution, and sets up // the inventory for use. The returned Inventory is ready for use with @@ -204,10 +212,13 @@ func cleanTools(tools []string) []string { // (i.e., they don't exist in the tool set and are not deprecated aliases). // This ensures invalid tool configurations fail fast at build time. func (b *Builder) Build() (*Inventory, error) { - // When insiders mode is disabled, strip insiders-only features from tools tools := b.tools - if !b.insidersMode { - tools = stripInsidersFeatures(b.tools) + + // When MCP Apps feature flag is not enabled, strip UI metadata from tools + // so clients won't attempt to load UI resources. + // The feature checker is the single source of truth for flag evaluation. + if !b.checkFeatureFlag(mcpAppsFeatureFlag) { + tools = stripMCPAppsMetadata(tools) } r := &Inventory{ @@ -375,24 +386,17 @@ func (b *Builder) processToolsets() (map[ToolsetID]bool, []string, []ToolsetID, return enabledToolsets, unrecognized, allToolsetIDs, validIDs, defaultToolsetIDList, descriptions } -// insidersOnlyMetaKeys lists the Meta keys that are only available in insiders mode. -// Add new experimental feature keys here to have them automatically stripped -// when insiders mode is disabled. -var insidersOnlyMetaKeys = []string{ +// mcpAppsMetaKeys lists the Meta keys controlled by the remote_mcp_ui_apps feature flag. +var mcpAppsMetaKeys = []string{ "ui", // MCP Apps UI metadata } -// stripInsidersFeatures removes insiders-only features from tools. -// This includes removing tools marked with InsidersOnly and stripping -// Meta keys listed in insidersOnlyMetaKeys from remaining tools. -func stripInsidersFeatures(tools []ServerTool) []ServerTool { +// stripMCPAppsMetadata removes MCP Apps UI metadata from tools when the +// remote_mcp_ui_apps feature flag is not enabled. +func stripMCPAppsMetadata(tools []ServerTool) []ServerTool { result := make([]ServerTool, 0, len(tools)) for _, tool := range tools { - // Skip tools marked as insiders-only - if tool.InsidersOnly { - continue - } - if stripped := stripInsidersMetaFromTool(tool); stripped != nil { + if stripped := stripMetaKeys(tool, mcpAppsMetaKeys); stripped != nil { result = append(result, *stripped) } else { result = append(result, tool) @@ -401,30 +405,30 @@ func stripInsidersFeatures(tools []ServerTool) []ServerTool { return result } -// stripInsidersMetaFromTool removes insiders-only Meta keys from a single tool. +// stripMetaKeys removes the specified Meta keys from a single tool. // Returns a modified copy if changes were made, nil otherwise. -func stripInsidersMetaFromTool(tool ServerTool) *ServerTool { - if tool.Tool.Meta == nil { +func stripMetaKeys(tool ServerTool, keys []string) *ServerTool { + if tool.Tool.Meta == nil || len(keys) == 0 { return nil } - // Check if any insiders-only keys exist - hasInsidersKeys := false - for _, key := range insidersOnlyMetaKeys { - if tool.Tool.Meta[key] != nil { - hasInsidersKeys = true + // Check if any of the specified keys exist + hasKeys := false + for _, key := range keys { + if _, ok := tool.Tool.Meta[key]; ok { + hasKeys = true break } } - if !hasInsidersKeys { + if !hasKeys { return nil } - // Make a shallow copy and remove insiders-only keys + // Make a shallow copy and remove specified keys toolCopy := tool newMeta := make(map[string]any, len(tool.Tool.Meta)) for k, v := range tool.Tool.Meta { - if !slices.Contains(insidersOnlyMetaKeys, k) { + if !slices.Contains(keys, k) { newMeta[k] = v } } diff --git a/pkg/inventory/registry_test.go b/pkg/inventory/registry_test.go index 207e65dba8..e6c9e450cb 100644 --- a/pkg/inventory/registry_test.go +++ b/pkg/inventory/registry_test.go @@ -1723,6 +1723,10 @@ func TestFilteringOrder(t *testing.T) { WithFeatureChecker(checker). WithFilter(filter)) + // Reset call order — Build() may call the checker for MCP Apps metadata. + // We're testing the AvailableTools filter order here. + callOrder = callOrder[:0] + _ = reg.AvailableTools(context.Background()) // Expected order: Enabled, FeatureFlag, ReadOnly (stops here because it's write tool) @@ -1853,13 +1857,13 @@ func mockToolWithMeta(name string, toolsetID string, meta map[string]any) Server ) } -func TestWithInsidersMode_DisabledStripsUIMetadata(t *testing.T) { +func TestWithMCPApps_DisabledStripsUIMetadata(t *testing.T) { toolWithUI := mockToolWithMeta("tool_with_ui", "toolset1", map[string]any{ "ui": map[string]any{"html": "
hello
"}, "description": "kept", }) - // Default: insiders mode is disabled - UI meta should be stripped + // Default: MCP Apps is disabled - UI meta should be stripped reg := mustBuild(t, NewBuilder().SetTools([]ServerTool{toolWithUI}).WithToolsets([]string{"all"})) available := reg.AvailableTools(context.Background()) @@ -1874,24 +1878,27 @@ func TestWithInsidersMode_DisabledStripsUIMetadata(t *testing.T) { } } -func TestWithInsidersMode_EnabledPreservesUIMetadata(t *testing.T) { +func TestWithMCPApps_EnabledPreservesUIMetadata(t *testing.T) { uiData := map[string]any{"html": "
hello
"} toolWithUI := mockToolWithMeta("tool_with_ui", "toolset1", map[string]any{ "ui": uiData, "description": "kept", }) - // Insiders mode enabled - UI meta should be preserved + // Feature checker enables MCP Apps - UI meta should be preserved + mcpAppsChecker := func(_ context.Context, flag string) (bool, error) { + return flag == mcpAppsFeatureFlag, nil + } reg := mustBuild(t, NewBuilder(). SetTools([]ServerTool{toolWithUI}). WithToolsets([]string{"all"}). - WithInsidersMode(true)) + WithFeatureChecker(mcpAppsChecker)) available := reg.AvailableTools(context.Background()) require.Len(t, available, 1) // UI metadata should be preserved if available[0].Tool.Meta["ui"] == nil { - t.Errorf("Expected 'ui' meta to be preserved in insiders mode") + t.Errorf("Expected 'ui' meta to be preserved with MCP Apps enabled") } // Other metadata should also be preserved if available[0].Tool.Meta["description"] != "kept" { @@ -1899,48 +1906,14 @@ func TestWithInsidersMode_EnabledPreservesUIMetadata(t *testing.T) { } } -func TestWithInsidersMode_EnabledPreservesInsidersOnlyTools(t *testing.T) { - normalTool := mockTool("normal", "toolset1", true) - insidersTool := mockTool("insiders_only", "toolset1", true) - insidersTool.InsidersOnly = true - - // With insiders mode enabled, both tools should be available - reg := mustBuild(t, NewBuilder(). - SetTools([]ServerTool{normalTool, insidersTool}). - WithToolsets([]string{"all"}). - WithInsidersMode(true)) - available := reg.AvailableTools(context.Background()) - - require.Len(t, available, 2) - names := []string{available[0].Tool.Name, available[1].Tool.Name} - require.Contains(t, names, "normal") - require.Contains(t, names, "insiders_only") -} - -func TestWithInsidersMode_DisabledRemovesInsidersOnlyTools(t *testing.T) { - normalTool := mockTool("normal", "toolset1", true) - insidersTool := mockTool("insiders_only", "toolset1", true) - insidersTool.InsidersOnly = true - - // With insiders mode disabled, insiders-only tool should be removed - reg := mustBuild(t, NewBuilder(). - SetTools([]ServerTool{normalTool, insidersTool}). - WithToolsets([]string{"all"}). - WithInsidersMode(false)) - available := reg.AvailableTools(context.Background()) - - require.Len(t, available, 1) - require.Equal(t, "normal", available[0].Tool.Name) -} - -func TestWithInsidersMode_ToolsWithoutUIMetaUnaffected(t *testing.T) { +func TestWithMCPApps_ToolsWithoutUIMetaUnaffected(t *testing.T) { toolNoUI := mockToolWithMeta("tool_no_ui", "toolset1", map[string]any{ "description": "kept", "version": "1.0", }) toolNilMeta := mockTool("tool_nil_meta", "toolset1", true) - // Test with insiders disabled + // Test with MCP Apps disabled (default) - non-UI meta should be unaffected reg := mustBuild(t, NewBuilder(). SetTools([]ServerTool{toolNoUI, toolNilMeta}). WithToolsets([]string{"all"})) @@ -1973,8 +1946,8 @@ func TestWithInsidersMode_ToolsWithoutUIMetaUnaffected(t *testing.T) { } } -func TestWithInsidersMode_UIOnlyMetaBecomesNil(t *testing.T) { - // Tool with ONLY ui metadata - should become nil after stripping +func TestWithMCPApps_UIOnlyMetaBecomesNil(t *testing.T) { + // Tool with ONLY ui metadata - should become nil after stripping when MCP Apps is disabled toolUIOnly := mockToolWithMeta("tool_ui_only", "toolset1", map[string]any{ "ui": map[string]any{"html": "
hello
"}, }) @@ -1985,44 +1958,57 @@ func TestWithInsidersMode_UIOnlyMetaBecomesNil(t *testing.T) { available := reg.AvailableTools(context.Background()) require.Len(t, available, 1) - // Meta should be nil since ui was the only key + // Meta should be nil since ui was the only key and MCP Apps is off by default if available[0].Tool.Meta != nil { t.Errorf("Expected Meta to be nil after stripping only key, got %v", available[0].Tool.Meta) } } -func TestStripInsidersMetaFromTool(t *testing.T) { +func TestStripMetaKeys(t *testing.T) { tests := []struct { name string meta map[string]any + keys []string expectChange bool expectedMeta map[string]any // nil means Meta should be nil }{ { name: "nil meta - no change", meta: nil, + keys: mcpAppsMetaKeys, expectChange: false, }, { - name: "no insiders keys - no change", + name: "no matching keys - no change", meta: map[string]any{"description": "test", "version": "1.0"}, + keys: mcpAppsMetaKeys, expectChange: false, }, { name: "ui key only - becomes nil", meta: map[string]any{"ui": "data"}, + keys: mcpAppsMetaKeys, expectChange: true, expectedMeta: nil, }, { name: "ui key with other keys - ui stripped", meta: map[string]any{"ui": "data", "description": "kept"}, + keys: mcpAppsMetaKeys, expectChange: true, expectedMeta: map[string]any{"description": "kept"}, }, { - name: "ui is nil value - no change (nil value means key not present)", + name: "ui is nil value - ui stripped", meta: map[string]any{"ui": nil, "description": "kept"}, + keys: mcpAppsMetaKeys, + expectChange: true, + expectedMeta: map[string]any{"description": "kept"}, + }, + { + name: "empty keys list - no change", + meta: map[string]any{"ui": "data"}, + keys: []string{}, expectChange: false, }, } @@ -2030,7 +2016,7 @@ func TestStripInsidersMetaFromTool(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tool := mockToolWithMeta("test", "toolset1", tt.meta) - result := stripInsidersMetaFromTool(tool) + result := stripMetaKeys(tool, tt.keys) if tt.expectChange { require.NotNil(t, result, "expected change but got nil") @@ -2050,14 +2036,14 @@ func TestStripInsidersMetaFromTool(t *testing.T) { } } -func TestStripInsidersFeatures(t *testing.T) { +func TestStripMCPAppsMetadata(t *testing.T) { tools := []ServerTool{ mockToolWithMeta("tool1", "toolset1", map[string]any{"ui": "data"}), mockToolWithMeta("tool2", "toolset1", map[string]any{"description": "kept"}), mockTool("tool3", "toolset1", true), // nil meta } - result := stripInsidersFeatures(tools) + result := stripMCPAppsMetadata(tools) require.Len(t, result, 3) @@ -2072,33 +2058,9 @@ func TestStripInsidersFeatures(t *testing.T) { require.Nil(t, result[2].Tool.Meta) } -func TestStripInsidersFeatures_RemovesInsidersOnlyTools(t *testing.T) { - // Create tools: one normal, one insiders-only, one normal - normalTool1 := mockTool("normal1", "toolset1", true) - insidersTool := mockTool("insiders_only", "toolset1", true) - insidersTool.InsidersOnly = true - normalTool2 := mockTool("normal2", "toolset1", true) - - tools := []ServerTool{normalTool1, insidersTool, normalTool2} - - result := stripInsidersFeatures(tools) - - // Should only have 2 tools (insiders-only tool filtered out) - require.Len(t, result, 2) - require.Equal(t, "normal1", result[0].Tool.Name) - require.Equal(t, "normal2", result[1].Tool.Name) -} - -func TestInsidersOnlyMetaKeys_FutureAdditions(t *testing.T) { +func TestStripMetaKeys_MultipleKeys(t *testing.T) { // This test verifies the mechanism works for multiple keys - // If we add new experimental keys to insidersOnlyMetaKeys, they should be stripped - - // Save original and restore after test - originalKeys := insidersOnlyMetaKeys - defer func() { insidersOnlyMetaKeys = originalKeys }() - - // Add a hypothetical future experimental key - insidersOnlyMetaKeys = []string{"ui", "experimental_feature", "beta"} + keys := []string{"ui", "experimental_feature", "beta"} tool := mockToolWithMeta("test", "toolset1", map[string]any{ "ui": "ui data", @@ -2107,7 +2069,7 @@ func TestInsidersOnlyMetaKeys_FutureAdditions(t *testing.T) { "description": "kept", }) - result := stripInsidersMetaFromTool(tool) + result := stripMetaKeys(tool, keys) require.NotNil(t, result) require.NotNil(t, result.Tool.Meta) @@ -2117,12 +2079,12 @@ func TestInsidersOnlyMetaKeys_FutureAdditions(t *testing.T) { require.Equal(t, "kept", result.Tool.Meta["description"], "description should be preserved") } -func TestWithInsidersMode_DoesNotMutateOriginalTools(t *testing.T) { +func TestWithMCPApps_DoesNotMutateOriginalTools(t *testing.T) { originalMeta := map[string]any{"ui": "data", "description": "kept"} tool := mockToolWithMeta("test", "toolset1", originalMeta) tools := []ServerTool{tool} - // Build with insiders disabled - should strip ui + // Build with MCP Apps disabled (default) - should strip ui _ = mustBuild(t, NewBuilder().SetTools(tools).WithToolsets([]string{"all"})) // Original tool should be unchanged diff --git a/pkg/inventory/server_tool.go b/pkg/inventory/server_tool.go index b08ae1f014..752a4c2bd0 100644 --- a/pkg/inventory/server_tool.go +++ b/pkg/inventory/server_tool.go @@ -82,10 +82,6 @@ type ServerTool struct { // This includes the required scopes plus any higher-level scopes that provide // the necessary permissions due to scope hierarchy. AcceptedScopes []string - - // InsidersOnly marks this tool as only available when insiders mode is enabled. - // When insiders mode is disabled, tools with this flag set are completely omitted. - InsidersOnly bool } // IsReadOnly returns true if this tool is marked as read-only via annotations. From b482ac6ead1a84877cddad552594f928116cef41 Mon Sep 17 00:00:00 2001 From: Sam Morrow Date: Wed, 15 Apr 2026 17:54:59 +0200 Subject: [PATCH 15/17] docs: add MCP Apps feature flag configuration section Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/server-configuration.md | 59 +++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/docs/server-configuration.md b/docs/server-configuration.md index 87d48e01e3..693c096a1b 100644 --- a/docs/server-configuration.md +++ b/docs/server-configuration.md @@ -14,6 +14,7 @@ We currently support the following ways in which the GitHub MCP Server can be co | Dynamic Mode | Not available | `--dynamic-toolsets` flag or `GITHUB_DYNAMIC_TOOLSETS` env var | | Lockdown Mode | `X-MCP-Lockdown` header | `--lockdown-mode` flag or `GITHUB_LOCKDOWN_MODE` env var | | Insiders Mode | `X-MCP-Insiders` header or `/insiders` URL | `--insiders` flag or `GITHUB_INSIDERS` env var | +| Feature Flags | `X-MCP-Features` header | `--features` flag | | Scope Filtering | Always enabled | Always enabled | | Server Name/Title | Not available | `GITHUB_MCP_SERVER_NAME` / `GITHUB_MCP_SERVER_TITLE` env vars or `github-mcp-server-config.json` | @@ -390,7 +391,7 @@ Lockdown mode ensures the server only surfaces content in public repositories fr **Best for:** Users who want early access to experimental features and new tools before they reach general availability. -Insiders Mode unlocks experimental features, such as [MCP Apps](./insiders-features.md#mcp-apps) support. We created this mode to have a way to roll out experimental features and collect feedback. So if you are using Insiders, please don't hesitate to share your feedback with us! Features in Insiders Mode may change, evolve, or be removed based on user feedback. +Insiders Mode unlocks experimental features, such as [MCP Apps](#mcp-apps) support. We created this mode to have a way to roll out experimental features and collect feedback. So if you are using Insiders, please don't hesitate to share your feedback with us! Features in Insiders Mode may change, evolve, or be removed based on user feedback. @@ -443,6 +444,62 @@ See [Insiders Features](./insiders-features.md) for a full list of what's availa --- +### MCP Apps + +[MCP Apps](https://modelcontextprotocol.io/docs/extensions/apps) is an extension to the Model Context Protocol that enables servers to deliver interactive user interfaces to end users. Instead of returning plain text that the LLM must interpret and relay, tools can render forms, profiles, and dashboards right in the chat. + +MCP Apps is enabled by [Insiders Mode](#insiders-mode), or independently via the `remote_mcp_ui_apps` feature flag. + +**Supported tools:** + +| Tool | Description | +|------|-------------| +| `get_me` | Displays your GitHub user profile with avatar, bio, and stats in a rich card | +| `issue_write` | Opens an interactive form to create or update issues | +| `create_pull_request` | Provides a full PR creation form to create a pull request (or a draft pull request) | + +**Client requirements:** MCP Apps requires a host that supports the [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps). Currently tested with VS Code (`chat.mcp.apps.enabled` setting). + +
Remote ServerLocal Server
+ + + + + +
Remote ServerLocal Server
+ +```json +{ + "type": "http", + "url": "https://api.githubcopilot.com/mcp/", + "headers": { + "X-MCP-Features": "remote_mcp_ui_apps" + } +} +``` + + + +```json +{ + "type": "stdio", + "command": "go", + "args": [ + "run", + "./cmd/github-mcp-server", + "stdio", + "--features=remote_mcp_ui_apps" + ], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}" + } +} +``` + +
+ +--- + ### Scope Filtering **Automatic feature:** The server handles OAuth scopes differently depending on authentication type: From fc7a7dcdea0f2412433549e342e5af5ef15f94fa Mon Sep 17 00:00:00 2001 From: Matt Holloway Date: Thu, 16 Apr 2026 13:43:45 +0100 Subject: [PATCH 16/17] feat: add granular tool to set issue field values --- .../__toolsnaps__/set_issue_fields.snap | 70 ++++++ pkg/github/granular_tools_test.go | 134 +++++++++++ pkg/github/issues_granular.go | 226 ++++++++++++++++++ pkg/github/tools.go | 1 + 4 files changed, 431 insertions(+) create mode 100644 pkg/github/__toolsnaps__/set_issue_fields.snap diff --git a/pkg/github/__toolsnaps__/set_issue_fields.snap b/pkg/github/__toolsnaps__/set_issue_fields.snap new file mode 100644 index 0000000000..7546ddc370 --- /dev/null +++ b/pkg/github/__toolsnaps__/set_issue_fields.snap @@ -0,0 +1,70 @@ +{ + "annotations": { + "destructiveHint": false, + "openWorldHint": true, + "title": "Set Issue Fields" + }, + "description": "Set issue field values for an issue. Fields are organization-level custom fields (text, number, date, or single select). Use this to create or update field values on an issue.", + "inputSchema": { + "properties": { + "fields": { + "description": "Array of issue field values to set. Each element must have a 'field_id' (string, the GraphQL node ID of the field) and exactly one value field: 'text_value' for text fields, 'number_value' for number fields, 'date_value' (ISO 8601 date string) for date fields, or 'single_select_option_id' (the GraphQL node ID of the option) for single select fields. Set 'delete' to true to remove a field value.", + "items": { + "properties": { + "date_value": { + "description": "The value to set for a date field (ISO 8601 date string)", + "type": "string" + }, + "delete": { + "description": "Set to true to delete this field value", + "type": "boolean" + }, + "field_id": { + "description": "The GraphQL node ID of the issue field", + "type": "string" + }, + "number_value": { + "description": "The value to set for a number field", + "type": "number" + }, + "single_select_option_id": { + "description": "The GraphQL node ID of the option to set for a single select field", + "type": "string" + }, + "text_value": { + "description": "The value to set for a text field", + "type": "string" + } + }, + "required": [ + "field_id" + ], + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "issue_number": { + "description": "The issue number to update", + "minimum": 1, + "type": "number" + }, + "owner": { + "description": "Repository owner (username or organization)", + "type": "string" + }, + "repo": { + "description": "Repository name", + "type": "string" + } + }, + "required": [ + "owner", + "repo", + "issue_number", + "fields" + ], + "type": "object" + }, + "name": "set_issue_fields" +} \ No newline at end of file diff --git a/pkg/github/granular_tools_test.go b/pkg/github/granular_tools_test.go index d50f6c5529..4d7996e96d 100644 --- a/pkg/github/granular_tools_test.go +++ b/pkg/github/granular_tools_test.go @@ -39,6 +39,7 @@ func TestGranularToolSnaps(t *testing.T) { GranularAddSubIssue, GranularRemoveSubIssue, GranularReprioritizeSubIssue, + GranularSetIssueFields, GranularUpdatePullRequestTitle, GranularUpdatePullRequestBody, GranularUpdatePullRequestState, @@ -81,6 +82,7 @@ func TestIssuesGranularToolset(t *testing.T) { "add_sub_issue", "remove_sub_issue", "reprioritize_sub_issue", + "set_issue_fields", } for _, name := range expected { assert.Contains(t, toolNames, name) @@ -774,3 +776,135 @@ func TestGranularUnresolveReviewThread(t *testing.T) { require.NoError(t, err) assert.False(t, result.IsError) } + +func TestGranularSetIssueFields(t *testing.T) { + t.Run("successful set with text value", func(t *testing.T) { + matchers := []githubv4mock.Matcher{ + // Mock the issue ID query + githubv4mock.NewQueryMatcher( + struct { + Repository struct { + Issue struct { + ID githubv4.ID + } `graphql:"issue(number: $issueNumber)"` + } `graphql:"repository(owner: $owner, name: $repo)"` + }{}, + map[string]any{ + "owner": githubv4.String("owner"), + "repo": githubv4.String("repo"), + "issueNumber": githubv4.Int(5), + }, + githubv4mock.DataResponse(map[string]any{ + "repository": map[string]any{ + "issue": map[string]any{"id": "ISSUE_123"}, + }, + }), + ), + // Mock the setIssueFieldValue mutation + githubv4mock.NewMutationMatcher( + struct { + SetIssueFieldValue struct { + Issue struct { + ID githubv4.ID + Number githubv4.Int + URL githubv4.String + } + IssueFieldValues []struct { + Field struct { + Name string + } `graphql:"... on IssueFieldDateValue"` + } + } `graphql:"setIssueFieldValue(input: $input)"` + }{}, + SetIssueFieldValueInput{ + IssueID: githubv4.ID("ISSUE_123"), + IssueFields: []IssueFieldCreateOrUpdateInput{ + { + FieldID: githubv4.ID("FIELD_1"), + TextValue: githubv4.NewString(githubv4.String("hello")), + }, + }, + }, + nil, + githubv4mock.DataResponse(map[string]any{ + "setIssueFieldValue": map[string]any{ + "issue": map[string]any{ + "id": "ISSUE_123", + "number": 5, + "url": "https://github.com/owner/repo/issues/5", + }, + }, + }), + ), + } + + gqlClient := githubv4.NewClient(githubv4mock.NewMockedHTTPClient(matchers...)) + deps := BaseDeps{GQLClient: gqlClient} + serverTool := GranularSetIssueFields(translations.NullTranslationHelper) + handler := serverTool.Handler(deps) + + request := createMCPRequest(map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(5), + "fields": []any{ + map[string]any{"field_id": "FIELD_1", "text_value": "hello"}, + }, + }) + result, err := handler(ContextWithDeps(context.Background(), deps), &request) + require.NoError(t, err) + assert.False(t, result.IsError) + }) + + t.Run("missing required parameter fields", func(t *testing.T) { + deps := BaseDeps{} + serverTool := GranularSetIssueFields(translations.NullTranslationHelper) + handler := serverTool.Handler(deps) + + request := createMCPRequest(map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(5), + }) + result, err := handler(ContextWithDeps(context.Background(), deps), &request) + require.NoError(t, err) + textContent := getTextResult(t, result) + assert.Contains(t, textContent.Text, "missing required parameter: fields") + }) + + t.Run("empty fields array", func(t *testing.T) { + deps := BaseDeps{} + serverTool := GranularSetIssueFields(translations.NullTranslationHelper) + handler := serverTool.Handler(deps) + + request := createMCPRequest(map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(5), + "fields": []any{}, + }) + result, err := handler(ContextWithDeps(context.Background(), deps), &request) + require.NoError(t, err) + textContent := getTextResult(t, result) + assert.Contains(t, textContent.Text, "fields array must not be empty") + }) + + t.Run("field missing value", func(t *testing.T) { + deps := BaseDeps{} + serverTool := GranularSetIssueFields(translations.NullTranslationHelper) + handler := serverTool.Handler(deps) + + request := createMCPRequest(map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(5), + "fields": []any{ + map[string]any{"field_id": "FIELD_1"}, + }, + }) + result, err := handler(ContextWithDeps(context.Background(), deps), &request) + require.NoError(t, err) + textContent := getTextResult(t, result) + assert.Contains(t, textContent.Text, "each field must have a value") + }) +} diff --git a/pkg/github/issues_granular.go b/pkg/github/issues_granular.go index 3daa1a62e4..107f8a74fb 100644 --- a/pkg/github/issues_granular.go +++ b/pkg/github/issues_granular.go @@ -15,6 +15,7 @@ import ( "github.com/google/go-github/v82/github" "github.com/google/jsonschema-go/jsonschema" "github.com/modelcontextprotocol/go-sdk/mcp" + "github.com/shurcooL/githubv4" ) // issueUpdateTool is a helper to create single-field issue update tools. @@ -593,3 +594,228 @@ func GranularReprioritizeSubIssue(t translations.TranslationHelperFunc) inventor st.FeatureFlagEnable = FeatureFlagIssuesGranular return st } + +// SetIssueFieldValueInput represents the input for the setIssueFieldValue GraphQL mutation. +type SetIssueFieldValueInput struct { + IssueID githubv4.ID `json:"issueId"` + IssueFields []IssueFieldCreateOrUpdateInput `json:"issueFields"` + ClientMutationID *githubv4.String `json:"clientMutationId,omitempty"` +} + +// IssueFieldCreateOrUpdateInput represents a single field value to set on an issue. +type IssueFieldCreateOrUpdateInput struct { + FieldID githubv4.ID `json:"fieldId"` + TextValue *githubv4.String `json:"textValue,omitempty"` + NumberValue *githubv4.Float `json:"numberValue,omitempty"` + DateValue *githubv4.String `json:"dateValue,omitempty"` + SingleSelectOptionID *githubv4.ID `json:"singleSelectOptionId,omitempty"` + Delete *githubv4.Boolean `json:"delete,omitempty"` +} + +// GranularSetIssueFields creates a tool to set issue field values on an issue using GraphQL. +func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.ServerTool { + st := NewTool( + ToolsetMetadataIssues, + mcp.Tool{ + Name: "set_issue_fields", + Description: t("TOOL_SET_ISSUE_FIELDS_DESCRIPTION", "Set issue field values for an issue. Fields are organization-level custom fields (text, number, date, or single select). Use this to create or update field values on an issue."), + Annotations: &mcp.ToolAnnotations{ + Title: t("TOOL_SET_ISSUE_FIELDS_USER_TITLE", "Set Issue Fields"), + ReadOnlyHint: false, + DestructiveHint: jsonschema.Ptr(false), + OpenWorldHint: jsonschema.Ptr(true), + }, + InputSchema: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "owner": { + Type: "string", + Description: "Repository owner (username or organization)", + }, + "repo": { + Type: "string", + Description: "Repository name", + }, + "issue_number": { + Type: "number", + Description: "The issue number to update", + Minimum: jsonschema.Ptr(1.0), + }, + "fields": { + Type: "array", + Description: "Array of issue field values to set. Each element must have a 'field_id' (string, the GraphQL node ID of the field) and exactly one value field: 'text_value' for text fields, 'number_value' for number fields, 'date_value' (ISO 8601 date string) for date fields, or 'single_select_option_id' (the GraphQL node ID of the option) for single select fields. Set 'delete' to true to remove a field value.", + MinItems: jsonschema.Ptr(1), + Items: &jsonschema.Schema{ + Type: "object", + Properties: map[string]*jsonschema.Schema{ + "field_id": { + Type: "string", + Description: "The GraphQL node ID of the issue field", + }, + "text_value": { + Type: "string", + Description: "The value to set for a text field", + }, + "number_value": { + Type: "number", + Description: "The value to set for a number field", + }, + "date_value": { + Type: "string", + Description: "The value to set for a date field (ISO 8601 date string)", + }, + "single_select_option_id": { + Type: "string", + Description: "The GraphQL node ID of the option to set for a single select field", + }, + "delete": { + Type: "boolean", + Description: "Set to true to delete this field value", + }, + }, + Required: []string{"field_id"}, + }, + }, + }, + Required: []string{"owner", "repo", "issue_number", "fields"}, + }, + }, + []scopes.Scope{scopes.Repo}, + func(ctx context.Context, deps ToolDependencies, _ *mcp.CallToolRequest, args map[string]any) (*mcp.CallToolResult, any, error) { + owner, err := RequiredParam[string](args, "owner") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil + } + repo, err := RequiredParam[string](args, "repo") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil + } + issueNumber, err := RequiredInt(args, "issue_number") + if err != nil { + return utils.NewToolResultError(err.Error()), nil, nil + } + + fieldsRaw, ok := args["fields"] + if !ok { + return utils.NewToolResultError("missing required parameter: fields"), nil, nil + } + + // Accept both []any and []map[string]any input forms + var fieldMaps []map[string]any + switch v := fieldsRaw.(type) { + case []any: + for _, f := range v { + fieldMap, ok := f.(map[string]any) + if !ok { + return utils.NewToolResultError("each field must be an object with 'field_id' and a value"), nil, nil + } + fieldMaps = append(fieldMaps, fieldMap) + } + case []map[string]any: + fieldMaps = v + default: + return utils.NewToolResultError("invalid parameter: fields must be an array"), nil, nil + } + if len(fieldMaps) == 0 { + return utils.NewToolResultError("fields array must not be empty"), nil, nil + } + + issueFields := make([]IssueFieldCreateOrUpdateInput, 0, len(fieldMaps)) + for _, fieldMap := range fieldMaps { + fieldID, err := RequiredParam[string](fieldMap, "field_id") + if err != nil { + return utils.NewToolResultError("field_id is required and must be a string"), nil, nil + } + + input := IssueFieldCreateOrUpdateInput{ + FieldID: githubv4.ID(fieldID), + } + + // Check for exactly one value type (or delete) + hasValue := false + + if v, err := OptionalParam[string](fieldMap, "text_value"); err == nil && v != "" { + input.TextValue = githubv4.NewString(githubv4.String(v)) + hasValue = true + } + if v, err := OptionalParam[float64](fieldMap, "number_value"); err == nil { + if _, exists := fieldMap["number_value"]; exists { + gqlFloat := githubv4.Float(v) + input.NumberValue = &gqlFloat + hasValue = true + } + } + if v, err := OptionalParam[string](fieldMap, "date_value"); err == nil && v != "" { + input.DateValue = githubv4.NewString(githubv4.String(v)) + hasValue = true + } + if v, err := OptionalParam[string](fieldMap, "single_select_option_id"); err == nil && v != "" { + optionID := githubv4.ID(v) + input.SingleSelectOptionID = &optionID + hasValue = true + } + if _, exists := fieldMap["delete"]; exists { + del, err := OptionalParam[bool](fieldMap, "delete") + if err == nil && del { + deleteVal := githubv4.Boolean(true) + input.Delete = &deleteVal + hasValue = true + } + } + + if !hasValue { + return utils.NewToolResultError("each field must have a value (text_value, number_value, date_value, single_select_option_id) or delete: true"), nil, nil + } + + issueFields = append(issueFields, input) + } + + gqlClient, err := deps.GetGQLClient(ctx) + if err != nil { + return utils.NewToolResultErrorFromErr("failed to get GitHub GraphQL client", err), nil, nil + } + + // Resolve issue node ID + issueID, _, err := fetchIssueIDs(ctx, gqlClient, owner, repo, issueNumber, 0) + if err != nil { + return ghErrors.NewGitHubGraphQLErrorResponse(ctx, "failed to get issue", err), nil, nil + } + + // Execute the setIssueFieldValue mutation + var mutation struct { + SetIssueFieldValue struct { + Issue struct { + ID githubv4.ID + Number githubv4.Int + URL githubv4.String + } + IssueFieldValues []struct { + Field struct { + Name string + } `graphql:"... on IssueFieldDateValue"` + } + } `graphql:"setIssueFieldValue(input: $input)"` + } + + mutationInput := SetIssueFieldValueInput{ + IssueID: issueID, + IssueFields: issueFields, + } + + if err := gqlClient.Mutate(ctx, &mutation, mutationInput, nil); err != nil { + return ghErrors.NewGitHubGraphQLErrorResponse(ctx, "failed to set issue field values", err), nil, nil + } + + r, err := json.Marshal(MinimalResponse{ + ID: fmt.Sprintf("%v", mutation.SetIssueFieldValue.Issue.ID), + URL: string(mutation.SetIssueFieldValue.Issue.URL), + }) + if err != nil { + return utils.NewToolResultErrorFromErr("failed to marshal response", err), nil, nil + } + return utils.NewToolResultText(string(r)), nil, nil + }, + ) + st.FeatureFlagEnable = FeatureFlagIssuesGranular + return st +} diff --git a/pkg/github/tools.go b/pkg/github/tools.go index cdb07beecb..559088f6d6 100644 --- a/pkg/github/tools.go +++ b/pkg/github/tools.go @@ -301,6 +301,7 @@ func AllTools(t translations.TranslationHelperFunc) []inventory.ServerTool { GranularAddSubIssue(t), GranularRemoveSubIssue(t), GranularReprioritizeSubIssue(t), + GranularSetIssueFields(t), // Granular pull request tools (feature-flagged, replace consolidated update_pull_request/pull_request_review_write) GranularUpdatePullRequestTitle(t), From 569a48d847236e7ed8d2b46ca57af8af7f768b36 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 14:01:02 +0100 Subject: [PATCH 17/17] Enforce exactly one value key per field in set_issue_fields (#2339) * Initial plan * Enforce exactly one value key per field in set_issue_fields and add tests Address review feedback: - Change validation to count value keys and reject when multiple are provided (e.g., text_value + number_value, or text_value + delete). - Add unit tests for multiple value keys and value + delete scenarios. - Run generate-docs (no doc changes needed; README was already current). Agent-Logs-Url: https://github.com/github/github-mcp-server/sessions/7e89edb3-5315-42dd-bfa1-6c962f1ba137 Co-authored-by: mattdholloway <918573+mattdholloway@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mattdholloway <918573+mattdholloway@users.noreply.github.com> --- pkg/github/granular_tools_test.go | 38 +++++++++++++++++++++++++++++++ pkg/github/issues_granular.go | 19 +++++++++------- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/pkg/github/granular_tools_test.go b/pkg/github/granular_tools_test.go index 4d7996e96d..883158bb25 100644 --- a/pkg/github/granular_tools_test.go +++ b/pkg/github/granular_tools_test.go @@ -907,4 +907,42 @@ func TestGranularSetIssueFields(t *testing.T) { textContent := getTextResult(t, result) assert.Contains(t, textContent.Text, "each field must have a value") }) + + t.Run("multiple value keys returns error", func(t *testing.T) { + deps := BaseDeps{} + serverTool := GranularSetIssueFields(translations.NullTranslationHelper) + handler := serverTool.Handler(deps) + + request := createMCPRequest(map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(5), + "fields": []any{ + map[string]any{"field_id": "FIELD_1", "text_value": "hello", "number_value": float64(42)}, + }, + }) + result, err := handler(ContextWithDeps(context.Background(), deps), &request) + require.NoError(t, err) + textContent := getTextResult(t, result) + assert.Contains(t, textContent.Text, "each field must have exactly one value") + }) + + t.Run("value key with delete returns error", func(t *testing.T) { + deps := BaseDeps{} + serverTool := GranularSetIssueFields(translations.NullTranslationHelper) + handler := serverTool.Handler(deps) + + request := createMCPRequest(map[string]any{ + "owner": "owner", + "repo": "repo", + "issue_number": float64(5), + "fields": []any{ + map[string]any{"field_id": "FIELD_1", "text_value": "hello", "delete": true}, + }, + }) + result, err := handler(ContextWithDeps(context.Background(), deps), &request) + require.NoError(t, err) + textContent := getTextResult(t, result) + assert.Contains(t, textContent.Text, "each field must have exactly one value") + }) } diff --git a/pkg/github/issues_granular.go b/pkg/github/issues_granular.go index 107f8a74fb..5dbd7d8d11 100644 --- a/pkg/github/issues_granular.go +++ b/pkg/github/issues_granular.go @@ -731,41 +731,44 @@ func GranularSetIssueFields(t translations.TranslationHelperFunc) inventory.Serv FieldID: githubv4.ID(fieldID), } - // Check for exactly one value type (or delete) - hasValue := false + // Count how many value keys are present; exactly one is required. + valueCount := 0 if v, err := OptionalParam[string](fieldMap, "text_value"); err == nil && v != "" { input.TextValue = githubv4.NewString(githubv4.String(v)) - hasValue = true + valueCount++ } if v, err := OptionalParam[float64](fieldMap, "number_value"); err == nil { if _, exists := fieldMap["number_value"]; exists { gqlFloat := githubv4.Float(v) input.NumberValue = &gqlFloat - hasValue = true + valueCount++ } } if v, err := OptionalParam[string](fieldMap, "date_value"); err == nil && v != "" { input.DateValue = githubv4.NewString(githubv4.String(v)) - hasValue = true + valueCount++ } if v, err := OptionalParam[string](fieldMap, "single_select_option_id"); err == nil && v != "" { optionID := githubv4.ID(v) input.SingleSelectOptionID = &optionID - hasValue = true + valueCount++ } if _, exists := fieldMap["delete"]; exists { del, err := OptionalParam[bool](fieldMap, "delete") if err == nil && del { deleteVal := githubv4.Boolean(true) input.Delete = &deleteVal - hasValue = true + valueCount++ } } - if !hasValue { + if valueCount == 0 { return utils.NewToolResultError("each field must have a value (text_value, number_value, date_value, single_select_option_id) or delete: true"), nil, nil } + if valueCount > 1 { + return utils.NewToolResultError("each field must have exactly one value (text_value, number_value, date_value, single_select_option_id) or delete: true, but multiple were provided"), nil, nil + } issueFields = append(issueFields, input) }