@smartbear/mcp 0.7.0 → 0.9.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.
Files changed (52) hide show
  1. package/README.md +19 -2
  2. package/dist/api-hub/client/api.js +198 -23
  3. package/dist/api-hub/client/registry-types.js +22 -0
  4. package/dist/api-hub/client/tools.js +19 -1
  5. package/dist/api-hub/client.js +9 -0
  6. package/dist/bugsnag/client/api/CurrentUser.js +13 -50
  7. package/dist/bugsnag/client/api/Error.js +30 -155
  8. package/dist/bugsnag/client/api/Project.js +56 -124
  9. package/dist/bugsnag/client/api/api.js +3743 -0
  10. package/dist/bugsnag/client/api/base.js +107 -32
  11. package/dist/bugsnag/client/api/configuration.js +26 -0
  12. package/dist/bugsnag/client/api/index.js +2 -0
  13. package/dist/bugsnag/client/filters.js +28 -0
  14. package/dist/bugsnag/client.js +157 -325
  15. package/dist/common/server.js +29 -4
  16. package/dist/common/types.js +6 -1
  17. package/dist/index.js +8 -1
  18. package/dist/pactflow/client/prompt-utils.js +2 -1
  19. package/dist/pactflow/client/tools.js +9 -9
  20. package/dist/pactflow/client/utils.js +5 -4
  21. package/dist/pactflow/client.js +16 -14
  22. package/dist/qmetry/client/api/client-api.js +21 -16
  23. package/dist/qmetry/client/api/error-handler.js +329 -0
  24. package/dist/qmetry/client/auto-resolve.js +74 -0
  25. package/dist/qmetry/client/handlers.js +19 -2
  26. package/dist/qmetry/client/issues.js +26 -0
  27. package/dist/qmetry/client/project.js +56 -0
  28. package/dist/qmetry/client/requirement.js +76 -0
  29. package/dist/qmetry/client/testcase.js +46 -8
  30. package/dist/qmetry/client/testsuite.js +117 -0
  31. package/dist/qmetry/client/tools.js +1455 -4
  32. package/dist/qmetry/client/utils.js +16 -0
  33. package/dist/qmetry/client.js +19 -16
  34. package/dist/qmetry/config/constants.js +14 -0
  35. package/dist/qmetry/config/rest-endpoints.js +20 -0
  36. package/dist/qmetry/types/common.js +313 -8
  37. package/dist/qmetry/types/issues.js +6 -0
  38. package/dist/qmetry/types/project.js +10 -0
  39. package/dist/qmetry/types/requirements.js +19 -0
  40. package/dist/qmetry/types/testcase.js +14 -0
  41. package/dist/qmetry/types/testsuite.js +26 -0
  42. package/dist/reflect/client.js +7 -6
  43. package/dist/zephyr/client.js +16 -0
  44. package/dist/zephyr/common/api-client.js +27 -0
  45. package/dist/zephyr/common/auth-service.js +15 -0
  46. package/dist/zephyr/common/types.js +35 -0
  47. package/dist/zephyr/tool/project/get-projects.js +54 -0
  48. package/dist/zephyr/tool/zephyr-tool.js +1 -0
  49. package/package.json +3 -2
  50. package/dist/bugsnag/client/api/filters.js +0 -167
  51. package/dist/bugsnag/client/configuration.js +0 -10
  52. package/dist/bugsnag/client/index.js +0 -2
