@zereight/mcp-gitlab 2.0.36 → 2.1.1

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.
@@ -16,8 +16,8 @@ const MOCK_PORT_BASE = 9200;
16
16
  const MCP_PORT_BASE = 3200;
17
17
  // Known tool counts per toolset (from TOOLSET_DEFINITIONS)
18
18
  const TOOLSET_TOOL_COUNTS = {
19
- merge_requests: 34,
20
- issues: 14,
19
+ merge_requests: 40,
20
+ issues: 20,
21
21
  repositories: 7,
22
22
  branches: 4,
23
23
  projects: 8,
@@ -28,7 +28,7 @@ const TOOLSET_TOOL_COUNTS = {
28
28
  releases: 7,
29
29
  users: 5,
30
30
  search: 3,
31
- workitems: 12,
31
+ workitems: 18,
32
32
  webhooks: 3,
33
33
  };
34
34
  const DEFAULT_TOOLSETS = [
@@ -38,15 +38,13 @@ const DEFAULT_TOOLSETS = [
38
38
  "branches",
39
39
  "projects",
40
40
  "labels",
41
- "pipelines",
42
- "milestones",
43
- "wiki",
44
- "releases",
45
41
  "users",
46
42
  ];
47
- const NON_DEFAULT_TOOLSETS = ["search", "webhooks"];
48
- const DEFAULT_TOOL_COUNT = DEFAULT_TOOLSETS.reduce((sum, id) => sum + TOOLSET_TOOL_COUNTS[id], 0);
49
- const ALL_TOOLSET_TOOL_COUNT = Object.values(TOOLSET_TOOL_COUNTS).reduce((sum, c) => sum + c, 0);
43
+ const NON_DEFAULT_TOOLSETS = ["pipelines", "milestones", "wiki", "releases", "workitems", "webhooks", "search"];
44
+ // discover_tools meta-tool is always force-injected (Step 5.5)
45
+ const DISCOVER_TOOLS_COUNT = 1;
46
+ const DEFAULT_TOOL_COUNT = DEFAULT_TOOLSETS.reduce((sum, id) => sum + TOOLSET_TOOL_COUNTS[id], 0) + DISCOVER_TOOLS_COUNT;
47
+ const ALL_TOOLSET_TOOL_COUNT = Object.values(TOOLSET_TOOL_COUNTS).reduce((sum, c) => sum + c, 0) + DISCOVER_TOOLS_COUNT;
50
48
  // Representative tools per toolset for spot-checking
51
49
  const TOOLSET_SAMPLE_TOOLS = {
52
50
  merge_requests: ["merge_merge_request", "create_merge_request_thread", "list_draft_notes"],
@@ -136,8 +134,10 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
136
134
  assertContainsAll(tools, TOOLSET_SAMPLE_TOOLS[id], id);
137
135
  }
138
136
  });
