UNPKG

gc-amass-mcp

Version:

Model Context Protocol (MCP) server for Amass - Advanced subdomain enumeration and reconnaissance tool

119 lines (118 loc) 4.95 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js"); const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js"); const zod_1 = require("zod"); const child_process_1 = require("child_process"); // Get amass path from environment variable const amassPath = process.env.AMASS_PATH; if (!amassPath) { console.error("AMASS_PATH environment variable not set"); process.exit(1); } // Create server instance const server = new mcp_js_1.McpServer({ name: "amass", version: "1.0.0", }); server.tool("amass", "Advanced subdomain enumeration and reconnaissance tool", { subcommand: zod_1.z.enum(["enum", "intel"]).describe(`Specify the Amass operation mode: - intel: Gather intelligence about target domains from various sources - enum: Perform subdomain enumeration and network mapping`), domain: zod_1.z.string().optional().describe("Target domain to perform reconnaissance against (e.g., example.com)"), intel_whois: zod_1.z.boolean().optional().describe("Whether to include WHOIS data in intelligence gathering (true/false)"), intel_organization: zod_1.z.string().optional().describe("Organization name to search for during intelligence gathering (e.g., 'Example Corp')"), enum_type: zod_1.z.enum(["active", "passive"]).optional().describe(`Enumeration approach type: - active: Includes DNS resolution and potential network interactions with target - passive: Only uses information from third-party sources without direct target interaction`), enum_brute: zod_1.z.boolean().optional().describe("Whether to perform brute force subdomain discovery (true/false)"), enum_brute_wordlist: zod_1.z.string().optional().describe("Path to custom wordlist file for brute force operations (e.g., '/path/to/wordlist.txt')") }, async ({ subcommand, domain, intel_whois, intel_organization, enum_type, enum_brute, enum_brute_wordlist }) => { const amassArgs = [subcommand]; // Handle different subcommands if (subcommand === "enum") { if (!domain) { throw new Error("Domain parameter is required for 'enum' subcommand"); } amassArgs.push("-d", domain); // Handle enum type if (enum_type === "passive") { amassArgs.push("-passive"); } else if (enum_type === "active") { // Active is default, but can be explicitly specified if needed } // Handle brute force options if (enum_brute === true) { amassArgs.push("-brute"); // Add custom wordlist if provided if (enum_brute_wordlist) { amassArgs.push("-w", enum_brute_wordlist); } } } else if (subcommand === "intel") { if (!domain && !intel_organization) { throw new Error("Either domain or organization parameter is required for 'intel' subcommand"); } // Add domain if provided if (domain) { amassArgs.push("-d", domain); // Add whois option if enabled if (intel_whois !== true) { throw new Error("For domain parameter whois is required"); } } // Add organization if provided if (intel_organization) { amassArgs.push("-org", `'${intel_organization}'`); } // Add whois flag if enabled if (intel_whois === true) { amassArgs.push("-whois"); } } console.log(`Executing: ${amassPath} ${amassArgs.join(' ')}`); const amass = (0, child_process_1.spawn)(amassPath, amassArgs); let output = ''; // Handle stdout amass.stdout.on('data', (data) => { const chunk = data.toString(); output += chunk; }); // Handle stderr amass.stderr.on('data', (data) => { const chunk = data.toString(); output += chunk; }); // Handle process completion return new Promise((resolve, reject) => { amass.on('close', (code) => { if (code === 0) { resolve({ content: [{ type: "text", text: output }] }); } else { reject(new Error(`Amass exited with code ${code}. Output: ${output}. Args:${amassArgs}`)); } }); amass.on('error', (error) => { reject(new Error(`Failed to start Amass: ${error.message}`)); }); }); }); // Start the server async function main() { const transport = new stdio_js_1.StdioServerTransport(); await server.connect(transport); console.error("AMASS MCP Server running on stdio"); } main().catch((error) => { console.error("Fatal error in main():", error); process.exit(1); });