get_linked_test_cycles
List all test cycles linked to a test plan using its internal ID. Returns paginated results with cycle ID, key, status, and priority.
Instructions
List all test cycles currently linked to a test plan. Returns paginated list with id, key, status, priority per cycle. Use the plan's internal id (not key).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | Test plan ID | |
| startAt | No | Page offset (default 0) | |
| maxResults | No | Items per page (max 100, default 50) | |
| sort | No | Sort e.g. "id:asc" or "updated:desc" | |
| fields | No | Comma-separated fields to return |
Implementation Reference
- src/index.ts:594-601 (handler)The handler function that executes the 'get_linked_test_cycles' tool logic. It sends a POST request to /testplans/{id}/testcycles with pagination query params and an empty filter body.
async ({ id, startAt, maxResults, sort, fields }) => ok( await qtmFetch(`/testplans/${id}/testcycles${qs({ startAt, maxResults, sort, fields })}`, { method: "POST", body: JSON.stringify({ filter: {} }), }) ) ); - src/index.ts:590-593 (schema)Input schema for the tool: takes a test plan ID and pagination fields (startAt, maxResults, sort, fields).
{ id: ID.describe("Test plan ID"), ...Pagination, }, - src/index.ts:587-601 (registration)Registration of the 'get_linked_test_cycles' tool via the 'tool()' wrapper which calls server.registerTool().
tool( "get_linked_test_cycles", "List all test cycles currently linked to a test plan. Returns paginated list with id, key, status, priority per cycle. Use the plan's internal id (not key).", { id: ID.describe("Test plan ID"), ...Pagination, }, async ({ id, startAt, maxResults, sort, fields }) => ok( await qtmFetch(`/testplans/${id}/testcycles${qs({ startAt, maxResults, sort, fields })}`, { method: "POST", body: JSON.stringify({ filter: {} }), }) ) ); - src/index.ts:25-66 (helper)HTTP fetch helper used by the handler to make API calls to QMetry.
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; }