Skip to content

Commit 8cd03c0

Browse files
timrogersCopilotSamMorrowDrums
authored
Add reaction tools for issues and pull requests (#2732)
* Add reaction tools for issues and pull requests Implement three granular-only tools for adding emoji reactions: - add_issue_reaction: Add reaction to an issue - add_issue_comment_reaction: Add reaction to an issue comment - add_pull_request_review_comment_reaction: Add reaction to a PR review comment All tools are feature-flagged with FeatureFlagEnable set to enable them only when clients request granular toolsets. Tools use go-github's Reactions service and return minimal ID response on success (HTTP 201). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Make reaction tools available in both granular and non-granular modes Remove feature flag gates from reaction tools so they're available to all clients regardless of granular toolset preference. Reaction tools are naturally atomic operations and work equally well in both modes. Updates test expectations to exclude reaction tools from granular-only test assertions, since they're now always available. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Update toolsnaps with aligned reaction tool descriptions Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align reaction tool descriptions with codebase style Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Improve reaction tool responses and wording Return reaction URLs in minimal responses and clarify issue tools apply to pull requests where applicable. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Expose reactions through default comment tools Keep the standalone reaction tools behind granular feature flags to avoid expanding the default tool count. Add optional reaction support to the existing issue comment and pull request comment reply tools, requiring at least one of body or reaction. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Clarify PR review comment IDs for reactions Document that PR review comment reaction inputs require the numeric review comment ID, not the GraphQL review thread node ID returned by review thread APIs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Support issue comment reactions in add_issue_comment Add optional comment_id support so the default add_issue_comment tool can react to a specific issue or pull request comment without exposing a separate default reaction tool. Keep body creation tied to issue_number and require reaction targets to provide either issue_number or comment_id. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Harden combined comment reaction tools Apply reactions before creating comments or replies so retrying a failed combined call cannot duplicate the non-idempotent comment operation. Also reject issue comment IDs without a reaction target to avoid silently ignoring the field. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Group reaction tools with granular registrations Keep standalone reaction tool registrations next to the granular issue and pull request tools they belong with, so the default compound tool sections stay focused. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Align granular reaction tool constructors Rename the standalone reaction tool constructors to match the granular tool naming convention and clarify issue comment reaction IDs for pull request comments. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Require issue number for comment reactions Make issue_number required on the consolidated add_issue_comment tool even when reacting to a specific issue comment, keeping the default tool input shape explicit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address issue comment feedback Return structured GitHub API errors for issue comment creation failures and assert MCP error results in tests. Also reject comment_id with body on the consolidated comment tool to avoid ambiguous comment-plus-comment-reaction requests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Validate issue comment reaction target Use the required issue_number to verify issue comment reaction targets before creating the reaction, and remove overlapping add_issue_comment test coverage. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Validate positive comment IDs Reject non-positive issue and pull request comment IDs in handlers and add the missing schema minimum for pull request review comment IDs. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Sam Morrow <sammorrowdrums@github.com> Co-authored-by: Sam Morrow <info@sam-morrow.com>
1 parent 29634da commit 8cd03c0

16 files changed

Lines changed: 1226 additions & 171 deletions

README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -873,9 +873,11 @@ The following sets of tools are available:
873873

874874
- **add_issue_comment** - Add comment to issue or pull request
875875
- **Required OAuth Scopes**: `repo`
876-
- `body`: Comment content (string, required)
877-
- `issue_number`: Issue number to comment on (number, required)
876+
- `body`: Comment content. Required unless reaction is provided. (string, optional)
877+
- `comment_id`: The numeric ID of the issue or pull request comment to react to. Use this for reactions to comments; omit it to react to the issue or pull request itself. Cannot be combined with body. (number, optional)
878+
- `issue_number`: Issue or pull request number to comment on or react to. (number, required)
878879
- `owner`: Repository owner (string, required)
880+
- `reaction`: Emoji reaction to add. Required unless body is provided. (string, optional)
879881
- `repo`: Repository name (string, required)
880882

881883
- **get_label** - Get a specific label from a repository
@@ -1130,10 +1132,11 @@ The following sets of tools are available:
11301132

11311133
- **add_reply_to_pull_request_comment** - Add reply to pull request comment
11321134
- **Required OAuth Scopes**: `repo`
1133-
- `body`: The text of the reply (string, required)
1134-
- `commentId`: The ID of the comment to reply to (number, required)
1135+
- `body`: The text of the reply. Required unless reaction is provided. (string, optional)
1136+
- `commentId`: The numeric ID of the pull request review comment to reply or react to. Use the number from a #discussion_r... anchor, not the GraphQL thread node ID (PRRT_...). (number, required)
11351137
- `owner`: Repository owner (string, required)
1136-
- `pullNumber`: Pull request number (number, required)
1138+
- `pullNumber`: Pull request number. Required when body is provided. (number, optional)
1139+
- `reaction`: Emoji reaction to add. Required unless body is provided. (string, optional)
11371140
- `repo`: Repository name (string, required)
11381141

11391142
- **create_pull_request** - Open new pull request

docs/feature-flags.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,20 @@ runtime behavior (such as output formatting) won't appear here.
9696

9797
### `issues_granular`
9898

99+
- **add_issue_comment_reaction** - Add Reaction to Issue or Pull Request Comment
100+
- **Required OAuth Scopes**: `repo`
101+
- `comment_id`: The issue or pull request comment ID (number, required)
102+
- `content`: The emoji reaction type (string, required)
103+
- `owner`: Repository owner (username or organization) (string, required)
104+
- `repo`: Repository name (string, required)
105+
106+
- **add_issue_reaction** - Add Reaction to Issue or Pull Request
107+
- **Required OAuth Scopes**: `repo`
108+
- `content`: The emoji reaction type (string, required)
109+
- `issue_number`: The issue number (number, required)
110+
- `owner`: Repository owner (username or organization) (string, required)
111+
- `repo`: Repository name (string, required)
112+
99113
- **add_sub_issue** - Add Sub-Issue
100114
- **Required OAuth Scopes**: `repo`
101115
- `issue_number`: The parent issue number (number, required)
@@ -202,6 +216,13 @@ runtime behavior (such as output formatting) won't appear here.
202216
- `startSide`: The start side of a multi-line comment (optional) (string, optional)
203217
- `subjectType`: The subject type of the comment (string, required)
204218

219+
- **add_pull_request_review_comment_reaction** - Add Pull Request Review Comment Reaction
220+
- **Required OAuth Scopes**: `repo`
221+
- `comment_id`: The numeric pull request review comment ID. Use the number from a #discussion_r... anchor, not the GraphQL thread node ID (PRRT_...). (number, required)
222+
- `content`: The emoji reaction type (string, required)
223+
- `owner`: Repository owner (username or organization) (string, required)
224+
- `repo`: Repository name (string, required)
225+
205226
- **create_pull_request_review** - Create Pull Request Review
206227
- **Required OAuth Scopes**: `repo`
207228
- `body`: The review body text (optional) (string, optional)

pkg/github/__toolsnaps__/add_issue_comment.snap

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,40 @@
22
"annotations": {
33
"title": "Add comment to issue or pull request"
44
},
5-
"description": "Add a comment to a specific issue in a GitHub repository. Use this tool to add comments to pull requests as well (in this case pass pull request number as issue_number), but only if user is not asking specifically to add review comments.",
5+
"description": "Add a comment and/or reaction to a specific issue or issue comment in a GitHub repository. Use this tool with pull requests as well (in this case pass pull request number as issue_number), but only if user is not asking specifically to add or react to review comments. At least one of body or reaction is required.",
66
"inputSchema": {
77
"properties": {
88
"body": {
9-
"description": "Comment content",
9+
"description": "Comment content. Required unless reaction is provided.",
1010
"type": "string"
1111
},
12+
"comment_id": {
13+
"description": "The numeric ID of the issue or pull request comment to react to. Use this for reactions to comments; omit it to react to the issue or pull request itself. Cannot be combined with body.",
14+
"minimum": 1,
15+
"type": "number"
16+
},
1217
"issue_number": {
13-
"description": "Issue number to comment on",
18+
"description": "Issue or pull request number to comment on or react to.",
1419
"type": "number"
1520
},
1621
"owner": {
1722
"description": "Repository owner",
1823
"type": "string"
1924
},
25+
"reaction": {
26+
"description": "Emoji reaction to add. Required unless body is provided.",
27+
"enum": [
28+
"+1",
29+
"-1",
30+
"laugh",
31+
"confused",
32+
"heart",
33+
"hooray",
34+
"rocket",
35+
"eyes"
36+
],
37+
"type": "string"
38+
},
2039
"repo": {
2140
"description": "Repository name",
2241
"type": "string"
@@ -25,8 +44,7 @@
2544
"required": [
2645
"owner",
2746
"repo",
28-
"issue_number",
29-
"body"
47+
"issue_number"
3048
],
3149
"type": "object"
3250
},
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Add Reaction to Issue or Pull Request Comment"
6+
},
7+
"description": "Add a reaction to an issue or pull request comment.",
8+
"inputSchema": {
9+
"properties": {
10+
"comment_id": {
11+
"description": "The issue or pull request comment ID",
12+
"minimum": 1,
13+
"type": "number"
14+
},
15+
"content": {
16+
"description": "The emoji reaction type",
17+
"enum": [
18+
"+1",
19+
"-1",
20+
"laugh",
21+
"confused",
22+
"heart",
23+
"hooray",
24+
"rocket",
25+
"eyes"
26+
],
27+
"type": "string"
28+
},
29+
"owner": {
30+
"description": "Repository owner (username or organization)",
31+
"type": "string"
32+
},
33+
"repo": {
34+
"description": "Repository name",
35+
"type": "string"
36+
}
37+
},
38+
"required": [
39+
"owner",
40+
"repo",
41+
"comment_id",
42+
"content"
43+
],
44+
"type": "object"
45+
},
46+
"name": "add_issue_comment_reaction"
47+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Add Reaction to Issue or Pull Request"
6+
},
7+
"description": "Add a reaction to an issue or pull request.",
8+
"inputSchema": {
9+
"properties": {
10+
"content": {
11+
"description": "The emoji reaction type",
12+
"enum": [
13+
"+1",
14+
"-1",
15+
"laugh",
16+
"confused",
17+
"heart",
18+
"hooray",
19+
"rocket",
20+
"eyes"
21+
],
22+
"type": "string"
23+
},
24+
"issue_number": {
25+
"description": "The issue number",
26+
"minimum": 1,
27+
"type": "number"
28+
},
29+
"owner": {
30+
"description": "Repository owner (username or organization)",
31+
"type": "string"
32+
},
33+
"repo": {
34+
"description": "Repository name",
35+
"type": "string"
36+
}
37+
},
38+
"required": [
39+
"owner",
40+
"repo",
41+
"issue_number",
42+
"content"
43+
],
44+
"type": "object"
45+
},
46+
"name": "add_issue_reaction"
47+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"annotations": {
3+
"destructiveHint": false,
4+
"openWorldHint": true,
5+
"title": "Add Pull Request Review Comment Reaction"
6+
},
7+
"description": "Add a reaction to a pull request review comment.",
8+
"inputSchema": {
9+
"properties": {
10+
"comment_id": {
11+
"description": "The numeric pull request review comment ID. Use the number from a #discussion_r... anchor, not the GraphQL thread node ID (PRRT_...).",
12+
"minimum": 1,
13+
"type": "number"
14+
},
15+
"content": {
16+
"description": "The emoji reaction type",
17+
"enum": [
18+
"+1",
19+
"-1",
20+
"laugh",
21+
"confused",
22+
"heart",
23+
"hooray",
24+
"rocket",
25+
"eyes"
26+
],
27+
"type": "string"
28+
},
29+
"owner": {
30+
"description": "Repository owner (username or organization)",
31+
"type": "string"
32+
},
33+
"repo": {
34+
"description": "Repository name",
35+
"type": "string"
36+
}
37+
},
38+
"required": [
39+
"owner",
40+
"repo",
41+
"comment_id",
42+
"content"
43+
],
44+
"type": "object"
45+
},
46+
"name": "add_pull_request_review_comment_reaction"
47+
}

