Compare commits

...

16 Commits

Author SHA1 Message Date
e4a28a9a47 버전 1.0.39로 업데이트 2025-05-20 18:34:05 +09:00
9f1e7b5bca Merge pull request #42 from vlucaswang/feat/add-docker
feat: add docker image and push to dockerhub
2025-05-20 18:32:19 +09:00
f37e210ee8 Merge pull request #41 from kamibayashi/fixed_resolve_outdated_diff_discussions_nullable
fixed resolve_outdated_diff_discussions nullable
2025-05-20 18:28:08 +09:00
6f789692be feat: add docker image and push to dockerhub 2025-05-20 16:04:37 +09:30
1bb70dccb9 fixed resolve_outdated_diff_discussions nullable 2025-05-19 17:18:01 +09:00
676bbcd4dd docs: add release-notes.md 2025-05-17 15:41:14 +09:00
0bb59a3217 Bump version 2025-05-17 15:38:18 +09:00
b908f03801 Merge pull request #40 from huerlisi/fix/discussion-enum
fix: add `expanded` to `start` and `end` for GitLabDiscussionNoteSchema
2025-05-17 15:36:11 +09:00
5024a2a5af fix: add expanded to start and end for GitLabDiscussionNoteSchema 2025-05-16 21:36:21 +02:00
d2cced1b38 Bump version 2025-05-15 10:53:14 +09:00
2fec95d469 Merge pull request #38 from ncrum/feat/merge-request-note
Adds threaded comment support for merge requests
2025-05-15 10:51:48 +09:00
3565d1b397 Merge pull request #37 from ncrum/fix/resolve-notes
Support resolving merge request discussion notes
2025-05-15 10:50:39 +09:00
353e62a401 refactor: rename add_merge_request_thread_note to create_merge_request_note for consistency 2025-05-13 16:52:17 -06:00
3f2b35535e feat: Implement add_merge_request_thread_note function for adding notes to existing MR threads 2025-05-13 16:20:21 -06:00
026dd58887 feat: Add create_merge_request_thread tool for diff notes
- Implement new tool for creating MR threads with positioning support
- Create schemas to handle diff notes with file and line number positions
- Support optional created_at timestamp parameter
- Update README with the new tool information
2025-05-13 15:45:43 -06:00
bde83c0a91 feat: support resolving merge request notes 2025-05-13 14:54:05 -06:00
8 changed files with 292 additions and 42 deletions

View File

