Skip to content

Commit c927390

Browse files
committed
refactor issue creation UI
1 parent 157ba4d commit c927390

9 files changed

Lines changed: 177 additions & 117 deletions

File tree

pkg/github/__toolsnaps__/issue_write.snap

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
{
2+
"_meta": {
3+
"ui": {
4+
"resourceUri": "ui://github-mcp-server/issue-write",
5+
"visibility": [
6+
"model",
7+
"app"
8+
]
9+
}
10+
},
211
"annotations": {
312
"title": "Create or update issue."
413
},
5-
"description": "Create a new or update an existing issue in a GitHub repository.",
14+
"description": "Create a new or update an existing issue in a GitHub repository.\n\nWhen show_ui is true, an interactive form is displayed for the user to fill in issue details. Use show_ui when:\n- Creating a new issue and you want user input on the details\n- The user hasn't specified all required fields (title, body, etc.)\n- Interactive feedback would be valuable\n\nWhen show_ui is false or omitted, the issue is created/updated directly with the provided parameters.",
615
"inputSchema": {
716
"properties": {
817
"assignees": {
@@ -51,6 +60,10 @@
5160
"description": "Repository name",
5261
"type": "string"
5362
},
63+
"show_ui": {
64+
"description": "If true, show an interactive form for the user to fill in issue details. If false or omitted, create/update the issue directly with the provided parameters. Use show_ui when you want user input or when not all fields are specified.",
65+
"type": "boolean"
66+
},
5467
"state": {
5568
"description": "New state",
5669
"enum": [

pkg/github/issues.go

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1152,19 +1152,40 @@ func SearchIssues(t translations.TranslationHelperFunc) inventory.ServerTool {
11521152
}
11531153

11541154
// IssueWrite creates a tool to create a new or update an existing issue in a GitHub repository.
1155+
// IssueWriteUIResourceURI is the URI for the issue_write tool's MCP App UI resource.
1156+
const IssueWriteUIResourceURI = "ui://github-mcp-server/issue-write"
1157+
11551158
func IssueWrite(t translations.TranslationHelperFunc) inventory.ServerTool {
11561159
return NewTool(
11571160
ToolsetMetadataIssues,
11581161
mcp.Tool{
1159-
Name: "issue_write",
1160-
Description: t("TOOL_ISSUE_WRITE_DESCRIPTION", "Create a new or update an existing issue in a GitHub repository."),
1162+
Name: "issue_write",
1163+
Description: t("TOOL_ISSUE_WRITE_DESCRIPTION", `Create a new or update an existing issue in a GitHub repository.
1164+
1165+
When show_ui is true, an interactive form is displayed for the user to fill in issue details. Use show_ui when:
1166+
- Creating a new issue and you want user input on the details
1167+
- The user hasn't specified all required fields (title, body, etc.)
1168+
- Interactive feedback would be valuable
1169+
1170+
When show_ui is false or omitted, the issue is created/updated directly with the provided parameters.`),
11611171
Annotations: &mcp.ToolAnnotations{
11621172
Title: t("TOOL_ISSUE_WRITE_USER_TITLE", "Create or update issue."),
11631173
ReadOnlyHint: false,
11641174
},
1175+
// MCP Apps UI metadata - links this tool to its UI resource
1176+
Meta: mcp.Meta{
1177+
"ui": map[string]any{
1178+
"resourceUri": IssueWriteUIResourceURI,
1179+
"visibility": []string{"model", "app"},
1180+
},
1181+
},
11651182
InputSchema: &jsonschema.Schema{
11661183
Type: "object",
11671184
Properties: map[string]*jsonschema.Schema{
1185+
"show_ui": {
1186+
Type: "boolean",
1187+
Description: "If true, show an interactive form for the user to fill in issue details. If false or omitted, create/update the issue directly with the provided parameters. Use show_ui when you want user input or when not all fields are specified.",
1188+
},
11681189
"method": {
11691190
Type: "string",
11701191
Description: `Write operation to perform on a single issue.
@@ -1249,6 +1270,26 @@ Options are:
12491270
if err != nil {
12501271
return utils.NewToolResultError(err.Error()), nil, nil
12511272
}
1273+
1274+
// Check if UI mode is requested
1275+
showUI, err := OptionalParam[bool](args, "show_ui")
1276+
if err != nil {
1277+
return utils.NewToolResultError(err.Error()), nil, nil
1278+
}
1279+
1280+
// If show_ui is true, return a message indicating the UI should be shown
1281+
// The host will detect the UI metadata and display the form
1282+
if showUI {
1283+
if method == "update" {
1284+
issueNumber, numErr := RequiredInt(args, "issue_number")
1285+
if numErr != nil {
1286+
return utils.NewToolResultError("issue_number is required for update method"), nil, nil
1287+
}
1288+
return utils.NewToolResultText(fmt.Sprintf("Ready to update issue #%d in %s/%s. The interactive form will be displayed.", issueNumber, owner, repo)), nil, nil
1289+
}
1290+
return utils.NewToolResultText(fmt.Sprintf("Ready to create an issue in %s/%s. The interactive form will be displayed.", owner, repo)), nil, nil
1291+
}
1292+
12521293
title, err := OptionalParam[string](args, "title")
12531294
if err != nil {
12541295
return utils.NewToolResultError(err.Error()), nil, nil

pkg/github/issues_ui.go

Lines changed: 0 additions & 103 deletions
This file was deleted.

pkg/github/tools.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,6 @@ func AllTools(t translations.TranslationHelperFunc) []inventory.ServerTool {
194194
ListAssignees(t),
195195
ListMilestones(t),
196196
IssueWrite(t),
197-
CreateIssueUI(t),
198197
AddIssueComment(t),
199198
AssignCopilotToIssue(t),
200199
SubIssueWrite(t),

pkg/github/ui_resources.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,11 @@ func RegisterUIResources(s *mcp.Server) {
4848
&mcp.Resource{
4949
URI: IssueWriteUIResourceURI,
5050
Name: "issue_write_ui",
51-
Description: "MCP App UI for creating GitHub issues",
51+
Description: "MCP App UI for creating and updating GitHub issues",
5252
MIMEType: "text/html",
5353
},
5454
func(_ context.Context, _ *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
55-
html := MustGetUIAsset("create-issue.html")
55+
html := MustGetUIAsset("issue-write.html")
5656
return &mcp.ReadResourceResult{
5757
Contents: []*mcp.ResourceContents{
5858
{

script/build-ui

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ npm run build
1717
echo "Organizing output..."
1818
mkdir -p dist
1919
mv dist/src/apps/get-me/index.html dist/get-me.html 2>/dev/null || true
20-
mv dist/src/apps/create-issue/index.html dist/create-issue.html 2>/dev/null || true
20+
mv dist/src/apps/issue-write/index.html dist/issue-write.html 2>/dev/null || true
2121
rm -rf dist/src 2>/dev/null || true
2222

2323
# Copy to Go embed location

ui/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
"type": "module",
66
"description": "MCP App UIs for github-mcp-server using Primer React",
77
"scripts": {
8-
"build": "npm run build:get-me && npm run build:create-issue",
8+
"build": "npm run build:get-me && npm run build:issue-write",
99
"build:get-me": "APP=get-me vite build",
10-
"build:create-issue": "APP=create-issue vite build",
10+
"build:issue-write": "APP=issue-write vite build",
1111
"dev": "npm run build",
1212
"typecheck": "tsc --noEmit",
1313
"clean": "rm -rf dist"

0 commit comments

Comments
 (0)