get_suite_hierarchy
Retrieve hierarchical test suite structures from Zebrunner Test Case Management with configurable depth and output formats for project organization.
Instructions
🌳 Get hierarchical test suite tree with configurable depth
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_key | Yes | Project key | |
| root_suite_id | No | Start from specific root suite | |
| max_depth | No | Maximum tree depth | |
| format | No | Output format | json |
| include_clickable_links | No | Include clickable links to Zebrunner web UI |
Implementation Reference
- src/handlers/tools.ts:146-196 (handler)Core handler function implementing the get_suite_hierarchy tool logic: fetches all suites, optionally filters descendants of a root suite, builds hierarchy tree using HierarchyProcessor, limits recursion depth, formats output, and handles errors.
async getSuiteHierarchy(input: z.infer<typeof GetSuiteHierarchyInputSchema>) { const { projectKey, rootSuiteId, maxDepth, format } = input; try { const allSuites = await this.client.getAllTestSuites(projectKey); let suitesToProcess = allSuites; // Filter by root suite if specified if (rootSuiteId) { const descendants = HierarchyProcessor.getSuiteDescendants(rootSuiteId, allSuites); const rootSuite = allSuites.find(s => s.id === rootSuiteId); suitesToProcess = rootSuite ? [rootSuite, ...descendants] : descendants; } // Build hierarchical tree const hierarchyTree = HierarchyProcessor.buildSuiteTree(suitesToProcess); // Limit depth if specified const limitDepth = (suites: any[], currentDepth: number): any[] => { if (currentDepth >= maxDepth) { return suites.map(suite => ({ ...suite, children: [] })); } return suites.map(suite => ({ ...suite, children: suite.children ? limitDepth(suite.children, currentDepth + 1) : [] })); }; const limitedTree = limitDepth(hierarchyTree, 0); const formattedData = FormatProcessor.format(limitedTree, format); return { content: [ { type: "text" as const, text: typeof formattedData === 'string' ? formattedData : JSON.stringify(formattedData, null, 2) } ] }; } catch (error: any) { return { content: [ { type: "text" as const, text: `Error retrieving suite hierarchy: ${error.message}` } ] }; } } - src/types/api.ts:112-117 (schema)Zod input schema defining parameters for the get_suite_hierarchy tool: projectKey (required), rootSuiteId (optional), maxDepth (default 5, max 10), format (default 'json').
export const GetSuiteHierarchyInputSchema = z.object({ projectKey: z.string().min(1), rootSuiteId: z.number().int().positive().optional(), maxDepth: z.number().int().positive().max(10).default(5), format: z.enum(['dto', 'json', 'string']).default('json') }); - src/index-enhanced.ts:133-143 (registration)MCP server tool registration for 'get_suite_hierarchy', including inline schema validation and binding to ZebrunnerToolHandlers.getSuiteHierarchy method.
server.tool( "get_suite_hierarchy", "Get hierarchical test suite tree with configurable depth", { projectKey: z.string().min(1), rootSuiteId: z.number().int().positive().optional(), maxDepth: z.number().int().positive().max(10).default(5), format: z.enum(['dto', 'json', 'string']).default('json') }, async (args) => toolHandlers.getSuiteHierarchy(args) ); - src/utils/hierarchy.ts:26-52 (helper)Key helper methods used by the handler: buildSuiteTree constructs the hierarchical tree from flat suite list, getSuiteDescendants retrieves all descendant suites for a given root suite ID.
static buildSuiteTree(suites: ZebrunnerTestSuite[]): ZebrunnerTestSuite[] { const suiteMap = new Map<number, ZebrunnerTestSuite>(); const rootSuites: ZebrunnerTestSuite[] = []; // First pass: create map and initialize children arrays suites.forEach(suite => { suiteMap.set(suite.id, { ...suite, children: [] }); }); // Second pass: build parent-child relationships suites.forEach(suite => { const suiteWithChildren = suiteMap.get(suite.id)!; // Handle self-referencing suites (treat them as root suites) if (suite.parentSuiteId === suite.id) { console.error(`⚠️ Self-referencing suite detected: ${suite.id} (${suite.title || suite.name})`); // Set parentSuiteId to null for self-referencing suites suiteWithChildren.parentSuiteId = null; rootSuites.push(suiteWithChildren); } else if (suite.parentSuiteId && suiteMap.has(suite.parentSuiteId)) { const parent = suiteMap.get(suite.parentSuiteId)!; parent.children = parent.children || []; parent.children.push(suiteWithChildren); } else { rootSuites.push(suiteWithChildren); } });