Repository navigation
Feature flags are header-only, making flagged tools unreachable on managed/hosted MCP connections #3145
Description
Toolsets can be selected two ways: by URL (https://api.githubcopilot.com/mcp/x/issues, with /readonly as a suffix) or by the X-MCP-Toolsets header. Feature flags have only one — the X-MCP-Features header.
That makes every flagged tool unreachable whenever the MCP connection is operated by someone other than the end user: a hosted IDE, an agent platform, any client that composes the URL on your behalf.
Concrete case: Claude Code on the web. Its GitHub MCP tools are provisioned by the harness — claude mcp list reports no configurable server at all, while mcp__github__* tools are present — so there is no header I can set on that connection. issue_dependency_read / issue_dependency_write are therefore unreachable, even though issue_dependencies is in AllowedFeatureFlags and the tools are implemented and shipped.
The available workaround is to declare a second GitHub MCP server pointing at the same endpoint, with its own PAT, purely to set one header. That's a duplicate connection and an extra long-lived credential to reach a tool that already exists.
Proposed solution
Mirror the existing toolset pattern for flags. Either shape would work:
- path segment —
https://api.githubcopilot.com/mcp/x/issues/f/issue_dependencies - query parameter —
https://api.githubcopilot.com/mcp/x/issues?features=issue_dependencies
Validation would be unchanged. ResolveFeatureFlags already filters user-supplied flags against AllowedFeatureFlags and silently drops unknown ones, so a URL-supplied flag is no more privileged than a header-supplied one — it's the same input arriving through a different channel.
This keeps the gate and its rationale intact. Flagged tools stay out of the default surface, so the fixed tool-schema cost doesn't change; it only widens how a user can opt in.
A less preferred alternative would be graduating issue_dependencies into the default issues toolset now that issue dependencies are GA in the REST API. I'd rather not argue for that — the flag exists specifically to hold down default context cost, and URL-addressability solves the problem without giving that up.
Example prompts or workflows (for tools/toolsets only)
Split frontend/backend repo pairs are the main driver here, since related_owner / related_repo make dependencies cross-repo:
- "What's blocking BE-99?" — where some blockers live in the sibling frontend repo
- "Mark FE-66 as blocked by BE-95" — a cross-repo write
- "List everything the children of issue chore: groundwork for multi-user to server #195 are blocked by, and flag any blocker that's already closed"
- "Before I start BE-100, show me its unresolved blockers"
- "Order these 27 sub-issues into a build sequence using their dependency graph"
Additional context
- Flag is
FeatureFlagIssueDependencies = "issue_dependencies"inpkg/github/feature_flags.go, present in bothAllowedFeatureFlagsandInsidersFeatureFlags. Tools added in Add issue dependency read/write MCP tools #2751. /insidersdoes enable it, but also turns oncsv_output, which changes the response format of everylist_*tool. That's too broad a side effect to accept in order to reach one tool.- Client is Claude Code on the web (Anthropic-hosted). Worth noting that "just use the REST API instead" isn't a workaround in that environment: its GitHub REST proxy silently omits cross-repo entries from response bodies — HTTP 200, no
Linkheader, entries simply absent. I verified this by comparingclient.SubIssue.ListByIssueresults via the MCP server (27 sub-issues, 8 of them cross-repo) against the identical REST endpoint through the proxy (19, same-repo only). So for cross-repo dependency reads specifically, the MCP tools aren't a convenience over REST — they're the only path that returns complete data.
Activity
GitHub native dependency reads are unavailable, not partial
skills: the blocked-by read exists, and a provisioned transport can c…