@@ -0,0 +1,16 @@
1
+ import { ApiClient } from "./common/api-client.js";
2
+ import { GetProjects } from "./tool/project/get-projects.js";
3
+ export class ZephyrClient {
4
+ apiClient;
5
+ name = "Zephyr";
6
+ prefix = "zephyr";
7
+ constructor(bearerToken, baseUrl = "https://api.zephyrscale.smartbear.com/v2") {
8
+ this.apiClient = new ApiClient(bearerToken, baseUrl);
9
+ }
10
+ registerTools(register, _getInput) {
11
+ const tools = [new GetProjects(this.apiClient)];
12
+ tools.forEach((tool) => {
13
+ register(tool.specification, tool.handle);
14
+ });
15
+ }
16
+ }
@@ -0,0 +1,27 @@
1
+ import { AuthService } from "./auth-service.js";
2
+ export class ApiClient {
3
+ baseUrl;
4
+ defaultHeaders;
5
+ constructor(bearerToken, baseUrl) {
6
+ this.baseUrl = baseUrl.trim().replace(/\/$/, "");
7
+ this.defaultHeaders = new AuthService(bearerToken).getAuthHeaders();
8
+ }
9
+ getUrl(endpoint, params) {
10
+ const url = new URL(this.baseUrl + endpoint);
11
+ if (params) {
12
+ Object.entries(params).forEach(([key, value]) => {
13
+ if (value !== undefined) {
14
+ url.searchParams.append(key, String(value));
15
+ }
16
+ });
17
+ }
18
+ return url.toString();
19
+ }
20
+ async get(endpoint, params) {
21
+ const response = await fetch(this.getUrl(endpoint, params), {
22
+ method: "GET",
23
+ headers: this.defaultHeaders,
24
+ });
25
+ return response.json();
26
+ }
27
+ }
@@ -0,0 +1,15 @@
1
+ import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "../../common/info.js";
2
+ export class AuthService {
3
+ bearerToken;
4
+ constructor(accessToken) {
5
+ this.bearerToken = accessToken.trim();
6
+ }
7
+ getAuthHeaders() {
8
+ return {
9
+ Authorization: `Bearer ${this.bearerToken}`,
10
+ "Content-Type": "application/json",
11
+ "User-Agent": `${MCP_SERVER_NAME}/${MCP_SERVER_VERSION}`,
12
+ "zscale-source": "smartbear-mcp",
13
+ };
14
+ }
15
+ }
@@ -0,0 +1,35 @@
1
+ import { z } from "zod";
2
+ export const MaxResultsSchema = z
3
+ .number()
4
+ .min(1)
5
+ .max(1000)
6
+ .describe(`
7
+ 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.
8
+
9
+ Note that the server may enforce a lower limit than requested, depending on resource availability or other internal constraints.
10
+ If this happens, the result set may be truncated. Always check the maxResults value in the response to confirm how many results were actually returned.
11
+ `);
12
+ export const StartAtSchema = z
13
+ .number()
14
+ .min(0)
15
+ .max(1000000)
16
+ .describe(`
17
+ Zero-indexed starting position used to paginate through results. Defaults to 0.
18
+ `);
19
+ export const ZephyrProjectSchema = z.object({
20
+ id: z.number(),
21
+ jiraProjectId: z.number(),
22
+ key: z.string(),
23
+ enabled: z.boolean(),
24
+ });
25
+ export function createListSchema(itemSchema) {
26
+ return z.object({
27
+ next: z.string().nullable(),
28
+ startAt: StartAtSchema,
29
+ maxResults: MaxResultsSchema,
30
+ total: z.number(),
31
+ isLast: z.boolean(),
32
+ values: z.array(itemSchema),
33
+ });
34
+ }
35
+ export const ZephyrProjectListSchema = createListSchema(ZephyrProjectSchema);
@@ -0,0 +1,54 @@
1
+ import { z } from "zod";
2
+ import { MaxResultsSchema, StartAtSchema } from "../../common/types.js";
3
+ export const GetProjectsInputSchema = z.object({
4
+ startAt: StartAtSchema.optional(),
5
+ maxResults: MaxResultsSchema.optional(),
6
+ });
7
+ export class GetProjects {
8
+ apiClient;
9
+ constructor(apiClient) {
10
+ this.apiClient = apiClient;
11
+ }
12
+ specification = {
13
+ title: "Get Projects",
14
+ summary: "Get details of projects in Zephyr",
15
+ readOnly: true,
16
+ idempotent: true,
17
+ zodSchema: GetProjectsInputSchema,
18
+ examples: [
19
+ {
20
+ description: "Get the first 10 projects",
21
+ parameters: {
22
+ maxResults: 10,
23
+ startAt: 0,
24
+ },
25
+ expectedOutput: "The first 10 projects with their details",
26
+ },
27
+ {
28
+ description: "Get any project",
29
+ parameters: {
30
+ maxResults: 1,
31
+ },
32
+ expectedOutput: "One project with its details",
33
+ },
34
+ {
35
+ description: "Get five projects starting from the 7th project of the list",
36
+ parameters: {
37
+ maxResults: 5,
38
+ startAt: 6,
39
+ },
40
+ expectedOutput: "The 7th to the 11th projects with their details",
41
+ },
42
+ ],
43
+ };
44
+ handle = async (args) => {
45
+ const { maxResults, startAt } = args;
46
+ const response = await this.apiClient.get("/projects", {
47
+ maxResults,
48
+ startAt,
49
+ });
50
+ return {
51
+ content: [{ type: "text", text: JSON.stringify(response) }],
52
+ };
53
+ };
54
+ }
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@smartbear/mcp",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "MCP server for interacting SmartBear Products",
5
5
  "keywords": [
6
6
  "smartbear",
@@ -8,7 +8,8 @@
8
8
  "bugsnag",
9
9
  "reflect",
10
10
  "api-hub",
11
- "pactflow"
11
+ "pactflow",
12
+ "zephyr"
12
13
  ],
