getTracInfo
Retrieve WordPress Trac metadata including components, milestones, priorities, and severities to streamline ticket tracking and development insights.
Instructions
Get WordPress Trac metadata like components, milestones, priorities, and severities.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Type of Trac information to retrieve |
Implementation Reference
- src/index.ts:701-834 (handler)The handler for the 'getTracInfo' tool. Fetches a CSV export of tickets from WordPress Trac, parses the CSV to extract headers and values for the specified metadata type (milestones, priorities, types, statuses), collects unique sorted values, and returns formatted result. Components and severities throw errors as not available in default query.case "getTracInfo": { const { type } = args; try { let data: any = {}; let uniqueValues = new Set<string>(); // Get a sample of tickets to extract unique values for the requested field const queryUrl = new URL('https://core.trac.wordpress.org/query'); queryUrl.searchParams.set('format', 'csv'); queryUrl.searchParams.set('max', '1000'); // Get more tickets for better coverage const response = await fetch(queryUrl.toString(), { headers: { 'User-Agent': 'Mozilla/5.0 (compatible; WordPress-Trac-MCP-Server/1.0)', 'Accept': 'text/csv,text/plain,*/*', 'Accept-Language': 'en-US,en;q=0.9', } }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const csvData = await response.text(); // Parse CSV data const lines = csvData.replace(/^\uFEFF/, '').trim().split('\n'); const headers = (lines[0] || '').split(',').map(h => h.replace(/"/g, '').trim()); // Find the column index for the requested type let columnIndex = -1; switch (type) { case "components": // Components are not in the default query, need different approach throw new Error(`Components list not available in default query. Try using the search function instead.`); case "milestones": columnIndex = headers.indexOf('Milestone'); break; case "priorities": columnIndex = headers.indexOf('Priority'); break; case "severities": // Severities are not in the default query throw new Error(`Severities list not available in default query. Try using the search function instead.`); case "types": columnIndex = headers.indexOf('Type'); break; case "statuses": columnIndex = headers.indexOf('Status'); break; default: throw new Error(`Unknown info type: ${type}. Available types: milestones, priorities, types, statuses`); } if (columnIndex === -1) { throw new Error(`Column not found for type: ${type}. Available columns: ${headers.join(', ')}`); } // Extract unique values using better CSV parsing for (let i = 1; i < lines.length && lines[i]; i++) { const line = lines[i]?.trim(); if (!line) continue; // Better CSV parsing - handle quoted fields properly const values = []; let currentField = ''; let inQuotes = false; let escapeNext = false; for (let j = 0; j < line.length; j++) { const char = line[j]; if (escapeNext) { currentField += char; escapeNext = false; continue; } if (char === '\\') { escapeNext = true; continue; } if (char === '"') { if (inQuotes) { // Check if this is an escaped quote if (j + 1 < line.length && line[j + 1] === '"') { currentField += '"'; j++; // Skip the next quote } else { inQuotes = false; } } else { inQuotes = true; } } else if (char === ',' && !inQuotes) { values.push(currentField.trim()); currentField = ''; } else { currentField += char; } } values.push(currentField.trim()); if (values[columnIndex]?.trim()) { uniqueValues.add(values[columnIndex]?.trim() || ''); } } data = Array.from(uniqueValues).sort(); result = { id: type, title: `WordPress Trac ${type}`, text: `${type.charAt(0).toUpperCase() + type.slice(1)} available in WordPress Trac:\n\n${data.join('\n')}`, url: 'https://core.trac.wordpress.org/', metadata: { type, data, total: data.length, }, }; } catch (error) { result = { id: type, title: `Error loading ${type}`, text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}. Available types: components, milestones, priorities, severities, types, statuses`, url: 'https://core.trac.wordpress.org/', metadata: { error: true }, }; } break; }
- src/index.ts:140-153 (registration)Registration of the 'getTracInfo' tool in the tools/list response, including name, description, and input schema defining the 'type' parameter with enum values.name: "getTracInfo", description: "Get WordPress Trac metadata like components, milestones, priorities, and severities.", inputSchema: { type: "object", properties: { type: { type: "string", enum: ["components", "milestones", "priorities", "severities"], description: "Type of Trac information to retrieve", }, }, required: ["type"], }, },
- src/index.ts:142-152 (schema)Input schema for getTracInfo tool defining the required 'type' parameter with allowed enum values: components, milestones, priorities, severities.inputSchema: { type: "object", properties: { type: { type: "string", enum: ["components", "milestones", "priorities", "severities"], description: "Type of Trac information to retrieve", }, }, required: ["type"], },
- src/index.ts:1365-1404 (helper)Helper function parseCSVLine used by getTracInfo (and other tools) to parse CSV lines handling quoted fields and escaped characters properly.function parseCSVLine(line: string): string[] { const values = []; let currentField = ''; let inQuotes = false; let escapeNext = false; for (let i = 0; i < line.length; i++) { const char = line[i]; if (escapeNext) { currentField += char; escapeNext = false; continue; } if (char === '\\') { escapeNext = true; continue; } if (char === '"') { if (inQuotes) { if (i + 1 < line.length && line[i + 1] === '"') { currentField += '"'; i++; } else { inQuotes = false; } } else { inQuotes = true; } } else if (char === ',' && !inQuotes) { values.push(currentField.trim()); currentField = ''; } else { currentField += char; } } values.push(currentField.trim()); return values;