@zereight/mcp-gitlab 2.1.6 → 2.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -25,15 +25,13 @@ import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middlew
25
25
  import { GitLabClientPool } from "./gitlab-client-pool.js";
26
26
  import { allTools, readOnlyTools, destructiveTools, parseEnabledToolsets, parseIndividualTools, buildFeatureFlagOverrides, isToolInEnabledToolset, TOOLSET_DEFINITIONS, ALL_TOOLSET_IDS, } from "./tools/registry.js";
27
27
  import { BulkPublishDraftNotesSchema, CancelPipelineJobSchema, CancelPipelineSchema, CreateBranchSchema, CreateDraftNoteSchema, CreateIssueLinkSchema, CreateIssueNoteSchema, CreateIssueSchema, CreateIssueEmojiReactionSchema, CreateIssueNoteEmojiReactionSchema, ListIssueEmojiReactionsSchema, ListIssueNoteEmojiReactionsSchema, CreateLabelSchema, // Added
28
- CreateMergeRequestNoteSchema, CreateMergeRequestDiscussionNoteSchema, CreateMergeRequestEmojiReactionSchema, CreateMergeRequestNoteEmojiReactionSchema, ListMergeRequestEmojiReactionsSchema, ListMergeRequestNoteEmojiReactionsSchema, CreateMergeRequestSchema, CreateMergeRequestThreadSchema, CreateNoteSchema, CreateOrUpdateFileSchema, CreatePipelineSchema, CreateProjectMilestoneSchema, CreateRepositorySchema, CreateWikiPageSchema, CreateGroupWikiPageSchema, DeleteDraftNoteSchema, DeleteGroupWikiPageSchema, DeleteIssueLinkSchema, DeleteIssueSchema, DeleteIssueEmojiReactionSchema, DeleteIssueNoteEmojiReactionSchema, DeleteLabelSchema, DeleteProjectMilestoneSchema, DeleteWikiPageSchema, DeleteMergeRequestNoteSchema, DeleteMergeRequestEmojiReactionSchema, DeleteMergeRequestNoteEmojiReactionSchema, EditProjectMilestoneSchema, ForkRepositorySchema, GetBranchDiffsSchema, GetCommitDiffSchema, GetCommitSchema, GetDraftNoteSchema, GetFileContentsSchema, GetIssueLinkSchema, GetIssueSchema, GetLabelSchema, GetMergeRequestDiffsSchema, GetMergeRequestSchema, GetMilestoneBurndownEventsSchema, GetMilestoneIssuesSchema, GetMilestoneMergeRequestsSchema, GetDeploymentSchema, GetEnvironmentSchema, GetNamespaceSchema,
29
- // pipeline job schemas
30
- GetPipelineJobOutputSchema, GetPipelineSchema, GetProjectMilestoneSchema, GetProjectSchema, GetRepositoryTreeSchema, GetUsersSchema, GetWikiPageSchema, GitLabCommitSchema, GitLabCompareResultSchema, GitLabContentSchema, GitLabCreateUpdateFileResponseSchema, GitLabDiffSchema,
28
+ CreateMergeRequestNoteSchema, CreateMergeRequestDiscussionNoteSchema, CreateMergeRequestEmojiReactionSchema, CreateMergeRequestNoteEmojiReactionSchema, ListMergeRequestEmojiReactionsSchema, ListMergeRequestNoteEmojiReactionsSchema, CreateMergeRequestSchema, CreateMergeRequestThreadSchema, CreateNoteSchema, CreateOrUpdateFileSchema, CreatePipelineSchema, CreateProjectMilestoneSchema, CreateRepositorySchema, CreateWikiPageSchema, CreateGroupWikiPageSchema, DeleteDraftNoteSchema, DeleteGroupWikiPageSchema, DeleteIssueLinkSchema, DeleteIssueSchema, DeleteIssueEmojiReactionSchema, DeleteIssueNoteEmojiReactionSchema, DeleteLabelSchema, DeleteProjectMilestoneSchema, DeleteWikiPageSchema, DeleteMergeRequestNoteSchema, DeleteMergeRequestEmojiReactionSchema, DeleteMergeRequestNoteEmojiReactionSchema, EditProjectMilestoneSchema, ForkRepositorySchema, GetBranchDiffsSchema, GetCommitDiffSchema, GetCommitSchema, GetDraftNoteSchema, GetFileContentsSchema, GetIssueLinkSchema, GetIssueSchema, GetLabelSchema, GetMergeRequestDiffsSchema, GetMergeRequestSchema, GetMilestoneBurndownEventsSchema, GetMilestoneIssuesSchema, GetMilestoneMergeRequestsSchema, GetDeploymentSchema, GetEnvironmentSchema, GetNamespaceSchema, GitLabCiLintResultSchema, GetPipelineJobOutputSchema, GetPipelineSchema, GetProjectMilestoneSchema, GetProjectSchema, GetRepositoryTreeSchema, GetUsersSchema, GetWikiPageSchema, GitLabCommitSchema, GitLabCompareResultSchema, GitLabContentSchema, GitLabCreateUpdateFileResponseSchema, GitLabDiffSchema,
31
29
  // Discussion Schemas
32
30
  GitLabDiscussionNoteSchema, // Added
33
31
  GitLabDiscussionSchema,
34
32
  // Draft Notes Schemas
35
- GitLabDraftNoteSchema, GitLabForkSchema, GitLabIssueLinkSchema, GitLabIssueSchema, GitLabIssueWithLinkDetailsSchema, GitLabMarkdownUploadSchema, GitLabMergeRequestSchema, GitLabMilestonesSchema, GitLabNamespaceExistsResponseSchema, GitLabNamespaceSchema, GitLabPipelineJobSchema, GitLabDeploymentSchema, GitLabEnvironmentSchema, GitLabPipelineSchema, GitLabPipelineTriggerJobSchema, GitLabProjectMemberSchema, GitLabProjectSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLabSearchBlobResultSchema, GitLabSearchResponseSchema, GitLabTreeItemSchema, GitLabUserSchema, GitLabUsersResponseSchema, GitLabWikiPageSchema, GroupIteration, ListCommitsSchema, ListDraftNotesSchema, ListGroupIterationsSchema, ListGroupProjectsSchema, ListIssueDiscussionsSchema, ListIssueLinksSchema, ListIssuesSchema, ListLabelsSchema, ListMergeRequestDiffsSchema, // Added
36
- GetMergeRequestFileDiffSchema, ListMergeRequestChangedFilesSchema, ListMergeRequestDiscussionsSchema, ListMergeRequestsSchema, ListMergeRequestVersionsSchema, GetMergeRequestVersionSchema, GitLabMergeRequestVersionSchema, GitLabMergeRequestVersionDetailSchema, ListNamespacesSchema, ListPipelineJobsSchema, ListPipelinesSchema, ListDeploymentsSchema, ListEnvironmentsSchema, ListPipelineTriggerJobsSchema, ListProjectMembersSchema, ListProjectMilestonesSchema, ListProjectsSchema, ListWikiPagesSchema, GetGroupWikiPageSchema, ListGroupWikiPagesSchema, UpdateGroupWikiPageSchema, MarkdownUploadSchema, DownloadAttachmentSchema, DownloadJobArtifactsSchema, GetJobArtifactFileSchema, GitLabArtifactEntrySchema, ListJobArtifactsSchema, MergeMergeRequestSchema, ApproveMergeRequestSchema, UnapproveMergeRequestSchema, GetMergeRequestApprovalStateSchema, GetMergeRequestConflictsSchema, GitLabMergeRequestApprovalsResponseSchema, GitLabMergeRequestApprovalStateSchema, MyIssuesSchema, PaginatedDiscussionsResponseSchema, PromoteProjectMilestoneSchema, PublishDraftNoteSchema, PlayPipelineJobSchema, PushFilesSchema, RetryPipelineJobSchema, RetryPipelineSchema, SearchCodeSchema, SearchGroupCodeSchema, SearchProjectCodeSchema, SearchRepositoriesSchema, UpdateDraftNoteSchema, UpdateIssueNoteSchema, UpdateIssueSchema, UpdateLabelSchema, UpdateMergeRequestNoteSchema, UpdateMergeRequestDiscussionNoteSchema, UpdateMergeRequestSchema, UpdateWikiPageSchema, VerifyNamespaceSchema, GitLabEventSchema, ListEventsSchema, GetProjectEventsSchema, ExecuteGraphQLSchema, GitLabReleaseSchema, ListReleasesSchema, GetReleaseSchema, CreateReleaseSchema, UpdateReleaseSchema, DeleteReleaseSchema, CreateReleaseEvidenceSchema, DownloadReleaseAssetSchema, GetMergeRequestNotesSchema, GetMergeRequestNoteSchema, DeleteMergeRequestDiscussionNoteSchema, ResolveMergeRequestThreadSchema, GetWorkItemSchema, ListWorkItemsSchema, CreateWorkItemSchema, UpdateWorkItemSchema, ConvertWorkItemTypeSchema, ListWorkItemStatusesSchema, ListWorkItemNotesSchema, CreateWorkItemNoteSchema, CreateWorkItemEmojiReactionSchema, CreateWorkItemNoteEmojiReactionSchema, ListWorkItemEmojiReactionsSchema, ListWorkItemNoteEmojiReactionsSchema, DeleteWorkItemEmojiReactionSchema, DeleteWorkItemNoteEmojiReactionSchema, MoveWorkItemSchema, ListCustomFieldDefinitionsSchema, GetTimelineEventsSchema, CreateTimelineEventSchema, ListWebhooksSchema, ListWebhookEventsSchema, GetWebhookEventSchema, } from "./schemas.js";
33
+ GitLabDraftNoteSchema, GitLabForkSchema, GitLabIssueLinkSchema, GitLabIssueSchema, GitLabIssueWithLinkDetailsSchema, GitLabMarkdownUploadSchema, GitLabMergeRequestSchema, GitLabMilestonesSchema, GitLabNamespaceExistsResponseSchema, GitLabNamespaceSchema, GitLabPipelineJobSchema, GitLabDeploymentSchema, GitLabEnvironmentSchema, GitLabPipelineSchema, GitLabPipelineTriggerJobSchema, GitLabProjectMemberSchema, GitLabProjectSchema, GitLabTodoSchema, GitLabReferenceSchema, GitLabRepositorySchema, GitLabSearchBlobResultSchema, GitLabSearchResponseSchema, GitLabTreeItemSchema, GitLabUserSchema, GitLabUsersResponseSchema, GitLabWikiPageSchema, GroupIteration, ListCommitsSchema, ListDraftNotesSchema, ListGroupIterationsSchema, ListGroupProjectsSchema, ListIssueDiscussionsSchema, ListIssueLinksSchema, ListIssuesSchema, ListTodosSchema, ListLabelsSchema, ListMergeRequestDiffsSchema, // Added
34
+ GetMergeRequestFileDiffSchema, ListMergeRequestChangedFilesSchema, ListMergeRequestDiscussionsSchema, ListMergeRequestsSchema, ListMergeRequestVersionsSchema, GetMergeRequestVersionSchema, GitLabMergeRequestVersionSchema, GitLabMergeRequestVersionDetailSchema, ListNamespacesSchema, ListPipelineJobsSchema, ListPipelinesSchema, ListDeploymentsSchema, ListEnvironmentsSchema, ListPipelineTriggerJobsSchema, ValidateCiLintSchema, ValidateProjectCiLintSchema, ListProjectMembersSchema, ListProjectMilestonesSchema, ListProjectsSchema, ListWikiPagesSchema, GetGroupWikiPageSchema, ListGroupWikiPagesSchema, UpdateGroupWikiPageSchema, MarkdownUploadSchema, DownloadAttachmentSchema, DownloadJobArtifactsSchema, GetJobArtifactFileSchema, GitLabArtifactEntrySchema, ListJobArtifactsSchema, MergeMergeRequestSchema, ApproveMergeRequestSchema, UnapproveMergeRequestSchema, GetMergeRequestApprovalStateSchema, GetMergeRequestConflictsSchema, GitLabMergeRequestApprovalsResponseSchema, GitLabMergeRequestApprovalStateSchema, MyIssuesSchema, MarkAllTodosDoneSchema, MarkTodoDoneSchema, PaginatedDiscussionsResponseSchema, PromoteProjectMilestoneSchema, PublishDraftNoteSchema, PlayPipelineJobSchema, PushFilesSchema, RetryPipelineJobSchema, RetryPipelineSchema, SearchCodeSchema, SearchGroupCodeSchema, SearchProjectCodeSchema, SearchRepositoriesSchema, UpdateDraftNoteSchema, UpdateIssueNoteSchema, UpdateIssueSchema, UpdateLabelSchema, UpdateMergeRequestNoteSchema, UpdateMergeRequestDiscussionNoteSchema, UpdateMergeRequestSchema, UpdateWikiPageSchema, VerifyNamespaceSchema, GitLabEventSchema, ListEventsSchema, GetProjectEventsSchema, ExecuteGraphQLSchema, GitLabReleaseSchema, ListReleasesSchema, GetReleaseSchema, CreateReleaseSchema, UpdateReleaseSchema, DeleteReleaseSchema, CreateReleaseEvidenceSchema, DownloadReleaseAssetSchema, ListTagsSchema, GetTagSchema, CreateTagSchema, DeleteTagSchema, GetTagSignatureSchema, GitLabTagSchema, GitLabTagSignatureSchema, GetMergeRequestNotesSchema, GetMergeRequestNoteSchema, DeleteMergeRequestDiscussionNoteSchema, ResolveMergeRequestThreadSchema, GetWorkItemSchema, ListWorkItemsSchema, CreateWorkItemSchema, UpdateWorkItemSchema, ConvertWorkItemTypeSchema, ListWorkItemStatusesSchema, ListWorkItemNotesSchema, CreateWorkItemNoteSchema, CreateWorkItemEmojiReactionSchema, CreateWorkItemNoteEmojiReactionSchema, ListWorkItemEmojiReactionsSchema, ListWorkItemNoteEmojiReactionsSchema, DeleteWorkItemEmojiReactionSchema, DeleteWorkItemNoteEmojiReactionSchema, MoveWorkItemSchema, ListCustomFieldDefinitionsSchema, GetTimelineEventsSchema, CreateTimelineEventSchema, ListWebhooksSchema, ListWebhookEventsSchema, GetWebhookEventSchema, } from "./schemas.js";
37
35
  import { randomUUID } from "node:crypto";
