@uarlouski/testrail-mcp-server 2.4.0 → 2.5.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/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ if (!parseResult.success) {
|
|
|
25
25
|
const { TESTRAIL_INSTANCE_URL, TESTRAIL_USERNAME, TESTRAIL_API_KEY, TESTRAIL_ENABLE_SHARED_STEPS, TESTRAIL_ENABLE_CASE_HISTORY, TESTRAIL_ALLOW_WRITE_OPERATIONS, TESTRAIL_ALLOW_READ_OPERATIONS, TESTRAIL_ALLOW_DELETE_OPERATIONS, TESTRAIL_ENABLE_DEPRECATED_TOOLS } = parseResult.data;
|
|
26
26
|
const server = new McpServer({
|
|
27
27
|
name: "TestRail MCP Server",
|
|
28
|
-
version: "2.
|
|
28
|
+
version: "2.5.0",
|
|
29
29
|
});
|
|
30
30
|
const client = new TestRailClient(TESTRAIL_INSTANCE_URL, TESTRAIL_USERNAME, TESTRAIL_API_KEY);
|
|
31
31
|
const tools = getToolsToRegister({
|
|
@@ -67,7 +67,7 @@ export function mapToFieldSchema(field) {
|
|
|
67
67
|
}
|
|
68
68
|
return schema;
|
|
69
69
|
}
|
|
70
|
-
function isFieldForProject(field, projectId) {
|
|
70
|
+
export function isFieldForProject(field, projectId) {
|
|
71
71
|
const contexts = field.configs.map(c => c.context).filter(Boolean);
|
|
72
72
|
if (contexts.length === 0)
|
|
73
73
|
return true;
|
|
@@ -5,7 +5,8 @@ import { updateCaseTool } from "./update_case.js";
|
|
|
5
5
|
import { updateCasesTool } from "./update_cases.js";
|
|
6
6
|
import { addCaseTool } from "./add_case.js";
|
|
7
7
|
import { getCaseHistoryTool } from "./get_case_history.js";
|
|
8
|
-
|
|
8
|
+
import { resolveCaseFieldTool } from "./resolve_case_field.js";
|
|
9
|
+
export { getCaseHistoryTool, resolveCaseFieldTool };
|
|
9
10
|
export const casesTools = [
|
|
10
11
|
getCaseTool,
|
|
11
12
|
getCasesTool,
|
|
@@ -13,4 +14,5 @@ export const casesTools = [
|
|
|
13
14
|
updateCaseTool,
|
|
14
15
|
updateCasesTool,
|
|
15
16
|
addCaseTool,
|
|
17
|
+
resolveCaseFieldTool,
|
|
16
18
|
];
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { parseDropdownOptions } from "../../utils/mapper.js";
|
|
3
|
+
import { isActive } from "../../utils/sanitizer.js";
|
|
4
|
+
import { isFieldForProject } from "./get_case_fields.js";
|
|
5
|
+
const parameters = {
|
|
6
|
+
project_id: z.number().describe("The ID of the project to resolve field values for"),
|
|
7
|
+
field_name: z.string().describe("The system name of the Multi-select field (e.g. 'custom_case_feature_tags')"),
|
|
8
|
+
refs: z.union([z.number(), z.array(z.number())]).describe("A single numeric ID or array of numeric IDs/references (e.g. [1, 55, 6] or 55) to resolve"),
|
|
9
|
+
};
|
|
10
|
+
const description = `
|
|
11
|
+
Resolve numeric reference IDs of a Multi-select case field (type ID 12) into their textual values for a specific project.
|
|
12
|
+
`;
|
|
13
|
+
export const resolveCaseFieldTool = {
|
|
14
|
+
name: "resolve_case_field",
|
|
15
|
+
mode: "read",
|
|
16
|
+
description: description.trim(),
|
|
17
|
+
parameters,
|
|
18
|
+
handler: async ({ project_id, field_name, refs }, client) => {
|
|
19
|
+
const caseFields = await client.getCaseFields();
|
|
20
|
+
const activeFields = caseFields.filter(isActive);
|
|
21
|
+
const targetField = activeFields.find(f => f.system_name.toLowerCase() === field_name.toLowerCase());
|
|
22
|
+
if (!targetField) {
|
|
23
|
+
throw new Error(`Field '${field_name}' not found in active case fields.`);
|
|
24
|
+
}
|
|
25
|
+
if (targetField.type_id !== 12) {
|
|
26
|
+
throw new Error(`Field '${targetField.system_name}' is of type_id ${targetField.type_id}, but resolve_case_field only supports Multi-select fields (type_id: 12).`);
|
|
27
|
+
}
|
|
28
|
+
if (!isFieldForProject(targetField, project_id)) {
|
|
29
|
+
throw new Error(`Field '${targetField.system_name}' is not enabled for project ID ${project_id}.`);
|
|
30
|
+
}
|
|
31
|
+
const options = parseDropdownOptions(targetField, project_id);
|
|
32
|
+
const refList = Array.isArray(refs) ? refs : [refs];
|
|
33
|
+
const resolved = refList.map(ref => {
|
|
34
|
+
const val = options.get(String(ref)) ?? null;
|
|
35
|
+
return {
|
|
36
|
+
id: ref,
|
|
37
|
+
value: val,
|
|
38
|
+
};
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
field_name: targetField.system_name,
|
|
42
|
+
resolved,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
};
|
package/dist/utils/mapper.js
CHANGED
|
@@ -42,15 +42,29 @@ export function processCustomFields(testCase, caseFields) {
|
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* Parse dropdown options from field configs.
|
|
45
|
+
* If projectId is provided, prioritizes configuration specific to that project.
|
|
45
46
|
* Format: "1, First\n2, Second\n3, Third"
|
|
46
47
|
*/
|
|
47
|
-
export function parseDropdownOptions(field) {
|
|
48
|
+
export function parseDropdownOptions(field, projectId) {
|
|
48
49
|
const options = new Map();
|
|
49
|
-
|
|
50
|
+
let configsToParse = field.configs;
|
|
51
|
+
if (projectId !== undefined) {
|
|
52
|
+
const projectConfig = field.configs.find(c => c.context && !c.context.is_global && c.context.project_ids.includes(projectId));
|
|
53
|
+
if (projectConfig) {
|
|
54
|
+
configsToParse = [projectConfig];
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
const globalConfig = field.configs.find(c => c.context?.is_global);
|
|
58
|
+
if (globalConfig) {
|
|
59
|
+
configsToParse = [globalConfig];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
for (const config of configsToParse) {
|
|
50
64
|
const items = config.options?.items;
|
|
51
65
|
if (!items)
|
|
52
66
|
continue;
|
|
53
|
-
const lines = items.split(
|
|
67
|
+
const lines = items.split(/\r?\n/);
|
|
54
68
|
for (const line of lines) {
|
|
55
69
|
const commaIndex = line.indexOf(',');
|
|
56
70
|
if (commaIndex > 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uarlouski/testrail-mcp-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"mcpName": "io.github.uarlouski/testrail-mcp-server",
|
|
5
5
|
"description": "Model Context Protocol (MCP) server for TestRail integration, enabling LLMs to fetch test cases and metadata.",
|
|
6
6
|
"main": "dist/index.js",
|