UNPKG

@therealchristhomas/gitlab-mcp-server

Version:
94 lines (93 loc) 3.5 kB
import { z } from "zod"; import { gitlabGet, gitlabGetWithHeaders, gitlabPost, gitlabPut, encodeProjectId, buildSearchParams } from "../utils/gitlab-client.js"; import { GitLabIssueSchema, GitLabCommentSchema } from "../types/index.js"; export async function listIssues(projectId, options = {}) { if (!projectId?.trim()) { throw new Error("Project ID is required"); } const endpoint = `/projects/${encodeProjectId(projectId)}/issues`; // If user explicitly provides page parameter, use single page request if (options.page !== undefined) { const params = buildSearchParams(options); const rawIssues = await gitlabGet(endpoint, params); return z.array(GitLabIssueSchema).parse(rawIssues); } // Otherwise, fetch all pages automatically const allIssues = []; let currentPage = 1; const perPage = options.per_page || 100; // Use max page size for efficiency while (true) { const params = buildSearchParams({ ...options, page: currentPage, per_page: perPage }); const response = await gitlabGetWithHeaders(endpoint, params); const pageIssues = response.data; if (pageIssues.length === 0) { break; // No more issues } allIssues.push(...pageIssues); // Check if there's a next page const nextPage = response.headers["x-next-page"]; if (!nextPage) { break; // No more pages } currentPage = parseInt(nextPage, 10); } return z.array(GitLabIssueSchema).parse(allIssues); } export async function createIssue(projectId, options) { if (!projectId?.trim()) { throw new Error("Project ID is required"); } if (!options?.title?.trim()) { throw new Error("Issue title is required"); } const endpoint = `/projects/${encodeProjectId(projectId)}/issues`; const issue = await gitlabPost(endpoint, { title: options.title, description: options.description, assignee_ids: options.assignee_ids, milestone_id: options.milestone_id, labels: options.labels?.join(",") }); return GitLabIssueSchema.parse(issue); } export async function updateIssue(projectId, issueIid, options) { if (!projectId?.trim()) { throw new Error("Project ID is required"); } if (!issueIid || issueIid < 1) { throw new Error("Valid issue IID is required"); } const endpoint = `/projects/${encodeProjectId(projectId)}/issues/${issueIid}`; const issue = await gitlabPut(endpoint, { ...options, labels: options.labels?.join(",") }); return GitLabIssueSchema.parse(issue); } export async function searchIssues(projectId, searchTerm, options = {}) { if (!searchTerm?.trim()) { throw new Error("Search term is required"); } return listIssues(projectId, { search: searchTerm, ...options }); } export async function addIssueComment(projectId, issueIid, body) { if (!projectId?.trim()) { throw new Error("Project ID is required"); } if (!issueIid || issueIid < 1) { throw new Error("Valid issue IID is required"); } if (!body?.trim()) { throw new Error("Comment body is required"); } const endpoint = `/projects/${encodeProjectId(projectId)}/issues/${issueIid}/notes`; const comment = await gitlabPost(endpoint, { body }); return GitLabCommentSchema.parse(comment); }