create_test_case
Create a test case in QMetry Test Management. Provide project ID and summary, optionally set priority, status, assignee, labels, components, fix versions, folder, and custom fields. Returns the test case key and internal ID.
Instructions
Create a new test case in QMetry. Returns the created test case object including its internal id and key (e.g. FS-TC-123). Priority, status, labels, and components use integer IDs — see field_reference.json for valid values.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| projectId | Yes | Jira project numeric ID (e.g. 10011) | |
| summary | Yes | Test case title/summary | |
| precondition | No | Precondition / description text | |
| priority | No | Priority integer ID (e.g. 600784 for High) | |
| status | No | Status integer ID (e.g. 544256 for Done) | |
| assignee | No | Assignee Jira account ID | |
| labels | No | Label IDs to attach | |
| components | No | Component IDs | |
| fixVersions | No | Fix version IDs | |
| folderId | No | Target folder ID | |
| customFields | No | Custom field values |
Implementation Reference
- src/index.ts:206-208 (handler)Handler function for the create_test_case tool. Sends a POST request to /testcases with the provided body, which includes projectId, summary, and optional fields. The result is wrapped with the ok() helper and returned as MCP content.
async (body) => { return ok(await qtmFetch("/testcases", { method: "POST", body: JSON.stringify(body) })); } - src/index.ts:193-205 (schema)Input schema for create_test_case defined with Zod. Required fields: projectId, summary. Optional fields: precondition, priority, status, assignee, labels, components, fixVersions, folderId, customFields.
{ projectId: z.union([z.string(), z.number()]).describe("Jira project numeric ID (e.g. 10011)"), summary: z.string().describe("Test case title/summary"), precondition: z.string().optional().describe("Precondition / description text"), priority: z.number().int().optional().describe("Priority integer ID (e.g. 600784 for High)"), status: z.number().int().optional().describe("Status integer ID (e.g. 544256 for Done)"), assignee: z.string().optional().describe("Assignee Jira account ID"), labels: z.array(z.number().int()).optional().describe("Label IDs to attach"), components: z.array(z.number().int()).optional().describe("Component IDs"), fixVersions: z.array(z.number().int()).optional().describe("Fix version IDs"), folderId: z.number().int().optional().describe("Target folder ID"), customFields: z.array(CustomField).optional().describe("Custom field values"), }, - src/index.ts:190-209 (registration)Registration of the tool named 'create_test_case' using the local tool() wrapper which internally calls server.registerTool() on the McpServer instance.
tool( "create_test_case", "Create a new test case in QMetry. Returns the created test case object including its internal id and key (e.g. FS-TC-123). Priority, status, labels, and components use integer IDs — see field_reference.json for valid values.", { projectId: z.union([z.string(), z.number()]).describe("Jira project numeric ID (e.g. 10011)"), summary: z.string().describe("Test case title/summary"), precondition: z.string().optional().describe("Precondition / description text"), priority: z.number().int().optional().describe("Priority integer ID (e.g. 600784 for High)"), status: z.number().int().optional().describe("Status integer ID (e.g. 544256 for Done)"), assignee: z.string().optional().describe("Assignee Jira account ID"), labels: z.array(z.number().int()).optional().describe("Label IDs to attach"), components: z.array(z.number().int()).optional().describe("Component IDs"), fixVersions: z.array(z.number().int()).optional().describe("Fix version IDs"), folderId: z.number().int().optional().describe("Target folder ID"), customFields: z.array(CustomField).optional().describe("Custom field values"), }, async (body) => { return ok(await qtmFetch("/testcases", { method: "POST", body: JSON.stringify(body) })); } ); - src/index.ts:25-66 (helper)qtmFetch() helper function that makes authenticated HTTP requests to the QMetry API, including exponential back-off retry for rate limiting (429).
async function qtmFetch( path: string, options: RequestInit = {}, attempt = 1 ): Promise<unknown> { const url = `${BASE_URL}${path}`; const headers: Record<string, string> = { apiKey: API_KEY ?? "", "Content-Type": "application/json", Accept: "application/json", ...(options.headers as Record<string, string> | undefined), }; const response = await fetch(url, { ...options, headers }); // Exponential back-off for rate limiting (max 3 attempts) if (response.status === 429 && attempt < 3) { const retryAfter = Number.parseInt( response.headers.get("Retry-After") ?? "1", 10 ); const delay = Math.max(retryAfter * 1000, 1000) * attempt; await new Promise((r) => setTimeout(r, delay)); return qtmFetch(path, options, attempt + 1); } const text = await response.text(); let body: unknown; try { body = text ? JSON.parse(text) : null; } catch { body = text; } if (!response.ok) { throw new Error( `HTTP ${response.status} ${response.statusText}: ${JSON.stringify(body)}` ); } return body; } - src/index.ts:68-73 (helper)ok() helper function that wraps API response data into the MCP tool content format (text type).
/** Wrap a successful API response as MCP tool content. */ function ok(data: unknown) { return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }], }; }