Skip to content

Commit 19e2515

Browse files
Always enable MCP Apps UI; remove remote_mcp_ui_apps flag gate
The remote_mcp_ui_apps flag is fully rolled out on the hosted server, but the OSS server still defaulted it off. Make MCP Apps unconditional: - _meta.ui is always emitted, stripped only when the client explicitly does not advertise the io.modelcontextprotocol/ui capability - ui_get is always registered - write tools defer to MCP App forms by default (still opt-out via mcp_apps_disable_form_deferral) - remove MCPAppsFeatureFlag and its AllowedFeatureFlags/InsidersFeatureFlags entries - update tests and regenerate docs Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
1 parent 85598ba commit 19e2515

21 files changed

Lines changed: 97 additions & 420 deletions

‎README.md‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,7 @@ The following sets of tools are available:
704704
<summary><picture><source media="(prefers-color-scheme: dark)" srcset="pkg/octicons/icons/person-dark.png"><source media="(prefers-color-scheme: light)" srcset="pkg/octicons/icons/person-light.png"><img src="pkg/octicons/icons/person-light.png" width="20" height="20" alt="person"></picture> Context</summary>
705705

706706
- **get_me** - Get my user profile
707+
- **MCP App UI**: `ui://github-mcp-server/get-me`
707708
- No parameters required
708709

709710
- **get_team_members** - Get team members
@@ -715,6 +716,12 @@ The following sets of tools are available:
715716
- **OAuth Challenge Scopes**: `read:org`
716717
- `user`: Username to get teams for. If not provided, uses the authenticated user. (string, optional)
717718

719+
- **ui_get** - Get UI data
720+
- **OAuth Challenge Scopes**: `repo`, `read:org`
721+
- `method`: The type of data to fetch (string, required)
722+
- `owner`: Repository owner (required for all methods) (string, required)
723+
- `repo`: Repository name (required for labels, assignees, milestones, branches, issue fields, reviewers) (string, optional)
724+
718725
</details>
719726

720727
<details>
@@ -983,6 +990,7 @@ The following sets of tools are available:
983990

984991
- **issue_write** - Create or update issue/pull request
985992
- **OAuth Challenge Scopes**: `repo`
993+
- **MCP App UI**: `ui://github-mcp-server/issue-write`
986994
- `assignees`: Usernames to assign to this issue (string[], optional)
987995
- `body`: Issue body content (string, optional)
988996
- `duplicate_of`: Issue number that this issue is a duplicate of. Required when state_reason is 'duplicate'. (number, optional)
@@ -1238,6 +1246,7 @@ The following sets of tools are available:
12381246

12391247
- **create_pull_request** - Open new pull request
12401248
- **OAuth Challenge Scopes**: `repo`
1249+
- **MCP App UI**: `ui://github-mcp-server/pr-write`
12411250
- `base`: Branch to merge into (string, required)
12421251
- `body`: PR description (string, optional)
12431252
- `draft`: Create as draft PR (boolean, optional)
@@ -1316,6 +1325,7 @@ The following sets of tools are available:
13161325

13171326
- **update_pull_request** - Edit pull request
13181327
- **OAuth Challenge Scopes**: `repo`
1328+
- **MCP App UI**: `ui://github-mcp-server/pr-edit`
13191329
- `base`: New base branch name (string, optional)
13201330
- `body`: New description (string, optional)
13211331
- `draft`: Mark pull request as draft (true) or ready for review (false) (boolean, optional)

‎cmd/github-mcp-server/generate_docs.go‎

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,7 @@ func writeToolDoc(buf *strings.Builder, tool inventory.ServerTool) {
222222
fmt.Fprintf(buf, " - **OAuth Challenge Scopes**: `%s`\n", strings.Join(scopes, "`, `"))
223223
}
224224

