@bun913/mcp-testrail 0.11.4
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/LICENSE +21 -0
- package/README.md +101 -0
- package/dist/client/api/baseClient.d.ts +39 -0
- package/dist/client/api/baseClient.js +103 -0
- package/dist/client/api/baseClient.js.map +1 -0
- package/dist/client/api/cases.d.ts +102 -0
- package/dist/client/api/cases.js +200 -0
- package/dist/client/api/cases.js.map +1 -0
- package/dist/client/api/index.d.ts +39 -0
- package/dist/client/api/index.js +50 -0
- package/dist/client/api/index.js.map +1 -0
- package/dist/client/api/milestones.d.ts +12 -0
- package/dist/client/api/milestones.js +22 -0
- package/dist/client/api/milestones.js.map +1 -0
- package/dist/client/api/plans.d.ts +12 -0
- package/dist/client/api/plans.js +20 -0
- package/dist/client/api/plans.js.map +1 -0
- package/dist/client/api/projects.d.ts +12 -0
- package/dist/client/api/projects.js +31 -0
- package/dist/client/api/projects.js.map +1 -0
- package/dist/client/api/results.d.ts +56 -0
- package/dist/client/api/results.js +125 -0
- package/dist/client/api/results.js.map +1 -0
- package/dist/client/api/runs.d.ts +40 -0
- package/dist/client/api/runs.js +79 -0
- package/dist/client/api/runs.js.map +1 -0
- package/dist/client/api/sections.d.ts +40 -0
- package/dist/client/api/sections.js +89 -0
- package/dist/client/api/sections.js.map +1 -0
- package/dist/client/api/sharedSteps.d.ts +11 -0
- package/dist/client/api/sharedSteps.js +20 -0
- package/dist/client/api/sharedSteps.js.map +1 -0
- package/dist/client/api/suites.d.ts +36 -0
- package/dist/client/api/suites.js +63 -0
- package/dist/client/api/suites.js.map +1 -0
- package/dist/client/api/tests.d.ts +32 -0
- package/dist/client/api/tests.js +47 -0
- package/dist/client/api/tests.js.map +1 -0
- package/dist/client/api/utils.d.ts +7 -0
- package/dist/client/api/utils.js +24 -0
- package/dist/client/api/utils.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/server/api/cases.d.ts +8 -0
- package/dist/server/api/cases.js +431 -0
- package/dist/server/api/cases.js.map +1 -0
- package/dist/server/api/index.d.ts +18 -0
- package/dist/server/api/index.js +40 -0
- package/dist/server/api/index.js.map +1 -0
- package/dist/server/api/milestones.d.ts +8 -0
- package/dist/server/api/milestones.js +29 -0
- package/dist/server/api/milestones.js.map +1 -0
- package/dist/server/api/plans.d.ts +8 -0
- package/dist/server/api/plans.js +29 -0
- package/dist/server/api/plans.js.map +1 -0
- package/dist/server/api/projects.d.ts +8 -0
- package/dist/server/api/projects.js +51 -0
- package/dist/server/api/projects.js.map +1 -0
- package/dist/server/api/results.d.ts +8 -0
- package/dist/server/api/results.js +164 -0
- package/dist/server/api/results.js.map +1 -0
- package/dist/server/api/runs.d.ts +8 -0
- package/dist/server/api/runs.js +113 -0
- package/dist/server/api/runs.js.map +1 -0
- package/dist/server/api/sections.d.ts +8 -0
- package/dist/server/api/sections.js +138 -0
- package/dist/server/api/sections.js.map +1 -0
- package/dist/server/api/sharedSteps.d.ts +8 -0
- package/dist/server/api/sharedSteps.js +26 -0
- package/dist/server/api/sharedSteps.js.map +1 -0
- package/dist/server/api/suites.d.ts +8 -0
- package/dist/server/api/suites.js +111 -0
- package/dist/server/api/suites.js.map +1 -0
- package/dist/server/api/tests.d.ts +8 -0
- package/dist/server/api/tests.js +68 -0
- package/dist/server/api/tests.js.map +1 -0
- package/dist/server/api/utils.d.ts +7 -0
- package/dist/server/api/utils.js +25 -0
- package/dist/server/api/utils.js.map +1 -0
- package/dist/server/server.d.ts +2 -0
- package/dist/server/server.js +70 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/templates.d.ts +8 -0
- package/dist/server/templates.js +43 -0
- package/dist/server/templates.js.map +1 -0
- package/dist/shared/schemas/cases.d.ts +668 -0
- package/dist/shared/schemas/cases.js +178 -0
- package/dist/shared/schemas/cases.js.map +1 -0
- package/dist/shared/schemas/common.d.ts +117 -0
- package/dist/shared/schemas/common.js +50 -0
- package/dist/shared/schemas/common.js.map +1 -0
- package/dist/shared/schemas/index.d.ts +10 -0
- package/dist/shared/schemas/index.js +23 -0
- package/dist/shared/schemas/index.js.map +1 -0
- package/dist/shared/schemas/milestones.d.ts +59 -0
- package/dist/shared/schemas/milestones.js +26 -0
- package/dist/shared/schemas/milestones.js.map +1 -0
- package/dist/shared/schemas/plans.d.ts +416 -0
- package/dist/shared/schemas/plans.js +43 -0
- package/dist/shared/schemas/plans.js.map +1 -0
- package/dist/shared/schemas/projects.d.ts +135 -0
- package/dist/shared/schemas/projects.js +61 -0
- package/dist/shared/schemas/projects.js.map +1 -0
- package/dist/shared/schemas/results.d.ts +407 -0
- package/dist/shared/schemas/results.js +178 -0
- package/dist/shared/schemas/results.js.map +1 -0
- package/dist/shared/schemas/runs.d.ts +267 -0
- package/dist/shared/schemas/runs.js +133 -0
- package/dist/shared/schemas/runs.js.map +1 -0
- package/dist/shared/schemas/sections.d.ts +136 -0
- package/dist/shared/schemas/sections.js +68 -0
- package/dist/shared/schemas/sections.js.map +1 -0
- package/dist/shared/schemas/sharedSteps.d.ts +135 -0
- package/dist/shared/schemas/sharedSteps.js +65 -0
- package/dist/shared/schemas/sharedSteps.js.map +1 -0
- package/dist/shared/schemas/suites.d.ts +120 -0
- package/dist/shared/schemas/suites.js +44 -0
- package/dist/shared/schemas/suites.js.map +1 -0
- package/dist/shared/schemas/tests.d.ts +87 -0
- package/dist/shared/schemas/tests.js +52 -0
- package/dist/shared/schemas/tests.js.map +1 -0
- package/dist/sse.d.ts +1 -0
- package/dist/sse.js +5 -0
- package/dist/sse.js.map +1 -0
- package/dist/stdio.d.ts +1 -0
- package/dist/stdio.js +52 -0
- package/dist/stdio.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createSuccessResponse, createErrorResponse } from "./utils.js";
|
|
2
|
+
import { getSuitesSchema, getSuiteSchema, addSuiteSchema, updateSuiteSchema, } from "../../shared/schemas/suites.js";
|
|
3
|
+
/**
|
|
4
|
+
* Function to register test suite-related API tools
|
|
5
|
+
* @param server McpServer instance
|
|
6
|
+
* @param testRailClient TestRail client instance
|
|
7
|
+
*/
|
|
8
|
+
export function registerSuiteTools(server, testRailClient) {
|
|
9
|
+
// Get all test suites for a project
|
|
10
|
+
server.tool("getSuites", "Retrieves all test suites for a specified TestRail project / 指定されたTestRailプロジェクトの全テストスイートを取得します", {
|
|
11
|
+
projectId: getSuitesSchema.shape.projectId.describe("TestRail Project ID to get suites from / スイート一覧を取得するTestRailプロジェクトID"),
|
|
12
|
+
}, async (args, extra) => {
|
|
13
|
+
try {
|
|
14
|
+
const { projectId } = args;
|
|
15
|
+
const suites = await testRailClient.suites.getSuites(projectId);
|
|
16
|
+
const successResponse = createSuccessResponse("Test suites retrieved successfully", {
|
|
17
|
+
suites,
|
|
18
|
+
});
|
|
19
|
+
return {
|
|
20
|
+
content: [{ type: "text", text: JSON.stringify(successResponse) }],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
const errorResponse = createErrorResponse(`Error fetching test suites for project ${args.projectId}`, error);
|
|
25
|
+
return {
|
|
26
|
+
content: [{ type: "text", text: JSON.stringify(errorResponse) }],
|
|
27
|
+
isError: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
// Get a specific test suite
|
|
32
|
+
server.tool("getSuite", "Retrieves details of a specific test suite by ID / 特定のテストスイートの詳細をIDで取得します", {
|
|
33
|
+
suiteId: getSuiteSchema.shape.suiteId.describe("TestRail Suite ID to retrieve / 取得するTestRailスイートID"),
|
|
34
|
+
}, async (args, extra) => {
|
|
35
|
+
try {
|
|
36
|
+
const { suiteId } = args;
|
|
37
|
+
const suite = await testRailClient.suites.getSuite(suiteId);
|
|
38
|
+
const successResponse = createSuccessResponse("Test suite retrieved successfully", {
|
|
39
|
+
suite,
|
|
40
|
+
});
|
|
41
|
+
return {
|
|
42
|
+
content: [{ type: "text", text: JSON.stringify(successResponse) }],
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
const errorResponse = createErrorResponse(`Error fetching test suite ${args.suiteId}`, error);
|
|
47
|
+
return {
|
|
48
|
+
content: [{ type: "text", text: JSON.stringify(errorResponse) }],
|
|
49
|
+
isError: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
// Create a new test suite
|
|
54
|
+
server.tool("addSuite", "Creates a new test suite in the specified project / 指定されたプロジェクトに新しいテストスイートを作成します", {
|
|
55
|
+
projectId: addSuiteSchema.shape.projectId.describe("TestRail Project ID where the suite will be created / スイートを作成するTestRailプロジェクトID"),
|
|
56
|
+
name: addSuiteSchema.shape.name.describe("Name of the test suite / テストスイートの名前"),
|
|
57
|
+
description: addSuiteSchema.shape.description.describe("Description of the test suite (optional) / テストスイートの説明(任意)"),
|
|
58
|
+
}, async (args, extra) => {
|
|
59
|
+
try {
|
|
60
|
+
const { projectId, name, description } = args;
|
|
61
|
+
const data = {
|
|
62
|
+
name,
|
|
63
|
+
description,
|
|
64
|
+
};
|
|
65
|
+
const suite = await testRailClient.suites.addSuite(projectId, data);
|
|
66
|
+
const successResponse = createSuccessResponse("Test suite created successfully", {
|
|
67
|
+
suite,
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
content: [{ type: "text", text: JSON.stringify(successResponse) }],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const errorResponse = createErrorResponse(`Error creating test suite for project ${args.projectId}`, error);
|
|
75
|
+
return {
|
|
76
|
+
content: [{ type: "text", text: JSON.stringify(errorResponse) }],
|
|
77
|
+
isError: true,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// Update an existing test suite
|
|
82
|
+
server.tool("updateSuite", "Updates an existing test suite / 既存のテストスイートを更新します", {
|
|
83
|
+
suiteId: updateSuiteSchema.shape.suiteId.describe("TestRail Suite ID to update / 更新するTestRailスイートID"),
|
|
84
|
+
name: updateSuiteSchema.shape.name.describe("New name for the test suite (optional) / テストスイートの新しい名前(任意)"),
|
|
85
|
+
description: updateSuiteSchema.shape.description.describe("New description for the test suite (optional) / テストスイートの新しい説明(任意)"),
|
|
86
|
+
}, async (args, extra) => {
|
|
87
|
+
try {
|
|
88
|
+
const { suiteId, name, description } = args;
|
|
89
|
+
const data = {};
|
|
90
|
+
if (name)
|
|
91
|
+
data.name = name;
|
|
92
|
+
if (description)
|
|
93
|
+
data.description = description;
|
|
94
|
+
const suite = await testRailClient.suites.updateSuite(suiteId, data);
|
|
95
|
+
const successResponse = createSuccessResponse("Suite updated successfully", {
|
|
96
|
+
suite,
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
content: [{ type: "text", text: JSON.stringify(successResponse) }],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
catch (error) {
|
|
103
|
+
const errorResponse = createErrorResponse(`Error updating suite ${args.suiteId}`, error);
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: "text", text: JSON.stringify(errorResponse) }],
|
|
106
|
+
isError: true,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=suites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"suites.js","sourceRoot":"","sources":["../../../src/server/api/suites.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EACN,eAAe,EACf,cAAc,EACd,cAAc,EACd,iBAAiB,GACjB,MAAM,gCAAgC,CAAC;AAExC;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CACjC,MAAiB,EACjB,cAA8B;IAE9B,oCAAoC;IACpC,MAAM,CAAC,IAAI,CACV,WAAW,EACX,iGAAiG,EACjG;QACC,SAAS,EAAE,eAAe,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAClD,sEAAsE,CACtE;KACD,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACJ,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;YAC3B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YAChE,MAAM,eAAe,GAAG,qBAAqB,CAC5C,oCAAoC,EACpC;gBACC,MAAM;aACN,CACD,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;aAClE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,aAAa,GAAG,mBAAmB,CACxC,0CAA0C,IAAI,CAAC,SAAS,EAAE,EAC1D,KAAK,CACL,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,IAAI;aACb,CAAC;QACH,CAAC;IACF,CAAC,CACD,CAAC;IAEF,4BAA4B;IAC5B,MAAM,CAAC,IAAI,CACV,UAAU,EACV,2EAA2E,EAC3E;QACC,OAAO,EAAE,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAC7C,oDAAoD,CACpD;KACD,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACJ,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;YACzB,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC5D,MAAM,eAAe,GAAG,qBAAqB,CAC5C,mCAAmC,EACnC;gBACC,KAAK;aACL,CACD,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;aAClE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,aAAa,GAAG,mBAAmB,CACxC,6BAA6B,IAAI,CAAC,OAAO,EAAE,EAC3C,KAAK,CACL,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,IAAI;aACb,CAAC;QACH,CAAC;IACF,CAAC,CACD,CAAC;IAEF,0BAA0B;IAC1B,MAAM,CAAC,IAAI,CACV,UAAU,EACV,kFAAkF,EAClF;QACC,SAAS,EAAE,cAAc,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CACjD,iFAAiF,CACjF;QACD,IAAI,EAAE,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CACvC,qCAAqC,CACrC;QACD,WAAW,EAAE,cAAc,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CACrD,2DAA2D,CAC3D;KACD,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACJ,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;YAC9C,MAAM,IAAI,GAAG;gBACZ,IAAI;gBACJ,WAAW;aACX,CAAC;YACF,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;YACpE,MAAM,eAAe,GAAG,qBAAqB,CAC5C,iCAAiC,EACjC;gBACC,KAAK;aACL,CACD,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;aAClE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,aAAa,GAAG,mBAAmB,CACxC,yCAAyC,IAAI,CAAC,SAAS,EAAE,EACzD,KAAK,CACL,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,IAAI;aACb,CAAC;QACH,CAAC;IACF,CAAC,CACD,CAAC;IAEF,gCAAgC;IAChC,MAAM,CAAC,IAAI,CACV,aAAa,EACb,mDAAmD,EACnD;QACC,OAAO,EAAE,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAChD,kDAAkD,CAClD;QACD,IAAI,EAAE,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAC1C,4DAA4D,CAC5D;QACD,WAAW,EAAE,iBAAiB,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CACxD,mEAAmE,CACnE;KACD,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACJ,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;YAC5C,MAAM,IAAI,GAA4C,EAAE,CAAC;YAEzD,IAAI,IAAI;gBAAE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;YAC3B,IAAI,WAAW;gBAAE,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;YAEhD,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACrE,MAAM,eAAe,GAAG,qBAAqB,CAC5C,4BAA4B,EAC5B;gBACC,KAAK;aACL,CACD,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;aAClE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,aAAa,GAAG,mBAAmB,CACxC,wBAAwB,IAAI,CAAC,OAAO,EAAE,EACtC,KAAK,CACL,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,IAAI;aACb,CAAC;QACH,CAAC;IACF,CAAC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { TestRailClient } from "../../client/api/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Function to register test-related API tools
|
|
5
|
+
* @param server McpServer instance
|
|
6
|
+
* @param testRailClient TestRail client instance
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerTestTools(server: McpServer, testRailClient: TestRailClient): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { createSuccessResponse, createErrorResponse } from "./utils.js";
|
|
2
|
+
import { getTestsSchema, getTestSchema } from "../../shared/schemas/tests.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
/**
|
|
5
|
+
* Function to register test-related API tools
|
|
6
|
+
* @param server McpServer instance
|
|
7
|
+
* @param testRailClient TestRail client instance
|
|
8
|
+
*/
|
|
9
|
+
export function registerTestTools(server, testRailClient) {
|
|
10
|
+
// Get a specific test case
|
|
11
|
+
server.tool("getTests", "Retrieves a list of tests for a test run / テスト実行に含まれるテスト一覧を取得します", {
|
|
12
|
+
runId: getTestsSchema.shape.runId,
|
|
13
|
+
limit: z
|
|
14
|
+
.number()
|
|
15
|
+
.min(1)
|
|
16
|
+
.optional()
|
|
17
|
+
.default(50)
|
|
18
|
+
.describe("Number of tests to return per page. If you cannot get all tests, try separating the request into multiple calls"),
|
|
19
|
+
offset: z
|
|
20
|
+
.number()
|
|
21
|
+
.optional()
|
|
22
|
+
.default(0)
|
|
23
|
+
.describe("Offset for pagination"),
|
|
24
|
+
}, async (args, extra) => {
|
|
25
|
+
try {
|
|
26
|
+
const { runId } = args;
|
|
27
|
+
const tests = await testRailClient.tests.getTests(runId);
|
|
28
|
+
// Return full case data for individual case requests
|
|
29
|
+
const successResponse = createSuccessResponse("Tests retrieved successfully", {
|
|
30
|
+
tests: tests,
|
|
31
|
+
});
|
|
32
|
+
return {
|
|
33
|
+
content: [{ type: "text", text: JSON.stringify(successResponse) }],
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
const errorResponse = createErrorResponse(`Error fetching tests ${args.runId}`, error);
|
|
38
|
+
return {
|
|
39
|
+
content: [{ type: "text", text: JSON.stringify(errorResponse) }],
|
|
40
|
+
isError: true,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
// Get a specific test case
|
|
45
|
+
server.tool("getTest", "Retrieves complete details for a single test, including all fields such as status, type, and results / 単一のテストの完全な詳細(ステータス、タイプ、結果などのすべてのフィールドを含む)を取得します", {
|
|
46
|
+
testId: getTestSchema.shape.testId,
|
|
47
|
+
}, async (args, extra) => {
|
|
48
|
+
try {
|
|
49
|
+
const { testId } = args;
|
|
50
|
+
const test = await testRailClient.tests.getTest(testId);
|
|
51
|
+
// Return full case data for individual case requests
|
|
52
|
+
const successResponse = createSuccessResponse("Test retrieved successfully", {
|
|
53
|
+
test: test,
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
content: [{ type: "text", text: JSON.stringify(successResponse) }],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const errorResponse = createErrorResponse(`Error fetching test ${args.testId}`, error);
|
|
61
|
+
return {
|
|
62
|
+
content: [{ type: "text", text: JSON.stringify(errorResponse) }],
|
|
63
|
+
isError: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=tests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tests.js","sourceRoot":"","sources":["../../../src/server/api/tests.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAChC,MAAiB,EACjB,cAA8B;IAE9B,2BAA2B;IAC3B,MAAM,CAAC,IAAI,CACV,UAAU,EACV,kEAAkE,EAClE;QACC,KAAK,EAAE,cAAc,CAAC,KAAK,CAAC,KAAK;QACjC,KAAK,EAAE,CAAC;aACN,MAAM,EAAE;aACR,GAAG,CAAC,CAAC,CAAC;aACN,QAAQ,EAAE;aACV,OAAO,CAAC,EAAE,CAAC;aACX,QAAQ,CACR,iHAAiH,CACjH;QACF,MAAM,EAAE,CAAC;aACP,MAAM,EAAE;aACR,QAAQ,EAAE;aACV,OAAO,CAAC,CAAC,CAAC;aACV,QAAQ,CAAC,uBAAuB,CAAC;KACnC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACJ,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;YACvB,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEzD,qDAAqD;YACrD,MAAM,eAAe,GAAG,qBAAqB,CAC5C,8BAA8B,EAC9B;gBACC,KAAK,EAAE,KAAK;aACZ,CACD,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;aAClE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,aAAa,GAAG,mBAAmB,CACxC,wBAAwB,IAAI,CAAC,KAAK,EAAE,EACpC,KAAK,CACL,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,IAAI;aACb,CAAC;QACH,CAAC;IACF,CAAC,CACD,CAAC;IAEF,2BAA2B;IAC3B,MAAM,CAAC,IAAI,CACV,SAAS,EACT,wJAAwJ,EACxJ;QACC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,MAAM;KAClC,EACD,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,EAAE;QACrB,IAAI,CAAC;YACJ,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;YACxB,MAAM,IAAI,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAExD,qDAAqD;YACrD,MAAM,eAAe,GAAG,qBAAqB,CAC5C,6BAA6B,EAC7B;gBACC,IAAI,EAAE,IAAI;aACV,CACD,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,CAAC;aAClE,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,aAAa,GAAG,mBAAmB,CACxC,uBAAuB,IAAI,CAAC,MAAM,EAAE,EACpC,KAAK,CACL,CAAC;YACF,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,CAAC;gBAChE,OAAO,EAAE,IAAI;aACb,CAAC;QACH,CAAC;IACF,CAAC,CACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type FastMCPToolResponse = {
|
|
2
|
+
type: "text";
|
|
3
|
+
text: string;
|
|
4
|
+
};
|
|
5
|
+
export declare function formatErrorMessage(error: unknown): string;
|
|
6
|
+
export declare function createSuccessResponse(message: string, data?: Record<string, unknown>): FastMCPToolResponse;
|
|
7
|
+
export declare function createErrorResponse(baseMessage: string, error: unknown): FastMCPToolResponse;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// Function to format error messages
|
|
2
|
+
export function formatErrorMessage(error) {
|
|
3
|
+
return error instanceof Error ? error.message : String(error);
|
|
4
|
+
}
|
|
5
|
+
// Function to create success response
|
|
6
|
+
export function createSuccessResponse(message, data) {
|
|
7
|
+
return {
|
|
8
|
+
type: "text",
|
|
9
|
+
text: JSON.stringify({
|
|
10
|
+
message,
|
|
11
|
+
...(data || {}),
|
|
12
|
+
}, null, 2),
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
// Function to create error response
|
|
16
|
+
export function createErrorResponse(baseMessage, error) {
|
|
17
|
+
const errorMessage = formatErrorMessage(error);
|
|
18
|
+
return {
|
|
19
|
+
type: "text",
|
|
20
|
+
text: JSON.stringify({
|
|
21
|
+
error: `${baseMessage}: ${errorMessage}`,
|
|
22
|
+
}, null, 2),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/server/api/utils.ts"],"names":[],"mappings":"AAMA,oCAAoC;AACpC,MAAM,UAAU,kBAAkB,CAAC,KAAc;IAChD,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/D,CAAC;AAED,sCAAsC;AACtC,MAAM,UAAU,qBAAqB,CACpC,OAAe,EACf,IAA8B;IAE9B,OAAO;QACN,IAAI,EAAE,MAAe;QACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CACnB;YACC,OAAO;YACP,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;SACf,EACD,IAAI,EACJ,CAAC,CACD;KACD,CAAC;AACH,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,mBAAmB,CAClC,WAAmB,EACnB,KAAc;IAEd,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO;QACN,IAAI,EAAE,MAAe;QACrB,IAAI,EAAE,IAAI,CAAC,SAAS,CACnB;YACC,KAAK,EAAE,GAAG,WAAW,KAAK,YAAY,EAAE;SACxC,EACD,IAAI,EACJ,CAAC,CACD;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
4
|
+
import "dotenv/config";
|
|
5
|
+
import { TestRailClient } from "../client/api/index.js";
|
|
6
|
+
import { registerAllTools } from "./api/index.js";
|
|
7
|
+
// Validate TestRail configuration
|
|
8
|
+
if (!process.env.TESTRAIL_URL ||
|
|
9
|
+
!process.env.TESTRAIL_USERNAME ||
|
|
10
|
+
!process.env.TESTRAIL_API_KEY) {
|
|
11
|
+
throw new Error("TESTRAIL_URL, TESTRAIL_USERNAME, and TESTRAIL_API_KEY must be set");
|
|
12
|
+
}
|
|
13
|
+
// Correct URL format: https://example.testrail.com/index.php?/
|
|
14
|
+
const url = process.env.TESTRAIL_URL;
|
|
15
|
+
const baseURL = url.endsWith("/index.php?/")
|
|
16
|
+
? url
|
|
17
|
+
: url.endsWith("/")
|
|
18
|
+
? `${url}index.php?/`
|
|
19
|
+
: `${url}/index.php?/`;
|
|
20
|
+
// TestRail client configuration
|
|
21
|
+
const testRailConfig = {
|
|
22
|
+
baseURL: baseURL,
|
|
23
|
+
auth: {
|
|
24
|
+
username: process.env.TESTRAIL_USERNAME,
|
|
25
|
+
password: process.env.TESTRAIL_API_KEY,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
// Initialize TestRail client
|
|
29
|
+
const testRailClient = new TestRailClient(testRailConfig);
|
|
30
|
+
// Create McpServer
|
|
31
|
+
const server = new McpServer({
|
|
32
|
+
name: "TestRail MCP Server",
|
|
33
|
+
version: "1.0.0",
|
|
34
|
+
});
|
|
35
|
+
// Map for transport management
|
|
36
|
+
const transports = {};
|
|
37
|
+
// Server startup function
|
|
38
|
+
export const startServer = async () => {
|
|
39
|
+
console.log("Starting TestRail MCP Server...");
|
|
40
|
+
// Create Express app
|
|
41
|
+
const app = express();
|
|
42
|
+
// Register all API tools
|
|
43
|
+
registerAllTools(server, testRailClient);
|
|
44
|
+
// SSE endpoint configuration
|
|
45
|
+
app.get("/sse", async (_, res) => {
|
|
46
|
+
const transport = new SSEServerTransport("/messages", res);
|
|
47
|
+
transports[transport.sessionId] = transport;
|
|
48
|
+
res.on("close", () => {
|
|
49
|
+
delete transports[transport.sessionId];
|
|
50
|
+
});
|
|
51
|
+
await server.connect(transport);
|
|
52
|
+
});
|
|
53
|
+
// Message handling endpoint configuration
|
|
54
|
+
app.post("/messages", async (req, res) => {
|
|
55
|
+
const sessionId = req.query.sessionId;
|
|
56
|
+
const transport = transports[sessionId];
|
|
57
|
+
if (transport) {
|
|
58
|
+
await transport.handlePostMessage(req, res);
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
res.status(400).send("No transport found for the session ID");
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// Start the server
|
|
65
|
+
app.listen(8080, () => {
|
|
66
|
+
console.log("Server started successfully.");
|
|
67
|
+
console.log("Server is running on SSE at http://localhost:8080/sse");
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { TestRailClient } from "../client/api/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Function to register resource templates
|
|
5
|
+
* @param server McpServer instance
|
|
6
|
+
* @param testRailClient TestRail client instance
|
|
7
|
+
*/
|
|
8
|
+
export declare function registerResourceTemplates(server: McpServer, testRailClient: TestRailClient): void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
/**
|
|
3
|
+
* Function to register resource templates
|
|
4
|
+
* @param server McpServer instance
|
|
5
|
+
* @param testRailClient TestRail client instance
|
|
6
|
+
*/
|
|
7
|
+
export function registerResourceTemplates(server, testRailClient) {
|
|
8
|
+
// Test case detail template
|
|
9
|
+
server.resource("testcase", new ResourceTemplate("testcase://{caseId}", { list: undefined }), async (uri, { caseId }) => {
|
|
10
|
+
try {
|
|
11
|
+
const numericCaseId = Number.parseInt(String(caseId), 10);
|
|
12
|
+
const testCase = await testRailClient.cases.getCase(numericCaseId);
|
|
13
|
+
const content = `# Test Case: ${testCase.title} (ID: ${testCase.id})\n\n` +
|
|
14
|
+
`**Type**: ${testCase.type_id}\n` +
|
|
15
|
+
`**Priority**: ${testCase.priority_id}\n` +
|
|
16
|
+
`**Section**: ${testCase.section_id}\n\n` +
|
|
17
|
+
`## Preconditions\n${testCase.custom_preconds || "None"}\n\n` +
|
|
18
|
+
`## Steps\n${testCase.custom_steps || "None"}\n\n` +
|
|
19
|
+
`## Expected Result\n${testCase.custom_expected || "None"}`;
|
|
20
|
+
return {
|
|
21
|
+
contents: [
|
|
22
|
+
{
|
|
23
|
+
uri: uri.href,
|
|
24
|
+
text: content,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
31
|
+
return {
|
|
32
|
+
contents: [
|
|
33
|
+
{
|
|
34
|
+
uri: uri.href,
|
|
35
|
+
text: `Error fetching test case ${caseId}: ${errorMessage}`,
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
// Additional resource templates (projects, sections, milestones, etc.) can be added here as needed
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/server/templates.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,gBAAgB,GAChB,MAAM,yCAAyC,CAAC;AAGjD;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACxC,MAAiB,EACjB,cAA8B;IAE9B,4BAA4B;IAC5B,MAAM,CAAC,QAAQ,CACd,UAAU,EACV,IAAI,gBAAgB,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,EAChE,KAAK,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;QACzB,IAAI,CAAC;YACJ,MAAM,aAAa,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;YAEnE,MAAM,OAAO,GACZ,gBAAgB,QAAQ,CAAC,KAAK,SAAS,QAAQ,CAAC,EAAE,OAAO;gBACzD,aAAa,QAAQ,CAAC,OAAO,IAAI;gBACjC,iBAAiB,QAAQ,CAAC,WAAW,IAAI;gBACzC,gBAAgB,QAAQ,CAAC,UAAU,MAAM;gBACzC,qBAAqB,QAAQ,CAAC,eAAe,IAAI,MAAM,MAAM;gBAC7D,aAAa,QAAQ,CAAC,YAAY,IAAI,MAAM,MAAM;gBAClD,uBAAuB,QAAQ,CAAC,eAAe,IAAI,MAAM,EAAE,CAAC;YAE7D,OAAO;gBACN,QAAQ,EAAE;oBACT;wBACC,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,IAAI,EAAE,OAAO;qBACb;iBACD;aACD,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YAChB,MAAM,YAAY,GACjB,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACxD,OAAO;gBACN,QAAQ,EAAE;oBACT;wBACC,GAAG,EAAE,GAAG,CAAC,IAAI;wBACb,IAAI,EAAE,4BAA4B,MAAM,KAAK,YAAY,EAAE;qBAC3D;iBACD;aACD,CAAC;QACH,CAAC;IACF,CAAC,CACD,CAAC;IAEF,mGAAmG;AACpG,CAAC"}
|