xcresult_list_attachments
Extract and list all attachments for a specific test from an .xcresult file, including attachment names, types, and indices, for easy export and analysis.
Instructions
List all attachments for a specific test - shows attachment names, types, and indices for export
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| test_id | Yes | Test ID or index number to list attachments for | |
| xcresult_path | Yes | Absolute path to the .xcresult file |
Implementation Reference
- src/tools/XCResultTools.ts:270-384 (handler)The primary handler function implementing the xcresult_list_attachments tool. Validates inputs, parses the XCResult file using XCResultParser, finds the test node, retrieves attachments, formats output with indices/types/sizes, and returns formatted text response.public static async xcresultListAttachments( xcresultPath: string, testId: string ): Promise<McpResult> { // Validate xcresult path if (!existsSync(xcresultPath)) { throw new McpError( ErrorCode.InvalidParams, `XCResult file not found: ${xcresultPath}` ); } if (!xcresultPath.endsWith('.xcresult')) { throw new McpError( ErrorCode.InvalidParams, `Path must be an .xcresult file: ${xcresultPath}` ); } // Check if xcresult is readable if (!XCResultParser.isXCResultReadable(xcresultPath)) { throw new McpError( ErrorCode.InternalError, `XCResult file is not readable or incomplete: ${xcresultPath}` ); } if (!testId || testId.trim() === '') { throw new McpError( ErrorCode.InvalidParams, 'Test ID or index is required' ); } try { const parser = new XCResultParser(xcresultPath); // First find the test node to get the actual test identifier const testNode = await parser.findTestNode(testId); if (!testNode) { throw new McpError( ErrorCode.InvalidParams, `Test '${testId}' not found. Run xcresult_browse "${xcresultPath}" to see all available tests` ); } if (!testNode.nodeIdentifier) { throw new McpError( ErrorCode.InvalidParams, `Test '${testId}' does not have a valid identifier for attachment retrieval` ); } // Get test attachments const attachments = await parser.getTestAttachments(testNode.nodeIdentifier); let output = `📎 Attachments for test: ${testNode.name}\n`; output += `Found ${attachments.length} attachments\n`; output += '='.repeat(80) + '\n\n'; if (attachments.length === 0) { output += 'No attachments found for this test.\n'; } else { attachments.forEach((att, index) => { const filename = att.name || att.filename || 'unnamed'; output += `[${index + 1}] ${filename}\n`; // Determine type from identifier or filename let type = att.uniform_type_identifier || att.uniformTypeIdentifier || ''; if (!type || type === 'unknown') { // Infer type from filename extension or special patterns const ext = filename.toLowerCase().split('.').pop(); if (ext === 'jpeg' || ext === 'jpg') type = 'public.jpeg'; else if (ext === 'png') type = 'public.png'; else if (ext === 'mp4') type = 'public.mpeg-4'; else if (ext === 'mov') type = 'com.apple.quicktime-movie'; else if (ext === 'txt') type = 'public.plain-text'; else if (filename.toLowerCase().includes('app ui hierarchy')) type = 'ui-hierarchy'; else if (filename.toLowerCase().includes('ui snapshot')) type = 'ui-snapshot'; else if (filename.toLowerCase().includes('synthesized event')) type = 'synthesized-event'; else type = 'unknown'; } output += ` Type: ${type}\n`; if (att.payloadSize || att.payload_size) { output += ` Size: ${att.payloadSize || att.payload_size} bytes\n`; } output += '\n'; }); output += '\n💡 To export a specific attachment, use xcresult_export_attachment with the attachment index.\n'; } return { content: [{ type: 'text', text: output }] }; } catch (error) { if (error instanceof McpError) { throw error; } const errorMessage = error instanceof Error ? error.message : String(error); if (errorMessage.includes('xcresulttool')) { throw new McpError( ErrorCode.InternalError, `XCResult parsing failed. Make sure Xcode Command Line Tools are installed: ${errorMessage}` ); } throw new McpError( ErrorCode.InternalError, `Failed to list attachments: ${errorMessage}` ); } }
- src/XcodeServer.ts:592-602 (registration)MCP server tool registration and dispatch handler. Performs parameter validation and calls the XCResultTools.xcresultListAttachments handler.case 'xcresult_list_attachments': if (!args.xcresult_path) { throw new McpError(ErrorCode.InvalidParams, `Missing required parameter: xcresult_path`); } if (!args.test_id) { throw new McpError(ErrorCode.InvalidParams, `Missing required parameter: test_id`); } return await XCResultTools.xcresultListAttachments( args.xcresult_path as string, args.test_id as string );
- Tool schema definition used for MCP listTools response and input validation, including inputSchema with required parameters xcresult_path and test_id.name: 'xcresult_list_attachments', description: 'List all attachments for a specific test - shows attachment names, types, and indices for export', inputSchema: { type: 'object', properties: { xcresult_path: { type: 'string', description: 'Absolute path to the .xcresult file', }, test_id: { type: 'string', description: 'Test ID or index number to list attachments for', }, }, required: ['xcresult_path', 'test_id'], },