Summary
When the server is started with --read-only and MCP Apps are enabled, write-tool UI form resources (issue_write_ui, pr_write_ui) are still registered and served, even though the underlying write tools (create_issue, update_issue, create_pull_request, etc.) are filtered out of the inventory.
Where
pkg/github/ui_resources.go — RegisterUIResources unconditionally calls s.AddResource for all three UI forms.
internal/ghmcp/server.go:182 — the only gating is on MCPAppsFeatureFlag + UIAssetsAvailable(); no read-only check.
mcpAppsEnabled, _ := featureChecker(context.Background(), github.MCPAppsFeatureFlag)
if mcpAppsEnabled && github.UIAssetsAvailable() {
github.RegisterUIResources(ghServer)
}
Why it matters
- Read-only mode should not expose UI affordances for mutating actions. A client that lists resources will see
issue_write_ui and pr_write_ui and may surface them, even though calling the backing tool is impossible.
- The mismatch is confusing — read-only is supposed to be the complete answer to "hide all write surface".
- Same concern applies regardless of feature-flag wiring: any read-only filter that excludes a write tool should also exclude its companion UI resource.
Suggested fix
Two options:
- Annotate each UI resource with the tool it backs and skip registration when that tool would be filtered out (parallel to the read-only / feature-flag pipeline on the tool side). Cleanest, future-proof.
- Pass
readOnly into RegisterUIResources and short-circuit the two write forms. Quick; doesn't generalise.
Likely also worth: treating these UI resources as part of the inventory (ServerResource with a ToolName or ReadOnlyHint field) so they flow through the same filter pipeline as tools, rather than living in a sibling registration path.
Related
Summary
When the server is started with
--read-onlyand MCP Apps are enabled, write-tool UI form resources (issue_write_ui,pr_write_ui) are still registered and served, even though the underlying write tools (create_issue,update_issue,create_pull_request, etc.) are filtered out of the inventory.Where
pkg/github/ui_resources.go—RegisterUIResourcesunconditionally callss.AddResourcefor all three UI forms.internal/ghmcp/server.go:182— the only gating is onMCPAppsFeatureFlag+UIAssetsAvailable(); no read-only check.Why it matters
issue_write_uiandpr_write_uiand may surface them, even though calling the backing tool is impossible.Suggested fix
Two options:
readOnlyintoRegisterUIResourcesand short-circuit the two write forms. Quick; doesn't generalise.Likely also worth: treating these UI resources as part of the inventory (
ServerResourcewith aToolNameorReadOnlyHintfield) so they flow through the same filter pipeline as tools, rather than living in a sibling registration path.Related
internal/ghmcp/server.go); the gap is specifically the read-only interaction.