createClientReport
Generate comprehensive penetration testing reports by compiling scan results, executive summaries, and security recommendations for client assessments.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| client | Yes | Client name for the report | |
| title | Yes | Title of the assessment report | |
| assessmentType | Yes | Type of assessment | |
| scanIds | Yes | IDs of scans to include | |
| summary | No | Executive summary | |
| recommendations | No | List of recommendations |
Implementation Reference
- src/index.ts:1065-1075 (schema)Zod schema defining the input parameters for the createClientReport tool, including client details, scan IDs, and optional summary/recommendations.const createClientReportToolSchema = z.object({ client: z.string().describe("Client name for the report"), title: z.string().describe("Title of the assessment report"), assessmentType: z.string().describe("Type of assessment"), scanIds: z.array(z.string()).describe("IDs of scans to include"), summary: z.string().optional().describe("Executive summary"), recommendations: z.array(z.string()).optional().describe("List of recommendations") }).describe( "Create a summarized client report from completed scans. Include scanIds returned from tools like `nmapScan`." ); server.tool("createClientReport", createClientReportToolSchema.shape, async (args /*: z.infer<typeof createClientReportToolSchema> */ /*, extra */) => {
- src/index.ts:1076-1088 (registration)Registers the createClientReport tool with MCP server using server.tool(), including the inline handler function.const { client, title, assessmentType, scanIds, summary, recommendations } = args; const reportId = `report-${Date.now()}`; const scans = scanIds.map(getScanDataById).filter(Boolean); const findings = analyzeFindings(scans); const report: ClientReport = { reportId, title, client, createdAt: Date.now(), assessmentType, findings, scans, summary: summary || "", recommendations: recommendations || [] }; clientReports.set(reportId, report); return { content: [ { type: "text", text: `Client report created: ${reportId}` }, { type: "text", text: `URI: mcp://pentest/clientReport/${reportId}` } ] }; });
- src/index.ts:1076-1087 (handler)The core handler logic for createClientReport: generates unique report ID, retrieves scans by ID, analyzes findings by severity, constructs ClientReport object, stores in memory map, and returns confirmation with resource URI.const { client, title, assessmentType, scanIds, summary, recommendations } = args; const reportId = `report-${Date.now()}`; const scans = scanIds.map(getScanDataById).filter(Boolean); const findings = analyzeFindings(scans); const report: ClientReport = { reportId, title, client, createdAt: Date.now(), assessmentType, findings, scans, summary: summary || "", recommendations: recommendations || [] }; clientReports.set(reportId, report); return { content: [ { type: "text", text: `Client report created: ${reportId}` }, { type: "text", text: `URI: mcp://pentest/clientReport/${reportId}` } ] }; });
- src/index.ts:124-172 (helper)Helper function analyzeFindings categorizes open ports from Nmap scans into severity levels based on common vulnerable ports (critical: RDP/Postgres/SQL/FTP/Telnet; high: SSH/SMB; etc.). Used by the tool handler.function analyzeFindings(scans: any[]): { critical: Finding[]; high: Finding[]; medium: Finding[]; low: Finding[]; info: Finding[]; } { const findings: { critical: Finding[]; high: Finding[]; medium: Finding[]; low: Finding[]; info: Finding[]; } = { critical: [], high: [], medium: [], low: [], info: [] }; for (const scan of scans) { if (!scan || !scan.results) continue; for (const ip in scan.results) { const host = scan.results[ip] as Host; if (!host.ports) continue; for (const port of host.ports) { if (port.state === 'open') { const finding: Finding = { host: ip, port: port.portId, service: port.service?.name || 'unknown', description: `Open port ${port.portId} (${port.service?.name || 'unknown'})`, details: port }; if (['3389', '5432', '1433', '21', '23'].includes(port.portId)) { findings.critical.push(finding); } else if (['22', '445', '139'].includes(port.portId)) { findings.high.push(finding); } else if (['80', '443', '8080'].includes(port.portId)) { findings.medium.push(finding); } else { findings.low.push(finding); } } } } } return findings; }
- src/index.ts:96-112 (helper)Helper function getScanDataById retrieves scan data for a given scanId from active scans (returns partial info) or null if not active (placeholder for log retrieval). Called by handler to fetch scans.function getScanDataById(scanId: string): any { // First check active scans const activeScan = activeScans.get(scanId); if (activeScan) { return { scanId, target: activeScan.progress.target, options: [], // Would need to store this in the activeScan object timestamp: activeScan.progress.startTime, results: {} // Would need to store partial results }; } // Otherwise, would need to retrieve from log file // This is a placeholder - real implementation would parse logs return null; }