Files
github--github-mcp-server/pkg
Matt Holloway 0e2fc38896 fix(mcp-apps): defer _meta.ui strip to per-request RegisterTools (#2446)
* fix(mcp-apps): defer _meta.ui strip to per-request RegisterTools

The MCP Apps `_meta.ui` strip lived in `Builder.Build()`, which calls
`checkFeatureFlag(context.Background())`. The HTTP feature checker
(`createHTTPFeatureChecker`) reads insiders mode from the request
context — a background context never has it set, so the FF reported
MCP Apps off and the strip ran eagerly at server startup. Per-request
inventory factories then served pre-stripped tools regardless of
whether the request actually arrived on the `/insiders` route.

Symptom: `github/github-mcp-server-remote` returns 0 tools with
`_meta.ui` over HTTP `/insiders`, despite the source unconditionally
setting it on `get_me`, `issue_write`, and `create_pull_request`.
VS Code only renders MCP App UIs because of its persistent tool cache
from earlier deploys. Reproducible locally with
`cmd/github-mcp-server http --insiders` plus a vanilla curl tools/list.

Fix: drop the strip from `Build()`. Apply it in `RegisterTools(ctx,…)`
where the per-request context is in scope and the HTTP feature checker
can correctly detect insiders mode (or the remote checker can correctly
read user identity for Statsig flag lookup).

The same root cause affects `github/github-mcp-server-remote` — its
`featureflags.NewComposedFeatureFlagChecker` reads
`requestctx.User(ctx)`, which background context lacks, so the
`remote_mcp_ui_apps` Statsig flag always returned false. The fix here
covers both downstreams since `RegisterTools` is the single entry
point for tool registration.

Stdio mode is unaffected: it uses a closure-captured insiders mode
flag (`createFeatureChecker`) that does not depend on context, and the
per-request strip in `RegisterTools` produces the same outcome.

Verified end-to-end against the deployed remote tool definitions:

  HTTP /insiders     → 3 tools with _meta.ui (was 0)
  HTTP /             → 0 tools with _meta.ui (correct)
  stdio --insiders   → 3 tools with _meta.ui (unchanged)
  stdio              → 0 tools with _meta.ui (correct)

Adds:
  - pkg/http: TestInsidersRoutePreservesUIMeta — pins the regression
  - pkg/inventory: updates the existing strip tests to use the new
    RegisterTools-as-strip-site contract via a captureRegisteredTools
    helper

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* style: gofmt handler_test.go and registry_test.go

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* lint: address revive (context-as-argument) and unused checkFeatureFlag

- Reorder captureRegisteredTools params to put context.Context first
- Remove dead Builder.checkFeatureFlag (was only called by Build's
  former MCP Apps strip, now done in RegisterTools via the Inventory
  receiver's checkFeatureFlag instead)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-08 09:08:50 -07:00
..
2026-02-19 15:17:52 +00:00
2026-02-12 11:04:54 +01:00
2025-11-06 14:48:11 +01:00