@smartbear/mcp 0.16.0 → 0.17.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.
@@ -113,6 +113,49 @@ class ErrorAPI extends BaseAPI {
113
113
  // Paginate results
114
114
  );
115
115
  }
116
+ /**
117
+ * List the Events on an Error
118
+ * GET /projects/{project_id}/errors/{error_id}/events
119
+ */
120
+ async listErrorEvents(projectId, errorId, base, sort, direction, perPage, filters, nextUrl) {
121
+ if (nextUrl) {
122
+ direction = void 0;
123
+ sort = void 0;
124
+ base = void 0;
125
+ }
126
+ const localVarFetchArgs = ErrorsApiFetchParamCreator(
127
+ this.configuration
128
+ ).listEventsOnError(
129
+ projectId,
130
+ errorId,
131
+ base ?? void 0,
132
+ sort,
133
+ direction,
134
+ void 0,
135
+ void 0,
136
+ // Filters are encoded separately below
137
+ void 0,
138
+ void 0
139
+ );
140
+ const url = new URL(
141
+ nextUrl ?? localVarFetchArgs.url,
142
+ this.configuration.basePath
143
+ );
144
+ if (perPage) {
145
+ url.searchParams.set("per_page", perPage.toString());
146
+ }
147
+ if (!nextUrl && filters) {
148
+ toUrlSearchParams(filters).forEach((value, key) => {
149
+ url.searchParams.append(key, value);
150
+ });
151
+ }
152
+ return await this.requestArray(
153
+ url.toString(),
154
+ localVarFetchArgs.options,
155
+ false
156
+ // Paginate results
157
+ );
158
+ }
116
159
  /**
117
160
  * Update an Error on a Project
118
161
  * PATCH /projects/{project_id}/errors/{error_id}
@@ -10,6 +10,7 @@ import { ListProjectErrors } from "./tool/error/list-project-errors.js";
10
10
  import { UpdateError } from "./tool/error/update-error.js";
11
11
  import { GetEvent } from "./tool/event/get-event.js";
12
12
  import { GetEventDetailsFromDashboardUrl } from "./tool/event/get-event-details-from-dashboard-url.js";
13
+ import { ListErrorEvents } from "./tool/event/list-error-events.js";
13
14
  import { GetNetworkEndpointGroupings } from "./tool/performance/get-network-endpoint-groupings.js";
14
15
  import { GetSpanGroup } from "./tool/performance/get-span-group.js";
15
16
  import { GetTrace } from "./tool/performance/get-trace.js";
@@ -273,6 +274,7 @@ class BugsnagClient {
273
274
  new UpdateError(this, getInput),
274
275
  new GetEvent(this),
275
276
  new GetEventDetailsFromDashboardUrl(this),
277
+ new ListErrorEvents(this),
276
278
  new ListReleases(this),
277
279
  new GetRelease(this),
278
280
  new GetBuild(this),
@@ -0,0 +1,62 @@
1
+ import { z } from "zod";
2
+ import { Tool } from "../../../common/tools.js";
3
+ import { toolInputParameters } from "../../input-schemas.js";
4
+ const inputSchema = z.object({
5
+ projectId: toolInputParameters.projectId,
6
+ errorId: toolInputParameters.errorId,
7
+ filters: toolInputParameters.filters.describe(
8
+ "Apply filters to narrow down the event list. Use the List Project Event Filters tool to discover available filter fields. Time filters support extended ISO 8601 format (e.g. 2018-05-20T00:00:00Z) or relative format (e.g. 7d, 24h)."
9
+ ),
10
+ direction: toolInputParameters.direction,
11
+ perPage: toolInputParameters.perPage,
12
+ nextUrl: toolInputParameters.nextUrl
13
+ });
14
+ class ListErrorEvents extends Tool {
15
+ specification = {
16
+ title: "Get Events on an Error",
17
+ summary: "Gets a list of events that have grouped into the specified error",
18
+ purpose: "Show the events that make up an error to see individual occurrences of the error for detailed analysis",
19
+ useCases: [
20
+ "Retrieving all the events for comparison to find commonalities or differences in stack traces, breadcrumbs and metadata"
21
+ ],
22
+ inputSchema,
23
+ examples: [
24
+ {
25
+ description: "Get events of an error",
26
+ parameters: {
27
+ projectId: "1234567890abcdef12345678",
28
+ errorId: "6863e2af012caf1d5c320000"
29
+ },
30
+ expectedOutput: "A list of events, ordered by timestamp, with complete details including stack trace, breadcrumbs, metadata, and context"
31
+ }
32
+ ]
33
+ };
34
+ handle = async (args, _extra) => {
35
+ const params = inputSchema.parse(args);
36
+ const project = await this.client.getInputProject(params.projectId);
37
+ const response = await this.client.errorsApi.listErrorEvents(
38
+ project.id,
39
+ params.errorId,
40
+ void 0,
41
+ // base
42
+ "timestamp",
43
+ // sort (the only available option)
44
+ params.direction,
45
+ params.perPage,
46
+ params.filters,
47
+ params.nextUrl
48
+ );
49
+ const result = {
50
+ data: response.body,
51
+ next_url: response.nextUrl ?? void 0,
52
+ data_count: response.body?.length,
53
+ total_count: response.totalCount ?? void 0
54
+ };
55
+ return {
56
+ content: [{ type: "text", text: JSON.stringify(result) }]
57
+ };
58
+ };
59
+ }
60
+ export {
61
+ ListErrorEvents
62
+ };
@@ -1,4 +1,4 @@
1
- const version = "0.16.0";
1
+ const version = "0.17.0";
2
2
  const config = { "mcpServerName": "SmartBear MCP Server" };
3
3
  const packageJson = {
4
4
  version,
@@ -34,6 +34,7 @@ import { GetTestExecutionLinks } from "./tool/test-execution/get-test-execution-
34
34
  import { GetTestExecutions } from "./tool/test-execution/get-test-executions.js";
35
35
  import { GetTestExecutionSteps } from "./tool/test-execution/get-test-steps.js";
36
36
  import { UpdateTestExecution } from "./tool/test-execution/update-test-execution.js";
37
+ import { UpdateTestExecutionSteps } from "./tool/test-execution/update-test-steps.js";
37
38
  const BASE_URL_DEFAULT = "https://api.zephyrscale.smartbear.com/v2";
38
39
  const ConfigurationSchema = zod__default.object({
39
40
  api_token: zod__default.string().describe("Zephyr Scale API token for authentication"),
@@ -91,6 +92,7 @@ class ZephyrClient {
91
92
  new GetTestCycles$1(this),
92
93
  new GetTestScript(this),
93
94
  new CreateTestCycleWebLink(this),
95
+ new UpdateTestExecutionSteps(this),
94
96
  new GetTestExecutionSteps(this),
95
97
  new GetTestExecutionLinks(this),
96
98
  new GetTestExecutions$1(this)
@@ -124,7 +124,7 @@ zod.object({
124
124
  type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
125
125
  }).strict()
126
126
  ).optional().describe("A list of web links for this entity")
127
- }).strict().optional().describe("This property is ignored on updates.")
127
+ }).strict().optional().describe("A list of links for this test case.")
128
128
  }).strict()
129
129
  ).optional()
130
130
  }).strict();
@@ -177,7 +177,10 @@ const ListTestCasesCursorPaginatedQueryParams = zod.object({
177
177
  limit: zod.number().min(1).max(listTestCasesCursorPaginatedQueryLimitMax).default(listTestCasesCursorPaginatedQueryLimitDefault).describe(
178
178
  "Specifies the maximum number of results to return in a single call. The default value is 10, and the maximum value that can be requested is 1000.\n\nNote that the server may enforce a lower limit than requested, depending on resource availability or other internal constraints. If this happens, the result set may be truncated. Always check the limit value in the response to confirm how many results were actually returned.\n"
179
179
  ),
180
- startAtId: zod.number().min(listTestCasesCursorPaginatedQueryStartAtIdMin).default(listTestCasesCursorPaginatedQueryStartAtIdDefault).describe("Zero-indexed starting position for ID-based pagination.")
180
+ startAtId: zod.number().min(listTestCasesCursorPaginatedQueryStartAtIdMin).default(listTestCasesCursorPaginatedQueryStartAtIdDefault).describe("Zero-indexed starting position for ID-based pagination."),
181
+ updatedAfter: zod.string().datetime({}).optional().describe(
182
+ "Filter only entities updated after the given time. Format: yyyy-MM-dd'T'HH:mm:ss'Z'"
183
+ )
181
184
  });
182
185
  const listTestCasesCursorPaginated200ResponseOneNextStartAtIdMin = 0;
183
186
  const listTestCasesCursorPaginated200ResponseOneLimitMin = 0;
@@ -287,7 +290,7 @@ const ListTestCasesCursorPaginated200Response = zod.object({
287
290
  type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
288
291
  }).strict()
289
292
  ).optional().describe("A list of web links for this entity")
290
- }).strict().optional().describe("This property is ignored on updates.")
293
+ }).strict().optional().describe("A list of links for this test case.")
291
294
  }).strict()
292
295
  ).optional()
293
296
  }).strict();
@@ -378,7 +381,7 @@ const GetTestCase200Response = zod.object({
378
381
  type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
379
382
  }).strict()
380
383
  ).optional().describe("A list of web links for this entity")
381
- }).strict().optional().describe("This property is ignored on updates.")
384
+ }).strict().optional().describe("A list of links for this test case.")
382
385
  }).strict();
383
386
  zod.object({
384
387
  errorCode: zod.number(),
@@ -404,9 +407,6 @@ const UpdateTestCaseBody = zod.object({
404
407
  id: zod.number().min(1).describe("The ID of the entity"),
405
408
  self: zod.string().url().optional().describe("The REST API endpoint to get more resource details.")
406
409
  }).strict().describe("ID and link relative to Zephyr project."),
407
- createdOn: zod.string().datetime({}).optional().describe(
408
- "Data and time test case was created. Format: yyyy-MM-dd'T'HH:mm:ss'Z'. This field is read-only, cannot be updated.\n"
409
- ),
410
410
  objective: zod.string().nullish().describe("A description of the objective."),
411
411
  precondition: zod.string().nullish().describe("Any conditions that need to be met."),
412
412
  estimatedTime: zod.number().min(updateTestCaseBodyEstimatedTimeMin).nullish().describe("Estimated duration in milliseconds."),
@@ -433,41 +433,9 @@ const UpdateTestCaseBody = zod.object({
433
433
  "The Jira REST API endpoint to get the full representation of the Jira user."
434
434
  )
435
435
  }).strict().nullish(),
436
- testScript: zod.object({
437
- self: zod.string().url().optional().describe("The REST API endpoint to get more resource details.")
438
- }).strict().optional(),
439
436
  customFields: zod.record(zod.string(), zod.unknown()).optional().describe(
440
437
  "Multi-line text fields support HTML and should denote new lines with the \\<br\\> tag.\nDates should be in the format 'yyyy-MM-dd'.\nUsers should have values of Jira User Account IDs.\n"
441
- ),
442
- links: zod.object({
443
- self: zod.string().url().optional().describe("The REST API endpoint to get more resource details."),
444
- issues: zod.array(
445
- zod.object({
446
- issueId: zod.number().min(1).describe("The Jira issue ID"),
447
- self: zod.string().url().optional().describe(
448
- "The Zephyr REST API endpoint relative to the link between the entity and the Jira issue."
449
- ),
450
- id: zod.number().min(1).optional().describe(
451
- "The ID that represents the link between the entity and the Jira issue."
452
- ),
453
- target: zod.string().url().optional().describe(
454
- "The Jira Cloud REST API endpoint to get the full representation of the issue"
455
- ),
456
- type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
457
- }).strict()
458
- ).optional().describe("A list of Jira issues linked to this entity"),
459
- webLinks: zod.array(
460
- zod.object({
461
- description: zod.string().optional().describe("The web link description"),
462
- url: zod.string().describe("The web link URL"),
463
- self: zod.string().url().optional().describe(
464
- "The Zephyr REST API endpoint relative to the link between the entity and this web link."
465
- ),
466
- id: zod.number().min(1).optional().describe("The ID of the entity"),
467
- type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
468
- }).strict()
469
- ).optional().describe("A list of web links for this entity")
470
- }).strict().optional().describe("This property is ignored on updates.")
438
+ )
471
439
  }).strict();
472
440
  zod.object({
473
441
  errorCode: zod.number(),
@@ -507,7 +475,7 @@ const GetTestCaseLinks200Response = zod.object({
507
475
  type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
508
476
  }).strict()
509
477
  ).optional().describe("A list of web links for this entity")
510
- }).strict().describe("This property is ignored on updates.");
478
+ }).strict().describe("A list of links for this test case.");
511
479
  zod.object({
512
480
  errorCode: zod.number(),
513
481
  message: zod.string()
@@ -676,7 +644,7 @@ zod.object({
676
644
  type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
677
645
  }).strict()
678
646
  ).optional().describe("A list of web links for this entity")
679
- }).strict().optional().describe("This property is ignored on updates.")
647
+ }).strict().optional().describe("A list of links for this test case.")
680
648
  }).strict();
681
649
  zod.object({
682
650
  errorCode: zod.number(),
@@ -739,7 +707,7 @@ const GetTestCaseTestStepsQueryParams = zod.object({
739
707
  });
740
708
  const getTestCaseTestSteps200ResponseOneStartAtMin = 0;
741
709
  const getTestCaseTestSteps200ResponseOneTotalMin = 0;
742
- const getTestCaseTestSteps200ResponseTwoValuesItemTestCaseTwoTestCaseKeyRegExp = /(.+-T[0-9]+)/;
710
+ const getTestCaseTestSteps200ResponseTwoValuesItemTestCaseOneTwoTestCaseKeyRegExp = /(.+-T[0-9]+)/;
743
711
  const GetTestCaseTestSteps200Response = zod.object({
744
712
  next: zod.string().url().nullish().describe(
745
713
  "URL to the next page of results, or null if there are no more results."
@@ -757,24 +725,24 @@ const GetTestCaseTestSteps200Response = zod.object({
757
725
  values: zod.array(
758
726
  zod.object({
759
727
  inline: zod.object({
760
- description: zod.string().optional().describe("The instruction to be followed"),
761
- testData: zod.string().optional().describe(
728
+ description: zod.string().nullish().describe("The instruction to be followed"),
729
+ testData: zod.string().nullish().describe(
762
730
  "Any test data required to perform the instruction (optional). The fields values provided can be interpolated into the description."
763
731
  ),
764
- expectedResult: zod.string().optional().describe(
732
+ expectedResult: zod.string().nullish().describe(
765
733
  "The expected outcome of executing the instruction"
766
734
  ),
767
735
  customFields: zod.record(zod.string(), zod.unknown()).optional().describe(
768
736
  "Multi-line text fields support HTML and should denote new lines with the \\<br\\> tag.\nDates should be in the format 'yyyy-MM-dd'.\nUsers should have values of Jira User Account IDs.\n"
769
737
  ),
770
- reflectRef: zod.string().optional().describe("The AI reference. Zephyr only feature")
771
- }).strict().optional(),
738
+ reflectRef: zod.string().nullish().describe("The AI reference. Zephyr only feature")
739
+ }).strict().nullish(),
772
740
  testCase: zod.object({
773
741
  self: zod.string().url().optional().describe(
774
742
  "The REST API endpoint to get more resource details."
775
743
  ),
776
744
  testCaseKey: zod.string().regex(
777
- getTestCaseTestSteps200ResponseTwoValuesItemTestCaseTwoTestCaseKeyRegExp
745
+ getTestCaseTestSteps200ResponseTwoValuesItemTestCaseOneTwoTestCaseKeyRegExp
778
746
  ).optional().describe(
779
747
  "The key of the other test case that the test step should delegate execution to. This cannot be the parent test case."
780
748
  ),
@@ -786,8 +754,8 @@ const GetTestCaseTestSteps200Response = zod.object({
786
754
  ),
787
755
  value: zod.string().optional().describe("Value of the parameter")
788
756
  }).strict()
789
- ).optional().describe("The list of parameters of the call to test step")
790
- }).strict().optional()
757
+ ).nullish().describe("The list of parameters of the call to test step")
758
+ }).strict().nullish()
791
759
  }).strict().describe(
792
760
  "An instruction to be followed as part of a step-by-step test script. The test step can have either an inline definition, or delegate execution to another test case. One of these options must be specified."
793
761
  )
@@ -990,9 +958,7 @@ const ListTestCycles200Response = zod.object({
990
958
  )
991
959
  }).strict()
992
960
  ).optional().describe("A list of test plans linked to a test cycle")
993
- }).strict().optional().describe(
994
- "Represents all links that a Test Cycle has. This property is ignored on update operations."
995
- )
961
+ }).strict().optional().describe("Represents all links that a Test Cycle has.")
996
962
  }).strict().describe("Details of a test cycle")
997
963
  ).optional()
998
964
  }).strict();
@@ -1122,9 +1088,7 @@ const GetTestCycle200Response = zod.object({
1122
1088
  )
1123
1089
  }).strict()
1124
1090
  ).optional().describe("A list of test plans linked to a test cycle")
1125
- }).strict().optional().describe(
1126
- "Represents all links that a Test Cycle has. This property is ignored on update operations."
1127
- )
1091
+ }).strict().optional().describe("Represents all links that a Test Cycle has.")
1128
1092
  }).strict().describe("Details of a test cycle");
1129
1093
  zod.object({
1130
1094
  errorCode: zod.number(),
@@ -1135,12 +1099,13 @@ const UpdateTestCycleParams = zod.object({
1135
1099
  testCycleIdOrKey: zod.string().regex(updateTestCyclePathTestCycleIdOrKeyRegExp).describe("The ID or key of the test cycle.")
1136
1100
  }).strict();
1137
1101
  const updateTestCycleBodyKeyRegExp = /([A-Z][A-Z_0-9]+-R[0-9]+)/;
1138
- const updateTestCycleBodyNameRegExp = /^(?!\s*$).+/;
1102
+ const updateTestCycleBodyNameMax = 255;
1103
+ const updateTestCycleBodyNameRegExp = /^(?!\\s*$).+/;
1139
1104
  const updateTestCycleBodyOwnerAccountIdRegExp = /^[-:a-zA-Z0-9]{1,128}$/;
1140
1105
  const UpdateTestCycleBody = zod.object({
1141
1106
  id: zod.number().min(1).describe("The ID of the entity"),
1142
1107
  key: zod.string().regex(updateTestCycleBodyKeyRegExp).describe("Unique key of the test cycle"),
1143
- name: zod.string().regex(updateTestCycleBodyNameRegExp).describe("Name of the Test Cycle"),
1108
+ name: zod.string().min(1).max(updateTestCycleBodyNameMax).regex(updateTestCycleBodyNameRegExp),
1144
1109
  project: zod.object({
1145
1110
  id: zod.number().min(1).describe("The ID of the entity"),
1146
1111
  self: zod.string().url().optional().describe("The REST API endpoint to get more resource details.")
@@ -1174,54 +1139,8 @@ const UpdateTestCycleBody = zod.object({
1174
1139
  }).strict().nullish(),
1175
1140
  customFields: zod.record(zod.string(), zod.unknown()).optional().describe(
1176
1141
  "Multi-line text fields support HTML and should denote new lines with the \\<br\\> tag.\nDates should be in the format 'yyyy-MM-dd'.\nUsers should have values of Jira User Account IDs.\n"
1177
- ),
1178
- links: zod.object({
1179
- self: zod.string().url().optional().describe("The REST API endpoint to get more resource details."),
1180
- issues: zod.array(
1181
- zod.object({
1182
- issueId: zod.number().min(1).describe("The Jira issue ID"),
1183
- self: zod.string().url().optional().describe(
1184
- "The Zephyr REST API endpoint relative to the link between the entity and the Jira issue."
1185
- ),
1186
- id: zod.number().min(1).optional().describe(
1187
- "The ID that represents the link between the entity and the Jira issue."
1188
- ),
1189
- target: zod.string().url().optional().describe(
1190
- "The Jira Cloud REST API endpoint to get the full representation of the issue"
1191
- ),
1192
- type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
1193
- }).strict()
1194
- ).optional().describe("A list of Jira issues linked to this entity"),
1195
- webLinks: zod.array(
1196
- zod.object({
1197
- description: zod.string().optional().describe("The web link description"),
1198
- url: zod.string().describe("The web link URL"),
1199
- self: zod.string().url().optional().describe(
1200
- "The Zephyr REST API endpoint relative to the link between the entity and this web link."
1201
- ),
1202
- id: zod.number().min(1).optional().describe("The ID of the entity"),
1203
- type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type")
1204
- }).strict()
1205
- ).optional().describe("A list of web links for this entity"),
1206
- testPlans: zod.array(
1207
- zod.object({
1208
- id: zod.number().min(1).optional().describe(
1209
- "The ID that represents the link between the Test Cycle and the Test Plan."
1210
- ),
1211
- self: zod.string().url().optional().describe(
1212
- "The Zephyr REST API endpoint relative to the link between the entity and the Jira issue."
1213
- ),
1214
- testPlanId: zod.number().optional().describe("The ID of the test plan"),
1215
- type: zod.enum(["COVERAGE", "BLOCKS", "RELATED"]).optional().describe("The link type"),
1216
- target: zod.string().url().optional().describe(
1217
- "The Zephyr REST API endpoint to get the full representation of the test plan"
1218
- )
1219
- }).strict()
1220
- ).optional().describe("A list of test plans linked to a test cycle")
1221
- }).strict().optional().describe(
1222
- "Represents all links that a Test Cycle has. This property is ignored on update operations."
1223
1142
  )
1224
- }).strict().describe("Details of a test cycle");
1143
+ }).strict();
1225
1144
  zod.object({
1226
1145
  errorCode: zod.number(),
1227
1146
  message: zod.string()
@@ -1273,9 +1192,7 @@ const GetTestCycleLinks200Response = zod.object({
1273
1192
  )
1274
1193
  }).strict()
1275
1194
  ).optional().describe("A list of test plans linked to a test cycle")
1276
- }).strict().describe(
1277
- "Represents all links that a Test Cycle has. This property is ignored on update operations."
1278
- );
1195
+ }).strict().describe("Represents all links that a Test Cycle has.");
1279
1196
  zod.object({
1280
1197
  errorCode: zod.number(),
1281
1198
  message: zod.string()
@@ -2076,13 +1993,13 @@ const GetTestExecutionTestSteps200Response = zod.object({
2076
1993
  ).optional().describe("The list of test steps")
2077
1994
  }).strict().describe("Response body when retrieving test steps for a test execution");
2078
1995
  const putTestExecutionTestStepsPathTestExecutionIdOrKeyRegExp = /([0-9]+)|(.+-E[0-9]+)/;
2079
- zod.object({
1996
+ const PutTestExecutionTestStepsParams = zod.object({
2080
1997
  testExecutionIdOrKey: zod.string().regex(putTestExecutionTestStepsPathTestExecutionIdOrKeyRegExp).describe(
2081
1998
  "The ID or key of the test execution. Test execution keys are of the format [A-Z]+-E[0-9]+"
2082
1999
  )
2083
2000
  }).strict();
2084
2001
  const putTestExecutionTestStepsBodyStepsItemStatusNameMax = 255;
2085
- zod.object({
2002
+ const PutTestExecutionTestStepsBody = zod.object({
2086
2003
  steps: zod.array(
2087
2004
  zod.object({
2088
2005
  actualResult: zod.string().optional().describe("The actual result."),
@@ -3026,6 +2943,8 @@ export {
3026
2943
  ListTestExecutionLinksParams,
3027
2944
  ListTestExecutionsNextgen200Response,
3028
2945
  ListTestExecutionsNextgenQueryParams,
2946
+ PutTestExecutionTestStepsBody,
2947
+ PutTestExecutionTestStepsParams,
3029
2948
  UpdateTestCaseBody,
3030
2949
  UpdateTestCaseParams,
3031
2950
  UpdateTestCycleBody,
@@ -3133,7 +3052,7 @@ export {
3133
3052
  getTestCaseTestScriptPathTestCaseKeyRegExp,
3134
3053
  getTestCaseTestSteps200ResponseOneStartAtMin,
3135
3054
  getTestCaseTestSteps200ResponseOneTotalMin,
3136
- getTestCaseTestSteps200ResponseTwoValuesItemTestCaseTwoTestCaseKeyRegExp,
3055
+ getTestCaseTestSteps200ResponseTwoValuesItemTestCaseOneTwoTestCaseKeyRegExp,
3137
3056
  getTestCaseTestStepsPathTestCaseKeyRegExp,
3138
3057
  getTestCaseTestStepsQueryMaxResultsDefault,
3139
3058
  getTestCaseTestStepsQueryStartAtDefault,
@@ -3334,6 +3253,7 @@ export {
3334
3253
  updateTestCaseBodyOwnerAccountIdRegExp,
3335
3254
  updateTestCasePathTestCaseKeyRegExp,
3336
3255
  updateTestCycleBodyKeyRegExp,
3256
+ updateTestCycleBodyNameMax,
3337
3257
  updateTestCycleBodyNameRegExp,
3338
3258
  updateTestCycleBodyOwnerAccountIdRegExp,
3339
3259
  updateTestCyclePathTestCycleIdOrKeyRegExp,
@@ -67,6 +67,8 @@ class UpdateTestCase extends Tool {
67
67
  const { testCaseKey, ...updates } = parsed;
68
68
  const existingTestCase = await this.client.getApiClient().get(`/testcases/${testCaseKey}`);
69
69
  const mergedBody = deepMerge(existingTestCase, updates);
70
+ delete mergedBody.createdOn;
71
+ delete mergedBody.links;
70
72
  await this.client.getApiClient().put(`/testcases/${testCaseKey}`, mergedBody);
71
73
  return {
72
74
  structuredContent: {},
@@ -78,6 +78,7 @@ class UpdateTestCycle extends Tool {
78
78
  if (updates.plannedEndDate === null) delete updates.plannedEndDate;
79
79
  const existingTestCycle = await this.client.getApiClient().get(`/testcycles/${testCycleIdOrKey}`);
80
80
  const mergedBody = deepMerge(existingTestCycle, updates);
81
+ delete mergedBody.links;
81
82
  await this.client.getApiClient().put(`/testcycles/${testCycleIdOrKey}`, mergedBody);
82
83
  return {
83
84
  structuredContent: {},
@@ -0,0 +1,89 @@
1
+ import { Tool } from "../../../common/tools.js";
2
+ import { PutTestExecutionTestStepsParams, PutTestExecutionTestStepsBody } from "../../common/rest-api-schemas.js";
3
+ class UpdateTestExecutionSteps extends Tool {
4
+ specification = {
5
+ title: "Update Test Execution Steps",
6
+ summary: "Update test steps for a given Test Execution in Zephyr. This operation updates the provided steps with their execution status and actual results. Only the fields included in the request will be modified.",
7
+ readOnly: false,
8
+ idempotent: true,
9
+ inputSchema: PutTestExecutionTestStepsParams.and(
10
+ PutTestExecutionTestStepsBody
11
+ ),
12
+ examples: [
13
+ {
14
+ description: "Mark the status of all steps in the test execution 'SA-E1' as 'Pass'. Set the actual result of step 1 to 'Dashboard widgets loaded correctly' and step 2 to 'Navigation menu responded correctly to user interactions'.",
15
+ parameters: {
16
+ testExecutionIdOrKey: "SA-E1",
17
+ steps: [
18
+ {
19
+ statusName: "Pass",
20
+ actualResult: "Dashboard widgets loaded correctly"
21
+ },
22
+ {
23
+ statusName: "Pass",
24
+ actualResult: "Navigation menu responded correctly to user interactions"
25
+ }
26
+ ]
27
+ },
28
+ expectedOutput: "Test steps are updated successfully, but no output is expected."
29
+ },
30
+ {
31
+ description: "Update only the status of step 2 in test execution 'SA-E5' to 'Fail'. Do not modify any other fields.",
32
+ parameters: {
33
+ testExecutionIdOrKey: "SA-E5",
34
+ steps: [
35
+ {},
36
+ {
37
+ statusName: "Fail"
38
+ }
39
+ ]
40
+ },
41
+ expectedOutput: "The test execution steps are updated, but no output is expected."
42
+ },
43
+ {
44
+ description: "Update only the actual results of the steps in test execution '10'. Set the actual result of step 1 to 'API returned 500 error' and step 2 actual result to 'API returned 200 success'",
45
+ parameters: {
46
+ testExecutionIdOrKey: "10",
47
+ steps: [
48
+ {
49
+ actualResult: "API returned 500 error"
50
+ },
51
+ {
52
+ actualResult: "API returned 200 success"
53
+ }
54
+ ]
55
+ },
56
+ expectedOutput: "Test steps are updated successfully, but no output is expected."
57
+ }
58
+ ]
59
+ };
60
+ handle = async (args) => {
61
+ const parsed = PutTestExecutionTestStepsParams.and(
62
+ PutTestExecutionTestStepsBody.required()
63
+ ).parse(args);
64
+ const { testExecutionIdOrKey, steps: stepUpdates } = parsed;
65
+ const response = await this.client.getApiClient().get(`/testexecutions/${testExecutionIdOrKey}/teststeps`);
66
+ const existingSteps = response.values;
67
+ const updatedSteps = existingSteps.map(
68
+ (existingStep, index) => {
69
+ const update = stepUpdates?.[index];
70
+ return {
71
+ actualResult: update?.actualResult ?? existingStep.inline.actualResult,
72
+ ...update?.statusName !== void 0 && {
73
+ statusName: update.statusName
74
+ }
75
+ };
76
+ }
77
+ );
78
+ await this.client.getApiClient().put(`/testexecutions/${testExecutionIdOrKey}/teststeps`, {
79
+ steps: updatedSteps
80
+ });
81
+ return {
82
+ structuredContent: {},
83
+ content: []
84
+ };
85
+ };
86
+ }
87
+ export {
88
+ UpdateTestExecutionSteps
89
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartbear/mcp",
3
- "version": "0.16.0",
3
+ "version": "0.17.0",
4
4
  "description": "MCP server for interacting SmartBear Products",
5
5
  "keywords": [
6
6
  "smartbear",