@smartbear/mcp 0.6.0 → 0.7.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/README.md +20 -3
- package/dist/api-hub/client/api.js +253 -0
- package/dist/api-hub/client/configuration.js +27 -0
- package/dist/api-hub/client/index.js +5 -0
- package/dist/api-hub/client/portal-types.js +131 -0
- package/dist/api-hub/client/registry-types.js +55 -0
- package/dist/api-hub/client/tools.js +86 -0
- package/dist/api-hub/client.js +64 -404
- package/dist/bugsnag/client/api/CurrentUser.js +16 -10
- package/dist/bugsnag/client/api/Error.js +35 -35
- package/dist/bugsnag/client/api/Project.js +21 -9
- package/dist/bugsnag/client/api/base.js +7 -4
- package/dist/bugsnag/client/api/filters.js +9 -9
- package/dist/bugsnag/client.js +165 -140
- package/dist/common/info.js +1 -1
- package/dist/common/server.js +35 -27
- package/dist/index.js +11 -4
- package/dist/pactflow/client/ai.js +20 -20
- package/dist/pactflow/client/base.js +48 -13
- package/dist/pactflow/client/prompts.js +10 -12
- package/dist/pactflow/client/tools.js +10 -10
- package/dist/pactflow/client/utils.js +1 -1
- package/dist/pactflow/client.js +16 -9
- package/dist/qmetry/client/api/client-api.js +39 -0
- package/dist/qmetry/client/handlers.js +11 -0
- package/dist/qmetry/client/project.js +27 -0
- package/dist/qmetry/client/testcase.js +104 -0
- package/dist/qmetry/client/tools.js +222 -0
- package/dist/qmetry/client.js +95 -0
- package/dist/qmetry/config/constants.js +12 -0
- package/dist/qmetry/config/rest-endpoints.js +11 -0
- package/dist/qmetry/types/common.js +174 -0
- package/dist/qmetry/types/testcase.js +19 -0
- package/dist/reflect/client.js +14 -14
- package/package.json +6 -5
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { QMetryToolsHandlers } from "../config/constants.js";
|
|
2
|
+
import { ProjectArgsSchema, TestCaseDetailsArgsSchema, TestCaseListArgsSchema, TestCaseStepsArgsSchema, TestCaseVersionDetailsArgsSchema, } from "../types/common.js";
|
|
3
|
+
export const TOOLS = [
|
|
4
|
+
{
|
|
5
|
+
title: "Set QMetry Project Info",
|
|
6
|
+
summary: "Set current QMetry project for your account",
|
|
7
|
+
handler: QMetryToolsHandlers.SET_PROJECT_INFO,
|
|
8
|
+
zodSchema: ProjectArgsSchema,
|
|
9
|
+
purpose: "Switch the active QMetry project context for the current session. " +
|
|
10
|
+
"This tool sets the default project that will be used for all subsequent QMetry operations. " +
|
|
11
|
+
"Essential for multi-project QMetry instances where you need to work with specific projects.",
|
|
12
|
+
useCases: [
|
|
13
|
+
"Switch to a specific project before performing test case operations",
|
|
14
|
+
"Set project context for batch operations on test cases",
|
|
15
|
+
"Configure the default project for the current session",
|
|
16
|
+
"Validate access to a specific project before proceeding with operations",
|
|
17
|
+
],
|
|
18
|
+
examples: [
|
|
19
|
+
{
|
|
20
|
+
description: "Set default project as active",
|
|
21
|
+
parameters: { projectKey: "default" },
|
|
22
|
+
expectedOutput: "Project context set to 'default' with confirmation of project details",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
description: "Switch to UT project",
|
|
26
|
+
parameters: { projectKey: "UT" },
|
|
27
|
+
expectedOutput: "Project context switched to 'UT' project with available configurations",
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
description: "Set MAC project as active for test case operations",
|
|
31
|
+
parameters: { projectKey: "MAC" },
|
|
32
|
+
expectedOutput: "Project context set to 'MAC' with viewIds and folder structure",
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
hints: [
|
|
36
|
+
"Always set the project context before performing test case operations in multi-project environments",
|
|
37
|
+
"Use the same project key that you'll use in subsequent test case operations",
|
|
38
|
+
"Common project keys include 'default', 'UT', 'MAC', 'VT' - check with your QMetry admin for available projects",
|
|
39
|
+
"This operation must be performed before fetching test cases if working with non-default projects",
|
|
40
|
+
"The project context persists for the current session until changed again",
|
|
41
|
+
],
|
|
42
|
+
outputFormat: "JSON object containing project configuration details, confirmation of project switch, and available project metadata",
|
|
43
|
+
readOnly: false,
|
|
44
|
+
idempotent: true,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
title: "Fetch QMetry Project Info",
|
|
48
|
+
summary: "Fetch QMetry project information including viewId and folderPath needed for other operations",
|
|
49
|
+
handler: QMetryToolsHandlers.FETCH_PROJECT_INFO,
|
|
50
|
+
zodSchema: ProjectArgsSchema,
|
|
51
|
+
purpose: "Prerequisite tool that provides project configuration data required by other QMetry operations. " +
|
|
52
|
+
"The project key to fetch info for. Use 'default' if not specified. " +
|
|
53
|
+
"Common project keys include 'UT', 'VT', 'MAC', etc. " +
|
|
54
|
+
"If user doesn't specify a project key, this tool will use 'default' automatically.",
|
|
55
|
+
useCases: [
|
|
56
|
+
"Get project configuration before fetching test cases",
|
|
57
|
+
"Retrieve available viewIds for test case listing",
|
|
58
|
+
"Get folderPath information for project navigation",
|
|
59
|
+
"Validate project access and permissions",
|
|
60
|
+
],
|
|
61
|
+
examples: [
|
|
62
|
+
{
|
|
63
|
+
description: "Get default project info",
|
|
64
|
+
parameters: {},
|
|
65
|
+
expectedOutput: "Project configuration with viewIds, folderPaths, and project details",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
description: "Get specific project info",
|
|
69
|
+
parameters: { projectKey: "MAC" },
|
|
70
|
+
expectedOutput: "MAC project configuration with available views and folders",
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
hints: [
|
|
74
|
+
"Always call this first when user doesn't provide viewId or folderPath",
|
|
75
|
+
"Use 'default' project key when user doesn't specify one",
|
|
76
|
+
"Extract viewId from latestViews.TC.viewId for test case operations",
|
|
77
|
+
"Use empty string '' as folderPath for root directory",
|
|
78
|
+
],
|
|
79
|
+
outputFormat: "JSON object containing project details, viewIds, folderPaths, and project configuration",
|
|
80
|
+
readOnly: true,
|
|
81
|
+
idempotent: true,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
title: "Fetch Test Cases",
|
|
85
|
+
summary: "Fetch QMetry test cases - automatically handles viewId resolution based on project",
|
|
86
|
+
handler: QMetryToolsHandlers.FETCH_TEST_CASES,
|
|
87
|
+
zodSchema: TestCaseListArgsSchema,
|
|
88
|
+
purpose: "Get test cases from QMetry. System automatically gets correct viewId from project info if not provided.",
|
|
89
|
+
useCases: [
|
|
90
|
+
"List all test cases in a project",
|
|
91
|
+
"Search for specific test cases using filters",
|
|
92
|
+
"Browse test cases in specific folders",
|
|
93
|
+
"Get paginated test case results",
|
|
94
|
+
],
|
|
95
|
+
examples: [
|
|
96
|
+
{
|
|
97
|
+
description: "Get all test cases from default project - system will auto-fetch viewId",
|
|
98
|
+
parameters: {},
|
|
99
|
+
expectedOutput: "List of test cases from default project with auto-resolved viewId",
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
description: "Get all test cases from UT project - system will auto-fetch UT project's viewId",
|
|
103
|
+
parameters: { projectKey: "UT" },
|
|
104
|
+
expectedOutput: "List of test cases from UT project using UT's specific TC viewId",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
description: "Get test cases with manual viewId (skip auto-resolution)",
|
|
108
|
+
parameters: { projectKey: "MAC", viewId: 167136, folderPath: "" },
|
|
109
|
+
expectedOutput: "Test cases using manually specified viewId 167136",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
description: "List test cases from specific project (ex: project key can be anything (VT, UT, PROJ1, TEST9)",
|
|
113
|
+
parameters: {
|
|
114
|
+
projectKey: "use specific given project key",
|
|
115
|
+
viewId: "fetch specific project given projectKey Test Case ViewId",
|
|
116
|
+
folderPath: "",
|
|
117
|
+
},
|
|
118
|
+
expectedOutput: "Test cases using manually specified viewId 167136 or projectKey",
|
|
119
|
+
},
|
|
120
|
+
],
|
|
121
|
+
hints: [
|
|
122
|
+
"CRITICAL WORKFLOW: Always use the SAME projectKey for both project info and test case fetching",
|
|
123
|
+
"Step 1: If user specifies projectKey (like 'UT', 'MAC'), use that EXACT projectKey for project info",
|
|
124
|
+
"Step 2: Get project info using that projectKey, extract latestViews.TC.viewId",
|
|
125
|
+
"Step 3: Use the SAME projectKey and the extracted TC viewId for fetching test cases",
|
|
126
|
+
"Step 4: If user doesn't specify projectKey, use 'default' for both project info and test case fetching",
|
|
127
|
+
"NEVER mix project keys - if user says 'MAC project', use projectKey='MAC' for everything",
|
|
128
|
+
'For search by test case key (like MAC-TC-1684), use filter: \'[{"type":"string","value":"MAC-TC-1684","field":"entityKeyId"}]\'',
|
|
129
|
+
],
|
|
130
|
+
outputFormat: "JSON object with 'data' array containing test cases and pagination info",
|
|
131
|
+
readOnly: true,
|
|
132
|
+
idempotent: true,
|
|
133
|
+
openWorld: false,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
title: "Fetch Test Case Details",
|
|
137
|
+
summary: "Get detailed information for a specific QMetry test case by numeric ID",
|
|
138
|
+
handler: QMetryToolsHandlers.FETCH_TEST_CASE_DETAILS,
|
|
139
|
+
zodSchema: TestCaseDetailsArgsSchema,
|
|
140
|
+
purpose: "Retrieve comprehensive test case information including metadata, status, and basic properties",
|
|
141
|
+
useCases: [
|
|
142
|
+
"Get test case details by numeric ID",
|
|
143
|
+
"Retrieve test case metadata for reporting",
|
|
144
|
+
"Get test case summary and properties",
|
|
145
|
+
"Fetch test case details before accessing steps or version details",
|
|
146
|
+
],
|
|
147
|
+
examples: [
|
|
148
|
+
{
|
|
149
|
+
description: "Get test case details by numeric ID",
|
|
150
|
+
parameters: { tcID: 4468020 },
|
|
151
|
+
expectedOutput: "Detailed test case information including summary, description, status",
|
|
152
|
+
},
|
|
153
|
+
],
|
|
154
|
+
hints: [
|
|
155
|
+
"⚠️ This API requires a numeric tcID parameter",
|
|
156
|
+
"If user provides entityKey (e.g., MAC-TC-1684), first call FETCH_TEST_CASES with a filter on entityKeyId to resolve the tcID",
|
|
157
|
+
"After resolving entityKey → tcID, call this tool with the resolved numeric tcID",
|
|
158
|
+
"This tool provides metadata and properties; use FETCH_TEST_CASE_STEPS for step-level details",
|
|
159
|
+
],
|
|
160
|
+
outputFormat: "JSON object with test case details including ID, key, summary, description, and metadata",
|
|
161
|
+
readOnly: true,
|
|
162
|
+
idempotent: true,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
title: "Fetch Test Case Version Details",
|
|
166
|
+
summary: "Get QMetry test case details for a specific version by numeric ID",
|
|
167
|
+
handler: QMetryToolsHandlers.FETCH_TEST_CASE_VERSION_DETAILS,
|
|
168
|
+
zodSchema: TestCaseVersionDetailsArgsSchema,
|
|
169
|
+
purpose: "Retrieve version-specific information for a test case including history and changes",
|
|
170
|
+
useCases: [
|
|
171
|
+
"Get specific version details of a test case",
|
|
172
|
+
"Compare different versions of a test case",
|
|
173
|
+
"Retrieve version history information",
|
|
174
|
+
"Audit changes made across test case versions",
|
|
175
|
+
],
|
|
176
|
+
examples: [
|
|
177
|
+
{
|
|
178
|
+
description: "Get version 2 details for test case ID 123",
|
|
179
|
+
parameters: { id: 123, version: 2 },
|
|
180
|
+
expectedOutput: "Version 2 details for test case 123",
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
hints: [
|
|
184
|
+
"⚠️ Requires numeric ID, not entityKey",
|
|
185
|
+
"If user provides entityKey (e.g., MAC-TC-1684), first resolve it to numeric ID using FETCH_TEST_CASES",
|
|
186
|
+
"Version defaults to 1 if not specified",
|
|
187
|
+
"Provides version-specific metadata and history",
|
|
188
|
+
],
|
|
189
|
+
outputFormat: "JSON object with version-specific test case details",
|
|
190
|
+
readOnly: true,
|
|
191
|
+
idempotent: true,
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
title: "Fetch Test Case Steps",
|
|
195
|
+
summary: "Get detailed test case steps for a specific test case by numeric ID",
|
|
196
|
+
handler: QMetryToolsHandlers.FETCH_TEST_CASE_STEPS,
|
|
197
|
+
zodSchema: TestCaseStepsArgsSchema,
|
|
198
|
+
purpose: "Retrieve step-by-step instructions and expected results for manual execution of a test case",
|
|
199
|
+
useCases: [
|
|
200
|
+
"Get step-by-step instructions with expected results",
|
|
201
|
+
"Retrieve test case execution procedure for manual runs",
|
|
202
|
+
"Export or display detailed test steps for documentation",
|
|
203
|
+
"Fetch steps before automation mapping",
|
|
204
|
+
],
|
|
205
|
+
examples: [
|
|
206
|
+
{
|
|
207
|
+
description: "Get steps for test case ID 123",
|
|
208
|
+
parameters: { id: 123 },
|
|
209
|
+
expectedOutput: "Detailed steps with actions and expected results for test case 123",
|
|
210
|
+
},
|
|
211
|
+
],
|
|
212
|
+
hints: [
|
|
213
|
+
"⚠️ Requires numeric ID, not entityKey",
|
|
214
|
+
"If user provides entityKey (e.g., MAC-TC-1684), resolve it first via FETCH_TEST_CASES to get the numeric ID",
|
|
215
|
+
"Version defaults to 1 if not specified",
|
|
216
|
+
"Use pagination for test cases with many steps",
|
|
217
|
+
],
|
|
218
|
+
outputFormat: "JSON object with array of test steps including step description, expected result, and order",
|
|
219
|
+
readOnly: true,
|
|
220
|
+
idempotent: true,
|
|
221
|
+
},
|
|
222
|
+
];
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { QMETRY_HANDLER_MAP } from "./client/handlers.js";
|
|
2
|
+
import { getProjectInfo } from "./client/project.js";
|
|
3
|
+
import { TOOLS } from "./client/tools.js";
|
|
4
|
+
import { QMETRY_DEFAULTS, QMetryToolsHandlers } from "./config/constants.js";
|
|
5
|
+
export class QmetryClient {
|
|
6
|
+
name = "QMetry";
|
|
7
|
+
prefix = "qmetry";
|
|
8
|
+
token;
|
|
9
|
+
projectApiKey;
|
|
10
|
+
endpoint;
|
|
11
|
+
constructor(token, endpoint) {
|
|
12
|
+
this.token = token;
|
|
13
|
+
this.projectApiKey = QMETRY_DEFAULTS.PROJECT_KEY;
|
|
14
|
+
this.endpoint = endpoint || QMETRY_DEFAULTS.BASE_URL;
|
|
15
|
+
}
|
|
16
|
+
getToken() {
|
|
17
|
+
return this.token;
|
|
18
|
+
}
|
|
19
|
+
getBaseUrl() {
|
|
20
|
+
return this.endpoint;
|
|
21
|
+
}
|
|
22
|
+
registerTools(register, _getInput) {
|
|
23
|
+
const resolveContext = (args) => ({
|
|
24
|
+
baseUrl: args.baseUrl ?? this.endpoint,
|
|
25
|
+
projectKey: args.projectKey ?? this.projectApiKey,
|
|
26
|
+
});
|
|
27
|
+
const handleAsync = async (fn) => {
|
|
28
|
+
try {
|
|
29
|
+
return await fn();
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
return {
|
|
33
|
+
content: [
|
|
34
|
+
{
|
|
35
|
+
success: false,
|
|
36
|
+
type: "text",
|
|
37
|
+
text: `Error: ${err instanceof Error ? err.message : String(err)}`,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
for (const tool of TOOLS) {
|
|
44
|
+
const handlerFn = QMETRY_HANDLER_MAP[tool.handler];
|
|
45
|
+
if (!handlerFn) {
|
|
46
|
+
console.error(`⚠️ No handler mapped for ${tool.title}`);
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
register(tool, (args) => handleAsync(async () => {
|
|
50
|
+
const a = args;
|
|
51
|
+
const { baseUrl, projectKey } = resolveContext(a);
|
|
52
|
+
// handling for FETCH_TEST_CASES to auto-resolve viewId and folderPath
|
|
53
|
+
if (tool.handler === QMetryToolsHandlers.FETCH_TEST_CASES) {
|
|
54
|
+
let viewId = a.viewId;
|
|
55
|
+
let folderPath = a.folderPath;
|
|
56
|
+
if (!viewId || folderPath === undefined) {
|
|
57
|
+
let projectInfo;
|
|
58
|
+
try {
|
|
59
|
+
projectInfo = (await getProjectInfo(this.token, baseUrl, projectKey));
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
throw new Error(`Failed to auto-resolve viewId/folderPath for project ${projectKey}. ` +
|
|
63
|
+
`Please provide them manually or check project access. ` +
|
|
64
|
+
`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
65
|
+
}
|
|
66
|
+
if (!viewId && projectInfo?.latestViews?.TC?.viewId) {
|
|
67
|
+
viewId = projectInfo.latestViews.TC.viewId;
|
|
68
|
+
}
|
|
69
|
+
if (folderPath === undefined) {
|
|
70
|
+
folderPath = "";
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
a.viewId = viewId;
|
|
74
|
+
a.folderPath = folderPath;
|
|
75
|
+
}
|
|
76
|
+
const result = await handlerFn(this.token, baseUrl, projectKey, a);
|
|
77
|
+
// Use custom formatter if available, otherwise return JSON
|
|
78
|
+
const formatted = tool.formatResponse
|
|
79
|
+
? tool.formatResponse(result)
|
|
80
|
+
: (result ?? {});
|
|
81
|
+
return {
|
|
82
|
+
content: [
|
|
83
|
+
{
|
|
84
|
+
success: true,
|
|
85
|
+
type: "text",
|
|
86
|
+
text: typeof formatted === "string"
|
|
87
|
+
? formatted
|
|
88
|
+
: JSON.stringify(formatted, null, 2),
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
};
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const QMETRY_DEFAULTS = {
|
|
2
|
+
BASE_URL: "https://testmanagement.qmetry.com",
|
|
3
|
+
PROJECT_KEY: "default",
|
|
4
|
+
};
|
|
5
|
+
export const QMetryToolsHandlers = {
|
|
6
|
+
SET_PROJECT_INFO: "setProjectInfo",
|
|
7
|
+
FETCH_PROJECT_INFO: "getProjectInfo",
|
|
8
|
+
FETCH_TEST_CASES: "getTestCases",
|
|
9
|
+
FETCH_TEST_CASE_DETAILS: "getTestCaseDetails",
|
|
10
|
+
FETCH_TEST_CASE_VERSION_DETAILS: "getTestCaseVersionDetails",
|
|
11
|
+
FETCH_TEST_CASE_STEPS: "getTestCaseSteps",
|
|
12
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const QMETRY_PATHS = {
|
|
2
|
+
PROJECT: {
|
|
3
|
+
GET_INFO: "/rest/admin/project/getinfo",
|
|
4
|
+
},
|
|
5
|
+
TESTCASE: {
|
|
6
|
+
GET_TC_LIST: "/rest/testcases/list/viewColumns",
|
|
7
|
+
GET_TC_DETAILS: "/rest/testcases/getVersionDetail",
|
|
8
|
+
GET_TC_DETAILS_BY_VERSION: "/rest/testcases/list",
|
|
9
|
+
GET_TC_STEPS: "/rest/testcases/steps/list",
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { QMETRY_DEFAULTS } from "../config/constants.js";
|
|
3
|
+
export const DEFAULT_PAGINATION = {
|
|
4
|
+
start: 0,
|
|
5
|
+
page: 1,
|
|
6
|
+
limit: 10,
|
|
7
|
+
};
|
|
8
|
+
export const DEFAULT_FILTER = {
|
|
9
|
+
filter: "[]",
|
|
10
|
+
};
|
|
11
|
+
export const DEFAULT_FOLDER_OPTIONS = {
|
|
12
|
+
scope: "project",
|
|
13
|
+
showRootOnly: false,
|
|
14
|
+
getSubEntities: true,
|
|
15
|
+
hideEmptyFolders: false,
|
|
16
|
+
folderSortColumn: "name",
|
|
17
|
+
folderSortOrder: "ASC",
|
|
18
|
+
restoreDefaultColumns: false,
|
|
19
|
+
folderID: null,
|
|
20
|
+
};
|
|
21
|
+
// Reusable Zod schema components
|
|
22
|
+
export const CommonFields = {
|
|
23
|
+
projectKey: z
|
|
24
|
+
.string()
|
|
25
|
+
.describe("Project key - unique identifier for the project")
|
|
26
|
+
.default(QMETRY_DEFAULTS.PROJECT_KEY),
|
|
27
|
+
projectKeyOptional: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Project key - unique identifier for the project")
|
|
31
|
+
.default(QMETRY_DEFAULTS.PROJECT_KEY),
|
|
32
|
+
baseUrl: z
|
|
33
|
+
.string()
|
|
34
|
+
.url()
|
|
35
|
+
.optional()
|
|
36
|
+
.describe("The base URL for the QMetry instance (must be a valid URL)")
|
|
37
|
+
.default(QMETRY_DEFAULTS.BASE_URL),
|
|
38
|
+
start: z
|
|
39
|
+
.number()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("Start index for pagination - defaults to 0")
|
|
42
|
+
.default(0),
|
|
43
|
+
page: z
|
|
44
|
+
.number()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Page number to return (starts from 1)")
|
|
47
|
+
.default(1),
|
|
48
|
+
limit: z
|
|
49
|
+
.number()
|
|
50
|
+
.optional()
|
|
51
|
+
.describe("Number of records (default 10).")
|
|
52
|
+
.default(10),
|
|
53
|
+
tcID: z
|
|
54
|
+
.number()
|
|
55
|
+
.describe("Test Case numeric ID (required for fetching specific test case details). " +
|
|
56
|
+
"This is the internal numeric identifier, not the entity key like 'MAC-TC-1684'. " +
|
|
57
|
+
"You can get this ID from test case search results or by using filters."),
|
|
58
|
+
id: z
|
|
59
|
+
.number()
|
|
60
|
+
.describe("Test Case numeric ID (required for fetching steps or version details). " +
|
|
61
|
+
"This is the internal numeric identifier, not the entity key like 'MAC-TC-1684'. " +
|
|
62
|
+
"You can get this ID from test case search results."),
|
|
63
|
+
version: z
|
|
64
|
+
.number()
|
|
65
|
+
.describe("Test Case version number (required for fetching specific test case version details). " +
|
|
66
|
+
"This is the internal numeric identifier for the version."),
|
|
67
|
+
versionOptional: z
|
|
68
|
+
.number()
|
|
69
|
+
.optional()
|
|
70
|
+
.describe("Test Case version number (optional, defaults to 1). " +
|
|
71
|
+
"This is the internal numeric identifier for the version."),
|
|
72
|
+
viewId: z
|
|
73
|
+
.number()
|
|
74
|
+
.describe("ViewId for test cases - SYSTEM AUTOMATICALLY RESOLVES THIS. " +
|
|
75
|
+
"Leave empty unless you have a specific viewId. " +
|
|
76
|
+
"System will fetch project info using the projectKey and extract latestViews.TC.viewId automatically. " +
|
|
77
|
+
"Manual viewId only needed if you want to override the automatic resolution."),
|
|
78
|
+
folderPath: z
|
|
79
|
+
.string()
|
|
80
|
+
.optional()
|
|
81
|
+
.describe("Folder path for test cases - SYSTEM AUTOMATICALLY SETS TO ROOT. " +
|
|
82
|
+
'Leave empty unless you want specific folder. System will automatically use "" (root directory). ' +
|
|
83
|
+
'Only specify if user wants specific folder like "Automation/Regression".')
|
|
84
|
+
.default(""),
|
|
85
|
+
folderID: z
|
|
86
|
+
.number()
|
|
87
|
+
.optional()
|
|
88
|
+
.describe("Folder ID for test cases - unique identifier for the folder containing test cases"),
|
|
89
|
+
scope: z
|
|
90
|
+
.string()
|
|
91
|
+
.optional()
|
|
92
|
+
.describe("Scope of the test cases (default 'project')")
|
|
93
|
+
.default("project"),
|
|
94
|
+
filter: z
|
|
95
|
+
.string()
|
|
96
|
+
.optional()
|
|
97
|
+
.describe("Filter criteria as JSON string (default '[]')")
|
|
98
|
+
.default("[]"),
|
|
99
|
+
udfFilter: z
|
|
100
|
+
.string()
|
|
101
|
+
.optional()
|
|
102
|
+
.describe("User-defined field filter as JSON string (default '[]')")
|
|
103
|
+
.default("[]"),
|
|
104
|
+
showRootOnly: z
|
|
105
|
+
.boolean()
|
|
106
|
+
.optional()
|
|
107
|
+
.describe("Whether to show only root folders."),
|
|
108
|
+
getSubEntities: z
|
|
109
|
+
.boolean()
|
|
110
|
+
.optional()
|
|
111
|
+
.describe("Whether to include sub-entities."),
|
|
112
|
+
hideEmptyFolders: z
|
|
113
|
+
.boolean()
|
|
114
|
+
.optional()
|
|
115
|
+
.describe("Whether to hide empty folders."),
|
|
116
|
+
folderSortColumn: z
|
|
117
|
+
.string()
|
|
118
|
+
.optional()
|
|
119
|
+
.describe("Folder sort column (default 'name')"),
|
|
120
|
+
restoreDefaultColumns: z
|
|
121
|
+
.boolean()
|
|
122
|
+
.optional()
|
|
123
|
+
.describe("Whether to restore default columns (default 'false')"),
|
|
124
|
+
folderSortOrder: z
|
|
125
|
+
.string()
|
|
126
|
+
.optional()
|
|
127
|
+
.describe("Folder sort order (ASC or DESC)"),
|
|
128
|
+
};
|
|
129
|
+
export const ProjectArgsSchema = z.object({
|
|
130
|
+
projectKey: CommonFields.projectKey,
|
|
131
|
+
});
|
|
132
|
+
export const TestCaseListArgsSchema = z.object({
|
|
133
|
+
projectKey: CommonFields.projectKeyOptional,
|
|
134
|
+
baseUrl: CommonFields.baseUrl,
|
|
135
|
+
viewId: CommonFields.viewId,
|
|
136
|
+
folderPath: CommonFields.folderPath,
|
|
137
|
+
folderID: CommonFields.folderID,
|
|
138
|
+
start: CommonFields.start,
|
|
139
|
+
page: CommonFields.page,
|
|
140
|
+
limit: CommonFields.limit,
|
|
141
|
+
scope: CommonFields.scope,
|
|
142
|
+
showRootOnly: CommonFields.showRootOnly,
|
|
143
|
+
getSubEntities: CommonFields.getSubEntities,
|
|
144
|
+
hideEmptyFolders: CommonFields.hideEmptyFolders,
|
|
145
|
+
folderSortColumn: CommonFields.folderSortColumn,
|
|
146
|
+
restoreDefaultColumns: CommonFields.restoreDefaultColumns,
|
|
147
|
+
folderSortOrder: CommonFields.folderSortOrder,
|
|
148
|
+
filter: CommonFields.filter,
|
|
149
|
+
udfFilter: CommonFields.udfFilter,
|
|
150
|
+
});
|
|
151
|
+
export const TestCaseDetailsArgsSchema = z.object({
|
|
152
|
+
projectKey: CommonFields.projectKeyOptional,
|
|
153
|
+
baseUrl: CommonFields.baseUrl,
|
|
154
|
+
tcID: CommonFields.tcID,
|
|
155
|
+
start: CommonFields.start,
|
|
156
|
+
page: CommonFields.page,
|
|
157
|
+
limit: CommonFields.limit,
|
|
158
|
+
});
|
|
159
|
+
export const TestCaseVersionDetailsArgsSchema = z.object({
|
|
160
|
+
projectKey: CommonFields.projectKeyOptional,
|
|
161
|
+
baseUrl: CommonFields.baseUrl,
|
|
162
|
+
id: CommonFields.id,
|
|
163
|
+
version: CommonFields.version,
|
|
164
|
+
scope: CommonFields.scope,
|
|
165
|
+
});
|
|
166
|
+
export const TestCaseStepsArgsSchema = z.object({
|
|
167
|
+
projectKey: CommonFields.projectKeyOptional,
|
|
168
|
+
baseUrl: CommonFields.baseUrl,
|
|
169
|
+
id: CommonFields.id,
|
|
170
|
+
version: CommonFields.versionOptional,
|
|
171
|
+
start: CommonFields.start,
|
|
172
|
+
page: CommonFields.page,
|
|
173
|
+
limit: CommonFields.limit,
|
|
174
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { DEFAULT_FILTER, DEFAULT_FOLDER_OPTIONS, DEFAULT_PAGINATION, } from "./common.js";
|
|
2
|
+
export const DEFAULT_FETCH_TESTCASES_PAYLOAD = {
|
|
3
|
+
...DEFAULT_PAGINATION,
|
|
4
|
+
...DEFAULT_FILTER,
|
|
5
|
+
...DEFAULT_FOLDER_OPTIONS,
|
|
6
|
+
udfFilter: "[]",
|
|
7
|
+
};
|
|
8
|
+
export const DEFAULT_FETCH_TESTCASE_DETAILS_PAYLOAD = {
|
|
9
|
+
...DEFAULT_PAGINATION,
|
|
10
|
+
...DEFAULT_FILTER,
|
|
11
|
+
};
|
|
12
|
+
export const DEFAULT_FETCH_TESTCASE_VERSION_DETAILS_PAYLOAD = {
|
|
13
|
+
...DEFAULT_FILTER,
|
|
14
|
+
scope: DEFAULT_FOLDER_OPTIONS.scope,
|
|
15
|
+
};
|
|
16
|
+
export const DEFAULT_FETCH_TESTCASE_STEPS_PAYLOAD = {
|
|
17
|
+
...DEFAULT_PAGINATION,
|
|
18
|
+
version: 1,
|
|
19
|
+
};
|
package/dist/reflect/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "../common/info.js";
|
|
2
1
|
import { z } from "zod";
|
|
2
|
+
import { MCP_SERVER_NAME, MCP_SERVER_VERSION } from "../common/info.js";
|
|
3
3
|
// ReflectClient class implementing the Client interface
|
|
4
4
|
export class ReflectClient {
|
|
5
5
|
headers;
|
|
@@ -61,7 +61,7 @@ export class ReflectClient {
|
|
|
61
61
|
});
|
|
62
62
|
return response.json();
|
|
63
63
|
}
|
|
64
|
-
async getReflectTestStatus(
|
|
64
|
+
async getReflectTestStatus(_testId, executionId) {
|
|
65
65
|
const response = await fetch(`https://api.reflect.run/v1/executions/${executionId}`, {
|
|
66
66
|
method: "GET",
|
|
67
67
|
headers: this.headers,
|
|
@@ -87,7 +87,7 @@ export class ReflectClient {
|
|
|
87
87
|
name: "suiteId",
|
|
88
88
|
type: z.string(),
|
|
89
89
|
description: "ID of the reflect suite to list executions for",
|
|
90
|
-
required: true
|
|
90
|
+
required: true,
|
|
91
91
|
},
|
|
92
92
|
],
|
|
93
93
|
}, async (args, _extra) => {
|
|
@@ -106,13 +106,13 @@ export class ReflectClient {
|
|
|
106
106
|
name: "suiteId",
|
|
107
107
|
type: z.string(),
|
|
108
108
|
description: "ID of the reflect suite to get execution status for",
|
|
109
|
-
required: true
|
|
109
|
+
required: true,
|
|
110
110
|
},
|
|
111
111
|
{
|
|
112
112
|
name: "executionId",
|
|
113
113
|
type: z.string(),
|
|
114
114
|
description: "ID of the reflect suite execution to get status for",
|
|
115
|
-
required: true
|
|
115
|
+
required: true,
|
|
116
116
|
},
|
|
117
117
|
],
|
|
118
118
|
}, async (args, _extra) => {
|
|
@@ -131,9 +131,9 @@ export class ReflectClient {
|
|
|
131
131
|
name: "suiteId",
|
|
132
132
|
type: z.string(),
|
|
133
133
|
description: "ID of the reflect suite to list executions for",
|
|
134
|
-
required: true
|
|
135
|
-
}
|
|
136
|
-
]
|
|
134
|
+
required: true,
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
137
|
}, async (args, _extra) => {
|
|
138
138
|
if (!args.suiteId)
|
|
139
139
|
throw new Error("suiteId argument is required");
|
|
@@ -150,13 +150,13 @@ export class ReflectClient {
|
|
|
150
150
|
name: "suiteId",
|
|
151
151
|
type: z.string(),
|
|
152
152
|
description: "ID of the reflect suite to cancel execution for",
|
|
153
|
-
required: true
|
|
153
|
+
required: true,
|
|
154
154
|
},
|
|
155
155
|
{
|
|
156
156
|
name: "executionId",
|
|
157
157
|
type: z.string(),
|
|
158
158
|
description: "ID of the reflect suite execution to cancel",
|
|
159
|
-
required: true
|
|
159
|
+
required: true,
|
|
160
160
|
},
|
|
161
161
|
],
|
|
162
162
|
}, async (args, _extra) => {
|
|
@@ -185,8 +185,8 @@ export class ReflectClient {
|
|
|
185
185
|
name: "testId",
|
|
186
186
|
type: z.string(),
|
|
187
187
|
description: "ID of the reflect test to run",
|
|
188
|
-
required: true
|
|
189
|
-
}
|
|
188
|
+
required: true,
|
|
189
|
+
},
|
|
190
190
|
],
|
|
191
191
|
}, async (args, _extra) => {
|
|
192
192
|
if (!args.testId)
|
|
@@ -204,13 +204,13 @@ export class ReflectClient {
|
|
|
204
204
|
name: "testId",
|
|
205
205
|
type: z.string(),
|
|
206
206
|
description: "ID of the reflect test to run",
|
|
207
|
-
required: true
|
|
207
|
+
required: true,
|
|
208
208
|
},
|
|
209
209
|
{
|
|
210
210
|
name: "executionId",
|
|
211
211
|
type: z.string(),
|
|
212
212
|
description: "ID of the reflect test execution to get status for",
|
|
213
|
-
required: true
|
|
213
|
+
required: true,
|
|
214
214
|
},
|
|
215
215
|
],
|
|
216
216
|
}, async (args, _extra) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartbear/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "MCP server for interacting SmartBear Products",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"smartbear",
|
|
@@ -31,7 +31,10 @@
|
|
|
31
31
|
},
|
|
32
32
|
"scripts": {
|
|
33
33
|
"build": "tsc && shx chmod +x dist/*.js",
|
|
34
|
-
"lint": "
|
|
34
|
+
"lint": "biome lint .",
|
|
35
|
+
"lint:fix": "biome lint . --fix",
|
|
36
|
+
"format": "biome format . --write",
|
|
37
|
+
"format:check": "biome format .",
|
|
35
38
|
"prepare": "npm run build",
|
|
36
39
|
"watch": "tsc --watch",
|
|
37
40
|
"test": "vitest",
|
|
@@ -50,15 +53,13 @@
|
|
|
50
53
|
"zod-to-json-schema": "^3.24.6"
|
|
51
54
|
},
|
|
52
55
|
"devDependencies": {
|
|
53
|
-
"@
|
|
56
|
+
"@biomejs/biome": "^2.2.4",
|
|
54
57
|
"@types/js-yaml": "^4.0.9",
|
|
55
58
|
"@types/node": "^22",
|
|
56
59
|
"@vitest/coverage-v8": "^3.2.4",
|
|
57
|
-
"eslint": "^9.29.0",
|
|
58
60
|
"globals": "^16.2.0",
|
|
59
61
|
"shx": "^0.3.4",
|
|
60
62
|
"typescript": "^5.6.2",
|
|
61
|
-
"typescript-eslint": "^8.34.1",
|
|
62
63
|
"vitest": "^3.2.4",
|
|
63
64
|
"vitest-fetch-mock": "^0.4.5"
|
|
64
65
|
}
|