@ -1,5 +1,8 @@
## [Released] - 2025-05-13 ## [1.0.38] - 2025-05-17
### Fixed ### Fixed
- **GitLab MCP Server:** Modified GitLab API helper functions to decode the `project_id` using `decodeURIComponent()` before processing. This resolves API call failures caused by differences in project ID encoding between Gemini and other AI models. API requests are now handled consistently regardless of the model. - Added `expanded` property to `start` and `end` in `GitLabDiscussionNoteSchema`
Now you can expand or collapse more information at the start and end of discussion notes.
Example: In code review, you can choose to show or hide specific parts of the discussion.
(See: [PR #40](https://github.com/zereight/gitlab-mcp/pull/40))

24
Dockerfile Normal file
View File

@ -0,0 +1,24 @@
FROM node:22.15-alpine AS builder
COPY . /app
COPY tsconfig.json /tsconfig.json
WORKDIR /app
RUN --mount=type=cache,target=/root/.npm npm install
RUN --mount=type=cache,target=/root/.npm-production npm ci --ignore-scripts --omit-dev
FROM node:22.12-alpine AS release
WORKDIR /app
COPY --from=builder /app/build /app/build
COPY --from=builder /app/package.json /app/package.json
COPY --from=builder /app/package-lock.json /app/package-lock.json
ENV NODE_ENV=production
RUN npm ci --ignore-scripts --omit-dev
ENTRYPOINT ["node", "build/index.js"]

View File

@ -14,6 +14,8 @@ GitLab MCP(Model Context Protocol) Server. **Includes bug fixes and improvements
When using with the Claude App, you need to set up your API key and URLs directly. When using with the Claude App, you need to set up your API key and URLs directly.
#### npx
```json ```json
{ {
"mcpServers": { "mcpServers": {
@ -24,7 +26,39 @@ When using with the Claude App, you need to set up your API key and URLs directl
"GITLAB_PERSONAL_ACCESS_TOKEN": "your_gitlab_token", "GITLAB_PERSONAL_ACCESS_TOKEN": "your_gitlab_token",
"GITLAB_API_URL": "your_gitlab_api_url", "GITLAB_API_URL": "your_gitlab_api_url",
"GITLAB_READ_ONLY_MODE": "false", "GITLAB_READ_ONLY_MODE": "false",
"USE_GITLAB_WIKI":"true" "USE_GITLAB_WIKI": "true"
}
}
}
}
```
#### Docker
```json
{
"mcpServers": {
"GitLab communication server": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-e",
"GITLAB_PERSONAL_ACCESS_TOKEN",
"-e",
"GITLAB_API_URL",
"-e",
"GITLAB_READ_ONLY_MODE",
"-e",
"USE_GITLAB_WIKI",
"nkwd/mcp-gitlab"
],
"env": {
"GITLAB_PERSONAL_ACCESS": "your_gitlab_token",
"GITLAB_API_URL": "https://gitlab.com/api/v4", // Optional, for self-hosted GitLab
"GITLAB_READ_ONLY_MODE": "false",
"USE_GITLAB_WIKI": "true"
} }
} }
} }
@ -33,7 +67,6 @@ When using with the Claude App, you need to set up your API key and URLs directl
### Environment Variables ### Environment Variables
- `GITLAB_PERSONAL_ACCESS_TOKEN`: Your GitLab personal access token. - `GITLAB_PERSONAL_ACCESS_TOKEN`: Your GitLab personal access token.
- `GITLAB_API_URL`: Your GitLab API URL. (Default: `https://gitlab.com/api/v4`) - `GITLAB_API_URL`: Your GitLab API URL. (Default: `https://gitlab.com/api/v4`)
- `GITLAB_READ_ONLY_MODE`: When set to 'true', restricts the server to only expose read-only operations. Useful for enhanced security or when write access is not needed. Also useful for using with Cursor and it's 40 tool limit. - `GITLAB_READ_ONLY_MODE`: When set to 'true', restricts the server to only expose read-only operations. Useful for enhanced security or when write access is not needed. Also useful for using with Cursor and it's 40 tool limit.
@ -42,6 +75,7 @@ When using with the Claude App, you need to set up your API key and URLs directl
## Tools 🛠️ ## Tools 🛠️
+<!-- TOOLS-START --> +<!-- TOOLS-START -->
1. `create_or_update_file` - Create or update a single file in a GitLab project 1. `create_or_update_file` - Create or update a single file in a GitLab project
2. `search_repositories` - Search for GitLab projects 2. `search_repositories` - Search for GitLab projects
3. `create_repository` - Create a new GitLab project 3. `create_repository` - Create a new GitLab project
@ -55,31 +89,33 @@ When using with the Claude App, you need to set up your API key and URLs directl
11. `get_merge_request_diffs` - Get the changes/diffs of a merge request (Either mergeRequestIid or branchName must be provided) 11. `get_merge_request_diffs` - Get the changes/diffs of a merge request (Either mergeRequestIid or branchName must be provided)
12. `update_merge_request` - Update a merge request (Either mergeRequestIid or branchName must be provided) 12. `update_merge_request` - Update a merge request (Either mergeRequestIid or branchName must be provided)
13. `create_note` - Create a new note (comment) to an issue or merge request 13. `create_note` - Create a new note (comment) to an issue or merge request
14. `mr_discussions` - List discussion items for a merge request 14. `create_merge_request_thread` - Create a new thread on a merge request
15. `update_merge_request_note` - Modify an existing merge request thread note 15. `mr_discussions` - List discussion items for a merge request
16. `list_issues` - List issues in a GitLab project with filtering options 16. `update_merge_request_note` - Modify an existing merge request thread note
17. `get_issue` - Get details of a specific issue in a GitLab project 17. `create_merge_request_note` - Add a new note to an existing merge request thread
18. `update_issue` - Update an issue in a GitLab project 18. `list_issues` - List issues in a GitLab project with filtering options
19. `delete_issue` - Delete an issue from a GitLab project 19. `get_issue` - Get details of a specific issue in a GitLab project
20. `list_issue_links` - List all issue links for a specific issue 20. `update_issue` - Update an issue in a GitLab project
21. `get_issue_link` - Get a specific issue link 21. `delete_issue` - Delete an issue from a GitLab project
22. `create_issue_link` - Create an issue link between two issues 22. `list_issue_links` - List all issue links for a specific issue
23. `delete_issue_link` - Delete an issue link 23. `get_issue_link` - Get a specific issue link
24. `list_namespaces` - List all namespaces available to the current user 24. `create_issue_link` - Create an issue link between two issues
25. `get_namespace` - Get details of a namespace by ID or path 25. `delete_issue_link` - Delete an issue link
26. `verify_namespace` - Verify if a namespace path exists 26. `list_namespaces` - List all namespaces available to the current user
27. `get_project` - Get details of a specific project 27. `get_namespace` - Get details of a namespace by ID or path
28. `list_projects` - List projects accessible by the current user 28. `verify_namespace` - Verify if a namespace path exists
29. `list_labels` - List labels for a project 29. `get_project` - Get details of a specific project
30. `get_label` - Get a single label from a project 30. `list_projects` - List projects accessible by the current user
31. `create_label` - Create a new label in a project 31. `list_labels` - List labels for a project
32. `update_label` - Update an existing label in a project 32. `get_label` - Get a single label from a project
33. `delete_label` - Delete a label from a project 33. `create_label` - Create a new label in a project
34. `list_group_projects` - List projects in a GitLab group with filtering options 34. `update_label` - Update an existing label in a project
35. `list_wiki_pages` - List wiki pages in a GitLab project 35. `delete_label` - Delete a label from a project
36. `get_wiki_page` - Get details of a specific wiki page 36. `list_group_projects` - List projects in a GitLab group with filtering options
37. `create_wiki_page` - Create a new wiki page in a GitLab project 37. `list_wiki_pages` - List wiki pages in a GitLab project
38. `update_wiki_page` - Update an existing wiki page in a GitLab project 38. `get_wiki_page` - Get details of a specific wiki page
39. `delete_wiki_page` - Delete a wiki page from a GitLab project 39. `create_wiki_page` - Create a new wiki page in a GitLab project
40. `get_repository_tree` - Get the repository tree for a GitLab project (list files and directories) 40. `update_wiki_page` - Update an existing wiki page in a GitLab project
41. `delete_wiki_page` - Delete a wiki page from a GitLab project
42. `get_repository_tree` - Get the repository tree for a GitLab project (list files and directories)
<!-- TOOLS-END --> <!-- TOOLS-END -->