225-
// MCP App UI metadata (only rendered when the remote_mcp_ui_apps flag
226-
// applied to the inventory; for the no-flags README this section is
227-
// stripped by inventory.ToolsForRegistration before rendering).
225+
// MCP App UI metadata.
228226
if ui, ok := tool.Tool.Meta["ui"].(map[string]any); ok {
229227
if uri, ok := ui["resourceUri"].(string); ok && uri != "" {
230228
fmt.Fprintf(buf, " - **MCP App UI**: `%s`\n", uri)

‎docs/feature-flags.md‎

Lines changed: 0 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -86,70 +86,6 @@ as output formatting) won't appear here.
8686

8787
<!-- START AUTOMATED FEATURE FLAG TOOLS -->
8888

89-
### `remote_mcp_ui_apps`
90-
91-
- **create_pull_request** - Open new pull request
92-
- **OAuth Challenge Scopes**: `repo`
93-
- **MCP App UI**: `ui://github-mcp-server/pr-write`
94-
- `base`: Branch to merge into (string, required)
95-
- `body`: PR description (string, optional)
96-
- `draft`: Create as draft PR (boolean, optional)
97-
- `head`: Branch containing changes (string, required)
98-
- `maintainer_can_modify`: Allow maintainer edits (boolean, optional)
99-
- `owner`: Repository owner (string, required)
100-
- `repo`: Repository name (string, required)
101-
- `reviewers`: GitHub usernames or ORG/team-slug team reviewers to request reviews from (string[], optional)
102-
- `title`: PR title (string, required)
103-
104-
- **get_me** - Get my user profile
105-
- **MCP App UI**: `ui://github-mcp-server/get-me`
106-
- No parameters required
107-
108-
- **issue_write** - Create or update issue/pull request
109-
- **OAuth Challenge Scopes**: `repo`
110-
- **MCP App UI**: `ui://github-mcp-server/issue-write`
111-
- `assignees`: Usernames to assign to this issue (string[], optional)
112-
- `body`: Issue body content (string, optional)
113-
- `duplicate_of`: Issue number that this issue is a duplicate of. Required when state_reason is 'duplicate'. (number, optional)
114-
- `issue_fields`: Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', or 'delete: true'. (object[], optional)
115-
- `issue_number`: Issue number to update (number, optional)
116-
- `labels`: Labels to apply to this issue (string[], optional)
117-
- `method`: Write operation to perform on a single issue.
118-
Options are:
119-
- 'create' - creates a new issue.
120-
- 'update' - updates an existing issue.
121-
(string, required)
122-
- `milestone`: Milestone number (number, optional)
123-
- `owner`: Repository owner (string, required)
124-
- `parent_issue_number`: Issue number of the parent issue. Only used when method is 'create' and cannot be combined with issue_fields. The new issue is created and attached to this parent in the same operation. (number, optional)
125-
- `parent_owner`: Repository owner of the parent issue. Must be provided with parent_repo. Omit both to use owner and repo. Only used when method is 'create' and parent_issue_number is provided. (string, optional)
126-
- `parent_repo`: Repository name of the parent issue. Must be provided with parent_owner. Omit both to use owner and repo. Only used when method is 'create' and parent_issue_number is provided. (string, optional)
127-
- `repo`: Repository name (string, required)
128-
- `state`: New state (string, optional)
129-
- `state_reason`: Reason for the state change. Ignored unless state is changed. (string, optional)
130-
- `title`: Issue title (string, optional)
131-
- `type`: Type of this issue. For updates, pass null to remove the current type. Only use if issue types are enabled for this repository. Use list_issue_types to get valid type values for this repository or its owner organization. If the repository doesn't support issue types, omit this parameter. (string | null, optional)
132-
133-
- **ui_get** - Get UI data
134-
- **OAuth Challenge Scopes**: `repo`, `read:org`
135-
- `method`: The type of data to fetch (string, required)
136-
- `owner`: Repository owner (required for all methods) (string, required)
137-
- `repo`: Repository name (required for labels, assignees, milestones, branches, issue fields, reviewers) (string, optional)
138-
139-
- **update_pull_request** - Edit pull request
140-
- **OAuth Challenge Scopes**: `repo`
141-
- **MCP App UI**: `ui://github-mcp-server/pr-edit`
142-
- `base`: New base branch name (string, optional)
143-
- `body`: New description (string, optional)
144-
- `draft`: Mark pull request as draft (true) or ready for review (false) (boolean, optional)
145-
- `maintainer_can_modify`: Allow maintainer edits (boolean, optional)
146-
- `owner`: Repository owner (string, required)
147-
- `pullNumber`: Pull request number to update (number, required)
148-
- `repo`: Repository name (string, required)
149-
- `reviewers`: GitHub usernames or ORG/team-slug team reviewers to request reviews from (string[], optional)
150-
- `state`: New state (string, optional)
151-
- `title`: New title (string, optional)
152-
15389
### `issues_granular`
15490

15591
- **add_issue_comment_reaction** - Add Reaction to Issue or Pull Request Comment

‎docs/insiders-features.md‎

Lines changed: 0 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -26,70 +26,6 @@ The list below is generated from the Go source. It covers tool **inventory and s
2626

2727
<!-- START AUTOMATED INSIDERS TOOLS -->
2828

29-
### `remote_mcp_ui_apps`
30-
31-
- **create_pull_request** - Open new pull request
32-
- **OAuth Challenge Scopes**: `repo`
33-
- **MCP App UI**: `ui://github-mcp-server/pr-write`
34-
- `base`: Branch to merge into (string, required)
35-
- `body`: PR description (string, optional)
36-
- `draft`: Create as draft PR (boolean, optional)
37-
- `head`: Branch containing changes (string, required)
38-
- `maintainer_can_modify`: Allow maintainer edits (boolean, optional)
39-
- `owner`: Repository owner (string, required)
40-
- `repo`: Repository name (string, required)
41-
- `reviewers`: GitHub usernames or ORG/team-slug team reviewers to request reviews from (string[], optional)
42-
- `title`: PR title (string, required)
43-
44-
- **get_me** - Get my user profile
45-
- **MCP App UI**: `ui://github-mcp-server/get-me`
46-
- No parameters required
47-
48-
- **issue_write** - Create or update issue/pull request
49-
- **OAuth Challenge Scopes**: `repo`
50-
- **MCP App UI**: `ui://github-mcp-server/issue-write`
51-
- `assignees`: Usernames to assign to this issue (string[], optional)
52-
- `body`: Issue body content (string, optional)
53-
- `duplicate_of`: Issue number that this issue is a duplicate of. Required when state_reason is 'duplicate'. (number, optional)
54-
- `issue_fields`: Issue field values to set or clear. Each item requires 'field_name' and exactly one of 'value', 'field_option_name', or 'delete: true'. (object[], optional)
55-
- `issue_number`: Issue number to update (number, optional)
56-
- `labels`: Labels to apply to this issue (string[], optional)
57-
- `method`: Write operation to perform on a single issue.
58-
Options are:
59-
- 'create' - creates a new issue.
60-
- 'update' - updates an existing issue.
61-
(string, required)
62-
- `milestone`: Milestone number (number, optional)
63-
- `owner`: Repository owner (string, required)
64-
- `parent_issue_number`: Issue number of the parent issue. Only used when method is 'create' and cannot be combined with issue_fields. The new issue is created and attached to this parent in the same operation. (number, optional)
65-
- `parent_owner`: Repository owner of the parent issue. Must be provided with parent_repo. Omit both to use owner and repo. Only used when method is 'create' and parent_issue_number is provided. (string, optional)
66-
- `parent_repo`: Repository name of the parent issue. Must be provided with parent_owner. Omit both to use owner and repo. Only used when method is 'create' and parent_issue_number is provided. (string, optional)
67-
- `repo`: Repository name (string, required)
68-
- `state`: New state (string, optional)
69-
- `state_reason`: Reason for the state change. Ignored unless state is changed. (string, optional)
70-
- `title`: Issue title (string, optional)
71-
- `type`: Type of this issue. For updates, pass null to remove the current type. Only use if issue types are enabled for this repository. Use list_issue_types to get valid type values for this repository or its owner organization. If the repository doesn't support issue types, omit this parameter. (string | null, optional)
72-
73-
- **ui_get** - Get UI data
74-
- **OAuth Challenge Scopes**: `repo`, `read:org`
75-
- `method`: The type of data to fetch (string, required)
76-
- `owner`: Repository owner (required for all methods) (string, required)
77-
- `repo`: Repository name (required for labels, assignees, milestones, branches, issue fields, reviewers) (string, optional)
78-
79-
- **update_pull_request** - Edit pull request
80-
- **OAuth Challenge Scopes**: `repo`
81-
- **MCP App UI**: `ui://github-mcp-server/pr-edit`
82-
- `base`: New base branch name (string, optional)
83-
- `body`: New description (string, optional)
84-
- `draft`: Mark pull request as draft (true) or ready for review (false) (boolean, optional)
85-
- `maintainer_can_modify`: Allow maintainer edits (boolean, optional)
86-
- `owner`: Repository owner (string, required)
87-
- `pullNumber`: Pull request number to update (number, required)
88-
- `repo`: Repository name (string, required)
89-
- `reviewers`: GitHub usernames or ORG/team-slug team reviewers to request reviews from (string[], optional)
90-
- `state`: New state (string, optional)
91-
- `title`: New title (string, optional)
92-
9329
### `file_blame`
9430

9531
- **get_file_blame** - Get file blame information
@@ -139,31 +75,6 @@ The list below is generated from the Go source. It covers tool **inventory and s
13975

14076
---
14177

142-
## MCP Apps
143-
144-
[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 using MCP Apps.
145-
146-
This means you can interact with GitHub visually: fill out forms to create issues, see user profiles with avatars, open pull requests — all without leaving your agent chat.
147-
148-
### Supported tools
149-
150-
The following tools have MCP Apps UIs:
151-
152-
| Tool | Description |
153-
|------|-------------|
154-
| `get_me` | Displays your GitHub user profile with avatar, bio, and stats in a rich card |
155-
| `issue_write` | Opens an interactive form to create or update issues |
156-
| `create_pull_request` | Provides a full PR creation form to create a pull request (or a draft pull request) |
157-
158-
### Client requirements
159-
160-
MCP Apps requires a host that supports the [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps). Currently tested and working with:
161-
162-
- **VS Code Insiders** — enable via the `chat.mcp.apps.enabled` setting
163-
- **Visual Studio Code** — enable via the `chat.mcp.apps.enabled` setting
164-
165-
---
166-
16778
## CSV output for list tools
16879

16980
CSV output mode returns supported list tool responses as CSV instead of JSON. This is intended to reduce response context for agents when scanning or summarising lists of GitHub data.

‎docs/server-configuration.md‎

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ As an intentional exception, content authored by trusted bot accounts (currently
345345

346346
**Best for:** Users who want early access to experimental features and new tools before they reach general availability.
347347

348-
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.
348+
Insiders Mode unlocks experimental features, such as [CSV output for list tools](./insiders-features.md#csv-output-for-list-tools). 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.
349349

350350
<table>
351351
<tr><th>Remote Server</th><th>Local Server</th></tr>
@@ -402,18 +402,18 @@ See [Insiders Features](./insiders-features.md) for a full list of what's availa
402402

403403
[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.
404404

405-
MCP Apps is enabled by [Insiders Mode](#insiders-mode), or independently via the `remote_mcp_ui_apps` feature flag.
405+
MCP Apps is enabled by default. Tools with MCP Apps UIs advertise them via `_meta.ui` to clients that support the [MCP Apps extension](https://modelcontextprotocol.io/docs/extensions/apps); the metadata is omitted for clients that do not advertise the `io.modelcontextprotocol/ui` capability.
406406

407407
To keep MCP App result views enabled while making write tools execute directly
408-
instead of first opening an interactive form, also enable the
409-
`mcp_apps_disable_form_deferral` feature flag. For the remote server, send both
410-
flags in the request header:
408+
instead of first opening an interactive form, enable the
409+
`mcp_apps_disable_form_deferral` feature flag. For the remote server, send the
410+
flag in the request header:
411411

412412
```http
413-
X-MCP-Features: remote_mcp_ui_apps,mcp_apps_disable_form_deferral
413+
X-MCP-Features: mcp_apps_disable_form_deferral
414414
```
415415

416-
For the local server, pass both flags to `--features`.
416+
For the local server, pass it to `--features`.
417417

418418
**Supported tools:**
419419

@@ -422,47 +422,10 @@ For the local server, pass both flags to `--features`.
422422
| `get_me` | Displays your GitHub user profile with avatar, bio, and stats in a rich card |
423423
| `issue_write` | Opens an interactive form to create or update issues |
424424
| `create_pull_request` | Provides a full PR creation form to create a pull request (or a draft pull request) |
425+
| `update_pull_request` | Opens an interactive form to edit a pull request |
425426

426427
**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).
427428

428-
<table>
429-
<tr><th>Remote Server</th><th>Local Server</th></tr>
430-
<tr valign="top">
431-
<td>
432-
433-
```json
434-
{
435-
"type": "http",
436-
"url": "https://api.githubcopilot.com/mcp/",
437-
"headers": {
438-
"X-MCP-Features": "remote_mcp_ui_apps"
439-
}
440-
}
441-
```
442-
443-
</td>
444-
<td>
445-
446-
```json
447-
{
448-
"type": "stdio",
449-
"command": "go",
450-
"args": [
451-
"run",
452-
"./cmd/github-mcp-server",
453-
"stdio",
454-
"--features=remote_mcp_ui_apps"
455-
],
456-
"env": {
457-
"GITHUB_PERSONAL_ACCESS_TOKEN": "${input:github_token}"
458-
}
459-
}
460-
```
461-
462-
</td>
463-
</tr>
464-
</table>
465-
466429
---
467430

468431
### Scope Filtering

‎pkg/github/feature_flags.go‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ import (
66
"github.com/github/github-mcp-server/pkg/inventory"
77
)
88

9-
// MCPAppsFeatureFlag is the feature flag name for MCP Apps (interactive UI forms).
10-
const MCPAppsFeatureFlag = "remote_mcp_ui_apps"
11-
129
// MCPAppsDisableFormDeferralFeatureFlag disables handing write-tool calls off
1310
// to MCP App forms while preserving MCP Apps UI metadata and result views.
1411
const MCPAppsDisableFormDeferralFeatureFlag = "mcp_apps_disable_form_deferral"
@@ -47,7 +44,6 @@ const FeatureFlagThreadResolutionReason = "thread_resolution_reason"
4744
// Only flags in this list are accepted; unknown flags are silently ignored.
4845
// This is the single source of truth for which flags are user-controllable.
4946
var AllowedFeatureFlags = []string{
50-
MCPAppsFeatureFlag,
5147
MCPAppsDisableFormDeferralFeatureFlag,
5248
FeatureFlagCSVOutput,
5349
FeatureFlagIFCLabels,
@@ -64,7 +60,6 @@ var AllowedFeatureFlags = []string{
6460
// This is the single source of truth for what "insiders" means in terms of
6561
// feature flag expansion.
6662
var InsidersFeatureFlags = []string{
67-
MCPAppsFeatureFlag,
6863
FeatureFlagCSVOutput,
6964
FeatureFlagFileBlame,
7065
FeatureFlagIssueDependencies,

‎pkg/github/feature_flags_benchmark_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ func featureBenchmarkDistributions() []featureBenchmarkDistribution {
146146
{
147147
name: "mixed",
148148
enabled: map[string]bool{
149-
MCPAppsFeatureFlag: true,
149+
FeatureFlagCSVOutput: true,
150150
FeatureFlagFileBlame: true,
151151
FeatureFlagIssuesGranular: true,
152152
FeatureFlagIssueDependencies: true,

‎pkg/github/feature_flags_test.go‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,12 @@ func TestResolveFeatureFlags(t *testing.T) {
149149
name: "no features, no insiders",
150150
enabledFeatures: nil,
151151
expectedFlags: nil,
152-
unexpectedFlags: []string{MCPAppsFeatureFlag},
152+
unexpectedFlags: []string{FeatureFlagCSVOutput},
153153
},
154154
{
155155
name: "explicit feature enabled",
156-
enabledFeatures: []string{MCPAppsFeatureFlag},
157-
expectedFlags: []string{MCPAppsFeatureFlag},
156+
enabledFeatures: []string{FeatureFlagCSVOutput},
157+
expectedFlags: []string{FeatureFlagCSVOutput},
158158
},
159159
{
160160
name: "MCP Apps form deferral can be disabled directly",
@@ -191,8 +191,8 @@ func TestResolveFeatureFlags(t *testing.T) {
191191
},
192192
{
193193
name: "mix of known and unknown flags",
194-
enabledFeatures: []string{MCPAppsFeatureFlag, "unknown_flag"},
195-
expectedFlags: []string{MCPAppsFeatureFlag},
194+
enabledFeatures: []string{FeatureFlagCSVOutput, "unknown_flag"},
195+
expectedFlags: []string{FeatureFlagCSVOutput},
196196
unexpectedFlags: []string{"unknown_flag"},
197197
},
198198
{
@@ -214,7 +214,7 @@ func TestResolveFeatureFlags(t *testing.T) {
214214
},
215215
{
216216
name: "explicit plus insiders deduplicates",
217-
enabledFeatures: []string{MCPAppsFeatureFlag},
217+
enabledFeatures: []string{FeatureFlagCSVOutput},
218218
insidersMode: true,
219219
expectedFlags: InsidersFeatureFlags,
220220
},

‎pkg/github/issues_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2216,7 +2216,7 @@ func Test_IssueWrite_MCPAppsFeature_UIGate(t *testing.T) {
22162216
deps := BaseDeps{
22172217
Client: client,
22182218
GQLClient: githubv4.NewClient(nil),
2219-
featureChecker: featureCheckerFor(MCPAppsFeatureFlag),
2219+
featureChecker: featureCheckerFor(),
22202220
}
22212221
handler := serverTool.Handler(deps)
22222222

0 commit comments

Comments
 (0)