38
36
  import { pino } from "pino";
39
37
  const logger = pino({
@@ -1097,6 +1095,36 @@ async function listIssues(projectId, options = {}) {
1097
1095
  const data = await response.json();
1098
1096
  return z.array(GitLabIssueSchema).parse(data);
1099
1097
  }
1098
+ async function listTodos(options = {}) {
1099
+ const url = new URL(`${getEffectiveApiUrl()}/todos`);
1100
+ Object.entries(options).forEach(([key, value]) => {
1101
+ if (value !== undefined) {
1102
+ url.searchParams.append(key, String(value));
1103
+ }
1104
+ });
1105
+ const response = await fetch(url.toString(), {
1106
+ ...getFetchConfig(),
1107
+ });
1108
+ await handleGitLabError(response);
1109
+ const data = await response.json();
1110
+ return z.array(GitLabTodoSchema).parse(data);
1111
+ }
1112
+ async function markTodoDone(id) {
1113
+ const response = await fetch(`${getEffectiveApiUrl()}/todos/${id}/mark_as_done`, {
1114
+ ...getFetchConfig(),
1115
+ method: "POST",
1116
+ });
1117
+ await handleGitLabError(response);
1118
+ const data = await response.json();
1119
+ return GitLabTodoSchema.parse(data);
1120
+ }
1121
+ async function markAllTodosDone() {
1122
+ const response = await fetch(`${getEffectiveApiUrl()}/todos/mark_as_done`, {
1123
+ ...getFetchConfig(),
1124
+ method: "POST",
1125
+ });
1126
+ await handleGitLabError(response);
1127
+ }
1100
1128
  /**
1101
1129
  * List merge requests globally or for a specific GitLab project
1102
1130
  *
@@ -4769,6 +4797,38 @@ async function getPipelineJobOutput(projectId, jobId, limit, offset) {
4769
4797
  }
4770
4798
  return fullTrace;
4771
4799
  }
4800
+ async function validateCiLint(projectId, options) {
4801
+ projectId = decodeURIComponent(projectId);
4802
+ const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/ci/lint`);
4803
+ const response = await fetch(url.toString(), {
4804
+ ...getFetchConfig(),
4805
+ method: "POST",
4806
+ body: JSON.stringify(options),
4807
+ });
4808
+ await handleGitLabError(response);
4809
+ const data = await response.json();
4810
+ return GitLabCiLintResultSchema.parse(data);
4811
+ }
4812
+ async function validateProjectCiLint(projectId, options) {
4813
+ projectId = decodeURIComponent(projectId);
4814
+ const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(getEffectiveProjectId(projectId))}/ci/lint`);
4815
+ Object.entries(options).forEach(([key, value]) => {
4816
+ if (value !== undefined) {
4817
+ if (typeof value === "boolean") {
4818
+ url.searchParams.append(key, value ? "true" : "false");
4819
+ }
4820
+ else {
4821
+ url.searchParams.append(key, value.toString());
4822
+ }
4823
+ }
4824
+ });
4825
+ const response = await fetch(url.toString(), {
4826
+ ...getFetchConfig(),
4827
+ });
4828
+ await handleGitLabError(response);
4829
+ const data = await response.json();
4830
+ return GitLabCiLintResultSchema.parse(data);
4831
+ }
4772
4832
  /**
4773
4833
  * List artifact files in a job's artifacts archive
4774
4834
  *
@@ -5700,12 +5760,98 @@ async function downloadReleaseAsset(projectId, tagName, directAssetPath) {
5700
5760
  await handleGitLabError(response);
5701
5761
  return await response.text();
5702
5762
  }
5763
+ /**
5764
+ * List repository tags
5765
+ *
5766
+ * @param projectId The ID or URL-encoded path of the project
5767
+ * @param options Optional parameters for filtering and pagination
5768
+ * @returns Array of GitLab tags
5769
+ */
5770
+ async function listTags(projectId, options = {}) {
5771
+ const effectiveProjectId = getEffectiveProjectId(projectId);
5772
+ const url = new URL(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/repository/tags`);
5773
+ Object.entries(options).forEach(([key, value]) => {
5774
+ if (value !== undefined) {
5775
+ url.searchParams.append(key, value.toString());
5776
+ }
5777
+ });
5778
+ const response = await fetch(url.toString(), {
5779
+ ...getFetchConfig(),
5780
+ });
5781
+ await handleGitLabError(response);
5782
+ const data = await response.json();
5783
+ return GitLabTagSchema.array().parse(data);
5784
+ }
5785
+ /**
5786
+ * Get a repository tag by name
5787
+ *
5788
+ * @param projectId The ID or URL-encoded path of the project
5789
+ * @param tagName The name of the tag
5790
+ * @returns GitLab tag
5791
+ */
5792
+ async function getTag(projectId, tagName) {
5793
+ const effectiveProjectId = getEffectiveProjectId(projectId);
5794
+ const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/repository/tags/${encodeURIComponent(tagName)}`, {
5795
+ ...getFetchConfig(),
5796
+ });
5797
+ await handleGitLabError(response);
5798
+ const data = await response.json();
5799
+ return GitLabTagSchema.parse(data);
5800
+ }
5801
+ /**
5802
+ * Create a new repository tag
5803
+ *
5804
+ * @param projectId The ID or URL-encoded path of the project
5805
+ * @param options Options for creating the tag
5806
+ * @returns Created GitLab tag
5807
+ */
5808
+ async function createTag(projectId, options) {
5809
+ const effectiveProjectId = getEffectiveProjectId(projectId);
5810
+ const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/repository/tags`, {
5811
+ ...getFetchConfig(),
5812
+ method: "POST",
5813
+ body: JSON.stringify(options),
5814
+ });
5815
+ await handleGitLabError(response);
5816
+ const data = await response.json();
5817
+ return GitLabTagSchema.parse(data);
5818
+ }
5819
+ /**
5820
+ * Delete a repository tag
5821
+ *
5822
+ * @param projectId The ID or URL-encoded path of the project
5823
+ * @param tagName The name of the tag
5824
+ */
5825
+ async function deleteTag(projectId, tagName) {
5826
+ const effectiveProjectId = getEffectiveProjectId(projectId);
5827
+ const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/repository/tags/${encodeURIComponent(tagName)}`, {
5828
+ ...getFetchConfig(),
5829
+ method: "DELETE",
5830
+ });
5831
+ await handleGitLabError(response);
5832
+ }
5833
+ /**
5834
+ * Get the signature of a repository tag
5835
+ *
5836
+ * @param projectId The ID or URL-encoded path of the project
5837
+ * @param tagName The name of the tag
5838
+ * @returns Tag signature
5839
+ */
5840
+ async function getTagSignature(projectId, tagName) {
5841
+ const effectiveProjectId = getEffectiveProjectId(projectId);
5842
+ const response = await fetch(`${getEffectiveApiUrl()}/projects/${encodeURIComponent(effectiveProjectId)}/repository/tags/${encodeURIComponent(tagName)}/signature`, {
5843
+ ...getFetchConfig(),
5844
+ });
5845
+ await handleGitLabError(response);
5846
+ const data = await response.json();
5847
+ return GitLabTagSignatureSchema.parse(data);
5848
+ }
5703
5849
  // Request handlers are now registered inside createServer() factory function
5704
5850
  // to ensure each transport connection gets its own Server instance (GHSA-345p-7cg4-v4c7).
5705
5851
  async function handleToolCall(params) {
5706
5852
  try {
5707
5853
  if (!params.arguments) {
5708
- throw new Error("Arguments are required");
5854
+ params.arguments = {};
5709
5855
  }
5710
5856
  // Ensure session is established for every request if cookie authentication is enabled
5711
5857
  if (GITLAB_AUTH_COOKIE_PATH) {
@@ -6064,6 +6210,35 @@ async function handleToolCall(params) {
6064
6210
  await deleteRestAwardEmoji(path);
6065
6211
  return { content: [{ type: "text", text: "Issue note emoji reaction deleted successfully" }] };
6066
6212
  }
6213
+ case "list_todos": {
6214
+ const args = ListTodosSchema.parse(params.arguments);
6215
+ const todos = await listTodos(args);
6216
+ return {
6217
+ content: [{ type: "text", text: JSON.stringify(todos, null, 2) }],
6218
+ };
6219
+ }
6220
+ case "mark_todo_done": {
6221
+ const args = MarkTodoDoneSchema.parse(params.arguments);
6222
+ const todo = await markTodoDone(args.id);
6223
+ return {
6224
+ content: [{ type: "text", text: JSON.stringify(todo, null, 2) }],
6225
+ };
6226
+ }
6227
+ case "mark_all_todos_done": {
6228
+ MarkAllTodosDoneSchema.parse(params.arguments);
6229
+ await markAllTodosDone();
6230
+ return {
6231
+ content: [
6232
+ {
6233
+ type: "text",
6234
+ text: JSON.stringify({
6235
+ status: "success",
6236
+ message: "All pending to-do items marked as done",
6237
+ }, null, 2),
6238
+ },
6239
+ ],
6240
+ };
6241
+ }
6067
6242
  case "get_merge_request": {
6068
6243
  const args = GetMergeRequestSchema.parse(params.arguments);
6069
6244
  const mergeRequest = await getMergeRequest(args.project_id, args.merge_request_iid, args.source_branch);
@@ -6816,6 +6991,22 @@ async function handleToolCall(params) {
6816
6991
  ],
6817
6992
  };
6818
6993
  }
6994
+ case "validate_ci_lint": {
6995
+ const args = ValidateCiLintSchema.parse(params.arguments);
6996
+ const { project_id, ...options } = args;
6997
+ const result = await validateCiLint(project_id, options);
6998
+ return {
6999
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
7000
+ };
7001
+ }
7002
+ case "validate_project_ci_lint": {
7003
+ const args = ValidateProjectCiLintSchema.parse(params.arguments);
7004
+ const { project_id, ...options } = args;
7005
+ const result = await validateProjectCiLint(project_id, options);
7006
+ return {
7007
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
7008
+ };
7009
+ }
6819
7010
  case "create_pipeline": {
6820
7011
  const { project_id, ref, variables, inputs } = CreatePipelineSchema.parse(params.arguments);
6821
7012
  const pipeline = await createPipeline(project_id, ref, variables, inputs);
@@ -7191,6 +7382,48 @@ async function handleToolCall(params) {
7191
7382
  content: [{ type: "text", text: assetContent }],
7192
7383
  };
7193
7384
  }
7385
+ case "list_tags": {
7386
+ const args = ListTagsSchema.parse(params.arguments);
7387
+ const { project_id, ...options } = args;
7388
+ const tags = await listTags(project_id, options);
7389
+ return {
7390
+ content: [{ type: "text", text: JSON.stringify(tags, null, 2) }],
7391
+ };
7392
+ }
7393
+ case "get_tag": {
7394
+ const args = GetTagSchema.parse(params.arguments);
7395
+ const tag = await getTag(args.project_id, args.tag_name);
7396
+ return {
7397
+ content: [{ type: "text", text: JSON.stringify(tag, null, 2) }],
7398
+ };
7399
+ }
7400
+ case "create_tag": {
7401
+ const args = CreateTagSchema.parse(params.arguments);
7402
+ const { project_id, ...options } = args;
7403
+ const tag = await createTag(project_id, options);
7404
+ return {
7405
+ content: [{ type: "text", text: JSON.stringify(tag, null, 2) }],
7406
+ };
7407
+ }
7408
+ case "delete_tag": {
7409
+ const args = DeleteTagSchema.parse(params.arguments);
7410
+ await deleteTag(args.project_id, args.tag_name);
7411
+ return {
7412
+ content: [
7413
+ {
7414
+ type: "text",
7415
+ text: JSON.stringify({ status: "success", message: `Tag '${args.tag_name}' deleted successfully` }, null, 2),
7416
+ },
7417
+ ],
7418
+ };
7419
+ }
7420
+ case "get_tag_signature": {
7421
+ const args = GetTagSignatureSchema.parse(params.arguments);
7422
+ const signature = await getTagSignature(args.project_id, args.tag_name);
7423
+ return {
7424
+ content: [{ type: "text", text: JSON.stringify(signature, null, 2) }],
7425
+ };
7426
+ }
7194
7427
  case "list_webhooks": {
7195
7428
  const args = ListWebhooksSchema.parse(params.arguments);
7196
7429
  const webhooks = await listWebhooks(args);
package/build/schemas.js CHANGED
@@ -275,6 +275,34 @@ export const ListPipelineTriggerJobsSchema = z
275
275
  .describe("The scope of trigger jobs to show"),
276
276
  })
277
277
  .merge(PaginationOptionsSchema);
278
+ export const GitLabCiLintResultSchema = z.object({
279
+ valid: z.coerce.boolean(),
280
+ errors: z.array(z.string()),
281
+ warnings: z.array(z.string()).optional(),
282
+ merged_yaml: z.string().optional(),
283
+ includes: z.array(z.unknown()).optional(),
284
+ jobs: z.array(z.unknown()).optional(),
285
+ });
286
+ export const ValidateCiLintSchema = z.object({
287
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
288
+ content: z.string().describe("GitLab CI/CD YAML content to validate"),
289
+ dry_run: z.coerce.boolean().optional().describe("Run pipeline creation simulation"),
290
+ include_jobs: z.coerce.boolean().optional().describe("Include jobs in the lint response"),
291
+ ref: z.string().optional().describe("Branch or tag context for dry_run validation"),
292
+ });
293
+ export const ValidateProjectCiLintSchema = z.object({
294
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
295
+ content_ref: z
296
+ .string()
297
+ .optional()
298
+ .describe("Commit SHA, branch, or tag to read the existing CI config from"),
299
+ dry_run: z.coerce.boolean().optional().describe("Run pipeline creation simulation"),
300
+ dry_run_ref: z
301
+ .string()
302
+ .optional()
303
+ .describe("Branch or tag context for dry_run validation"),
304
+ include_jobs: z.coerce.boolean().optional().describe("Include jobs in the lint response"),
305
+ });
278
306
  // Deployment related schemas
279
307
  export const GitLabDeploymentSchema = z.object({
280
308
  id: z.coerce.string(),
@@ -1234,6 +1262,60 @@ export const CreateIssueSchema = ProjectParamsSchema.extend({
1234
1262
  .describe("The type of issue. One of issue, incident, test_case or task."),
1235
1263
  weight: z.coerce.number().optional().describe("Weight of the issue (numeric, typically hours of work)"),
1236
1264
  });
1265
+ export const GitLabTodoSchema = z.object({
1266
+ id: z.coerce.number(),
1267
+ project: z.unknown().optional(),
1268
+ author: z.unknown().optional(),
1269
+ action_name: z.string().optional(),
1270
+ target_type: z.string().optional(),
1271
+ target: z.unknown().optional(),
1272
+ target_url: z.string().optional(),
1273
+ body: z.string().optional(),
1274
+ state: z.string(),
1275
+ created_at: z.string().optional(),
1276
+ updated_at: z.string().optional(),
1277
+ });
1278
+ export const ListTodosSchema = z
1279
+ .object({
1280
+ action: z
1281
+ .enum([
1282
+ "assigned",
1283
+ "mentioned",
1284
+ "build_failed",
1285
+ "marked",
1286
+ "approval_required",
1287
+ "unmergeable",
1288
+ "directly_addressed",
1289
+ "merge_train_removed",
1290
+ "member_access_requested",
1291
+ ])
1292
+ .optional()
1293
+ .describe("Filter by to-do action"),
1294
+ author_id: z.coerce.number().optional().describe("Filter by author ID"),
1295
+ project_id: z.coerce.number().optional().describe("Filter by project ID"),
1296
+ group_id: z.coerce.number().optional().describe("Filter by group ID"),
1297
+ state: z.enum(["pending", "done"]).optional().describe("Filter by to-do state"),
1298
+ type: z
1299
+ .enum([
1300
+ "Issue",
1301
+ "MergeRequest",
1302
+ "Commit",
1303
+ "Epic",
1304
+ "DesignManagement::Design",
1305
+ "AlertManagement::Alert",
1306
+ "Project",
1307
+ "Namespace",
1308
+ "Vulnerability",
1309
+ "WikiPage::Meta",
1310
+ ])
1311
+ .optional()
1312
+ .describe("Filter by to-do target type"),
1313
+ })
1314
+ .merge(PaginationOptionsSchema);
1315
+ export const MarkTodoDoneSchema = z.object({
1316
+ id: z.coerce.number().describe("The ID of the to-do item"),
1317
+ });
1318
+ export const MarkAllTodosDoneSchema = z.object({});
1237
1319
  const MergeRequestOptionsSchema = {
1238
1320
  title: z.string().describe("Merge request title"),
1239
1321
  description: z.string().optional().describe("Merge request description"),
@@ -2570,6 +2652,84 @@ export const DownloadReleaseAssetSchema = z.object({
2570
2652
  .string()
2571
2653
  .describe("Path to the release asset file as specified when creating or updating its link"),
2572
2654
  });
2655
+ // Tag schemas
2656
+ export const ListTagsSchema = z
2657
+ .object({
2658
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2659
+ order_by: z
2660
+ .enum(["name", "updated", "version"])
2661
+ .optional()
2662
+ .describe("Return tags ordered by name, updated, or version. Default is updated."),
2663
+ sort: z.enum(["asc", "desc"]).optional().describe("Sort direction"),
2664
+ search: z
2665
+ .string()
2666
+ .optional()
2667
+ .describe("Restrict on tag name. You can use ^term and term$ to find tags that begin and end with term. No other regular expressions are supported."),
2668
+ })
2669
+ .merge(PaginationOptionsSchema);
2670
+ export const GetTagSchema = z.object({
2671
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2672
+ tag_name: z.string().describe("The name of the tag"),
2673
+ });
2674
+ export const CreateTagSchema = z.object({
2675
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2676
+ tag_name: z.string().describe("The name of the tag"),
2677
+ ref: z.string().describe("Create tag using commit SHA, another tag name, or branch name"),
2678
+ message: z.string().optional().describe("Create annotated tag with message"),
2679
+ });
2680
+ export const DeleteTagSchema = z.object({
2681
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2682
+ tag_name: z.string().describe("The name of the tag"),
2683
+ });
2684
+ export const GetTagSignatureSchema = z.object({
2685
+ project_id: z.coerce.string().describe("Project ID or URL-encoded path"),
2686
+ tag_name: z.string().describe("The name of the tag"),
2687
+ });
2688
+ export const GitLabTagSchema = z.object({
2689
+ name: z.string(),
2690
+ message: z.string().nullable(),
2691
+ target: z.string(),
2692
+ commit: z.object({
2693
+ id: z.string(),
2694
+ short_id: z.string(),
2695
+ title: z.string(),
2696
+ created_at: z.string(),
2697
+ parent_ids: z.array(z.string()),
2698
+ message: z.string(),
2699
+ author_name: z.string(),
2700
+ author_email: z.string(),
2701
+ authored_date: z.string(),
2702
+ committer_name: z.string(),
2703
+ committer_email: z.string(),
2704
+ committed_date: z.string(),
2705
+ }),
2706
+ release: z
2707
+ .object({
2708
+ tag_name: z.string(),
2709
+ description: z.string(),
2710
+ })
2711
+ .nullable(),
2712
+ protected: z.boolean(),
2713
+ created_at: z.string().nullable(),
2714
+ });
2715
+ export const GitLabTagSignatureSchema = z.object({
2716
+ signature_type: z.literal("X509"),
2717
+ verification_status: z.string(),
2718
+ x509_certificate: z.object({
2719
+ id: z.number(),
2720
+ subject: z.string(),
2721
+ subject_key_identifier: z.string(),
2722
+ email: z.string().nullable().optional(),
2723
+ serial_number: z.number(),
2724
+ certificate_status: z.string(),
2725
+ x509_issuer: z.object({
2726
+ id: z.number(),
2727
+ subject: z.string(),
2728
+ subject_key_identifier: z.string(),
2729
+ crl_url: z.string().nullable().optional(),
2730
+ }),
2731
+ }),
2732
+ });
2573
2733
  // --- Work item schemas (GraphQL-based) ---
2574
2734
  // Case-insensitive work item type enum (accepts "ISSUE", "Issue", "issue")
2575
2735
  const workItemTypeEnum = z.string().transform(v => v.toLowerCase()).pipe(z.enum(["issue", "task", "incident", "test_case", "epic", "key_result", "objective", "requirement", "ticket"]));