150
index.ts
View File

@ -75,6 +75,7 @@ import {
UpdateLabelSchema, UpdateLabelSchema,
DeleteLabelSchema, DeleteLabelSchema,
CreateNoteSchema, CreateNoteSchema,
CreateMergeRequestThreadSchema,
ListGroupProjectsSchema, ListGroupProjectsSchema,
ListWikiPagesSchema, ListWikiPagesSchema,
GetWikiPageSchema, GetWikiPageSchema,
@ -86,6 +87,7 @@ import {
GitLabDiscussionNoteSchema, // Added GitLabDiscussionNoteSchema, // Added
GitLabDiscussionSchema, GitLabDiscussionSchema,
UpdateMergeRequestNoteSchema, // Added UpdateMergeRequestNoteSchema, // Added
CreateMergeRequestNoteSchema, // Added
ListMergeRequestDiscussionsSchema, ListMergeRequestDiscussionsSchema,
type GitLabFork, type GitLabFork,
type GitLabReference, type GitLabReference,
@ -108,6 +110,7 @@ import {
// Discussion Types // Discussion Types
type GitLabDiscussionNote, // Added type GitLabDiscussionNote, // Added
type GitLabDiscussion, type GitLabDiscussion,
type MergeRequestThreadPosition,
type GetWikiPageOptions, type GetWikiPageOptions,
type CreateWikiPageOptions, type CreateWikiPageOptions,
type UpdateWikiPageOptions, type UpdateWikiPageOptions,
@ -263,6 +266,11 @@ const allTools = [
description: "Create a new note (comment) to an issue or merge request", description: "Create a new note (comment) to an issue or merge request",
inputSchema: zodToJsonSchema(CreateNoteSchema), inputSchema: zodToJsonSchema(CreateNoteSchema),
}, },
{
name: "create_merge_request_thread",
description: "Create a new thread on a merge request",
inputSchema: zodToJsonSchema(CreateMergeRequestThreadSchema),
},
{ {
name: "mr_discussions", name: "mr_discussions",
description: "List discussion items for a merge request", description: "List discussion items for a merge request",
@ -273,6 +281,11 @@ const allTools = [
description: "Modify an existing merge request thread note", description: "Modify an existing merge request thread note",
inputSchema: zodToJsonSchema(UpdateMergeRequestNoteSchema), inputSchema: zodToJsonSchema(UpdateMergeRequestNoteSchema),
}, },
{
name: "create_merge_request_note",
description: "Add a new note to an existing merge request thread",
inputSchema: zodToJsonSchema(CreateMergeRequestNoteSchema),
},
{ {
name: "list_issues", name: "list_issues",
description: "List issues in a GitLab project with filtering options", description: "List issues in a GitLab project with filtering options",
@ -1027,7 +1040,7 @@ async function updateMergeRequestNote(
mergeRequestIid: number, mergeRequestIid: number,
discussionId: string, discussionId: string,
noteId: number, noteId: number,
body: string, body?: string,
resolved?: boolean resolved?: boolean
): Promise<GitLabDiscussionNote> { ): Promise<GitLabDiscussionNote> {
projectId = decodeURIComponent(projectId); // Decode project ID projectId = decodeURIComponent(projectId); // Decode project ID
@ -1037,8 +1050,11 @@ async function updateMergeRequestNote(
)}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}` )}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes/${noteId}`
); );
const payload: { body: string; resolved?: boolean } = { body }; // Only one of body or resolved can be sent according to GitLab API
if (resolved !== undefined) { const payload: { body?: string; resolved?: boolean } = {};
if (body !== undefined) {
payload.body = body;
} else if (resolved !== undefined) {
payload.resolved = resolved; payload.resolved = resolved;
} }
@ -1053,6 +1069,47 @@ async function updateMergeRequestNote(
return GitLabDiscussionNoteSchema.parse(data); return GitLabDiscussionNoteSchema.parse(data);
} }
/**
* Add a new note to an existing merge request thread
* 기존 병합 요청 스레드에 새 노트 추가
*
* @param {string} projectId - The ID or URL-encoded path of the project
* @param {number} mergeRequestIid - The IID of a merge request
* @param {string} discussionId - The ID of a thread
* @param {string} body - The content of the new note
* @param {string} [createdAt] - The creation date of the note (ISO 8601 format)
* @returns {Promise<GitLabDiscussionNote>} The created note
*/
async function createMergeRequestNote(
projectId: string,
mergeRequestIid: number,
discussionId: string,
body: string,
createdAt?: string
): Promise<GitLabDiscussionNote> {
projectId = decodeURIComponent(projectId); // Decode project ID
const url = new URL(
`${GITLAB_API_URL}/projects/${encodeURIComponent(
projectId
)}/merge_requests/${mergeRequestIid}/discussions/${discussionId}/notes`
);
const payload: { body: string; created_at?: string } = { body };
if (createdAt) {
payload.created_at = createdAt;
}
const response = await fetch(url.toString(), {
...DEFAULT_FETCH_CONFIG,
method: "POST",
body: JSON.stringify(payload),
});
await handleGitLabError(response);
const data = await response.json();
return GitLabDiscussionNoteSchema.parse(data);
}
/** /**
* Create or update a file in a GitLab project * Create or update a file in a GitLab project
* 파일 생성 또는 업데이트 * 파일 생성 또는 업데이트
@ -1520,6 +1577,59 @@ async function createNote(
return await response.json(); return await response.json();
} }
/**
* Create a new thread on a merge request
* 📦 새로운 함수: createMergeRequestThread - 병합 요청에 새로운 스레드(토론)를 생성하는 함수
* (New function: createMergeRequestThread - Function to create a new thread (discussion) on a merge request)
*
* This function provides more capabilities than createNote, including the ability to:
* - Create diff notes (comments on specific lines of code)
* - Specify exact positions for comments
* - Set creation timestamps
*
* @param {string} projectId - The ID or URL-encoded path of the project
* @param {number} mergeRequestIid - The internal ID of the merge request
* @param {string} body - The content of the thread
* @param {MergeRequestThreadPosition} [position] - Position information for diff notes
* @param {string} [createdAt] - ISO 8601 formatted creation date
* @returns {Promise<GitLabDiscussion>} The created discussion thread
*/
async function createMergeRequestThread(
projectId: string,
mergeRequestIid: number,
body: string,
position?: MergeRequestThreadPosition,
createdAt?: string
): Promise<GitLabDiscussion> {
projectId = decodeURIComponent(projectId); // Decode project ID
const url = new URL(
`${GITLAB_API_URL}/projects/${encodeURIComponent(
projectId
)}/merge_requests/${mergeRequestIid}/discussions`
);
const payload: Record<string, any> = { body };
// Add optional parameters if provided
if (position) {
payload.position = position;
}
if (createdAt) {
payload.created_at = createdAt;
}
const response = await fetch(url.toString(), {
...DEFAULT_FETCH_CONFIG,
method: "POST",
body: JSON.stringify(payload),
});
await handleGitLabError(response);
const data = await response.json();
return GitLabDiscussionSchema.parse(data);
}
/** /**
* List all namespaces * List all namespaces
* 사용 가능한 모든 네임스페이스 목록 조회 * 사용 가능한 모든 네임스페이스 목록 조회
@ -2270,8 +2380,24 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
args.merge_request_iid, args.merge_request_iid,
args.discussion_id, args.discussion_id,
args.note_id, args.note_id,
args.body, // Now optional
args.resolved // Now one of body or resolved must be provided, not both
);
return {
content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
};
}
case "create_merge_request_note": {
const args = CreateMergeRequestNoteSchema.parse(
request.params.arguments
);
const note = await createMergeRequestNote(
args.project_id,
args.merge_request_iid,
args.discussion_id,
args.body, args.body,
args.resolved // Pass resolved if provided args.created_at
); );
return { return {
content: [{ type: "text", text: JSON.stringify(note, null, 2) }], content: [{ type: "text", text: JSON.stringify(note, null, 2) }],
@ -2454,6 +2580,22 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}; };
} }
case "create_merge_request_thread": {
const args = CreateMergeRequestThreadSchema.parse(request.params.arguments);
const { project_id, merge_request_iid, body, position, created_at } = args;
const thread = await createMergeRequestThread(
project_id,
merge_request_iid,
body,
position,
created_at
);
return {
content: [{ type: "text", text: JSON.stringify(thread, null, 2) }],
};
}
case "list_issues": { case "list_issues": {
const args = ListIssuesSchema.parse(request.params.arguments); const args = ListIssuesSchema.parse(request.params.arguments);
const { project_id, ...options } = args; const { project_id, ...options } = args;

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "@zereight/mcp-gitlab", "name": "@zereight/mcp-gitlab",
"version": "1.0.33", "version": "1.0.38",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@zereight/mcp-gitlab", "name": "@zereight/mcp-gitlab",
"version": "1.0.33", "version": "1.0.38",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@modelcontextprotocol/sdk": "1.8.0", "@modelcontextprotocol/sdk": "1.8.0",

View File

@ -1,6 +1,6 @@
{ {
"name": "@zereight/mcp-gitlab", "name": "@zereight/mcp-gitlab",
"version": "1.0.36", "version": "1.0.39",
"description": "MCP server for using the GitLab API", "description": "MCP server for using the GitLab API",
"license": "MIT", "license": "MIT",
"author": "zereight", "author": "zereight",

6
release-notes.md Normal file
View File

@ -0,0 +1,6 @@
### Fixed
- Added `expanded` property to `start` and `end` in `GitLabDiscussionNoteSchema`
Now you can expand or collapse more information at the start and end of discussion notes.
Example: In code review, you can choose to show or hide specific parts of the discussion.
(See: [PR #40](https://github.com/zereight/gitlab-mcp/pull/40))

View File

@ -107,7 +107,7 @@ export const GitLabRepositorySchema = z.object({
jobs_enabled: z.boolean().optional(), jobs_enabled: z.boolean().optional(),
snippets_enabled: z.boolean().optional(), snippets_enabled: z.boolean().optional(),
can_create_merge_request_in: z.boolean().optional(), can_create_merge_request_in: z.boolean().optional(),
resolve_outdated_diff_discussions: z.boolean().optional(), resolve_outdated_diff_discussions: z.boolean().nullable().optional(),
shared_runners_enabled: z.boolean().optional(), shared_runners_enabled: z.boolean().optional(),
shared_with_groups: z shared_with_groups: z
.array( .array(
@ -436,13 +436,13 @@ export const GitLabDiscussionNoteSchema = z.object({
.object({ .object({
start: z.object({ start: z.object({
line_code: z.string(), line_code: z.string(),
type: z.enum(["new", "old"]), type: z.enum(["new", "old", "expanded"]),
old_line: z.number().nullable(), old_line: z.number().nullable(),
new_line: z.number().nullable(), new_line: z.number().nullable(),
}), }),
end: z.object({ end: z.object({
line_code: z.string(), line_code: z.string(),
type: z.enum(["new", "old"]), type: z.enum(["new", "old", "expanded"]),
old_line: z.number().nullable(), old_line: z.number().nullable(),
new_line: z.number().nullable(), new_line: z.number().nullable(),
}), }),
@ -475,8 +475,20 @@ export const UpdateMergeRequestNoteSchema = ProjectParamsSchema.extend({
merge_request_iid: z.number().describe("The IID of a merge request"), merge_request_iid: z.number().describe("The IID of a merge request"),
discussion_id: z.string().describe("The ID of a thread"), discussion_id: z.string().describe("The ID of a thread"),
note_id: z.number().describe("The ID of a thread note"), note_id: z.number().describe("The ID of a thread note"),
body: z.string().optional().describe("The content of the note or reply"),
resolved: z.boolean().optional().describe("Resolve or unresolve the note"),
}).refine(data => data.body !== undefined || data.resolved !== undefined, {
message: "At least one of 'body' or 'resolved' must be provided"
}).refine(data => !(data.body !== undefined && data.resolved !== undefined), {
message: "Only one of 'body' or 'resolved' can be provided, not both"
});
// Input schema for adding a note to an existing merge request discussion
export const CreateMergeRequestNoteSchema = ProjectParamsSchema.extend({
merge_request_iid: z.number().describe("The IID of a merge request"),
discussion_id: z.string().describe("The ID of a thread"),
body: z.string().describe("The content of the note or reply"), body: z.string().describe("The content of the note or reply"),
resolved: z.boolean().optional().describe("Resolve or unresolve the note"), // Optional based on API docs created_at: z.string().optional().describe("Date the note was created at (ISO 8601 format)"),
}); });
// API Operation Parameter Schemas // API Operation Parameter Schemas
@ -1004,6 +1016,30 @@ export const GitLabWikiPageSchema = z.object({
updated_at: z.string().optional(), updated_at: z.string().optional(),
}); });
// Merge Request Thread position schema - used for diff notes
export const MergeRequestThreadPositionSchema = z.object({
base_sha: z.string().describe("Base commit SHA in the source branch"),
head_sha: z.string().describe("SHA referencing HEAD of the source branch"),
start_sha: z.string().describe("SHA referencing the start commit of the source branch"),
position_type: z.enum(["text", "image", "file"]).describe("Type of position reference"),
new_path: z.string().optional().describe("File path after change"),
old_path: z.string().optional().describe("File path before change"),
new_line: z.number().nullable().optional().describe("Line number after change"),
old_line: z.number().nullable().optional().describe("Line number before change"),
width: z.number().optional().describe("Width of the image (for image diffs)"),
height: z.number().optional().describe("Height of the image (for image diffs)"),
x: z.number().optional().describe("X coordinate on the image (for image diffs)"),
y: z.number().optional().describe("Y coordinate on the image (for image diffs)"),
});
// Schema for creating a new merge request thread
export const CreateMergeRequestThreadSchema = ProjectParamsSchema.extend({
merge_request_iid: z.number().describe("The IID of a merge request"),
body: z.string().describe("The content of the thread"),
position: MergeRequestThreadPositionSchema.optional().describe("Position when creating a diff note"),
created_at: z.string().optional().describe("Date the thread was created at (ISO 8601 format)"),
});
// Export types // Export types
export type GitLabAuthor = z.infer<typeof GitLabAuthorSchema>; export type GitLabAuthor = z.infer<typeof GitLabAuthorSchema>;
export type GitLabFork = z.infer<typeof GitLabForkSchema>; export type GitLabFork = z.infer<typeof GitLabForkSchema>;
@ -1053,3 +1089,6 @@ export type DeleteWikiPageOptions = z.infer<typeof DeleteWikiPageSchema>;
export type GitLabWikiPage = z.infer<typeof GitLabWikiPageSchema>; export type GitLabWikiPage = z.infer<typeof GitLabWikiPageSchema>;
export type GitLabTreeItem = z.infer<typeof GitLabTreeItemSchema>; export type GitLabTreeItem = z.infer<typeof GitLabTreeItemSchema>;
export type GetRepositoryTreeOptions = z.infer<typeof GetRepositoryTreeSchema>; export type GetRepositoryTreeOptions = z.infer<typeof GetRepositoryTreeSchema>;
export type MergeRequestThreadPosition = z.infer<typeof MergeRequestThreadPositionSchema>;
export type CreateMergeRequestThreadOptions = z.infer<typeof CreateMergeRequestThreadSchema>;
export type CreateMergeRequestNoteOptions = z.infer<typeof CreateMergeRequestNoteSchema>;