13
14
  "homepage": "https://developer.smartbear.com/smartbear-mcp",
14
15
  "mcpName": "com.smartbear/smartbear-mcp",
@@ -1,167 +0,0 @@
1
- /**
2
- * Filters utility for BugSnag API
3
- *
4
- * This file provides utility functions for creating filter URL parameters
5
- * based on the BugSnag filtering specification described in the Filtering.md document.
6
- */
7
- import { z } from "zod";
8
- export const FilterValueSchema = z.object({
9
- type: z.enum(["eq", "ne", "empty"]),
10
- value: z.union([z.string(), z.boolean(), z.number()]),
11
- });
12
- export const FilterObjectSchema = z.record(z.array(FilterValueSchema));
13
- /**
14
- * Creates a filter value object for equality comparison
15
- *
16
- * @param value The value to compare against
17
- * @returns FilterValue with type 'eq'
18
- */
19
- export function equals(value) {
20
- return {
21
- type: "eq",
22
- value,
23
- };
24
- }
25
- /**
26
- * Creates a filter value object for inequality comparison
27
- *
28
- * @param value The value to compare against
29
- * @returns FilterValue with type 'ne'
30
- */
31
- export function notEquals(value) {
32
- return {
33
- type: "ne",
34
- value,
35
- };
36
- }
37
- /**
38
- * Creates a filter value object for checking if a field is empty or not
39
- *
40
- * @param isEmpty Whether the field should be empty (true) or not (false)
41
- * @returns FilterValue with type 'empty'
42
- */
43
- export function empty(isEmpty) {
44
- return {
45
- type: "empty",
46
- value: isEmpty.toString(),
47
- };
48
- }
49
- /**
50
- * Creates a relative time filter for event.since or event.before
51
- *
52
- * @param value The amount of time
53
- * @param unit The time unit ('h' for hours, 'd' for days)
54
- * @returns FilterValue for the relative time
55
- */
56
- export function relativeTime(value, unit) {
57
- return {
58
- type: "eq",
59
- value: `${value}${unit}`,
60
- };
61
- }
62
- /**
63
- * Creates an ISO 8601 time filter (must be in UTC format like 2018-05-20T00:00:00Z)
64
- *
65
- * @param date The date object to convert to ISO string
66
- * @returns FilterValue for the ISO time
67
- */
68
- export function isoTime(date) {
69
- return {
70
- type: "eq",
71
- value: date.toISOString(),
72
- };
73
- }
74
- /**
75
- * Converts a FilterObject to URL search parameters
76
- *
77
- * @param filters The filter object to convert
78
- * @returns URLSearchParams object with the encoded filters
79
- */
80
- export function toUrlSearchParams(filters) {
81
- const params = new URLSearchParams();
82
- Object.entries(filters).forEach(([field, filterValues]) => {
83
- filterValues.forEach((filterValue) => {
84
- params.append(`filters[${field}][][type]`, filterValue.type);
85
- params.append(`filters[${field}][][value]`, filterValue.value.toString());
86
- });
87
- });
88
- return params;
89
- }
90
- /**
91
- * Converts a FilterObject to a query string
92
- *
93
- * @param filters The filter object to convert
94
- * @returns Query string representation of the filters
95
- */
96
- export function toQueryString(filters) {
97
- return toUrlSearchParams(filters).toString();
98
- }
99
- /**
100
- * Helper to build a FilterObject with type safety
101
- *
102
- * @returns An empty FilterObject that can be built upon
103
- */
104
- export function createFilter() {
105
- return {};
106
- }
107
- /**
108
- * Adds a field filter to an existing FilterObject
109
- *
110
- * @param filters The FilterObject to add to
111
- * @param field The field name (e.g., 'error.status', 'event.since')
112
- * @param filterValue The FilterValue to add
113
- * @returns The updated FilterObject for chaining
114
- */
115
- export function addFilter(filters, field, filterValue) {
116
- if (!filters[field]) {
117
- filters[field] = [];
118
- }
119
- filters[field].push(filterValue);
120
- return filters;
121
- }
122
- /**
123
- * Utility to create a time range filter between two dates
124
- *
125
- * @param filters The FilterObject to add to
126
- * @param since Start date
127
- * @param before End date
128
- * @returns The updated FilterObject for chaining
129
- */
130
- export function addTimeRange(filters, since, before) {
131
- addFilter(filters, "event.since", isoTime(since));
132
- addFilter(filters, "event.before", isoTime(before));
133
- return filters;
134
- }
135
- /**
136
- * Utility to create a relative time range filter
137
- *
138
- * @param filters The FilterObject to add to
139
- * @param amount The amount of time (e.g., 7 for 7 days)
140
- * @param unit The time unit ('h' for hours, 'd' for days)
141
- * @returns The updated FilterObject for chaining
142
- */
143
- export function addRelativeTimeRange(filters, amount, unit) {
144
- addFilter(filters, "event.since", relativeTime(amount, unit));
145
- return filters;
146
- }
147
- /**
148
- * Usage examples:
149
- *
150
- * // Example 1: Open errors with events in the last day
151
- * const filters = createFilter();
152
- * addRelativeTimeRange(filters, 1, 'd');
153
- * addFilter(filters, 'error.status', equals('open'));
154
- * const queryString = toQueryString(filters);
155
- *
156
- * // Example 2: Events affecting specific users on a specific day
157
- * const filters = createFilter();
158
- * addTimeRange(filters, new Date('2017-01-01'), new Date('2017-01-02'));
159
- * addFilter(filters, 'user.email', equals('user1@example.com'));
160
- * addFilter(filters, 'user.email', equals('user2@example.com'));
161
- * const queryString = toQueryString(filters);
162
- *
163
- * // Example 3: Events that have user data
164
- * const filters = createFilter();
165
- * addFilter(filters, 'user.id', empty(false));
166
- * const queryString = toQueryString(filters);
167
- */
@@ -1,10 +0,0 @@
1
- export class Configuration {
2
- authToken;
3
- basePath;
4
- headers;
5
- constructor(param) {
6
- this.authToken = param.authToken;
7
- this.basePath = param.basePath;
8
- this.headers = param.headers || {};
9
- }
10
- }
@@ -1,2 +0,0 @@
1
- export * from "./api/index.js";
2
- export * from "./configuration.js";