diff --git a/README.md b/README.md index 76a5e31..cf6d9d7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# @zereight/mcp-gitlab +# Better GitLab MCP Server + +## @zereight/mcp-gitlab [![smithery badge](https://smithery.ai/badge/@zereight/gitlab-mcp)](https://smithery.ai/server/@zereight/gitlab-mcp) @@ -126,6 +128,7 @@ GitLab MCP(Model Context Protocol) Server. - Returns: Array of merge request diff information 12. `update_merge_request` + - Update a merge request. πŸ”„ - Inputs: - `project_id` (string): Project ID or namespace/project_path @@ -138,6 +141,15 @@ GitLab MCP(Model Context Protocol) Server. - `allow_collaboration` (optional boolean): Allow collaborators to push commits to the source branch - Returns: Updated merge request details +13. `create_note` + - Create a new note (comment) to an issue or merge request. πŸ’¬ + - Inputs: + - `project_id` (string): Project ID or namespace/project_path + - `noteable_type` (string): Type of noteable ("issue" or "merge_request") + - `noteable_iid` (number): IID of the issue or merge request + - `body` (string): Note content + - Returns: Details of the created note + ## Environment Variable Configuration Before running the server, you need to set the following environment variables: diff --git a/index.ts b/index.ts index 7d4eecf..0886855 100644 --- a/index.ts +++ b/index.ts @@ -51,6 +51,7 @@ import { type GitLabCommit, type FileOperation, type GitLabMergeRequestDiff, + CreateNoteSchema, } from "./schemas.js"; const server = new Server( @@ -573,6 +574,30 @@ async function updateMergeRequest( return GitLabMergeRequestSchema.parse(await response.json()); } +// πŸ“¦ μƒˆλ‘œμš΄ ν•¨μˆ˜: createNote - 이슈 λ˜λŠ” 병합 μš”μ²­μ— λ…ΈνŠΈ(λŒ“κΈ€)λ₯Ό μΆ”κ°€ν•˜λŠ” ν•¨μˆ˜ +async function createNote( + projectId: string, + noteableType: "issue" | "merge_request", // 'issue' λ˜λŠ” 'merge_request' νƒ€μž… λͺ…μ‹œ + noteableIid: number, + body: string +): Promise { + // βš™οΈ 응닡 νƒ€μž…μ€ GitLab API λ¬Έμ„œμ— 따라 μ‘°μ • κ°€λŠ₯ + const url = new URL( + `${GITLAB_API_URL}/projects/${encodeURIComponent( + projectId + )}/${noteableType}/${noteableIid}/notes` + ); + + const response = await fetch(url.toString(), { + method: "POST", + headers: DEFAULT_HEADERS, + body: JSON.stringify({ body }), + }); + + await handleGitLabError(response); + return await response.json(); // βš™οΈ 응닡 νƒ€μž…μ€ GitLab API λ¬Έμ„œμ— 따라 μ‘°μ • κ°€λŠ₯, ν•„μš”ν•˜λ©΄ μŠ€ν‚€λ§ˆ μ •μ˜ +} + server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ @@ -639,6 +664,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { description: "Update a merge request", inputSchema: zodToJsonSchema(UpdateMergeRequestSchema), }, + { + name: "create_note", + description: "Create a new note (comment) to an issue or merge request", + inputSchema: zodToJsonSchema(CreateNoteSchema), + }, ], }; }); @@ -797,6 +827,31 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { }; } + case "create_note": { + try { + const args = CreateNoteSchema.parse(request.params.arguments); + const { project_id, noteable_type, noteable_iid, body } = args; + const note = await createNote( + project_id, + noteable_type, + noteable_iid, + body + ); + return { + content: [{ type: "text", text: JSON.stringify(note, null, 2) }], + }; + } catch (error) { + if (error instanceof z.ZodError) { + throw new Error( + `Invalid arguments: ${error.errors + .map((e) => `${e.path.join(".")}: ${e.message}`) + .join(", ")}` + ); + } + throw error; + } + } + default: throw new Error(`Unknown tool: ${request.params.name}`); } diff --git a/schemas.ts b/schemas.ts index b014291..fa1ae3b 100644 --- a/schemas.ts +++ b/schemas.ts @@ -388,6 +388,15 @@ export const GetMergeRequestDiffsSchema = GetMergeRequestSchema.extend({ view: z.enum(["inline", "parallel"]).optional().describe("Diff view type"), }); +export const CreateNoteSchema = z.object({ + project_id: z.string().describe("Project ID or namespace/project_path"), + noteable_type: z + .enum(["issue", "merge_request"]) + .describe("Type of noteable (issue or merge_request)"), + noteable_iid: z.number().describe("IID of the issue or merge request"), + body: z.string().describe("Note content"), +}); + // Export types export type GitLabAuthor = z.infer; export type GitLabFork = z.infer; @@ -418,3 +427,4 @@ export type GitLabSearchResponse = z.infer; export type GitLabMergeRequestDiff = z.infer< typeof GitLabMergeRequestDiffSchema >; +export type CreateNoteOptions = z.infer;