Files
github--github-mcp-server/pkg/http/server_test.go
Sam Morrow a24c0be254 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>
2026-04-16 11:41:19 +02:00

109 lines
3.2 KiB
Go

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(t *testing.T) {
checker := createHTTPFeatureChecker()
tests := []struct {
name string
flagName string
headerFeatures []string
insidersMode bool
wantEnabled bool
}{
{
name: "allowed issues_granular flag accepted from header",
flagName: github.FeatureFlagIssuesGranular,
headerFeatures: []string{github.FeatureFlagIssuesGranular},
wantEnabled: true,
},
{
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",
headerFeatures: []string{"unknown_flag"},
wantEnabled: false,
},
{
name: "allowed flag not in header returns false",
flagName: github.FeatureFlagIssuesGranular,
headerFeatures: nil,
wantEnabled: false,
},
{
name: "allowed flag with different flag in header returns false",
flagName: github.FeatureFlagIssuesGranular,
headerFeatures: []string{github.FeatureFlagPullRequestsGranular},
wantEnabled: false,
},
{
name: "multiple allowed 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,
},
{
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 {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
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)
assert.Equal(t, tt.wantEnabled, enabled)
})
}
}
func TestHeaderAllowedFeatureFlagsMatchesAllowed(t *testing.T) {
// Ensure HeaderAllowedFeatureFlags delegates to AllowedFeatureFlags
allowed := github.HeaderAllowedFeatureFlags()
assert.Equal(t, github.AllowedFeatureFlags, allowed,
"HeaderAllowedFeatureFlags() should match AllowedFeatureFlags")
assert.NotEmpty(t, allowed, "AllowedFeatureFlags should not be empty")
}