recon.full
Execute comprehensive reconnaissance by scanning domains with subfinder, httpx, and amass to identify targets and services for security assessment.
Instructions
Run full reconnaissance workflow: subfinder -> httpx -> amass
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Target domain |
Implementation Reference
- src/tools/recon.ts:220-275 (handler)Handler function that executes the full reconnaissance workflow: discovers subdomains using subfinder and amass, then probes live hosts with httpx, stores results in working memory.async ({ domain }: any): Promise<ToolResult> => { try { const results: ReconResult = { subdomains: [] as string[], liveHosts: [] as string[], }; // Run subfinder const subfinderExists = await checkCommandExists('subfinder'); if (subfinderExists) { const subfinderResult = await runCommand('subfinder', ['-d', domain, '-silent']); const subdomains = subfinderResult.stdout .split('\n') .filter((s) => s.trim().length > 0); results.subdomains = subdomains; } // Run amass const amassExists = await checkCommandExists('amass'); if (amassExists) { const amassResult = await runCommand('amass', ['enum', '-d', domain, '-passive'], 120000); const amassSubs = amassResult.stdout .split('\n') .filter((s) => s.trim().length > 0 && s.includes('.')); results.subdomains = [...new Set([...(results.subdomains || []), ...amassSubs])]; } // Check live hosts if (results.subdomains && results.subdomains.length > 0) { const httpxExists = await checkCommandExists('httpx'); if (httpxExists) { const inputFile = path.join('/tmp', `subdomains_${Date.now()}.txt`); await fs.writeFile(inputFile, results.subdomains.join('\n')); const httpxResult = await runCommand('httpx', ['-l', inputFile, '-silent', '-status-code']); results.liveHosts = httpxResult.stdout .split('\n') .filter((s) => s.trim().length > 0); await fs.remove(inputFile); } } await setWorkingMemory(`recon:${domain}:full`, results, 7200); return formatToolResult(true, { ...results, summary: { totalSubdomains: results.subdomains?.length || 0, liveHosts: results.liveHosts?.length || 0, }, }); } catch (error: any) { return formatToolResult(false, null, error.message); } }
- src/tools/recon.ts:210-219 (schema)Schema definition for the recon.full tool, specifying input as an object with required 'domain' string.{ description: 'Run full reconnaissance workflow: subfinder -> httpx -> amass', inputSchema: { type: 'object', properties: { domain: { type: 'string', description: 'Target domain' }, }, required: ['domain'], }, },
- src/tools/recon.ts:208-276 (registration)Registration of the 'recon.full' tool on the MCP server using server.tool(), including schema and inline handler.server.tool( 'recon.full', { description: 'Run full reconnaissance workflow: subfinder -> httpx -> amass', inputSchema: { type: 'object', properties: { domain: { type: 'string', description: 'Target domain' }, }, required: ['domain'], }, }, async ({ domain }: any): Promise<ToolResult> => { try { const results: ReconResult = { subdomains: [] as string[], liveHosts: [] as string[], }; // Run subfinder const subfinderExists = await checkCommandExists('subfinder'); if (subfinderExists) { const subfinderResult = await runCommand('subfinder', ['-d', domain, '-silent']); const subdomains = subfinderResult.stdout .split('\n') .filter((s) => s.trim().length > 0); results.subdomains = subdomains; } // Run amass const amassExists = await checkCommandExists('amass'); if (amassExists) { const amassResult = await runCommand('amass', ['enum', '-d', domain, '-passive'], 120000); const amassSubs = amassResult.stdout .split('\n') .filter((s) => s.trim().length > 0 && s.includes('.')); results.subdomains = [...new Set([...(results.subdomains || []), ...amassSubs])]; } // Check live hosts if (results.subdomains && results.subdomains.length > 0) { const httpxExists = await checkCommandExists('httpx'); if (httpxExists) { const inputFile = path.join('/tmp', `subdomains_${Date.now()}.txt`); await fs.writeFile(inputFile, results.subdomains.join('\n')); const httpxResult = await runCommand('httpx', ['-l', inputFile, '-silent', '-status-code']); results.liveHosts = httpxResult.stdout .split('\n') .filter((s) => s.trim().length > 0); await fs.remove(inputFile); } } await setWorkingMemory(`recon:${domain}:full`, results, 7200); return formatToolResult(true, { ...results, summary: { totalSubdomains: results.subdomains?.length || 0, liveHosts: results.liveHosts?.length || 0, }, }); } catch (error: any) { return formatToolResult(false, null, error.message); } } );
- src/index.ts:35-35 (registration)Invocation of registerReconTools which includes registration of recon.full and other recon tools.registerReconTools(server);