feat: add emoji reaction tools for MRs, issues and comments#412
feat: add emoji reaction tools for MRs, issues and comments#412Killusions wants to merge 1 commit intozereight:mainfrom
Conversation
2b9717d to
db6eb60
Compare
|
Forgot to add tools for listing reactions, added. |
|
@zereight What do you think of this? |
There was a problem hiding this comment.
Pull request overview
Adds first-class emoji reaction tooling to the GitLab MCP server so agents can add/list/remove reactions on merge requests, issues, and work items (including comment/note reactions), aligning with the existing toolset + schema-driven approach.
Changes:
- Introduces Zod schemas for emoji reaction operations across REST (MRs/issues) and GraphQL (work items).
- Registers new emoji reaction tools in the tool registry/toolsets and marks delete variants as destructive.
- Implements REST + GraphQL handlers in
index.tsand updates tests/tool counts + schema test coverage.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
tools/registry.ts |
Registers emoji reaction tools, adds them to toolsets, and flags delete variants as destructive. |
index.ts |
Implements REST/GraphQL helpers and handleToolCall cases for emoji reaction list/create/delete. |
schemas.ts |
Adds Zod schemas for MR/issue (REST) and work item (GraphQL) emoji reactions. |
test/test-toolset-filtering.ts |
Updates expected tool counts and extends the issues toolset filtering assertions. |
test/test-token-optimizations.ts |
Extends the issues tool list used in policy edge-case testing. |
test/schema-tests.ts |
Adds schema-level validation tests for the new emoji reaction schemas. |
| #!/usr/bin/env ts-node | ||
|
|
||
| import { GetFileContentsSchema, GitLabFileContentSchema, CreatePipelineSchema, CreateIssueNoteSchema } from '../schemas.js'; | ||
| import { GetFileContentsSchema, GitLabFileContentSchema, CreatePipelineSchema, CreateIssueNoteSchema, CreateMergeRequestEmojiReactionSchema, CreateIssueEmojiReactionSchema, DeleteMergeRequestEmojiReactionSchema, DeleteIssueEmojiReactionSchema, CreateMergeRequestNoteEmojiReactionSchema, DeleteMergeRequestNoteEmojiReactionSchema, CreateIssueNoteEmojiReactionSchema, DeleteIssueNoteEmojiReactionSchema, CreateWorkItemEmojiReactionSchema, DeleteWorkItemEmojiReactionSchema, CreateWorkItemNoteEmojiReactionSchema, DeleteWorkItemNoteEmojiReactionSchema } from '../schemas.js'; |
There was a problem hiding this comment.
The updated import list is now large enough that it hurts readability and is likely to exceed the repo’s configured Prettier printWidth (100). Please reformat this import into a multi-line import (or group imports) so it stays readable and consistent with formatting checks.
| import { GetFileContentsSchema, GitLabFileContentSchema, CreatePipelineSchema, CreateIssueNoteSchema, CreateMergeRequestEmojiReactionSchema, CreateIssueEmojiReactionSchema, DeleteMergeRequestEmojiReactionSchema, DeleteIssueEmojiReactionSchema, CreateMergeRequestNoteEmojiReactionSchema, DeleteMergeRequestNoteEmojiReactionSchema, CreateIssueNoteEmojiReactionSchema, DeleteIssueNoteEmojiReactionSchema, CreateWorkItemEmojiReactionSchema, DeleteWorkItemEmojiReactionSchema, CreateWorkItemNoteEmojiReactionSchema, DeleteWorkItemNoteEmojiReactionSchema } from '../schemas.js'; | |
| import { | |
| GetFileContentsSchema, | |
| GitLabFileContentSchema, | |
| CreatePipelineSchema, | |
| CreateIssueNoteSchema, | |
| CreateMergeRequestEmojiReactionSchema, | |
| CreateIssueEmojiReactionSchema, | |
| DeleteMergeRequestEmojiReactionSchema, | |
| DeleteIssueEmojiReactionSchema, | |
| CreateMergeRequestNoteEmojiReactionSchema, | |
| DeleteMergeRequestNoteEmojiReactionSchema, | |
| CreateIssueNoteEmojiReactionSchema, | |
| DeleteIssueNoteEmojiReactionSchema, | |
| CreateWorkItemEmojiReactionSchema, | |
| DeleteWorkItemEmojiReactionSchema, | |
| CreateWorkItemNoteEmojiReactionSchema, | |
| DeleteWorkItemNoteEmojiReactionSchema | |
| } from '../schemas.js'; |
| let path = `${getEffectiveApiUrl()}/projects/${pp}/${entity}/${entityIid}`; | ||
| if (opts?.noteId) { | ||
| path = opts.discussionId | ||
| ? `${path}/discussions/${opts.discussionId}/notes/${opts.noteId}` | ||
| : `${path}/notes/${opts.noteId}`; | ||
| } | ||
| path += "/award_emoji"; | ||
| if (opts?.awardId) path += `/${opts.awardId}`; |
There was a problem hiding this comment.
buildAwardEmojiPath uses if (opts?.noteId) / if (opts?.awardId) but then dereferences opts.discussionId, opts.noteId, and opts.awardId. With strict: true, the optional-chaining checks do not narrow opts, so this should fail TypeScript compilation (opts possibly undefined). Use an explicit if (opts && opts.noteId) / if (opts && opts.awardId) guard, or destructure from opts ?? {} before building the path.
| let path = `${getEffectiveApiUrl()}/projects/${pp}/${entity}/${entityIid}`; | |
| if (opts?.noteId) { | |
| path = opts.discussionId | |
| ? `${path}/discussions/${opts.discussionId}/notes/${opts.noteId}` | |
| : `${path}/notes/${opts.noteId}`; | |
| } | |
| path += "/award_emoji"; | |
| if (opts?.awardId) path += `/${opts.awardId}`; | |
| const { noteId, discussionId, awardId } = opts ?? {}; | |
| let path = `${getEffectiveApiUrl()}/projects/${pp}/${entity}/${entityIid}`; | |
| if (noteId) { | |
| path = discussionId | |
| ? `${path}/discussions/${discussionId}/notes/${noteId}` | |
| : `${path}/notes/${noteId}`; | |
| } | |
| path += "/award_emoji"; | |
| if (awardId) path += `/${awardId}`; |
| "list_issue_emoji_reactions", | ||
| "list_issue_note_emoji_reactions", | ||
| "create_issue_emoji_reaction", | ||
| "delete_issue_emoji_reaction", | ||
| "create_issue_note_emoji_reaction", |
There was a problem hiding this comment.
The newly added list_*_emoji_reactions tools are read-only (GET) but they are not included in the readOnlyTools allowlist. In GITLAB_READ_ONLY_MODE=true, these list tools will be filtered out even though they should be safe to keep. Add the new list emoji-reaction tools (MR/issue/work item, including note variants) to readOnlyTools and adjust the read-only-mode tests accordingly.
| "create_note", | ||
| "list_issue_emoji_reactions", | ||
| "list_issue_note_emoji_reactions", | ||
| "create_issue_emoji_reaction", | ||
| "delete_issue_emoji_reaction", |
There was a problem hiding this comment.
In the read-only mode test, writeIssueTools includes list_issue_emoji_reactions and list_issue_note_emoji_reactions. These are GET/list operations and should be treated as read-only tools (i.e., expected to be present in read-only mode once the readOnlyTools allowlist is updated). Move the list_* emoji-reaction tools into readOnlyIssueTools and keep only the create/delete variants in writeIssueTools.
Allow Agents to react to show approval, disapproval, pending review, and receive feedback, tested locally.