139
- test("excludes non-default toolsets (search)", () => {
137
+ test("excludes non-default toolsets (search, pipelines, wiki)", () => {
140
138
  assertContainsNone(tools, TOOLSET_SAMPLE_TOOLS.search, "non-default search");
139
+ assertContainsNone(tools, TOOLSET_SAMPLE_TOOLS.pipelines, "non-default pipelines");
140
+ assertContainsNone(tools, TOOLSET_SAMPLE_TOOLS.wiki, "non-default wiki");
141
141
  });
142
142
  test("excludes execute_graphql (not in any toolset)", () => {
143
143
  assertContainsNone(tools, ["execute_graphql"], "unassigned");
@@ -155,8 +155,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
155
155
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
156
156
  });
157
157
  after(() => cleanupServers([server]));
158
- test("returns only issue tools", () => {
159
- assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues);
158
+ test("returns only issue tools + discover_tools", () => {
159
+ assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues + DISCOVER_TOOLS_COUNT);
160
160
  });
161
161
  test("includes issue sample tools", () => {
162
162
  assertContainsAll(tools, TOOLSET_SAMPLE_TOOLS.issues, "issues");
@@ -201,14 +201,14 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
201
201
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
202
202
  });
203
203
  after(() => cleanupServers([server]));
204
- test("returns default tools plus execute_graphql (list_pipelines already in default)", () => {
205
- assert.strictEqual(tools.length, DEFAULT_TOOL_COUNT + 1);
204
+ test("returns default tools plus list_pipelines and execute_graphql (both not in default toolsets)", () => {
205
+ assert.strictEqual(tools.length, DEFAULT_TOOL_COUNT + 2);
206
206
  });
207
207
  test("includes the individually added tools", () => {
208
208
  assertContainsAll(tools, ["list_pipelines", "execute_graphql"], "individual");
209
209
  });
210
- test("includes pipeline tools from default toolset", () => {
211
- assertContainsAll(tools, ["create_pipeline", "cancel_pipeline"], "default pipelines");
210
+ test("excludes other pipeline tools (not individually enabled)", () => {
211
+ assertContainsNone(tools, ["create_pipeline", "cancel_pipeline"], "non-enabled pipelines");
212
212
  });
213
213
  });
214
214
  // ---- 5. Toolset + individual tools combined ----
@@ -224,8 +224,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
224
224
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
225
225
  });
226
226
  after(() => cleanupServers([server]));
227
- test("returns issue tools + 2 individual pipeline tools", () => {
228
- assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues + 2);
227
+ test("returns issue tools + 2 individual pipeline tools + discover_tools", () => {
228
+ assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues + 2 + DISCOVER_TOOLS_COUNT);
229
229
  });
230
230
  test("includes issue tools and the two pipeline tools", () => {
231
231
  assertContainsAll(tools, TOOLSET_SAMPLE_TOOLS.issues, "issues");
@@ -248,8 +248,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
248
248
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
249
249
  });
250
250
  after(() => cleanupServers([server]));
251
- test("returns issue tools + all pipeline tools", () => {
252
- assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues + TOOLSET_TOOL_COUNTS.pipelines);
251
+ test("returns issue tools + all pipeline tools + discover_tools", () => {
252
+ assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues + TOOLSET_TOOL_COUNTS.pipelines + DISCOVER_TOOLS_COUNT);
253
253
  });
254
254
  test("includes all pipeline tools via legacy flag", () => {
255
255
  assertContainsAll(tools, TOOLSET_SAMPLE_TOOLS.pipelines, "pipelines");
@@ -267,8 +267,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
267
267
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
268
268
  });
269
269
  after(() => cleanupServers([server]));
270
- test("returns default tool count (wiki is already default)", () => {
271
- assert.strictEqual(tools.length, DEFAULT_TOOL_COUNT);
270
+ test("returns default tools + wiki tools (wiki is NOT default, USE_GITLAB_WIKI adds it)", () => {
271
+ assert.strictEqual(tools.length, DEFAULT_TOOL_COUNT + TOOLSET_TOOL_COUNTS.wiki);
272
272
  });
273
273
  test("includes wiki tools", () => {
274
274
  assertContainsAll(tools, TOOLSET_SAMPLE_TOOLS.wiki, "wiki");
@@ -286,6 +286,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
286
286
  "list_issue_links",
287
287
  "list_issue_discussions",
288
288
  "get_issue_link",
289
+ "list_issue_emoji_reactions",
290
+ "list_issue_note_emoji_reactions",
289
291
  ];
290
292
  const writeIssueTools = [
291
293
  "create_issue",
@@ -296,6 +298,10 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
296
298
  "create_issue_link",
297
299
  "delete_issue_link",
298
300
  "create_note",
301
+ "create_issue_emoji_reaction",
302
+ "delete_issue_emoji_reaction",
303
+ "create_issue_note_emoji_reaction",
304
+ "delete_issue_note_emoji_reaction",
299
305
  ];
300
306
  before(async () => {
301
307
  const port = await nextMcpPort();
@@ -312,8 +318,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
312
318
  test("excludes write issue tools", () => {
313
319
  assertContainsNone(tools, writeIssueTools, "write issues");
314
320
  });
315
- test("returns correct count", () => {
316
- assert.strictEqual(tools.length, readOnlyIssueTools.length);
321
+ test("returns correct count (read-only issues + discover_tools)", () => {
322
+ assert.strictEqual(tools.length, readOnlyIssueTools.length + DISCOVER_TOOLS_COUNT);
317
323
  });
318
324
  });
319
325
  // ---- 9. GITLAB_DENIED_TOOLS_REGEX applied after toolset filter ----
@@ -378,8 +384,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
378
384
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
379
385
  });
380
386
  after(() => cleanupServers([server]));
381
- test("returns exactly pipeline tool count (no duplicates)", () => {
382
- assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.pipelines);
387
+ test("returns exactly pipeline tool count + discover_tools (no duplicates)", () => {
388
+ assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.pipelines + DISCOVER_TOOLS_COUNT);
383
389
  });
384
390
  });
385
391
  // ---- 12. GITLAB_TOOLS with tool already in enabled toolset (no dupes) ----
@@ -395,8 +401,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
395
401
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
396
402
  });
397
403
  after(() => cleanupServers([server]));
398
- test("returns exactly issue tool count (no duplicates)", () => {
399
- assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues);
404
+ test("returns exactly issue tool count + discover_tools (no duplicates)", () => {
405
+ assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues + DISCOVER_TOOLS_COUNT);
400
406
  });
401
407
  });
402
408
  // ---- 13. Invalid toolset ID is silently ignored ----
@@ -411,8 +417,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
411
417
  tools = await getToolNames(`http://${HOST}:${port}/mcp`);
412
418
  });
413
419
  after(() => cleanupServers([server]));
414
- test("returns only issue tools (invalid toolset ignored)", () => {
415
- assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues);
420
+ test("returns only issue tools + discover_tools (invalid toolset ignored)", () => {
421
+ assert.strictEqual(tools.length, TOOLSET_TOOL_COUNTS.issues + DISCOVER_TOOLS_COUNT);
416
422
  });
417
423
  });
418
424
  // ---- 14. GITLAB_TOOLS case-insensitive matching ----
@@ -430,8 +436,8 @@ describe("Toolset Filtering", { concurrency: 1 }, () => {
430
436
  test("resolves mixed-case tool names to lowercase equivalents", () => {
431
437
  assertContainsAll(tools, ["list_pipelines", "execute_graphql"], "case-insensitive tools");
432
438
  });
433
- test("returns default tools plus execute_graphql (list_pipelines already in default)", () => {
434
- assert.strictEqual(tools.length, DEFAULT_TOOL_COUNT + 1);
439
+ test("returns default tools plus list_pipelines and execute_graphql", () => {
440
+ assert.strictEqual(tools.length, DEFAULT_TOOL_COUNT + 2);
435
441
  });
436
442
  });
437
443
  // ---- 15. GITLAB_TOOLS with unknown tool names ----