@testkase/mcp-server 1.0.1 → 2.0.0
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/PAT_APIS_INVENTORY.csv +27 -0
- package/README.md +90 -30
- package/build/index.js +1018 -1
- package/build/index.js.map +1 -1
- package/package.json +6 -32
- package/src/index.ts +0 -302
- package/src/test-config.ts +0 -89
- package/tsconfig.json +0 -19
package/build/index.js
CHANGED
|
@@ -92,6 +92,416 @@ const GET_TESTCASES_TOOL = {
|
|
|
92
92
|
required: ["projectId", "organizationId"],
|
|
93
93
|
},
|
|
94
94
|
};
|
|
95
|
+
const GET_TESTCASE_DETAIL_TOOL = {
|
|
96
|
+
name: "get_testcase_detail",
|
|
97
|
+
description: "Get detailed information about a specific testcase including all fields, test steps, attachments, and related data. " +
|
|
98
|
+
"Use this tool to retrieve complete information about a single testcase.",
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: "object",
|
|
101
|
+
properties: {
|
|
102
|
+
projectId: {
|
|
103
|
+
type: "string",
|
|
104
|
+
description: "The unique identifier of the project",
|
|
105
|
+
},
|
|
106
|
+
testcaseId: {
|
|
107
|
+
type: "string",
|
|
108
|
+
description: "The unique identifier of the testcase",
|
|
109
|
+
},
|
|
110
|
+
organizationId: {
|
|
111
|
+
type: "number",
|
|
112
|
+
description: "The organization ID that owns the project",
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
required: ["projectId", "testcaseId", "organizationId"],
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
const GET_TESTCASE_HISTORY_TOOL = {
|
|
119
|
+
name: "get_testcase_history",
|
|
120
|
+
description: "Get the complete history of changes made to a testcase. " +
|
|
121
|
+
"Returns a list of all modifications with timestamps, user information, and changed fields. " +
|
|
122
|
+
"Useful for tracking testcase evolution and audit trails.",
|
|
123
|
+
inputSchema: {
|
|
124
|
+
type: "object",
|
|
125
|
+
properties: {
|
|
126
|
+
projectId: {
|
|
127
|
+
type: "string",
|
|
128
|
+
description: "The unique identifier of the project",
|
|
129
|
+
},
|
|
130
|
+
testcaseId: {
|
|
131
|
+
type: "string",
|
|
132
|
+
description: "The unique identifier of the testcase",
|
|
133
|
+
},
|
|
134
|
+
organizationId: {
|
|
135
|
+
type: "number",
|
|
136
|
+
description: "The organization ID that owns the project",
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
required: ["projectId", "testcaseId", "organizationId"],
|
|
140
|
+
},
|
|
141
|
+
};
|
|
142
|
+
const GET_FOLDERS_TOOL = {
|
|
143
|
+
name: "get_folders",
|
|
144
|
+
description: "Get the folder/section structure of a project. " +
|
|
145
|
+
"Returns a hierarchical list of folders and sections used to organize testcases. " +
|
|
146
|
+
"Useful for understanding project organization and navigating testcase structure.",
|
|
147
|
+
inputSchema: {
|
|
148
|
+
type: "object",
|
|
149
|
+
properties: {
|
|
150
|
+
organizationId: {
|
|
151
|
+
type: "number",
|
|
152
|
+
description: "The organization ID",
|
|
153
|
+
},
|
|
154
|
+
projectId: {
|
|
155
|
+
type: "string",
|
|
156
|
+
description: "The unique identifier of the project",
|
|
157
|
+
},
|
|
158
|
+
folder_id: {
|
|
159
|
+
type: "string",
|
|
160
|
+
description: "Optional: Filter by specific folder ID",
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
required: ["organizationId", "projectId"],
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
const GET_LABELS_TOOL = {
|
|
167
|
+
name: "get_labels",
|
|
168
|
+
description: "Get all labels/tags available in a project. " +
|
|
169
|
+
"Labels are used to categorize and filter testcases. " +
|
|
170
|
+
"Returns label names, colors, and usage counts.",
|
|
171
|
+
inputSchema: {
|
|
172
|
+
type: "object",
|
|
173
|
+
properties: {
|
|
174
|
+
projectId: {
|
|
175
|
+
type: "string",
|
|
176
|
+
description: "The unique identifier of the project",
|
|
177
|
+
},
|
|
178
|
+
organizationId: {
|
|
179
|
+
type: "number",
|
|
180
|
+
description: "The organization ID",
|
|
181
|
+
},
|
|
182
|
+
},
|
|
183
|
+
required: ["projectId", "organizationId"],
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
const GET_ISSUES_TOOL = {
|
|
187
|
+
name: "get_issues",
|
|
188
|
+
description: "Get all issues/defects reported in a project. " +
|
|
189
|
+
"Returns a list of issues with their status, priority, and linked testcases. " +
|
|
190
|
+
"Useful for tracking bugs and defects found during testing.",
|
|
191
|
+
inputSchema: {
|
|
192
|
+
type: "object",
|
|
193
|
+
properties: {
|
|
194
|
+
projectId: {
|
|
195
|
+
type: "string",
|
|
196
|
+
description: "The unique identifier of the project",
|
|
197
|
+
},
|
|
198
|
+
organizationId: {
|
|
199
|
+
type: "number",
|
|
200
|
+
description: "The organization ID",
|
|
201
|
+
},
|
|
202
|
+
page: {
|
|
203
|
+
type: "number",
|
|
204
|
+
description: "Page number for pagination (default: 1)",
|
|
205
|
+
},
|
|
206
|
+
limit: {
|
|
207
|
+
type: "number",
|
|
208
|
+
description: "Number of items per page (default: 20)",
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
required: ["projectId", "organizationId"],
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
const GET_MY_PROJECTS_TOOL = {
|
|
215
|
+
name: "get_my_projects",
|
|
216
|
+
description: "Get all projects that the current user (PAT token owner) has access to across all organizations. " +
|
|
217
|
+
"Returns project details including name, ID, organization, and team members. " +
|
|
218
|
+
"Useful for discovering available projects and their basic information.",
|
|
219
|
+
inputSchema: {
|
|
220
|
+
type: "object",
|
|
221
|
+
properties: {
|
|
222
|
+
page: {
|
|
223
|
+
type: "number",
|
|
224
|
+
description: "Page number for pagination (default: 1)",
|
|
225
|
+
},
|
|
226
|
+
limit: {
|
|
227
|
+
type: "number",
|
|
228
|
+
description: "Number of items per page (default: 12)",
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
required: [],
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
const CREATE_TESTCASE_TOOL = {
|
|
235
|
+
name: "create_testcase",
|
|
236
|
+
description: "Create a new test case with optional test steps and metadata",
|
|
237
|
+
inputSchema: {
|
|
238
|
+
type: "object",
|
|
239
|
+
properties: {
|
|
240
|
+
projectId: { type: "string", description: "Project ID" },
|
|
241
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
242
|
+
title: { type: "string", description: "Test case title" },
|
|
243
|
+
summary: { type: "string", description: "Test case summary/description" },
|
|
244
|
+
priority: { type: "string", description: "Priority (low, medium, high, critical)" },
|
|
245
|
+
status: { type: "string", description: "Status" },
|
|
246
|
+
folder_id: { type: "string", description: "Folder ID" },
|
|
247
|
+
labels: { type: "array", items: { type: "string" }, description: "Label IDs" },
|
|
248
|
+
automated: { type: "boolean", description: "Is automated test" },
|
|
249
|
+
test_steps: { type: "array", description: "Array of test steps" },
|
|
250
|
+
},
|
|
251
|
+
required: ["projectId", "organizationId", "title"],
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
const CREATE_BULK_TESTCASE_TOOL = {
|
|
255
|
+
name: "create_bulk_testcase",
|
|
256
|
+
description: "Create multiple test cases at once in bulk",
|
|
257
|
+
inputSchema: {
|
|
258
|
+
type: "object",
|
|
259
|
+
properties: {
|
|
260
|
+
projectId: { type: "string", description: "Project ID" },
|
|
261
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
262
|
+
testcases: { type: "string", description: "JSON string of testcase array" },
|
|
263
|
+
},
|
|
264
|
+
required: ["projectId", "organizationId", "testcases"],
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
const UPDATE_TESTCASE_FIELD_TOOL = {
|
|
268
|
+
name: "update_testcase_field",
|
|
269
|
+
description: "Update a single field for one or multiple test cases",
|
|
270
|
+
inputSchema: {
|
|
271
|
+
type: "object",
|
|
272
|
+
properties: {
|
|
273
|
+
projectId: { type: "string", description: "Project ID" },
|
|
274
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
275
|
+
ids: { type: "string", description: "Comma-separated testcase IDs" },
|
|
276
|
+
field: { type: "string", description: "Field name to update" },
|
|
277
|
+
value: { type: "string", description: "New field value" },
|
|
278
|
+
},
|
|
279
|
+
required: ["projectId", "organizationId", "ids", "field", "value"],
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
const DELETE_TESTCASE_TOOL = {
|
|
283
|
+
name: "delete_testcase",
|
|
284
|
+
description: "Delete single or multiple test cases",
|
|
285
|
+
inputSchema: {
|
|
286
|
+
type: "object",
|
|
287
|
+
properties: {
|
|
288
|
+
projectId: { type: "string", description: "Project ID" },
|
|
289
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
290
|
+
ids: { type: "string", description: "Comma-separated testcase IDs to delete" },
|
|
291
|
+
},
|
|
292
|
+
required: ["projectId", "organizationId", "ids"],
|
|
293
|
+
},
|
|
294
|
+
};
|
|
295
|
+
const CLONE_TESTCASE_TOOL = {
|
|
296
|
+
name: "clone_testcase",
|
|
297
|
+
description: "Clone an existing test case with all its steps",
|
|
298
|
+
inputSchema: {
|
|
299
|
+
type: "object",
|
|
300
|
+
properties: {
|
|
301
|
+
projectId: { type: "string", description: "Project ID" },
|
|
302
|
+
id: { type: "string", description: "Test case ID to clone" },
|
|
303
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
304
|
+
},
|
|
305
|
+
required: ["projectId", "id", "organizationId"],
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
const CREATE_TEST_STEP_TOOL = {
|
|
309
|
+
name: "create_test_step",
|
|
310
|
+
description: "Create or update test steps for a test case",
|
|
311
|
+
inputSchema: {
|
|
312
|
+
type: "object",
|
|
313
|
+
properties: {
|
|
314
|
+
projectId: { type: "string", description: "Project ID" },
|
|
315
|
+
testcaseId: { type: "string", description: "Test case ID" },
|
|
316
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
317
|
+
steps: { type: "string", description: "JSON string of test steps array" },
|
|
318
|
+
},
|
|
319
|
+
required: ["projectId", "testcaseId", "organizationId", "steps"],
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
const DELETE_TEST_STEP_TOOL = {
|
|
323
|
+
name: "delete_test_step",
|
|
324
|
+
description: "Delete test steps from a test case",
|
|
325
|
+
inputSchema: {
|
|
326
|
+
type: "object",
|
|
327
|
+
properties: {
|
|
328
|
+
testcaseId: { type: "string", description: "Test case ID" },
|
|
329
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
330
|
+
stepIds: { type: "string", description: "Comma-separated step IDs to delete" },
|
|
331
|
+
},
|
|
332
|
+
required: ["testcaseId", "organizationId", "stepIds"],
|
|
333
|
+
},
|
|
334
|
+
};
|
|
335
|
+
const DOWNLOAD_TESTCASES_TOOL = {
|
|
336
|
+
name: "download_testcases",
|
|
337
|
+
description: "Download test cases as CSV file (returns download URL or data)",
|
|
338
|
+
inputSchema: {
|
|
339
|
+
type: "object",
|
|
340
|
+
properties: {
|
|
341
|
+
projectId: { type: "string", description: "Project ID" },
|
|
342
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
343
|
+
filters: { type: "string", description: "Optional filters as JSON string" },
|
|
344
|
+
},
|
|
345
|
+
required: ["projectId", "organizationId"],
|
|
346
|
+
},
|
|
347
|
+
};
|
|
348
|
+
const IMPORT_TESTCASES_TOOL = {
|
|
349
|
+
name: "import_testcases",
|
|
350
|
+
description: "Import test cases from a CSV file",
|
|
351
|
+
inputSchema: {
|
|
352
|
+
type: "object",
|
|
353
|
+
properties: {
|
|
354
|
+
projectId: { type: "string", description: "Project ID" },
|
|
355
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
356
|
+
file: { type: "string", description: "File data or path" },
|
|
357
|
+
},
|
|
358
|
+
required: ["projectId", "organizationId", "file"],
|
|
359
|
+
},
|
|
360
|
+
};
|
|
361
|
+
const CREATE_FOLDER_TOOL = {
|
|
362
|
+
name: "create_folder",
|
|
363
|
+
description: "Create a new folder in a project",
|
|
364
|
+
inputSchema: {
|
|
365
|
+
type: "object",
|
|
366
|
+
properties: {
|
|
367
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
368
|
+
projectId: { type: "string", description: "Project ID" },
|
|
369
|
+
folder_name: { type: "string", description: "Name of the new folder" },
|
|
370
|
+
parent_folder_id: { type: "string", description: "Parent folder ID (optional)" },
|
|
371
|
+
},
|
|
372
|
+
required: ["organizationId", "projectId", "folder_name"],
|
|
373
|
+
},
|
|
374
|
+
};
|
|
375
|
+
const DELETE_FOLDER_TOOL = {
|
|
376
|
+
name: "delete_folder",
|
|
377
|
+
description: "Delete a folder and its subfolders",
|
|
378
|
+
inputSchema: {
|
|
379
|
+
type: "object",
|
|
380
|
+
properties: {
|
|
381
|
+
id: { type: "string", description: "Folder ID to delete" },
|
|
382
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
383
|
+
},
|
|
384
|
+
required: ["id", "organizationId"],
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
const UPDATE_FOLDER_TOOL = {
|
|
388
|
+
name: "update_folder",
|
|
389
|
+
description: "Rename or update folder details",
|
|
390
|
+
inputSchema: {
|
|
391
|
+
type: "object",
|
|
392
|
+
properties: {
|
|
393
|
+
id: { type: "string", description: "Folder ID" },
|
|
394
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
395
|
+
folder_name: { type: "string", description: "New folder name" },
|
|
396
|
+
},
|
|
397
|
+
required: ["id", "organizationId", "folder_name"],
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
const CREATE_LABEL_TOOL = {
|
|
401
|
+
name: "create_label",
|
|
402
|
+
description: "Create new labels for a project",
|
|
403
|
+
inputSchema: {
|
|
404
|
+
type: "object",
|
|
405
|
+
properties: {
|
|
406
|
+
projectId: { type: "string", description: "Project ID" },
|
|
407
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
408
|
+
values: { type: "array", items: { type: "string" }, description: "Array of label names" },
|
|
409
|
+
},
|
|
410
|
+
required: ["projectId", "organizationId", "values"],
|
|
411
|
+
},
|
|
412
|
+
};
|
|
413
|
+
const GET_USER_PROFILE_TOOL = {
|
|
414
|
+
name: "get_user_profile",
|
|
415
|
+
description: "Get current logged-in user profile information",
|
|
416
|
+
inputSchema: {
|
|
417
|
+
type: "object",
|
|
418
|
+
properties: {},
|
|
419
|
+
required: [],
|
|
420
|
+
},
|
|
421
|
+
};
|
|
422
|
+
const GET_ORGANIZATION_TOOL = {
|
|
423
|
+
name: "get_organization",
|
|
424
|
+
description: "Get current user organization details",
|
|
425
|
+
inputSchema: {
|
|
426
|
+
type: "object",
|
|
427
|
+
properties: {},
|
|
428
|
+
required: [],
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
const GET_MAPPED_ISSUES_TOOL = {
|
|
432
|
+
name: "get_mapped_issues",
|
|
433
|
+
description: "Get mapped issues for a specific test case from integration platforms",
|
|
434
|
+
inputSchema: {
|
|
435
|
+
type: "object",
|
|
436
|
+
properties: {
|
|
437
|
+
organization_id: { type: "number", description: "Organization ID" },
|
|
438
|
+
project_id: { type: "string", description: "Project ID" },
|
|
439
|
+
integration_type: { type: "string", description: "Integration type (requirement/defect)" },
|
|
440
|
+
testcase_id: { type: "string", description: "Test case ID" },
|
|
441
|
+
},
|
|
442
|
+
required: ["organization_id", "project_id", "integration_type", "testcase_id"],
|
|
443
|
+
},
|
|
444
|
+
};
|
|
445
|
+
const SEARCH_ISSUES_TOOL = {
|
|
446
|
+
name: "search_issues",
|
|
447
|
+
description: "Search issues from integrated platform (Jira, GitHub, GitLab)",
|
|
448
|
+
inputSchema: {
|
|
449
|
+
type: "object",
|
|
450
|
+
properties: {
|
|
451
|
+
project_id: { type: "string", description: "Project ID" },
|
|
452
|
+
integration_type: { type: "string", description: "Integration type (requirement/defect)" },
|
|
453
|
+
search: { type: "string", description: "Search query string" },
|
|
454
|
+
page: { type: "number", description: "Page number" },
|
|
455
|
+
limit: { type: "number", description: "Items per page" },
|
|
456
|
+
},
|
|
457
|
+
required: ["project_id", "integration_type"],
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
const MAP_ISSUES_TOOL = {
|
|
461
|
+
name: "map_issues",
|
|
462
|
+
description: "Map integration issues to a TestKase requirement/defect",
|
|
463
|
+
inputSchema: {
|
|
464
|
+
type: "object",
|
|
465
|
+
properties: {
|
|
466
|
+
organization_id: { type: "number", description: "Organization ID" },
|
|
467
|
+
project_id: { type: "string", description: "Project ID" },
|
|
468
|
+
testcase_id: { type: "string", description: "Test case ID" },
|
|
469
|
+
integration_type: { type: "string", description: "Integration type (requirement/defect)" },
|
|
470
|
+
issues: { type: "string", description: "JSON string of issue IDs to map" },
|
|
471
|
+
},
|
|
472
|
+
required: ["organization_id", "project_id", "testcase_id", "integration_type", "issues"],
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
const GENERATE_TESTCASES_TOOL = {
|
|
476
|
+
name: "generate_testcases",
|
|
477
|
+
description: "Generate test cases using AI from requirement text",
|
|
478
|
+
inputSchema: {
|
|
479
|
+
type: "object",
|
|
480
|
+
properties: {
|
|
481
|
+
project_id: { type: "string", description: "Project ID" },
|
|
482
|
+
requirement: { type: "string", description: "Requirement text" },
|
|
483
|
+
issue_id: { type: "string", description: "Issue ID (optional)" },
|
|
484
|
+
selected_fields: { type: "string", description: "Comma-separated field names" },
|
|
485
|
+
},
|
|
486
|
+
required: ["project_id"],
|
|
487
|
+
},
|
|
488
|
+
};
|
|
489
|
+
const CREATE_ISSUE_TOOL = {
|
|
490
|
+
name: "create_issue",
|
|
491
|
+
description: "Create or update a requirement or defect issue",
|
|
492
|
+
inputSchema: {
|
|
493
|
+
type: "object",
|
|
494
|
+
properties: {
|
|
495
|
+
projectId: { type: "string", description: "Project ID" },
|
|
496
|
+
organizationId: { type: "number", description: "Organization ID" },
|
|
497
|
+
type: { type: "string", description: "Issue type (REQUIREMENT or DEFECT)" },
|
|
498
|
+
title: { type: "string", description: "Issue title" },
|
|
499
|
+
description: { type: "string", description: "Issue description" },
|
|
500
|
+
id: { type: "string", description: "Issue ID (if updating)" },
|
|
501
|
+
},
|
|
502
|
+
required: ["projectId", "organizationId", "type", "title"],
|
|
503
|
+
},
|
|
504
|
+
};
|
|
95
505
|
// Create server instance
|
|
96
506
|
const server = new Server({
|
|
97
507
|
name: "testkase-mcp-server",
|
|
@@ -104,7 +514,35 @@ const server = new Server({
|
|
|
104
514
|
// List available tools
|
|
105
515
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
106
516
|
return {
|
|
107
|
-
tools: [
|
|
517
|
+
tools: [
|
|
518
|
+
GET_TESTCASES_TOOL,
|
|
519
|
+
GET_TESTCASE_DETAIL_TOOL,
|
|
520
|
+
GET_TESTCASE_HISTORY_TOOL,
|
|
521
|
+
GET_FOLDERS_TOOL,
|
|
522
|
+
GET_LABELS_TOOL,
|
|
523
|
+
GET_ISSUES_TOOL,
|
|
524
|
+
GET_MY_PROJECTS_TOOL,
|
|
525
|
+
CREATE_TESTCASE_TOOL,
|
|
526
|
+
CREATE_BULK_TESTCASE_TOOL,
|
|
527
|
+
UPDATE_TESTCASE_FIELD_TOOL,
|
|
528
|
+
DELETE_TESTCASE_TOOL,
|
|
529
|
+
CLONE_TESTCASE_TOOL,
|
|
530
|
+
CREATE_TEST_STEP_TOOL,
|
|
531
|
+
DELETE_TEST_STEP_TOOL,
|
|
532
|
+
DOWNLOAD_TESTCASES_TOOL,
|
|
533
|
+
IMPORT_TESTCASES_TOOL,
|
|
534
|
+
CREATE_FOLDER_TOOL,
|
|
535
|
+
DELETE_FOLDER_TOOL,
|
|
536
|
+
UPDATE_FOLDER_TOOL,
|
|
537
|
+
CREATE_LABEL_TOOL,
|
|
538
|
+
GET_USER_PROFILE_TOOL,
|
|
539
|
+
GET_ORGANIZATION_TOOL,
|
|
540
|
+
GET_MAPPED_ISSUES_TOOL,
|
|
541
|
+
SEARCH_ISSUES_TOOL,
|
|
542
|
+
MAP_ISSUES_TOOL,
|
|
543
|
+
GENERATE_TESTCASES_TOOL,
|
|
544
|
+
CREATE_ISSUE_TOOL,
|
|
545
|
+
],
|
|
108
546
|
};
|
|
109
547
|
});
|
|
110
548
|
// Handle tool calls
|
|
@@ -114,6 +552,84 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
114
552
|
if (name === "get_testcases") {
|
|
115
553
|
return await handleGetTestcases(args);
|
|
116
554
|
}
|
|
555
|
+
else if (name === "get_testcase_detail") {
|
|
556
|
+
return await handleGetTestcaseDetail(args);
|
|
557
|
+
}
|
|
558
|
+
else if (name === "get_testcase_history") {
|
|
559
|
+
return await handleGetTestcaseHistory(args);
|
|
560
|
+
}
|
|
561
|
+
else if (name === "get_folders") {
|
|
562
|
+
return await handleGetFolders(args);
|
|
563
|
+
}
|
|
564
|
+
else if (name === "get_labels") {
|
|
565
|
+
return await handleGetLabels(args);
|
|
566
|
+
}
|
|
567
|
+
else if (name === "get_issues") {
|
|
568
|
+
return await handleGetIssues(args);
|
|
569
|
+
}
|
|
570
|
+
else if (name === "get_my_projects") {
|
|
571
|
+
return await handleGetMyProjects(args);
|
|
572
|
+
}
|
|
573
|
+
else if (name === "create_testcase") {
|
|
574
|
+
return await handleCreateTestcase(args);
|
|
575
|
+
}
|
|
576
|
+
else if (name === "create_bulk_testcase") {
|
|
577
|
+
return await handleCreateBulkTestcase(args);
|
|
578
|
+
}
|
|
579
|
+
else if (name === "update_testcase_field") {
|
|
580
|
+
return await handleUpdateTestcaseField(args);
|
|
581
|
+
}
|
|
582
|
+
else if (name === "delete_testcase") {
|
|
583
|
+
return await handleDeleteTestcase(args);
|
|
584
|
+
}
|
|
585
|
+
else if (name === "clone_testcase") {
|
|
586
|
+
return await handleCloneTestcase(args);
|
|
587
|
+
}
|
|
588
|
+
else if (name === "create_test_step") {
|
|
589
|
+
return await handleCreateTestStep(args);
|
|
590
|
+
}
|
|
591
|
+
else if (name === "delete_test_step") {
|
|
592
|
+
return await handleDeleteTestStep(args);
|
|
593
|
+
}
|
|
594
|
+
else if (name === "download_testcases") {
|
|
595
|
+
return await handleDownloadTestcases(args);
|
|
596
|
+
}
|
|
597
|
+
else if (name === "import_testcases") {
|
|
598
|
+
return await handleImportTestcases(args);
|
|
599
|
+
}
|
|
600
|
+
else if (name === "create_folder") {
|
|
601
|
+
return await handleCreateFolder(args);
|
|
602
|
+
}
|
|
603
|
+
else if (name === "delete_folder") {
|
|
604
|
+
return await handleDeleteFolder(args);
|
|
605
|
+
}
|
|
606
|
+
else if (name === "update_folder") {
|
|
607
|
+
return await handleUpdateFolder(args);
|
|
608
|
+
}
|
|
609
|
+
else if (name === "create_label") {
|
|
610
|
+
return await handleCreateLabel(args);
|
|
611
|
+
}
|
|
612
|
+
else if (name === "get_user_profile") {
|
|
613
|
+
return await handleGetUserProfile(args);
|
|
614
|
+
}
|
|
615
|
+
else if (name === "get_organization") {
|
|
616
|
+
return await handleGetOrganization(args);
|
|
617
|
+
}
|
|
618
|
+
else if (name === "get_mapped_issues") {
|
|
619
|
+
return await handleGetMappedIssues(args);
|
|
620
|
+
}
|
|
621
|
+
else if (name === "search_issues") {
|
|
622
|
+
return await handleSearchIssues(args);
|
|
623
|
+
}
|
|
624
|
+
else if (name === "map_issues") {
|
|
625
|
+
return await handleMapIssues(args);
|
|
626
|
+
}
|
|
627
|
+
else if (name === "generate_testcases") {
|
|
628
|
+
return await handleGenerateTestcases(args);
|
|
629
|
+
}
|
|
630
|
+
else if (name === "create_issue") {
|
|
631
|
+
return await handleCreateIssue(args);
|
|
632
|
+
}
|
|
117
633
|
throw new Error(`Unknown tool: ${name}`);
|
|
118
634
|
}
|
|
119
635
|
catch (error) {
|
|
@@ -255,6 +771,507 @@ async function handleGetTestcases(args) {
|
|
|
255
771
|
throw error;
|
|
256
772
|
}
|
|
257
773
|
}
|
|
774
|
+
// Handler for get_testcase_detail tool
|
|
775
|
+
async function handleGetTestcaseDetail(args) {
|
|
776
|
+
validateAuth();
|
|
777
|
+
const queryParams = new URLSearchParams();
|
|
778
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
779
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/get-testcase-detail/${args.projectId}/${args.testcaseId}?${queryParams.toString()}`;
|
|
780
|
+
try {
|
|
781
|
+
const response = await axios.get(url, {
|
|
782
|
+
headers: {
|
|
783
|
+
"Content-Type": "application/json",
|
|
784
|
+
"Authorization": `Bearer ${config.patToken}`,
|
|
785
|
+
},
|
|
786
|
+
});
|
|
787
|
+
const data = response.data;
|
|
788
|
+
return formatResponse(data, `Testcase Detail: ${args.testcaseId}`);
|
|
789
|
+
}
|
|
790
|
+
catch (error) {
|
|
791
|
+
throw handleApiError(error);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
// Handler for get_testcase_history tool
|
|
795
|
+
async function handleGetTestcaseHistory(args) {
|
|
796
|
+
validateAuth();
|
|
797
|
+
const queryParams = new URLSearchParams();
|
|
798
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
799
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/get-testcase-history/${args.projectId}/${args.testcaseId}?${queryParams.toString()}`;
|
|
800
|
+
try {
|
|
801
|
+
const response = await axios.get(url, {
|
|
802
|
+
headers: {
|
|
803
|
+
"Content-Type": "application/json",
|
|
804
|
+
"Authorization": `Bearer ${config.patToken}`,
|
|
805
|
+
},
|
|
806
|
+
});
|
|
807
|
+
const data = response.data;
|
|
808
|
+
return formatResponse(data, `Testcase History: ${args.testcaseId}`);
|
|
809
|
+
}
|
|
810
|
+
catch (error) {
|
|
811
|
+
throw handleApiError(error);
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
// Handler for get_folders tool
|
|
815
|
+
async function handleGetFolders(args) {
|
|
816
|
+
validateAuth();
|
|
817
|
+
const queryParams = new URLSearchParams();
|
|
818
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
819
|
+
queryParams.append("projectId", args.projectId);
|
|
820
|
+
if (args.folder_id) {
|
|
821
|
+
queryParams.append("folder_id", args.folder_id);
|
|
822
|
+
}
|
|
823
|
+
const url = `${config.apiBaseUrl}/api/v1/folders/get-folders?${queryParams.toString()}`;
|
|
824
|
+
try {
|
|
825
|
+
const response = await axios.get(url, {
|
|
826
|
+
headers: {
|
|
827
|
+
"Content-Type": "application/json",
|
|
828
|
+
"Authorization": `Bearer ${config.patToken}`,
|
|
829
|
+
},
|
|
830
|
+
});
|
|
831
|
+
const data = response.data;
|
|
832
|
+
return formatResponse(data, `Folders for Project: ${args.projectId}`);
|
|
833
|
+
}
|
|
834
|
+
catch (error) {
|
|
835
|
+
throw handleApiError(error);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
// Handler for get_labels tool
|
|
839
|
+
async function handleGetLabels(args) {
|
|
840
|
+
validateAuth();
|
|
841
|
+
const queryParams = new URLSearchParams();
|
|
842
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
843
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/get-testcase-detail/${args.projectId}?${queryParams.toString()}`;
|
|
844
|
+
try {
|
|
845
|
+
const response = await axios.get(url, {
|
|
846
|
+
headers: {
|
|
847
|
+
"Content-Type": "application/json",
|
|
848
|
+
"Authorization": `Bearer ${config.patToken}`,
|
|
849
|
+
},
|
|
850
|
+
});
|
|
851
|
+
const data = response.data;
|
|
852
|
+
return formatResponse(data, `Labels for Project: ${args.projectId}`);
|
|
853
|
+
}
|
|
854
|
+
catch (error) {
|
|
855
|
+
throw handleApiError(error);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
// Handler for get_issues tool
|
|
859
|
+
async function handleGetIssues(args) {
|
|
860
|
+
validateAuth();
|
|
861
|
+
const queryParams = new URLSearchParams();
|
|
862
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
863
|
+
if (args.page)
|
|
864
|
+
queryParams.append("page", args.page.toString());
|
|
865
|
+
if (args.limit)
|
|
866
|
+
queryParams.append("limit", args.limit.toString());
|
|
867
|
+
const url = `${config.apiBaseUrl}/api/v1/issues/get-issues/${args.projectId}?${queryParams.toString()}`;
|
|
868
|
+
try {
|
|
869
|
+
const response = await axios.get(url, {
|
|
870
|
+
headers: {
|
|
871
|
+
"Content-Type": "application/json",
|
|
872
|
+
"Authorization": `Bearer ${config.patToken}`,
|
|
873
|
+
},
|
|
874
|
+
});
|
|
875
|
+
const data = response.data;
|
|
876
|
+
return formatResponse(data, `Issues for Project: ${args.projectId}`);
|
|
877
|
+
}
|
|
878
|
+
catch (error) {
|
|
879
|
+
throw handleApiError(error);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
// Handler for get_my_projects tool
|
|
883
|
+
async function handleGetMyProjects(args) {
|
|
884
|
+
validateAuth();
|
|
885
|
+
const queryParams = new URLSearchParams();
|
|
886
|
+
if (args.page)
|
|
887
|
+
queryParams.append("page", args.page.toString());
|
|
888
|
+
if (args.limit)
|
|
889
|
+
queryParams.append("limit", args.limit.toString());
|
|
890
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/user/my-projects?${queryParams.toString()}`;
|
|
891
|
+
try {
|
|
892
|
+
const response = await axios.get(url, {
|
|
893
|
+
headers: {
|
|
894
|
+
"Content-Type": "application/json",
|
|
895
|
+
"Authorization": `Bearer ${config.patToken}`,
|
|
896
|
+
},
|
|
897
|
+
});
|
|
898
|
+
const data = response.data;
|
|
899
|
+
return formatResponse(data, "My Projects");
|
|
900
|
+
}
|
|
901
|
+
catch (error) {
|
|
902
|
+
throw handleApiError(error);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
// Handler for create_testcase tool
|
|
906
|
+
async function handleCreateTestcase(args) {
|
|
907
|
+
validateAuth();
|
|
908
|
+
const queryParams = new URLSearchParams();
|
|
909
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
910
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/create-testcase/${args.projectId}?${queryParams.toString()}`;
|
|
911
|
+
try {
|
|
912
|
+
const response = await axios.post(url, args, {
|
|
913
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
914
|
+
});
|
|
915
|
+
return formatResponse(response.data, "Testcase Created");
|
|
916
|
+
}
|
|
917
|
+
catch (error) {
|
|
918
|
+
throw handleApiError(error);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
// Handler for create_bulk_testcase tool
|
|
922
|
+
async function handleCreateBulkTestcase(args) {
|
|
923
|
+
validateAuth();
|
|
924
|
+
const queryParams = new URLSearchParams();
|
|
925
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
926
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/create-bulk-testcase/${args.projectId}?${queryParams.toString()}`;
|
|
927
|
+
const testcases = typeof args.testcases === 'string' ? JSON.parse(args.testcases) : args.testcases;
|
|
928
|
+
try {
|
|
929
|
+
const response = await axios.post(url, { testcases }, {
|
|
930
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
931
|
+
});
|
|
932
|
+
return formatResponse(response.data, "Bulk Testcases Created");
|
|
933
|
+
}
|
|
934
|
+
catch (error) {
|
|
935
|
+
throw handleApiError(error);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
// Handler for update_testcase_field tool
|
|
939
|
+
async function handleUpdateTestcaseField(args) {
|
|
940
|
+
validateAuth();
|
|
941
|
+
const queryParams = new URLSearchParams();
|
|
942
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
943
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/update-field/${args.projectId}?${queryParams.toString()}`;
|
|
944
|
+
try {
|
|
945
|
+
const response = await axios.patch(url, {
|
|
946
|
+
ids: args.ids.split(','),
|
|
947
|
+
field: args.field,
|
|
948
|
+
value: args.value,
|
|
949
|
+
}, {
|
|
950
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
951
|
+
});
|
|
952
|
+
return formatResponse(response.data, "Testcase Field Updated");
|
|
953
|
+
}
|
|
954
|
+
catch (error) {
|
|
955
|
+
throw handleApiError(error);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
// Handler for delete_testcase tool
|
|
959
|
+
async function handleDeleteTestcase(args) {
|
|
960
|
+
validateAuth();
|
|
961
|
+
const queryParams = new URLSearchParams();
|
|
962
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
963
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/delete-testcase/${args.projectId}?${queryParams.toString()}`;
|
|
964
|
+
try {
|
|
965
|
+
const response = await axios.delete(url, {
|
|
966
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
967
|
+
data: { ids: args.ids.split(',') },
|
|
968
|
+
});
|
|
969
|
+
return formatResponse(response.data, "Testcase Deleted");
|
|
970
|
+
}
|
|
971
|
+
catch (error) {
|
|
972
|
+
throw handleApiError(error);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
// Handler for clone_testcase tool
|
|
976
|
+
async function handleCloneTestcase(args) {
|
|
977
|
+
validateAuth();
|
|
978
|
+
const queryParams = new URLSearchParams();
|
|
979
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
980
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/clone/${args.projectId}/${args.id}?${queryParams.toString()}`;
|
|
981
|
+
try {
|
|
982
|
+
const response = await axios.post(url, {}, {
|
|
983
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
984
|
+
});
|
|
985
|
+
return formatResponse(response.data, "Testcase Cloned");
|
|
986
|
+
}
|
|
987
|
+
catch (error) {
|
|
988
|
+
throw handleApiError(error);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
// Handler for create_test_step tool
|
|
992
|
+
async function handleCreateTestStep(args) {
|
|
993
|
+
validateAuth();
|
|
994
|
+
const queryParams = new URLSearchParams();
|
|
995
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
996
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/teststeps/${args.projectId}/${args.testcaseId}?${queryParams.toString()}`;
|
|
997
|
+
const steps = typeof args.steps === 'string' ? JSON.parse(args.steps) : args.steps;
|
|
998
|
+
try {
|
|
999
|
+
const response = await axios.post(url, { steps }, {
|
|
1000
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1001
|
+
});
|
|
1002
|
+
return formatResponse(response.data, "Test Steps Created");
|
|
1003
|
+
}
|
|
1004
|
+
catch (error) {
|
|
1005
|
+
throw handleApiError(error);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
// Handler for delete_test_step tool
|
|
1009
|
+
async function handleDeleteTestStep(args) {
|
|
1010
|
+
validateAuth();
|
|
1011
|
+
const queryParams = new URLSearchParams();
|
|
1012
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
1013
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/teststeps/${args.testcaseId}?${queryParams.toString()}`;
|
|
1014
|
+
try {
|
|
1015
|
+
const response = await axios.delete(url, {
|
|
1016
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1017
|
+
data: { stepIds: args.stepIds.split(',') },
|
|
1018
|
+
});
|
|
1019
|
+
return formatResponse(response.data, "Test Steps Deleted");
|
|
1020
|
+
}
|
|
1021
|
+
catch (error) {
|
|
1022
|
+
throw handleApiError(error);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
// Handler for download_testcases tool
|
|
1026
|
+
async function handleDownloadTestcases(args) {
|
|
1027
|
+
validateAuth();
|
|
1028
|
+
const queryParams = new URLSearchParams();
|
|
1029
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
1030
|
+
if (args.filters)
|
|
1031
|
+
queryParams.append("filters", args.filters);
|
|
1032
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/download/${args.projectId}?${queryParams.toString()}`;
|
|
1033
|
+
try {
|
|
1034
|
+
const response = await axios.get(url, {
|
|
1035
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1036
|
+
});
|
|
1037
|
+
return formatResponse(response.data, "Testcases Download");
|
|
1038
|
+
}
|
|
1039
|
+
catch (error) {
|
|
1040
|
+
throw handleApiError(error);
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
// Handler for import_testcases tool
|
|
1044
|
+
async function handleImportTestcases(args) {
|
|
1045
|
+
validateAuth();
|
|
1046
|
+
const queryParams = new URLSearchParams();
|
|
1047
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
1048
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/testcases/import/${args.projectId}?${queryParams.toString()}`;
|
|
1049
|
+
try {
|
|
1050
|
+
const response = await axios.post(url, { file: args.file }, {
|
|
1051
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1052
|
+
});
|
|
1053
|
+
return formatResponse(response.data, "Testcases Imported");
|
|
1054
|
+
}
|
|
1055
|
+
catch (error) {
|
|
1056
|
+
throw handleApiError(error);
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
// Handler for create_folder tool
|
|
1060
|
+
async function handleCreateFolder(args) {
|
|
1061
|
+
validateAuth();
|
|
1062
|
+
const url = `${config.apiBaseUrl}/api/v1/folders/create-folders`;
|
|
1063
|
+
try {
|
|
1064
|
+
const response = await axios.post(url, args, {
|
|
1065
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1066
|
+
});
|
|
1067
|
+
return formatResponse(response.data, "Folder Created");
|
|
1068
|
+
}
|
|
1069
|
+
catch (error) {
|
|
1070
|
+
throw handleApiError(error);
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
// Handler for delete_folder tool
|
|
1074
|
+
async function handleDeleteFolder(args) {
|
|
1075
|
+
validateAuth();
|
|
1076
|
+
const queryParams = new URLSearchParams();
|
|
1077
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
1078
|
+
const url = `${config.apiBaseUrl}/api/v1/folders/delete/${args.id}?${queryParams.toString()}`;
|
|
1079
|
+
try {
|
|
1080
|
+
const response = await axios.delete(url, {
|
|
1081
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1082
|
+
});
|
|
1083
|
+
return formatResponse(response.data, "Folder Deleted");
|
|
1084
|
+
}
|
|
1085
|
+
catch (error) {
|
|
1086
|
+
throw handleApiError(error);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
// Handler for update_folder tool
|
|
1090
|
+
async function handleUpdateFolder(args) {
|
|
1091
|
+
validateAuth();
|
|
1092
|
+
const queryParams = new URLSearchParams();
|
|
1093
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
1094
|
+
const url = `${config.apiBaseUrl}/api/v1/folders/${args.id}?${queryParams.toString()}`;
|
|
1095
|
+
try {
|
|
1096
|
+
const response = await axios.patch(url, { folder_name: args.folder_name }, {
|
|
1097
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1098
|
+
});
|
|
1099
|
+
return formatResponse(response.data, "Folder Updated");
|
|
1100
|
+
}
|
|
1101
|
+
catch (error) {
|
|
1102
|
+
throw handleApiError(error);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
// Handler for create_label tool
|
|
1106
|
+
async function handleCreateLabel(args) {
|
|
1107
|
+
validateAuth();
|
|
1108
|
+
const queryParams = new URLSearchParams();
|
|
1109
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
1110
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/labels/create/${args.projectId}?${queryParams.toString()}`;
|
|
1111
|
+
try {
|
|
1112
|
+
const response = await axios.post(url, { values: args.values }, {
|
|
1113
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1114
|
+
});
|
|
1115
|
+
return formatResponse(response.data, "Label Created");
|
|
1116
|
+
}
|
|
1117
|
+
catch (error) {
|
|
1118
|
+
throw handleApiError(error);
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
// Handler for get_user_profile tool
|
|
1122
|
+
async function handleGetUserProfile(args) {
|
|
1123
|
+
validateAuth();
|
|
1124
|
+
const url = `${config.apiBaseUrl}/api/v1/auth/me`;
|
|
1125
|
+
try {
|
|
1126
|
+
const response = await axios.get(url, {
|
|
1127
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1128
|
+
});
|
|
1129
|
+
return formatResponse(response.data, "User Profile");
|
|
1130
|
+
}
|
|
1131
|
+
catch (error) {
|
|
1132
|
+
throw handleApiError(error);
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
// Handler for get_organization tool
|
|
1136
|
+
async function handleGetOrganization(args) {
|
|
1137
|
+
validateAuth();
|
|
1138
|
+
const url = `${config.apiBaseUrl}/api/v1/my-organization`;
|
|
1139
|
+
try {
|
|
1140
|
+
const response = await axios.get(url, {
|
|
1141
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1142
|
+
});
|
|
1143
|
+
return formatResponse(response.data, "Organization Details");
|
|
1144
|
+
}
|
|
1145
|
+
catch (error) {
|
|
1146
|
+
throw handleApiError(error);
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
// Handler for get_mapped_issues tool
|
|
1150
|
+
async function handleGetMappedIssues(args) {
|
|
1151
|
+
validateAuth();
|
|
1152
|
+
const url = `${config.apiBaseUrl}/api/v1/${args.organization_id}/${args.project_id}/${args.integration_type}/testcases/${args.testcase_id}/issues`;
|
|
1153
|
+
try {
|
|
1154
|
+
const response = await axios.get(url, {
|
|
1155
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1156
|
+
});
|
|
1157
|
+
return formatResponse(response.data, "Mapped Issues");
|
|
1158
|
+
}
|
|
1159
|
+
catch (error) {
|
|
1160
|
+
throw handleApiError(error);
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
// Handler for search_issues tool
|
|
1164
|
+
async function handleSearchIssues(args) {
|
|
1165
|
+
validateAuth();
|
|
1166
|
+
const queryParams = new URLSearchParams();
|
|
1167
|
+
if (args.search)
|
|
1168
|
+
queryParams.append("search", args.search);
|
|
1169
|
+
if (args.page)
|
|
1170
|
+
queryParams.append("page", args.page.toString());
|
|
1171
|
+
if (args.limit)
|
|
1172
|
+
queryParams.append("limit", args.limit.toString());
|
|
1173
|
+
const url = `${config.apiBaseUrl}/api/v1/${args.project_id}/${args.integration_type}/issues/search?${queryParams.toString()}`;
|
|
1174
|
+
try {
|
|
1175
|
+
const response = await axios.get(url, {
|
|
1176
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1177
|
+
});
|
|
1178
|
+
return formatResponse(response.data, "Search Issues");
|
|
1179
|
+
}
|
|
1180
|
+
catch (error) {
|
|
1181
|
+
throw handleApiError(error);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
// Handler for map_issues tool
|
|
1185
|
+
async function handleMapIssues(args) {
|
|
1186
|
+
validateAuth();
|
|
1187
|
+
const url = `${config.apiBaseUrl}/api/v1/${args.organization_id}/${args.project_id}/${args.testcase_id}/${args.integration_type}/issues/map`;
|
|
1188
|
+
const issues = typeof args.issues === 'string' ? JSON.parse(args.issues) : args.issues;
|
|
1189
|
+
try {
|
|
1190
|
+
const response = await axios.post(url, { issues }, {
|
|
1191
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1192
|
+
});
|
|
1193
|
+
return formatResponse(response.data, "Issues Mapped");
|
|
1194
|
+
}
|
|
1195
|
+
catch (error) {
|
|
1196
|
+
throw handleApiError(error);
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
// Handler for generate_testcases tool
|
|
1200
|
+
async function handleGenerateTestcases(args) {
|
|
1201
|
+
validateAuth();
|
|
1202
|
+
const queryParams = new URLSearchParams();
|
|
1203
|
+
if (args.requirement)
|
|
1204
|
+
queryParams.append("requirement", args.requirement);
|
|
1205
|
+
if (args.issue_id)
|
|
1206
|
+
queryParams.append("issue_id", args.issue_id);
|
|
1207
|
+
if (args.selected_fields)
|
|
1208
|
+
queryParams.append("selected_fields", args.selected_fields);
|
|
1209
|
+
const url = `${config.apiBaseUrl}/api/v1/${args.project_id}/testcases/generate?${queryParams.toString()}`;
|
|
1210
|
+
try {
|
|
1211
|
+
const response = await axios.get(url, {
|
|
1212
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1213
|
+
});
|
|
1214
|
+
return formatResponse(response.data, "Generated Testcases");
|
|
1215
|
+
}
|
|
1216
|
+
catch (error) {
|
|
1217
|
+
throw handleApiError(error);
|
|
1218
|
+
}
|
|
1219
|
+
}
|
|
1220
|
+
// Handler for create_issue tool
|
|
1221
|
+
async function handleCreateIssue(args) {
|
|
1222
|
+
validateAuth();
|
|
1223
|
+
const queryParams = new URLSearchParams();
|
|
1224
|
+
queryParams.append("organizationId", args.organizationId.toString());
|
|
1225
|
+
const url = `${config.apiBaseUrl}/api/v1/projects/issues/create-issues/${args.projectId}?${queryParams.toString()}`;
|
|
1226
|
+
try {
|
|
1227
|
+
const response = await axios.post(url, args, {
|
|
1228
|
+
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${config.patToken}` },
|
|
1229
|
+
});
|
|
1230
|
+
return formatResponse(response.data, "Issue Created/Updated");
|
|
1231
|
+
}
|
|
1232
|
+
catch (error) {
|
|
1233
|
+
throw handleApiError(error);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
// Helper function to validate authentication
|
|
1237
|
+
function validateAuth() {
|
|
1238
|
+
if (!config.patToken) {
|
|
1239
|
+
throw new Error("Authentication required. Please set TESTKASE_PAT_TOKEN environment variable. " +
|
|
1240
|
+
"Generate a Personal Access Token (PAT) from your TestKase account settings.");
|
|
1241
|
+
}
|
|
1242
|
+
if (!config.patToken.startsWith("xyz_")) {
|
|
1243
|
+
throw new Error("Invalid PAT token format. TestKase PAT tokens must start with 'xyz_' prefix. " +
|
|
1244
|
+
"Please generate a valid PAT from your TestKase account settings.");
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
// Helper function to format API response
|
|
1248
|
+
function formatResponse(data, title) {
|
|
1249
|
+
let resultText = `# ${title}\n\n`;
|
|
1250
|
+
resultText += "```json\n";
|
|
1251
|
+
resultText += JSON.stringify(data, null, 2);
|
|
1252
|
+
resultText += "\n```\n";
|
|
1253
|
+
return {
|
|
1254
|
+
content: [
|
|
1255
|
+
{
|
|
1256
|
+
type: "text",
|
|
1257
|
+
text: resultText,
|
|
1258
|
+
},
|
|
1259
|
+
],
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
// Helper function to handle API errors
|
|
1263
|
+
function handleApiError(error) {
|
|
1264
|
+
if (axios.isAxiosError(error)) {
|
|
1265
|
+
const axiosError = error;
|
|
1266
|
+
let errorMessage = `API request failed: ${axiosError.message}`;
|
|
1267
|
+
if (axiosError.response) {
|
|
1268
|
+
errorMessage += `\nStatus: ${axiosError.response.status}`;
|
|
1269
|
+
errorMessage += `\nResponse: ${JSON.stringify(axiosError.response.data)}`;
|
|
1270
|
+
}
|
|
1271
|
+
return new Error(errorMessage);
|
|
1272
|
+
}
|
|
1273
|
+
return error;
|
|
1274
|
+
}
|
|
258
1275
|
// Start the server
|
|
259
1276
|
async function main() {
|
|
260
1277
|
const transport = new StdioServerTransport();
|