pkg/github/__toolsnaps__/add_reply_to_pull_request_comment.snap

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,40 @@
22
"annotations": {
33
"title": "Add reply to pull request comment"
44
},
5-
"description": "Add a reply to an existing pull request comment. This creates a new comment that is linked as a reply to the specified comment.",
5+
"description": "Add a reply and/or reaction to an existing pull request comment. This can create a new comment linked as a reply to the specified comment, add an emoji reaction to the specified comment, or do both. At least one of body or reaction is required.",
66
"inputSchema": {
77
"properties": {
88
"body": {
9-
"description": "The text of the reply",
9+
"description": "The text of the reply. Required unless reaction is provided.",
1010
"type": "string"
1111
},
1212
"commentId": {
13-
"description": "The ID of the comment to reply to",
13+
"description": "The numeric ID of the pull request review comment to reply or react to. Use the number from a #discussion_r... anchor, not the GraphQL thread node ID (PRRT_...).",
14+
"minimum": 1,
1415
"type": "number"
1516
},
1617
"owner": {
1718
"description": "Repository owner",
1819
"type": "string"
1920
},
2021
"pullNumber": {
21-
"description": "Pull request number",
22+
"description": "Pull request number. Required when body is provided.",
2223
"type": "number"
2324
},
25+
"reaction": {
26+
"description": "Emoji reaction to add. Required unless body is provided.",
27+
"enum": [
28+
"+1",
29+
"-1",
30+
"laugh",
31+
"confused",
32+
"heart",
33+
"hooray",
34+
"rocket",
35+
"eyes"
36+
],
37+
"type": "string"
38+
},
2439
"repo": {
2540
"description": "Repository name",
2641
"type": "string"
@@ -29,9 +44,7 @@
2944
"required": [
3045
"owner",
3146
"repo",
32-
"pullNumber",
33-
"commentId",
34-
"body"
47+
"commentId"
3548
],
3649
"type": "object"
3750
},

0 commit comments

Comments
 (0)