#
tokens: 41020/50000 33/150 files (page 2/2)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 2 of 2. Use http://codebase.md/cyproxio/mcp-for-security?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .dockerignore
├── .DS_Store
├── .github
│   └── workflows
│       └── docker.yml
├── .gitignore
├── alterx-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── amass-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── arjun-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── assetfinder-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── cero
│   ├── .gitignore
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── commix-mcp
│   ├── .gitignore
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── crtsh-mcp
│   ├── .gitignore
│   ├── build
│   │   ├── crtsh.js
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   ├── crtsh.ts
│   │   └── index.ts
│   └── tsconfig.json
├── Dockerfile
├── ffuf-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── gowitness-mcp
│   ├── .gitignore
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── http-headers-security-mcp
│   ├── .gitignore
│   ├── build
│   │   ├── index.js
│   │   ├── owasp_headers_add.json
│   │   └── owasp_headers_remove.json
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   ├── index.ts
│   │   ├── owasp_headers_add.json
│   │   └── owasp_headers_remove.json
│   └── tsconfig.json
├── httpx-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── katana-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── LICENSE
├── masscan-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── mobsf-mcp
│   ├── .gitignore
│   ├── build
│   │   ├── index.js
│   │   └── mobsf.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   ├── index.ts
│   │   └── mobsf.ts
│   └── tsconfig.json
├── nmap-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── nuclei-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── readme.md
├── scoutsuite-mcp
│   ├── .gitignore
│   ├── build
│   │   ├── index.js
│   │   └── parser.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   ├── index.ts
│   │   └── parser.ts
│   └── tsconfig.json
├── shuffledns-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── smuggler-mcp
│   ├── .gitignore
│   ├── build.sh
│   ├── LICENSE
│   ├── mcp.json
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── sqlmap-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── sslscan-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── start.sh
├── waybackurls-mcp
│   ├── .gitignore
│   ├── build
│   │   └── index.js
│   ├── build.sh
│   ├── package-lock.json
│   ├── package.json
│   ├── readme.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
└── wpscan-mcp
    ├── .gitignore
    ├── build.sh
    ├── package-lock.json
    ├── package.json
    ├── readme.md
    ├── src
    │   └── index.ts
    └── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/commix-mcp/build.sh:
--------------------------------------------------------------------------------

```bash
 1 | #!/bin/bash
 2 | 
 3 | set -e
 4 | 
 5 | npm install >/dev/null 
 6 | npm run build >/dev/null 
 7 | 
 8 | # Clone Smuggler if not already present
 9 | [ -d "/opt/commix" ] || git clone https://github.com/commixproject/commix.git /opt/commix
10 | 
11 | PYTHON_PATH=$(which python3)
12 | COMMIX_PATH="/opt/commix/commix.py"
13 | SERVICE_PATH=$(pwd)
14 | INDEX_PATH="$SERVICE_PATH/build/index.js"
15 | COMMAND_NAME=$(basename "$SERVICE_PATH")
16 | CONFIG_FILE="$SERVICE_PATH/../mcp-config.json"
17 | echo $COMMIX_PATH
18 | [ -f "$COMMIX_PATH" ] || exit 1
19 | [ -f "$CONFIG_FILE" ] || echo "{}" > "$CONFIG_FILE"
20 | 
21 | 
22 | jq --arg cmd "$COMMAND_NAME" \
23 |    --arg index_path "$INDEX_PATH" \
24 |    --arg py_path "$PYTHON_PATH" \
25 |    --arg commix_path "$COMMIX_PATH" \
26 |    '.[$cmd] = { "command": "node", "args": [$index_path, $py_path, $commix_path] }' \
27 |    "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE"
```

--------------------------------------------------------------------------------
/alterx-mcp/build.sh:
--------------------------------------------------------------------------------

```bash
 1 | #!/bin/bash
 2 | 
 3 | set -e
 4 | 
 5 | npm install && npm run build
 6 | 
 7 | go install github.com/projectdiscovery/alterx/cmd/alterx@latest
 8 | 
 9 | # Get absolute path to this directory and index.js
10 | SERVICE_PATH=$(pwd)
11 | INDEX_PATH="$SERVICE_PATH/build/index.js"
12 | 
13 | # Get full path to the 'alterx' binary
14 | ALTERX_PATH=$(which alterx)
15 | 
16 | # Set dynamic command name (folder name is a good default)
17 | COMMAND_NAME=$(basename "$SERVICE_PATH")
18 | 
19 | # Output config file
20 | CONFIG_FILE="$SERVICE_PATH/../mcp-config.json"
21 | 
22 | # Ensure mcp-config.json exists (if not, initialize it)
23 | if [ ! -f "$CONFIG_FILE" ]; then
24 |     echo "{}" > "$CONFIG_FILE"
25 | fi
26 | 
27 | 
28 | jq --arg cmd "$COMMAND_NAME" \
29 |    --arg node_path "$INDEX_PATH" \
30 |    --arg alterx_path "$ALTERX_PATH" \
31 |    '.[$cmd] = { "command": "node", "args": [$node_path, $alterx_path] }' \
32 |    "$CONFIG_FILE" > "$CONFIG_FILE.tmp" && mv "$CONFIG_FILE.tmp" "$CONFIG_FILE"
```

--------------------------------------------------------------------------------
/.github/workflows/docker.yml:
--------------------------------------------------------------------------------

```yaml
 1 | name: Manual Docker Build and Push with Release
 2 | 
 3 | on:
 4 |   workflow_dispatch:
 5 |     inputs:
 6 |       tag:
 7 |         description: 'Docker image tag (default: latest)'
 8 |         required: false
 9 |         default: 'latest'
10 | 
11 | jobs:
12 |   build-and-release:
13 |     runs-on: ubuntu-latest
14 | 
15 |     steps:
16 |       - name: Checkout
17 |         uses: actions/checkout@v2
18 | 
19 |       - name: Docker Push
20 |         uses: docker/build-push-action@v2
21 |         with:
22 |           username: cyprox
23 |           password: ${{secrets.CYPROX_DOCKER_HUB_PASSWORD}}
24 |           repository: cyprox/mcp-for-security
25 |           tags: ${{ github.event.inputs.tag }}
26 | 
27 |       - name: Create GitHub Release
28 |         uses: softprops/action-gh-release@v1
29 |         with:
30 |           tag_name: ${{ github.event.inputs.tag }}
31 |           name: MCP Docker Image - ${{ github.event.inputs.tag }}
32 |           body: |
33 |             Docker image published to Docker Hub:
34 |             `docker pull cyprox/mcp-for-security:${{ github.event.inputs.tag }}`
35 |         env:
36 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | FROM golang:1.24-bullseye AS golang
 2 | 
 3 | # Set working directory
 4 | WORKDIR /app
 5 | 
 6 | 
 7 | 
 8 | # Install Python, pip, Go, virtualenv, and other tools
 9 | RUN apt-get update && apt-get install -y --no-install-recommends \
10 |     python3 \
11 |     python3-pip \
12 |     python3-venv \
13 |     jq \
14 |     curl \
15 |     git \
16 |     masscan \
17 |     nmap \
18 |     ruby-full && \
19 |     apt-get clean && rm -rf /var/lib/apt/lists/* && \
20 |     git clone https://github.com/sqlmapproject/sqlmap /opt/sqlmap && \
21 |     ln -s /opt/sqlmap/sqlmap.py /usr/local/bin/sqlmap && \
22 |     chmod +x /usr/local/bin/sqlmap
23 | 
24 | 
25 |     RUN curl -fsSL https://deb.nodesource.com/setup_24.x | bash - && \
26 |     apt-get install -y nodejs && \
27 |     if ! command -v npm >/dev/null 2>&1; then \
28 |         echo "[*] npm not found, installing manually..."; \
29 |         apt-get install -y npm; \
30 |     else \
31 |         echo "[+] npm is already included with Node.js"; \
32 |     fi && \
33 |     npm install -g npm@latest \ 
34 |     npm install -g @cyproxio/mcp-manager
35 | 
36 | # Create a global virtualenv
37 | RUN python3 -m venv /opt/venv
38 | 
39 | # Install pip tools inside venv if needed (optional)
40 | RUN /opt/venv/bin/pip install --upgrade pip
41 | 
42 | # Add venv to PATH (so pip, python point to venv by default)
43 | ENV PATH="/opt/venv/bin:$PATH"
44 | 
45 | # Copy project files
46 | COPY . .
47 | 
48 | # Make sure the entrypoint is executable
49 | COPY start.sh /app/start.sh
50 | RUN chmod +x /app/start.sh && /app/start.sh
51 | 
52 | RUN cat mcp-config.json
53 | CMD ["bash"]
54 | 
```

--------------------------------------------------------------------------------
/crtsh-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | import { z } from "zod";
 4 | import { GetCrtSh } from './crtsh'
 5 | 
 6 | const args = process.argv.slice(1);
 7 | if (args.length === 0) {
 8 |     console.error("Usage: crtsh-mcp");
 9 |     process.exit(1);
10 | }
11 | 
12 | // Create server instance
13 | const server = new McpServer({
14 |     name: "crtsh",
15 |     version: "1.0.0",
16 | });
17 | 
18 | server.tool(
19 |     "crtsh",
20 |     "Discovers subdomains from SSL certificate logs",
21 |     {
22 |         target: z.string().describe("Target domain to analyze (e.g., example.com)."),
23 |     },
24 |     async ({ target }) => {
25 |         return new Promise((resolve, reject) => {
26 |             GetCrtSh(target)
27 |                 .then(async domains => {
28 |                     const resolveData: any = {
29 |                         content: [{
30 |                             type: "text",
31 |                             text: JSON.stringify(domains, null, 2)
32 |                         }]
33 |                     }
34 |                     resolve(resolveData);
35 |                 })
36 |                 .catch(error => {
37 |                     reject(error);
38 |                 });
39 |         });
40 |     }
41 | );
42 | 
43 | // Start the server
44 | async function main() {
45 |     const transport = new StdioServerTransport();
46 |     await server.connect(transport);
47 |     console.error("crtsh MCP Server running on stdio");
48 | }
49 | 
50 | main().catch((error) => {
51 |     console.error("Fatal error in main():", error);
52 |     process.exit(1);
53 | });
```

--------------------------------------------------------------------------------
/scoutsuite-mcp/src/parser.ts:
--------------------------------------------------------------------------------

```typescript
 1 | const fs = require('fs');
 2 | const vm = require('vm');
 3 | 
 4 | interface Findings {
 5 |     [key: string]: any;
 6 | }
 7 | 
 8 | interface ServiceData {
 9 |     filters?: object;
10 |     findings?: Findings;
11 |     [key: string]: any;
12 | }
13 | 
14 | interface ScoutSuiteResults {
15 |     services: {
16 |         [serviceName: string]: ServiceData;
17 |     };
18 | }
19 | 
20 | type FullReportResult = Record<string, Findings>;
21 | type SummaryReportResult = Record<string, string[]>;
22 | 
23 | function getFindingsFromScoutSuite(
24 |     filePath: string,
25 |     full_report: true
26 | ): FullReportResult;
27 | function getFindingsFromScoutSuite(
28 |     filePath: string,
29 |     full_report: false
30 | ): SummaryReportResult;
31 | function getFindingsFromScoutSuite(
32 |     filePath: string,
33 |     full_report: boolean
34 | ): FullReportResult | SummaryReportResult {
35 |     const fileContent = fs.readFileSync(filePath, 'utf-8');
36 | 
37 |     const context: Record<string, any> = {};
38 |     vm.createContext(context);
39 |     vm.runInContext(fileContent, context);
40 | 
41 |     const results: ScoutSuiteResults = context.scoutsuite_results;
42 |     const services = results.services;
43 | 
44 |     const servicesWithFindings: FullReportResult | SummaryReportResult = {};
45 | 
46 |     for (const [serviceName, serviceData] of Object.entries(services)) {
47 |         if (
48 |             serviceData.findings &&
49 |             Object.keys(serviceData.findings).length > 0
50 |         ) {
51 |             servicesWithFindings[serviceName] = full_report
52 |                 ? serviceData.findings
53 |                 : Object.keys(serviceData.findings);
54 |         }
55 |     }
56 | 
57 |     return servicesWithFindings;
58 | }
59 | 
60 | function extractReportJsPath(output: string): string | null {
61 |     const regex = /Saving data to (scoutsuite-report\/scoutsuite-results\/scoutsuite_results_[\w\-]+\.js)/;
62 |     const match = output.match(regex);
63 |     return match ? match[1] : null;
64 | }
65 | 
66 | 
67 | module.exports = { getFindingsFromScoutSuite,extractReportJsPath };
```

--------------------------------------------------------------------------------
/http-headers-security-mcp/src/owasp_headers_add.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |     "headers": [
 3 |         {
 4 |             "name": "Cache-Control",
 5 |             "value": "no-store, max-age=0"
 6 |         },
 7 |         {
 8 |             "name": "Clear-Site-Data",
 9 |             "value": "\"cache\",\"cookies\",\"storage\""
10 |         },
11 |         {
12 |             "name": "Content-Security-Policy",
13 |             "value": "default-src 'self'; form-action 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content"
14 |         },
15 |         {
16 |             "name": "Cross-Origin-Embedder-Policy",
17 |             "value": "require-corp"
18 |         },
19 |         {
20 |             "name": "Cross-Origin-Opener-Policy",
21 |             "value": "same-origin"
22 |         },
23 |         {
24 |             "name": "Cross-Origin-Resource-Policy",
25 |             "value": "same-origin"
26 |         },
27 |         {
28 |             "name": "Permissions-Policy",
29 |             "value": "accelerometer=(), autoplay=(), camera=(), cross-origin-isolated=(), display-capture=(), encrypted-media=(), fullscreen=(), geolocation=(), gyroscope=(), keyboard-map=(), magnetometer=(), microphone=(), midi=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(self), usb=(), web-share=(), xr-spatial-tracking=(), clipboard-read=(), clipboard-write=(), gamepad=(), hid=(), idle-detection=(), interest-cohort=(), serial=(), unload=()"
30 |         },
31 |         {
32 |             "name": "Referrer-Policy",
33 |             "value": "no-referrer"
34 |         },
35 |         {
36 |             "name": "Strict-Transport-Security",
37 |             "value": "max-age=31536000; includeSubDomains"
38 |         },
39 |         {
40 |             "name": "X-Content-Type-Options",
41 |             "value": "nosniff"
42 |         },
43 |         {
44 |             "name": "X-Frame-Options",
45 |             "value": "deny"
46 |         },
47 |         {
48 |             "name": "X-Permitted-Cross-Domain-Policies",
49 |             "value": "none"
50 |         }
51 |     ]
52 | }
```

--------------------------------------------------------------------------------
/crtsh-mcp/src/crtsh.ts:
--------------------------------------------------------------------------------

```typescript
 1 | interface CrtShResponse {
 2 |     issuer_ca_id: number;
 3 |     issuer_name: string;
 4 |     common_name: string;
 5 |     name_value: string;
 6 |     id: number;
 7 |     entry_timestamp: string;
 8 |     not_before: string;
 9 |     not_after: string;
10 |     serial_number: string;
11 |     result_count: number;
12 | }
13 | 
14 | 
15 | export async function GetCrtSh(target: string): Promise<string[]> {
16 |     const subdomains = await sendReqCrtSh(target);
17 |     var results  = ClearResult(subdomains,target)
18 |     return results;
19 | }
20 | 
21 | async function sendReqCrtSh(query: string): Promise<string[]> {
22 |     try {
23 |         const response = await fetch(`https://crt.sh/?q=${query}&output=json`);
24 | 
25 |         if (!response.ok) {
26 |             return [];
27 |         }
28 | 
29 |         const crtshResponse: CrtShResponse[] = await response.json();
30 |         const domains: string[] = [];
31 | 
32 |         for (const crtshResp of crtshResponse) {
33 |             // NameValue'yi parse et ve domains array'ine ekle
34 |             const nameValues = parseNameValue(crtshResp.name_value);
35 |             domains.push(...nameValues);
36 |         }
37 | 
38 |         return domains;
39 |     } catch (error) {
40 |         console.error("Error fetching from crt.sh:", error);
41 |         return [];
42 |     }
43 | }
44 | 
45 | function parseNameValue(nameValue: string): string[] {
46 |     // \n karakterine göre böl
47 |     const values = nameValue.split("\n");
48 | 
49 |     // Boş değerleri filtrele
50 |     const result = values.filter(v => v !== "");
51 | 
52 |     return result;
53 | }
54 | 
55 | function ClearResult(result: string[], name: string): string[] {
56 |    
57 |     const escapedName = name.replace(/\./g, "\\.");
58 | 
59 |     
60 |     const re = new RegExp(`[^.]+\\.${escapedName}\\b`);
61 | 
62 |     const unique: { [key: string]: boolean } = {};
63 |     const uniqueList: string[] = [];
64 | 
65 |     
66 |     for (const val of result) {
67 |         if (!unique[val]) {
68 |             if (re.test(val)) {
69 |                 unique[val] = true;
70 |                 uniqueList.push(val);
71 |             }
72 |         }
73 |     }
74 | 
75 |     return uniqueList;
76 | }
```

--------------------------------------------------------------------------------
/http-headers-security-mcp/src/owasp_headers_remove.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |     "headers": [
 3 |         "$wsep",
 4 |         "Host-Header",
 5 |         "K-Proxy-Request",
 6 |         "Liferay-Portal",
 7 |         "OracleCommerceCloud-Version",
 8 |         "Pega-Host",
 9 |         "Powered-By",
10 |         "Product",
11 |         "Server",
12 |         "SourceMap",
13 |         "X-AspNet-Version",
14 |         "X-AspNetMvc-Version",
15 |         "X-Atmosphere-error",
16 |         "X-Atmosphere-first-request",
17 |         "X-Atmosphere-tracking-id",
18 |         "X-B3-ParentSpanId",
19 |         "X-B3-Sampled",
20 |         "X-B3-SpanId",
21 |         "X-B3-TraceId",
22 |         "X-BEServer",
23 |         "X-Backside-Transport",
24 |         "X-CF-Powered-By",
25 |         "X-CMS",
26 |         "X-CalculatedBETarget",
27 |         "X-Cocoon-Version",
28 |         "X-Content-Encoded-By",
29 |         "X-DiagInfo",
30 |         "X-Envoy-Attempt-Count",
31 |         "X-Envoy-External-Address",
32 |         "X-Envoy-Internal",
33 |         "X-Envoy-Original-Dst-Host",
34 |         "X-Envoy-Upstream-Service-Time",
35 |         "X-FEServer",
36 |         "X-Framework",
37 |         "X-Generated-By",
38 |         "X-Generator",
39 |         "X-Jitsi-Release",
40 |         "X-Joomla-Version",
41 |         "X-Kubernetes-PF-FlowSchema-UI",
42 |         "X-Kubernetes-PF-PriorityLevel-UID",
43 |         "X-LiteSpeed-Cache",
44 |         "X-LiteSpeed-Purge",
45 |         "X-LiteSpeed-Tag",
46 |         "X-LiteSpeed-Vary",
47 |         "X-Litespeed-Cache-Control",
48 |         "X-Mod-Pagespeed",
49 |         "X-Nextjs-Cache",
50 |         "X-Nextjs-Matched-Path",
51 |         "X-Nextjs-Page",
52 |         "X-Nextjs-Redirect",
53 |         "X-OWA-Version",
54 |         "X-Old-Content-Length",
55 |         "X-OneAgent-JS-Injection",
56 |         "X-Page-Speed",
57 |         "X-Php-Version",
58 |         "X-Powered-By",
59 |         "X-Powered-By-Plesk",
60 |         "X-Powered-CMS",
61 |         "X-Redirect-By",
62 |         "X-Server-Powered-By",
63 |         "X-SourceFiles",
64 |         "X-SourceMap",
65 |         "X-Turbo-Charged-By",
66 |         "X-Umbraco-Version",
67 |         "X-Varnish-Backend",
68 |         "X-Varnish-Server",
69 |         "X-dtAgentId",
70 |         "X-dtHealthCheck",
71 |         "X-dtInjectedServlet",
72 |         "X-ruxit-JS-Agent"
73 |     ]
74 | }
```

--------------------------------------------------------------------------------
/commix-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | import { z } from "zod";
 4 | import { spawn } from 'child_process';
 5 | 
 6 | const args = process.argv.slice(2);
 7 | if (args.length !== 2) {
 8 |     console.error("Usage: commix-mcp [python path] [commix.py path]");
 9 |     process.exit(1);
10 | }
11 | 
12 | const server = new McpServer({
13 |     name: "commix",
14 |     version: "1.0.0",
15 | });
16 | 
17 | server.tool(
18 |     "do-commix",
19 |     "Run Smuggler to detect HTTP Request Smuggling vulnerabilities",
20 |     {
21 |         url: z.string().url().describe("Target URL to detect HTTP Request Smuggling")
22 |     },
23 |     async ({ url }) => {
24 |         const baseArgs = [args[1],"-u", url];
25 |         const allArgs = [...baseArgs, url];
26 |         let output = '';
27 | 
28 |         const commix = spawn(args[0],allArgs);
29 | 
30 |         commix.stdout.on('data', (data) => {
31 |             output += data.toString();
32 |         });
33 | 
34 |         commix.stderr.on('data', (data) => {
35 |             output += data.toString();
36 |         });
37 | 
38 |         return new Promise((resolve, reject) => {
39 |             commix.on('close', (code) => {
40 |                 if (code === 0) {
41 |                     output = removeAnsiCodes(output);
42 |                     
43 |                     resolve({
44 |                         content: [{
45 |                             type: "text",
46 |                             text: output
47 |                         }]
48 |                     });
49 |                 } else {
50 |                     reject(new Error(`commix exited with code ${code}`));
51 |                 }
52 |             });
53 |             
54 |             commix.on('error', (error) => {
55 |                 reject(new Error(`Failed to start commix: ${error.message}`));
56 |             });
57 |         });
58 |     },
59 | );
60 | 
61 | function removeAnsiCodes(input: string): string {
62 |     return input.replace(/\x1B\[[0-9;]*[mGK]/g, '');
63 | }
64 | 
65 | async function main() {
66 |     const transport = new StdioServerTransport();
67 |     await server.connect(transport);
68 |     console.error("Smuggler MCP Server running on stdio");
69 | }
70 | 
71 | main().catch((error) => {
72 |     console.error("Fatal error in main():", error);
73 |     process.exit(1);
74 | }); 
```

--------------------------------------------------------------------------------
/masscan-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | import { z } from "zod";
 4 | import { spawn } from 'child_process';
 5 | 
 6 | const args = process.argv.slice(2);
 7 | if (args.length === 0) {
 8 |     console.error("Usage: masscan <masscan binary>");
 9 |     process.exit(1);
10 | }
11 | 
12 | // Create server instance
13 | const server = new McpServer({
14 |     name: "masscan",
15 |     version: "1.0.0",
16 | });
17 | 
18 | server.tool(
19 |     "do-masscan",
20 |     "Run masscan with specified target MASSCAN is a fast port scanner. The primary input parameters are the IP addresses/ranges you want to scan, and the port numbers.",
21 |     {
22 |         target: z.string().describe(`Target information. Example: 1.1.1.1
23 |             1.1.1.1
24 |             `),
25 |         port: z.string().describe(`Target port. Example: 1234
26 |                0-65535
27 |                 `),
28 |         masscan_args: z.array(z.string()).describe(`Additional masscan arguments 
29 |             --max-rate 
30 |             `),
31 |     },
32 |     async ({ target, port,masscan_args }) => {
33 |         const masscan = spawn(args[0], ["-p" + port, target, ...masscan_args]);
34 |         let output = '';
35 | 
36 |         // Handle stdout
37 |         masscan.stdout.on('data', (data) => {
38 |             output += data.toString();
39 |         });
40 | 
41 |         // Handle stderr
42 |         masscan.stderr.on('data', (data) => {
43 |             output += data.toString();
44 |         });
45 | 
46 |         // Handle process completion
47 |         return new Promise((resolve, reject) => {
48 |             masscan.on('close', (code) => {
49 |                 if (code === 0) {
50 |                     resolve({
51 |                         content: [{
52 |                             type: "text",
53 |                             text: output + "\n masscan completed successfully"
54 |                         }]
55 |                     });
56 |                 } else {
57 |                     reject(new Error(`masscan exited with code ${code}`));
58 |                 }
59 |             });
60 | 
61 |             masscan.on('error', (error) => {
62 |                 reject(new Error(`Failed to start masscan: ${error.message}`));
63 |             });
64 |         });
65 |     },
66 | );
67 | 
68 | // Start the server
69 | async function main() {
70 |     const transport = new StdioServerTransport();
71 |     await server.connect(transport);
72 |     console.error("Masscan MCP Server running on stdio");
73 | }
74 | 
75 | main().catch((error) => {
76 |     console.error("Fatal error in main():", error);
77 |     process.exit(1);
78 | });
```

--------------------------------------------------------------------------------
/assetfinder-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | const z = require('zod');
 4 | const pty = require('node-pty');
 5 | const args = process.argv.slice(2);
 6 | if (args.length === 0) {
 7 |     console.error("Usage: assetfinder-mcp <assetfinder binary>");
 8 |     process.exit(1);
 9 | }
10 | 
11 | // Create server instance
12 | const server = new McpServer({
13 |     name: "assetfinder",
14 |     version: "1.0.0",
15 | });
16 | 
17 | server.tool(
18 |     "do-assetfinder",
19 |     "Find related domains and subdomains using assetfinder for a given target.",
20 |     {
21 |         target: z.string().describe("The root domain (e.g., example.com) to discover associated subdomains and related domains."),
22 |     },
23 |     async ({ target }) => {
24 | 
25 |         const assetfinderArgs = ["-subs-only", target];
26 |         let output = "";
27 |         const assetfinder = pty.spawn(args[0], assetfinderArgs, {
28 |             name: 'xterm-color',
29 |             cols: 80,
30 |             rows: 30,
31 |             cwd: process.cwd(),
32 |             env: process.env
33 |         });
34 | 
35 |         assetfinder.on('data', function (data: string) {
36 |             output += data.toString();
37 |         });
38 | 
39 |         // Handle process completion
40 |         return new Promise((resolve, reject) => {
41 |             assetfinder.on('close', function (code: number) {
42 |                 if (code === 0 || typeof code === "undefined") {
43 |                     output = removeAnsiCodes(output)
44 |                     const resolveData: any = {
45 |                         content: [{
46 |                             type: "text",
47 |                             text: output
48 |                         }]
49 |                     };
50 |                     resolve(resolveData);
51 |                 } else {
52 |                     reject(new Error(`assetfinder exited with code ${code}`));
53 |                 }
54 |             });
55 |             assetfinder.on('error', function (error: Error) {
56 |                 if (typeof error.cause !== "undefined") {
57 |                     reject(new Error(`Error to start assetfinder: ${error.cause}`));
58 |                 }
59 |             });
60 |         });
61 |     },
62 | );
63 | 
64 | function removeAnsiCodes(input: string): string {
65 |     return input.replace(/\x1B\[[0-9;]*m/g, '');
66 | }
67 | 
68 | // Start the server
69 | async function main() {
70 |     const transport = new StdioServerTransport();
71 |     await server.connect(transport);
72 |     console.error("assetfinder MCP Server running on stdio");
73 | }
74 | 
75 | main().catch((error) => {
76 |     console.error("Fatal error in main():", error);
77 |     process.exit(1);
78 | });
```

--------------------------------------------------------------------------------
/waybackurls-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | import { z } from "zod";
 4 | import { spawn } from 'child_process';
 5 | 
 6 | const args = process.argv.slice(2);
 7 | if (args.length === 0) {
 8 |     console.error("Usage: waybackurls-mcp <waybackurls binary>");
 9 |     process.exit(1);
10 | }
11 | 
12 | // Create server instance
13 | const server = new McpServer({
14 |     name: "waybackurls",
15 |     version: "1.0.0",
16 | });
17 | 
18 | server.tool(
19 |     "do-waybackurls",
20 |     "Execute Waybackurls, a tool that fetches known URLs from the Wayback Machine archive for a given domain. This helps in discovering historical endpoints, forgotten API paths, and potentially vulnerable URLs that might not be directly accessible or linked from the current version of the website.",
21 |     {
22 |         target: z.string().url().describe("Target domain to retrieve historical URLs from the Wayback Machine (e.g., example.com)"),
23 |         noSub: z.boolean().nullable().describe("When set to true, only retrieves URLs from the exact domain specified, excluding all subdomains"),
24 |     },
25 |     async ({ target, noSub }) => {
26 |         const waybackurls = spawn(args[0], [target, ...(noSub ? ['--no-subs'] : [])]);
27 | 
28 |         let output = '';
29 | 
30 |         // Handle stdout
31 |         waybackurls.stdout.on('data', (data: Buffer) => {
32 |             output += data.toString();
33 |         });
34 | 
35 |         // Handle stderr
36 |         waybackurls.stderr.on('data', (data) => {
37 |             output += data.toString();
38 |         });
39 | 
40 |         // Handle process completion
41 |         return new Promise((resolve, reject) => {
42 |             waybackurls.on('close', (code) => {
43 |                 if (code === 0) {
44 |                     resolve({
45 |                         content: [{
46 |                             type: "text",
47 |                             text: output + "\n waybackurls completed successfully"
48 |                         }]
49 |                     });
50 |                 } else {
51 |                     reject(new Error(`waybackurls exited with code ${code}`));
52 |                 }
53 |             });
54 | 
55 |             waybackurls.on('error', (error) => {
56 |                 reject(new Error(`Failed to start waybackurls: ${error.message}`));
57 |             });
58 |         });
59 |     },
60 | );
61 | 
62 | // Start the server
63 | async function main() {
64 |     const transport = new StdioServerTransport();
65 |     await server.connect(transport);
66 |     console.error("waybackurls MCP Server running on stdio");
67 | }
68 | 
69 | main().catch((error) => {
70 |     console.error("Fatal error in main():", error);
71 |     process.exit(1);
72 | });
```

--------------------------------------------------------------------------------
/shuffledns-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | import { z } from "zod";
 4 | const pty = require('node-pty');
 5 | 
 6 | const args = process.argv.slice(2);
 7 | if (args.length < 2) {
 8 |     console.error("Usage: shuffledns-mcp <shuffledns binary> <massdns binary>");
 9 |     process.exit(1);
10 | }
11 | 
12 | // Create server instance
13 | const server = new McpServer({
14 |     name: "shuffledns",
15 |     version: "1.0.0",
16 | });
17 | 
18 | server.tool(
19 |     "shuffledns",
20 |     "DNS Brute force",
21 |     {
22 |         target: z.string().describe("A list of domain names (e.g., example.com) to scan for HTTP and HTTPS services."),
23 |         resolver: z.string().describe("Resolver file path"),
24 |         mode: z.enum(["bruteforce", "resolve", "filter"]).describe("Mode"),
25 |         wordlist: z.string().describe("wordlist"),
26 |         rateLimit: z.number().optional().describe("ratelimit")
27 |     },
28 |     async ({ target, resolver, mode, wordlist, rateLimit }) => {
29 |         const shufflednsArgs = ["-d", target, "-r", resolver, "-mode", mode, "-w", wordlist, "-m", args[1],"-silent"];
30 |         if (rateLimit) {
31 |             shufflednsArgs.push("-t", rateLimit.toString());
32 |         }
33 |         let output = '';
34 |         const shuffledns = pty.spawn(args[0], shufflednsArgs, {
35 |             name: 'xterm-color',
36 |             cols: 80,
37 |             rows: 30,
38 |             cwd: process.cwd(),
39 |             env: process.env
40 |         });
41 | 
42 |         shuffledns.on('data', function (data: string) {
43 |             output += data.toString();
44 |         });
45 | 
46 |         // Handle process completion
47 |         return new Promise((resolve, reject) => {
48 |             shuffledns.on('close', function (code: number) {
49 |                 if (code === 0 || typeof code === "undefined") {
50 |                     output = removeAnsiCodes(output)
51 |                     const resolveData: any = {
52 |                         content: [{
53 |                             type: "text",
54 |                             text: output
55 |                         }]
56 |                     };
57 |                     resolve(resolveData);
58 |                 } else {
59 |                     reject(new Error(`shuffledns exited with code ${code}`));
60 |                 }
61 |             });
62 |             shuffledns.on('error', function (error: Error) {
63 |                 if (typeof error.cause !== "undefined") {
64 |                     reject(new Error(`Error to start shuffledns: ${error.cause}`));
65 |                 }
66 |             });
67 |         });
68 |     },
69 | );
70 | 
71 | function removeAnsiCodes(input: string): string {
72 |     return input.replace(/\x1B\[[0-9;]*m/g, '');
73 | }
74 | 
75 | // Start the server
76 | async function main() {
77 |     const transport = new StdioServerTransport();
78 |     await server.connect(transport);
79 |     console.error("shuffledns MCP Server running on stdio");
80 | }
81 | 
82 | main().catch((error) => {
83 |     console.error("Fatal error in main():", error);
84 |     process.exit(1);
85 | });
```

--------------------------------------------------------------------------------
/smuggler-mcp/mcp.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "smuggler",
 3 |   "version": "1.0.0",
 4 |   "description": "HTTP Request Smuggling / Desync testing tool",
 5 |   "tools": [
 6 |     {
 7 |       "name": "do-smuggler",
 8 |       "description": "Run Smuggler to detect HTTP Request Smuggling vulnerabilities",
 9 |       "input_schema": {
10 |         "type": "object",
11 |         "required": ["url"],
12 |         "properties": {
13 |           "url": {
14 |             "type": "string",
15 |             "description": "Target URL to detect HTTP Request Smuggling"
16 |           },
17 |           "smuggler_args": {
18 |             "type": "array",
19 |             "items": {
20 |               "type": "string"
21 |             },
22 |             "description": "Additional smuggler arguments\n        -m, --method METHOD  Specify the HTTP method to use (default: POST)\n        -v, --vhost VHOST    Specify a virtual host to use\n        -l, --len            Enable Content-Length header in all requests\n        -c, --configfile FILE\n                             Specify a configuration file to load payloads from\n        -x                   Exit on the first finding\n        -t, --timeout TIMEOUT\n                             Socket timeout value (default: 5)\n        -verify VERIFY       Verify findings with more requests; never, quick or thorough (default: quick)"
23 |           }
24 |         }
25 |       },
26 |       "output_schema": {
27 |         "type": "object",
28 |         "properties": {
29 |           "content": {
30 |             "type": "array",
31 |             "items": {
32 |               "type": "object",
33 |               "properties": {
34 |                 "type": {
35 |                   "type": "string",
36 |                   "enum": ["text"]
37 |                 },
38 |                 "text": {
39 |                   "type": "string"
40 |                 }
41 |               }
42 |             }
43 |           },
44 |           "metadata": {
45 |             "type": "object",
46 |             "properties": {
47 |               "findings": {
48 |                 "type": "object",
49 |                 "properties": {
50 |                   "cl_te": {
51 |                     "type": "array",
52 |                     "items": {
53 |                       "type": "object",
54 |                       "properties": {
55 |                         "mutation": {
56 |                           "type": "string"
57 |                         },
58 |                         "severity": {
59 |                           "type": "string",
60 |                           "enum": ["high", "medium", "low"]
61 |                         }
62 |                       }
63 |                     }
64 |                   },
65 |                   "te_cl": {
66 |                     "type": "array",
67 |                     "items": {
68 |                       "type": "object",
69 |                       "properties": {
70 |                         "mutation": {
71 |                           "type": "string"
72 |                         },
73 |                         "severity": {
74 |                           "type": "string",
75 |                           "enum": ["high", "medium", "low"]
76 |                         }
77 |                       }
78 |                     }
79 |                   }
80 |                 }
81 |               },
82 |               "raw_output": {
83 |                 "type": "string"
84 |               }
85 |             }
86 |           }
87 |         }
88 |       }
89 |     }
90 |   ]
91 | } 
```

--------------------------------------------------------------------------------
/arjun-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: arjun-mcp <arjun binary or python3 arjun>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "arjun",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-arjun",
 20 |     "Run Arjun to discover hidden HTTP parameters",
 21 |     {
 22 |         url: z.string().url().describe("Target URL to scan for hidden parameters"),
 23 |         textFile: z.string().optional().describe("Path to file containing multiple URLs"),
 24 |         wordlist: z.string().optional().describe("Path to custom wordlist file"),
 25 |         method: z.enum(["GET", "POST", "JSON", "HEADERS"]).optional().describe("HTTP method to use for scanning (default: GET)"),
 26 |         rateLimit: z.number().optional().describe("Maximum requests per second (default: 9999)"),
 27 |         chunkSize: z.number().optional().describe("Chunk size. The number of parameters to be sent at once"),
 28 | 
 29 |     },
 30 |     async ({ url, textFile, wordlist, method, rateLimit,chunkSize }) => {
 31 |         // Build command arguments
 32 |         const arjunArgs = []
 33 | 
 34 |         if (!url && !textFile) {
 35 |             throw new Error("url or textfile parameter required");
 36 |         }
 37 |         if (url) {
 38 |             arjunArgs.push('-u', url);
 39 |         }
 40 |         if (textFile) {
 41 |             arjunArgs.push('-f', textFile);
 42 |         }
 43 |         if (wordlist) {
 44 |             arjunArgs.push('-w', wordlist);
 45 |         }
 46 |         if (method) {
 47 |             arjunArgs.push('-m', method);
 48 |         }
 49 |         if (rateLimit) {
 50 |             arjunArgs.push('--rate-limit', rateLimit.toString());
 51 |         }
 52 |         if (chunkSize){
 53 |             arjunArgs.push('--rate-limit', chunkSize.toString());
 54 |         }
 55 |         
 56 | 
 57 |         const arjun = spawn(args[0], arjunArgs);
 58 |         let output = '';
 59 |         // Handle stdout
 60 |         arjun.stdout.on('data', (data) => {
 61 |             output += data.toString();
 62 |         });
 63 | 
 64 |         // Handle stderr
 65 |         arjun.stderr.on('data', (data) => {
 66 |             output += data.toString();
 67 |         });
 68 | 
 69 |         // Handle process completion
 70 |         return new Promise((resolve, reject) => {
 71 |             arjun.on('close', (code) => {
 72 |                 if (code === 0) {
 73 |                     resolve({
 74 |                         content: [{
 75 |                             type: "text",
 76 |                             text: output
 77 |                         }]
 78 |                     });
 79 |                 } else {
 80 |                     reject(new Error(`arjun exited with code ${code}`));
 81 |                 }
 82 |             });
 83 | 
 84 |             arjun.on('error', (error) => {
 85 |                 reject(new Error(`Failed to start arjun: ${error.message}`));
 86 |             });
 87 |         });
 88 |     },
 89 | );
 90 | 
 91 | // Start the server
 92 | async function main() {
 93 |     const transport = new StdioServerTransport();
 94 |     await server.connect(transport);
 95 |     console.error("arjun MCP Server running on stdio");
 96 | }
 97 | 
 98 | main().catch((error) => {
 99 |     console.error("Fatal error in main():", error);
100 |     process.exit(1);
101 | });
```

--------------------------------------------------------------------------------
/cero/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | const pty = require('node-pty');
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: cero-mcp <cero binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "cero",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-cero",
 20 |     "Execute Cero, a high-performance certificate-based subdomain enumeration tool. It connects to specified targets over TLS, extracts domain names from certificates (e.g., SAN fields), and outputs discovered hostnames. Useful for reconnaissance and OSINT tasks.",
 21 |     {
 22 |         target: z.string().describe("The target host or IP address to scan. Can be a single hostname, IPv4/IPv6 address, or a CIDR range (e.g., 192.168.0.0/24)."),
 23 |         concurrency: z.number().optional().describe("Maximum number of concurrent TLS connections to use during scanning. Higher values increase speed but consume more system resources."),
 24 |         ports: z.array(z.string()).optional().describe("List of TLS ports to scan for certificate information. If omitted, the default port 443 is used. Accepts multiple ports (e.g., ['443', '8443'])."),
 25 |         timeOut: z.number().optional().describe("Maximum time (in seconds) to wait for a TLS handshake with a target. Used to prevent long delays on unresponsive hosts. Default is 4 seconds.")
 26 |     },
 27 |     async ({ target, concurrency, ports, timeOut }) => {
 28 | 
 29 | 
 30 |         const ceroArgs = [target];
 31 | 
 32 |         if (concurrency) {
 33 |             ceroArgs.push("-c", concurrency.toString())
 34 |         }
 35 | 
 36 |         if (ports && ports.length > 0) {
 37 |             ceroArgs.push("-p", ports.join(","));
 38 |         }
 39 | 
 40 |         if (timeOut) {
 41 |             ceroArgs.push("-t", timeOut.toString())
 42 |         }
 43 | 
 44 | 
 45 |         let output = '';
 46 | 
 47 | 
 48 |         const cero = pty.spawn(args[0], ceroArgs, {
 49 |             name: 'xterm-color',
 50 |             cols: 80,
 51 |             rows: 30,
 52 |             cwd: process.cwd(),
 53 |             env: process.env
 54 |         });
 55 | 
 56 |         cero.on('data', function (data: string) {
 57 |             output += data.toString();
 58 |             console.log(data.toString())
 59 |         });
 60 | 
 61 |         // Handle process completion
 62 |         return new Promise((resolve, reject) => {
 63 |             cero.on('close', function (code: number) {
 64 |                 if (code === 0 || typeof code === "undefined") {
 65 |                     output = removeAnsiCodes(output)
 66 |                     const resolveData: any = {
 67 |                         content: [{
 68 |                             type: "text",
 69 |                             text: output
 70 |                         }]
 71 |                     };
 72 |                     resolve(resolveData);
 73 |                 } else {
 74 |                     reject(new Error(`cero exited with code ${code}`));
 75 |                 }
 76 |             });
 77 |             cero.on('error', function (error: Error) {
 78 |                 if (typeof error.cause !== "undefined") {
 79 |                     reject(new Error(`Error to start cero: ${error.cause}`));
 80 |                 }
 81 |             });
 82 |         });
 83 |     },
 84 | );
 85 | 
 86 | function removeAnsiCodes(input: string): string {
 87 |     return input.replace(/\x1B\[[0-9;]*m/g, '');
 88 | }
 89 | 
 90 | 
 91 | // Start the server
 92 | async function main() {
 93 |     const transport = new StdioServerTransport();
 94 |     await server.connect(transport);
 95 |     console.error("cero MCP Server running on stdio");
 96 | }
 97 | 
 98 | main().catch((error) => {
 99 |     console.error("Fatal error in main():", error);
100 |     process.exit(1);
101 | });
```

--------------------------------------------------------------------------------
/http-headers-security-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 3 | import { z } from "zod";
 4 | import axios from 'axios';
 5 | import removeHeadersData from "./owasp_headers_remove.json";
 6 | import addHeadersData from "./owasp_headers_add.json";
 7 | 
 8 | // Create server instance
 9 | const server = new McpServer({
10 |     name: "http-headers-security",
11 |     version: "1.0.0",
12 | });
13 | 
14 | async function fetchHttpHeaders(target: string): Promise<string[]> {
15 |     try {
16 |         const response = await axios.get(target, {
17 |             timeout: 100000,
18 |             validateStatus: () => true // Accept all status codes
19 |         });
20 | 
21 |         return Object.entries(response.headers).map(([key, value]) => `${key}: ${value}`);
22 |     } catch (error: unknown) {
23 |         if (error instanceof Error) {
24 |             throw new Error(`Failed to fetch headers: ${error.message}`);
25 |         }
26 |         throw new Error('Failed to fetch headers: Unknown error occurred');
27 |     }
28 | }
29 | 
30 | async function findMatchingRemoveHeaders(headers: string[]): Promise<string[]> {
31 |     const removeHeaders = removeHeadersData.headers;
32 | 
33 |     return headers.filter(header => {
34 |         const headerName = header.split(':')[0].trim().toLowerCase();
35 |         return removeHeaders.some(h => h.toLowerCase() === headerName);
36 |     });
37 | }
38 | 
39 | async function findMatchingAddedHeaders(headers: string[]): Promise<string[]> {
40 |     const addHeaders = addHeadersData.headers;
41 |     const existingHeaderNames = headers.map(header => header.split(':')[0].trim().toLowerCase());
42 | 
43 |     return addHeaders
44 |         .filter(header => !existingHeaderNames.includes(header.name.toLowerCase()))
45 |         .map(header => `${header.name}: ${header.value}`);
46 | }
47 | 
48 | server.tool(
49 |     "analyze-http-header",
50 |     "Perform security analysis of HTTP response headers for a web application. This tool examines HTTP headers against OWASP security best practices, identifying both potentially dangerous headers that should be removed and recommended security headers that are missing. Results include specific recommendations for improving security posture.",
51 |     {
52 |         target: z.string().describe("Target URL to analyze (e.g., https://example.com). The tool will make a request to this URL and evaluate its HTTP response headers for security issues."),
53 |     },
54 |     async ({ target }) => {
55 |         return new Promise((resolve, reject) => {
56 |             fetchHttpHeaders(target)
57 |                 .then(async headers => {
58 |                     const removeHeaders = await findMatchingRemoveHeaders(headers);
59 |                     const addedHeaders = await findMatchingAddedHeaders(headers);
60 |                     const result = { 
61 |                         removeHeaders: removeHeaders.length > 0 ? removeHeaders : ["No headers to remove"],
62 |                         addedHeaders: addedHeaders.length > 0 ? addedHeaders : ["No headers to add"]
63 |                     };
64 |                     resolve({
65 |                         content: [{
66 |                             type: "text",
67 |                             text: JSON.stringify(result, null, 2)
68 |                         }]
69 |                     });
70 |                 })
71 |                 .catch(error => {
72 |                     reject(error);
73 |                 });
74 |         });
75 |     }
76 | );
77 | 
78 | // Start the server
79 | async function main() {
80 |     const transport = new StdioServerTransport();
81 |     await server.connect(transport);
82 |     console.error("http-headers-security MCP Server running on stdio");
83 | }
84 | 
85 | main().catch((error) => {
86 |     console.error("Fatal error in main():", error);
87 |     process.exit(1);
88 | });
```

--------------------------------------------------------------------------------
/nuclei-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | const pty = require('node-pty');
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: nuclei-mcp <nuclei binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "nuclei",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-nuclei",
 20 |     "Execute Nuclei, an advanced vulnerability scanner that uses YAML-based templates to detect security vulnerabilities, misconfigurations, and exposures in web applications and infrastructure. Nuclei offers fast scanning with a vast template library covering various security checks.",
 21 |     {
 22 |         url: z.string().url().describe("Target URL to run nuclei"),
 23 |         //nuclei_args: z.array(z.string()).describe(),
 24 |         tags: z.array(z.string()).optional().describe("Tags to run nuclei for multiple choise use ,")
 25 |     },
 26 |     async ({ url, tags }) => {
 27 | 
 28 | 
 29 |         const nucleiArgs = ["-u", url, "-silent"];
 30 | 
 31 |         if (tags && tags.length > 0) {
 32 |             nucleiArgs.push("-tags", tags.join(","));
 33 |         }
 34 | 
 35 | 
 36 |         let output = '';
 37 | 
 38 | 
 39 |         const nuclei = pty.spawn(args[0], nucleiArgs, {
 40 |             name: 'xterm-color',
 41 |             cols: 80,
 42 |             rows: 30,
 43 |             cwd: process.cwd(),
 44 |             env: process.env
 45 |         });
 46 | 
 47 |         nuclei.on('data', function (data: string) {
 48 |             output += data.toString();
 49 |             console.log(data.toString())
 50 |         });
 51 | 
 52 |         // Handle process completion
 53 |         return new Promise((resolve, reject) => {
 54 |             nuclei.on('close', function (code: number) {
 55 |                 if (code === 0 || typeof code === "undefined") {
 56 |                     output = removeAnsiCodes(output)
 57 |                     const resolveData: any = {
 58 |                         content: [{
 59 |                             type: "text",
 60 |                             text: output
 61 |                         }]
 62 |                     };
 63 |                     resolve(resolveData);
 64 |                 } else {
 65 |                     reject(new Error(`nuclei exited with code ${code}`));
 66 |                 }
 67 |             });
 68 |             nuclei.on('error', function (error: Error) {
 69 |                 if (typeof error.cause !== "undefined") {
 70 |                     reject(new Error(`Error to start nuclei: ${error.cause}`));
 71 |                 }
 72 |             });
 73 |         });
 74 |     },
 75 | );
 76 | 
 77 | server.tool(
 78 |     "get-nuclei-tags",
 79 |     "Get Nuclei Tags",
 80 |     {},
 81 |     async () => {
 82 |         return new Promise((resolve, reject) => {
 83 |             fetch('https://raw.githubusercontent.com/projectdiscovery/nuclei-templates/refs/heads/main/TEMPLATES-STATS.json')
 84 |                 .then(response => response.json())
 85 |                 .then((data: { tags: { name: string }[] }) => {
 86 |                     const tagNames = data.tags.map(tag => tag.name);
 87 |                     resolve({
 88 |                         content: [{
 89 |                             type: "text",
 90 |                             text: JSON.stringify(tagNames)
 91 |                         }]
 92 |                     });
 93 |                 })
 94 |                 .catch(error => {
 95 |                     reject(new Error(`Failed to fetch nuclei tags: ${error.message}`));
 96 |                 });
 97 |         });
 98 |     }
 99 | )
100 | 
101 | 
102 | function removeAnsiCodes(input: string): string {
103 |     return input.replace(/\x1B\[[0-9;]*m/g, '');
104 | }
105 | 
106 | 
107 | // Start the server
108 | async function main() {
109 |     const transport = new StdioServerTransport();
110 |     await server.connect(transport);
111 |     console.error("nuclei MCP Server running on stdio");
112 | }
113 | 
114 | main().catch((error) => {
115 |     console.error("Fatal error in main():", error);
116 |     process.exit(1);
117 | });
```

--------------------------------------------------------------------------------
/alterx-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: alterx-mcp <alterx binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "alterx",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-alterx",
 20 |     "Execute Alterx, a tool that generates domain wordlists using pattern-based permutations for subdomain discovery and DNS enumeration",
 21 |     {
 22 |         domain: z.string().describe("Target domain or subdomains to use as a base for creating permutations (accepts stdin input, comma-separated values, or file path)"),
 23 |         pattern: z.string().describe(`Pattern template for generating wordlist variations. Multiple patterns can be specified using comma-separation.
 24 |     
 25 |             Available pattern types:
 26 |             
 27 |             - Dash-based patterns (e.g., api-dev.example.com):
 28 |               "{{word}}-{{sub}}.{{suffix}}"  // Produces: dev-api.example.com
 29 |               "{{sub}}-{{word}}.{{suffix}}"  // Produces: api-dev.example.com
 30 |               
 31 |             - Dot-based patterns (e.g., dev.api.example.com):
 32 |               "{{word}}.{{sub}}.{{suffix}}"  // Produces: word.api.example.com
 33 |               "{{sub}}.{{word}}.{{suffix}}"  // Produces: api.word.example.com
 34 |               
 35 |             - Iteration-based patterns:
 36 |               "{{sub}}{{number}}.{{suffix}}"  // Produces: api1.example.com, api2.example.com
 37 |               
 38 |             - Replacement patterns:
 39 |               "{{word}}.{{suffix}}"  // Replaces current subdomain completely
 40 |               
 41 |             - No separator patterns:
 42 |               "{{sub}}{{word}}.{{suffix}}"  // Produces: apidev.example.com
 43 |               
 44 |             - Region prefix patterns:
 45 |               "{{region}}.{{sub}}.{{suffix}}"  // Produces: us-east.api.example.com
 46 |               
 47 |             - Combination patterns:
 48 |               "{{word}}{{number}}.{{suffix}}"  // Combines words and numbers
 49 |             `),
 50 |         outputFilePath: z.string().nullable().describe("Path where the generated wordlist should be saved (optional)")
 51 |     },
 52 |     async ({ domain,pattern,outputFilePath  }) => {
 53 |         let alterx;
 54 | 
 55 |         const alterxArgs = [];
 56 | 
 57 | 
 58 |         alterxArgs.push("-l" ,domain);
 59 |         alterxArgs.push('-p', pattern);
 60 | 
 61 |         
 62 | 
 63 |         if (outputFilePath != null) {
 64 |             alterxArgs.push("-o", outputFilePath)
 65 |         }
 66 | 
 67 |         alterx = spawn(args[0], alterxArgs);
 68 | 
 69 | 
 70 |         let output = '';
 71 | 
 72 |         // Handle stdout
 73 |         alterx.stdout.on('data', (data: Buffer) => {
 74 |             output += data.toString();
 75 |         });
 76 | 
 77 |         // Handle stderr
 78 |         alterx.stderr.on('data', (data) => {
 79 |             output += data.toString();
 80 |         });
 81 | 
 82 |         // Handle process completion
 83 |         return new Promise((resolve, reject) => {
 84 |             alterx.on('close', (code) => {
 85 |                 if (code === 0) {
 86 |                     resolve({
 87 |                         content: [{
 88 |                             type: "text",
 89 |                             text: output + "\n alterx completed successfully"
 90 |                         }]
 91 |                     });
 92 |                 } else {
 93 |                     reject(new Error(`alterx exited with code ${code}`));
 94 |                 }
 95 |             });
 96 | 
 97 |             alterx.on('error', (error) => {
 98 |                 reject(new Error(`Failed to start alterx: ${error.message}`));
 99 |             });
100 |         });
101 |     },
102 | );
103 | 
104 | // Start the server
105 | async function main() {
106 |     const transport = new StdioServerTransport();
107 |     await server.connect(transport);
108 |     console.error("alterx MCP Server running on stdio");
109 | }
110 | 
111 | main().catch((error) => {
112 |     console.error("Fatal error in main():", error);
113 |     process.exit(1);
114 | });
```

--------------------------------------------------------------------------------
/smuggler-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length !== 2) {
  8 |     console.error("Usage: smuggler-mcp [python path] [smuggler.py path]");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | const server = new McpServer({
 13 |     name: "smuggler",
 14 |     version: "1.0.0",
 15 | });
 16 | 
 17 | server.tool(
 18 |     "do-smuggler",
 19 |     "Run Smuggler to detect HTTP Request Smuggling vulnerabilities",
 20 |     {
 21 |         url: z.string().url().describe("Target URL to detect HTTP Request Smuggling"),
 22 |         smuggler_args: z.array(z.string()).optional().describe(`Additional smuggler arguments
 23 |         -m, --method METHOD  Specify the HTTP method to use (default: POST)
 24 |         -v, --vhost VHOST    Specify a virtual host to use
 25 |         -l, --len            Enable Content-Length header in all requests
 26 |         -c, --configfile FILE
 27 |                              Specify a configuration file to load payloads from
 28 |         -x                   Exit on the first finding
 29 |         -t, --timeout TIMEOUT
 30 |                              Socket timeout value (default: 5)
 31 |         -verify VERIFY       Verify findings with more requests; never, quick or thorough (default: quick)`)
 32 |     },
 33 |     async ({ url, smuggler_args = [] }) => {
 34 |         const baseArgs = [args[1],"-u", url];
 35 |         const allArgs = [...baseArgs, ...smuggler_args];
 36 |         let output = '';
 37 | 
 38 |         const smuggler = spawn(args[0],allArgs);
 39 | 
 40 |         smuggler.stdout.on('data', (data) => {
 41 |             output += data.toString();
 42 |         });
 43 | 
 44 |         smuggler.stderr.on('data', (data) => {
 45 |             output += data.toString();
 46 |         });
 47 | 
 48 |         return new Promise((resolve, reject) => {
 49 |             smuggler.on('close', (code) => {
 50 |                 if (code === 0) {
 51 |                     output = removeAnsiCodes(output);
 52 |                     const vulnResults = parseResults(output);
 53 |                     
 54 |                     resolve({
 55 |                         content: [{
 56 |                             type: "text",
 57 |                             text: output
 58 |                         }],
 59 |                         metadata: {
 60 |                             findings: vulnResults
 61 |                         }
 62 |                     });
 63 |                 } else {
 64 |                     reject(new Error(`Smuggler exited with code ${code}`));
 65 |                 }
 66 |             });
 67 |             
 68 |             smuggler.on('error', (error) => {
 69 |                 reject(new Error(`Failed to start Smuggler: ${error.message}`));
 70 |             });
 71 |         });
 72 |     },
 73 | );
 74 | 
 75 | function removeAnsiCodes(input: string): string {
 76 |     return input.replace(/\x1B\[[0-9;]*[mGK]/g, '');
 77 | }
 78 | 
 79 | interface VulnEntry {
 80 |     mutation: string;
 81 |     severity: string;
 82 | }
 83 | 
 84 | function parseResults(output: string): any {
 85 |     const vulnerabilities: {
 86 |         cl_te: VulnEntry[];
 87 |         te_cl: VulnEntry[];
 88 |     } = {
 89 |         cl_te: [],
 90 |         te_cl: []
 91 |     };
 92 | 
 93 |     const clteRegex = /\[(\+|\!)\] Potential (CL\.TE) Vulnerability Found \((\w+)\)/gi;
 94 |     const teclRegex = /\[(\+|\!)\] Potential (TE\.CL) Vulnerability Found \((\w+)\)/gi;
 95 | 
 96 |     let match;
 97 |     while ((match = clteRegex.exec(output)) !== null) {
 98 |         vulnerabilities.cl_te.push({
 99 |             mutation: match[3],
100 |             severity: match[1] === '+' ? 'high' : 'medium'
101 |         });
102 |     }
103 | 
104 |     while ((match = teclRegex.exec(output)) !== null) {
105 |         vulnerabilities.te_cl.push({
106 |             mutation: match[3],
107 |             severity: match[1] === '+' ? 'high' : 'medium'
108 |         });
109 |     }
110 | 
111 |     return vulnerabilities;
112 | }
113 | 
114 | async function main() {
115 |     const transport = new StdioServerTransport();
116 |     await server.connect(transport);
117 |     console.error("Smuggler MCP Server running on stdio");
118 | }
119 | 
120 | main().catch((error) => {
121 |     console.error("Fatal error in main():", error);
122 |     process.exit(1);
123 | }); 
```

--------------------------------------------------------------------------------
/httpx-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | const pty = require('node-pty');
  5 | const args = process.argv.slice(2);
  6 | if (args.length === 0) {
  7 |     console.error("Usage: httpx-mcp <httpx binary>");
  8 |     process.exit(1);
  9 | }
 10 | 
 11 | // Create server instance
 12 | const server = new McpServer({
 13 |     name: "httpx",
 14 |     version: "1.0.0",
 15 | });
 16 | 
 17 | server.tool(
 18 |     "httpx",
 19 |     "Scans the given target domains and detects active HTTP/HTTPS services on ports like 80 and 443.",
 20 |     {
 21 |         target: z.array(z.string()).describe("A list of domain names (e.g., example.com) to scan for HTTP and HTTPS services."),
 22 |         ports: z.array(z.number()).optional().describe(""),
 23 |         probes: z.array(z.string()).optional().describe(`Available probe options:
 24 |             status-code      Display response status-code
 25 |             content-length   Display response content-length
 26 |             content-type     Display response content-type
 27 |             location         Display response redirect location
 28 |             favicon          Display mmh3 hash for '/favicon.ico' file
 29 |             hash             Display response body hash (supported: md5,mmh3,simhash,sha1,sha256,sha512)
 30 |             jarm             Display jarm fingerprint hash
 31 |             response-time    Display response time
 32 |             line-count       Display response body line count
 33 |             word-count       Display response body word count
 34 |             title            Display page title
 35 |             body-preview     Display first N characters of response body (default 100)
 36 |             web-server       Display server name
 37 |             tech-detect      Display technology in use based on wappalyzer dataset
 38 |             method           Display http request method
 39 |             websocket        Display server using websocket
 40 |             ip               Display host ip
 41 |             cname            Display host cname
 42 |             extract-fqdn     Get domain and subdomains from response body and header
 43 |             asn              Display host asn information
 44 |             cdn              Display cdn/waf in use (default true)
 45 |             probe            Display probe status`)
 46 |     },
 47 |     async ({ target, ports, probes }) => {
 48 | 
 49 | 
 50 |         const httpxArgs = ["-u", target.join(","), "-silent"];
 51 | 
 52 |         if (ports && ports.length > 0) {
 53 |             httpxArgs.push("-p", ports.join(","));
 54 |         }
 55 | 
 56 |         if (probes && probes.length > 0) {
 57 |             for (const probe of probes) {
 58 |                 httpxArgs.push(`-${probe}`);
 59 |             }
 60 |         }
 61 | 
 62 |         let output = '';
 63 | 
 64 | 
 65 |         const httpx = pty.spawn(args[0], httpxArgs, {
 66 |             name: 'xterm-color',
 67 |             cols: 80,
 68 |             rows: 30,
 69 |             cwd: process.cwd(),
 70 |             env: process.env
 71 |         });
 72 | 
 73 |         httpx.on('data', function (data: string) {
 74 |             output += data.toString();
 75 |         });
 76 | 
 77 |         // Handle process completion
 78 |         return new Promise((resolve, reject) => {
 79 |             httpx.on('close', function (code: number) {
 80 |                 if (code === 0 || typeof code === "undefined") {
 81 |                     output = removeAnsiCodes(output)
 82 |                     const resolveData: any = {
 83 |                         content: [{
 84 |                             type: "text",
 85 |                             text: output
 86 |                         }]
 87 |                     };
 88 |                     resolve(resolveData);
 89 |                 } else {
 90 |                     reject(new Error(`httpx exited with code ${code}`));
 91 |                 }
 92 |             });
 93 |             httpx.on('error', function (error: Error) {
 94 |                 if (typeof error.cause !== "undefined") {
 95 |                     reject(new Error(`Error to start httpx: ${error.cause}`));
 96 |                 }
 97 |             });
 98 |         });
 99 |     },
100 | );
101 | 
102 | function removeAnsiCodes(input: string): string {
103 |     return input.replace(/\x1B\[[0-9;]*m/g, '');
104 | }
105 | 
106 | // Start the server
107 | async function main() {
108 |     const transport = new StdioServerTransport();
109 |     await server.connect(transport);
110 |     console.error("httpx MCP Server running on stdio");
111 | }
112 | 
113 | main().catch((error) => {
114 |     console.error("Fatal error in main():", error);
115 |     process.exit(1);
116 | });
```

--------------------------------------------------------------------------------
/katana-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | const pty = require('node-pty');
  5 | const args = process.argv.slice(2);
  6 | if (args.length === 0) {
  7 |     console.error("Usage: katana-mcp <katana binary>");
  8 |     process.exit(1);
  9 | }
 10 | 
 11 | // Create server instance
 12 | const server = new McpServer({
 13 |     name: "katana",
 14 |     version: "1.0.0",
 15 | });
 16 | 
 17 | server.tool(
 18 |     "do-katana",
 19 |     "Performs fast and configurable web crawling on the given target URLs, identifying endpoints, parameters, and JS-based links.",
 20 |     {
 21 |         target: z.array(z.string()).describe("List of target URLs (e.g., https://example.com) to scan for endpoints and JavaScript-based links."),
 22 |         exclude: z.array(z.string()).optional().describe("List of URLs or regex patterns to exclude from crawling."),
 23 |         depth: z.number().optional().describe("Maximum crawl depth (e.g., 3 for three levels deep)."),
 24 |         js_crawl: z.boolean().optional().describe("Enable crawling and endpoint extraction from JavaScript files."),
 25 |         jsluice: z.boolean().optional().describe("Enable JSluice parsing for deeper JavaScript-based link analysis (memory intensive)."),
 26 |         headers: z.array(z.string()).optional().describe("List of custom headers or cookies to include in requests (format: Header:Value)."),
 27 |         strategy: z.enum(["depth-first", "breadth-first"]).optional().describe("Crawling strategy to use: 'depth-first' or 'breadth-first' (default is depth-first)."),
 28 |         headless: z.boolean().optional().describe("Enable headless browser-based hybrid crawling (experimental)."),
 29 |         system_chrome: z.boolean().optional().describe("Use the locally installed Chrome browser instead of the built-in one."),
 30 |         show_brwoser: z.boolean().optional().describe("Show the browser window even in headless mode (for debugging/visual inspection)."),
 31 |     },
 32 |     async ({ target, exclude, depth, js_crawl, jsluice, headers, strategy, headless, system_chrome, show_brwoser }) => {
 33 |         
 34 |         const katanaArgs = ["-u", target.join(","), "-silent"];
 35 | 
 36 |         if (exclude && exclude.length > 0) {
 37 |             katanaArgs.push("-exclude", exclude.join(","));
 38 |         }
 39 |         if (depth !== undefined) {
 40 |             katanaArgs.push("-d", depth.toString());
 41 |         }
 42 |         if (js_crawl) {
 43 |             katanaArgs.push("-jc");
 44 |         }
 45 |         if (jsluice) {
 46 |             katanaArgs.push("-jsl");
 47 |         }
 48 |         if (headers && headers.length > 0) {
 49 |             headers.forEach(header => katanaArgs.push("-H", header));
 50 |         }
 51 |         if (strategy) {
 52 |             katanaArgs.push("-strategy", strategy);
 53 |         }
 54 |         if (headless) {
 55 |             katanaArgs.push("-headless");
 56 |         }
 57 |         if (system_chrome) {
 58 |             katanaArgs.push("-system-chrome");
 59 |         }
 60 |         if (show_brwoser) {
 61 |             katanaArgs.push("-show-browser");
 62 |         }
 63 |         let output = "";
 64 | 
 65 |         const katana = pty.spawn(args[0], katanaArgs, {
 66 |             name: 'xterm-color',
 67 |             cols: 80,
 68 |             rows: 30,
 69 |             cwd: process.cwd(),
 70 |             env: process.env
 71 |         });
 72 | 
 73 |         katana.on('data', function (data: string) {
 74 |             output += data.toString();
 75 |         });
 76 | 
 77 |         // Handle process completion
 78 |         return new Promise((resolve, reject) => {
 79 |             katana.on('close', function (code: number) {
 80 |                 if (code === 0 || typeof code === "undefined") {
 81 |                     output = removeAnsiCodes(output)
 82 |                     const resolveData: any = {
 83 |                         content: [{
 84 |                             type: "text",
 85 |                             text: output
 86 |                         }]
 87 |                     };
 88 |                     resolve(resolveData);
 89 |                 } else {
 90 |                     reject(new Error(`katana exited with code ${code}`));
 91 |                 }
 92 |             });
 93 |             katana.on('error', function (error: Error) {
 94 |                 if (typeof error.cause !== "undefined") {
 95 |                     reject(new Error(`Error to start katana: ${error.cause}`));
 96 |                 }
 97 |             });
 98 |         });
 99 |     },
100 | );
101 | 
102 | function removeAnsiCodes(input: string): string {
103 |     return input.replace(/\x1B\[[0-9;]*m/g, '');
104 | }
105 | 
106 | // Start the server
107 | async function main() {
108 |     const transport = new StdioServerTransport();
109 |     await server.connect(transport);
110 |     console.error("katana MCP Server running on stdio");
111 | }
112 | 
113 | main().catch((error) => {
114 |     console.error("Fatal error in main():", error);
115 |     process.exit(1);
116 | });
```

--------------------------------------------------------------------------------
/sqlmap-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: sqlmap-mcp <sqlmap binary or python3 sqlmap>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "sqlmap",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-sqlmap",
 20 |     "Run sqlmap with specified URL",
 21 |     {
 22 |         url: z.string().url().describe("Target URL to detect SQL Injection"),
 23 |         sqlmap_args: z.array(z.string()).describe(`Additional SQLmap arguments 
 24 |             
 25 |             -g GOOGLEDORK       Process Google dork results as target URLs
 26 | 
 27 |   Request:
 28 |     These options can be used to specify how to connect to the target URL
 29 | 
 30 |     --data=DATA         Data string to be sent through POST (e.g. "id=1")
 31 |     --cookie=COOKIE     HTTP Cookie header value (e.g. "PHPSESSID=a8d127e..")
 32 |     --random-agent      Use randomly selected HTTP User-Agent header value
 33 |     --proxy=PROXY       Use a proxy to connect to the target URL
 34 |     --tor               Use Tor anonymity network
 35 |     --check-tor         Check to see if Tor is used properly
 36 | 
 37 |   Injection:
 38 |     These options can be used to specify which parameters to test for,
 39 |     provide custom injection payloads and optional tampering scripts
 40 | 
 41 |     -p TESTPARAMETER    Testable parameter(s)
 42 |     --dbms=DBMS         Force back-end DBMS to provided value
 43 | 
 44 |   Detection:
 45 |     These options can be used to customize the detection phase
 46 | 
 47 |     --level=LEVEL       Level of tests to perform (1-5, default 1)
 48 |     --risk=RISK         Risk of tests to perform (1-3, default 1)
 49 | 
 50 |   Techniques:
 51 |     These options can be used to tweak testing of specific SQL injection
 52 |     techniques
 53 | 
 54 |     --technique=TECH..  SQL injection techniques to use (default "BEUSTQ")
 55 | 
 56 |   Enumeration:
 57 |     These options can be used to enumerate the back-end database
 58 |     management system information, structure and data contained in the
 59 |     tables
 60 | 
 61 |     -a, --all           Retrieve everything
 62 |     -b, --banner        Retrieve DBMS banner
 63 |     --current-user      Retrieve DBMS current user
 64 |     --current-db        Retrieve DBMS current database
 65 |     --passwords         Enumerate DBMS users password hashes
 66 |     --dbs               Enumerate DBMS databases
 67 |     --tables            Enumerate DBMS database tables
 68 |     --columns           Enumerate DBMS database table columns
 69 |     --schema            Enumerate DBMS schema
 70 |     --dump              Dump DBMS database table entries
 71 |     --dump-all          Dump all DBMS databases tables entries
 72 |     -D DB               DBMS database to enumerate
 73 |     -T TBL              DBMS database table(s) to enumerate
 74 |     -C COL              DBMS database table column(s) to enumerate
 75 | 
 76 |   Operating system access:
 77 |     These options can be used to access the back-end database management
 78 |     system underlying operating system
 79 | 
 80 |     --os-shell          Prompt for an interactive operating system shell
 81 |     --os-pwn            Prompt for an OOB shell, Meterpreter or VNC
 82 | 
 83 |   General:
 84 |     These options can be used to set some general working parameters
 85 | 
 86 |     --batch             Never ask for user input, use the default behavior
 87 |     --flush-session     Flush session files for current target
 88 | 
 89 |   Miscellaneous:
 90 |     These options do not fit into any other category
 91 | 
 92 |     --wizard            Simple wizard interface for beginner users
 93 |     
 94 |     `),
 95 |     },
 96 |     async ({ url, sqlmap_args }) => {
 97 |         const sqlmap = spawn(args[0], ['-u', url, ...sqlmap_args]);
 98 |         let output = '';
 99 | 
100 |         // Handle stdout
101 |         sqlmap.stdout.on('data', (data) => {
102 |             output += data.toString();
103 |         });
104 | 
105 |         // Handle stderr
106 |         sqlmap.stderr.on('data', (data) => {
107 |             output += data.toString();
108 |         });
109 | 
110 |         // Handle process completion
111 |         return new Promise((resolve, reject) => {
112 |             sqlmap.on('close', (code) => {
113 |                 if (code === 0) {
114 |                     resolve({
115 |                         content: [{
116 |                             type: "text",
117 |                             text: output + "\n sqlmap completed successfully"
118 |                         }]
119 |                     });
120 |                 } else {
121 |                     reject(new Error(`sqlmap exited with code ${code}`));
122 |                 }
123 |             });
124 | 
125 |             sqlmap.on('error', (error) => {
126 |                 reject(new Error(`Failed to start sqlmap: ${error.message}`));
127 |             });
128 |         });
129 |     },
130 | );
131 | 
132 | // Start the server
133 | async function main() {
134 |     const transport = new StdioServerTransport();
135 |     await server.connect(transport);
136 |     console.error("sqlmap MCP Server running on stdio");
137 | }
138 | 
139 | main().catch((error) => {
140 |     console.error("Fatal error in main():", error);
141 |     process.exit(1);
142 | });
```

--------------------------------------------------------------------------------
/mobsf-mcp/src/mobsf.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
  2 | import FormData from 'form-data';
  3 | import fs from 'fs';
  4 | 
  5 | 
  6 | export class MobSFClient {
  7 |   private baseUrl: string;
  8 |   private apiKey: string;
  9 | 
 10 |   constructor(baseUrl: string, apiKey: string) {
 11 |     this.baseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
 12 |     this.apiKey = apiKey;
 13 |   }
 14 | 
 15 |   private createRequestConfig(
 16 |     path: string,
 17 |     method: 'GET' | 'POST' | 'PUT' | 'DELETE' = 'GET',
 18 |     data?: any,
 19 |     headers?: Record<string, string>,
 20 |     params?: Record<string, any>
 21 |   ): AxiosRequestConfig {
 22 |     return {
 23 |       url: `${this.baseUrl}${path}`,
 24 |       method,
 25 |       headers: {
 26 |         'Authorization': this.apiKey,
 27 |         'X-Mobsf-Api-Key': this.apiKey,
 28 |         'Content-Type': 'application/json',
 29 |         ...headers
 30 |       },
 31 |       data,
 32 |       params
 33 |     };
 34 |   }
 35 | 
 36 |   private async sendRequest<T>(config: AxiosRequestConfig): Promise<T> {
 37 |     try {
 38 |       const response: AxiosResponse<T> = await axios(config);
 39 |       return response.data;
 40 |     } catch (error) {
 41 |       if (axios.isAxiosError(error)) {
 42 |         const errorData = error.response?.data ? JSON.stringify(error.response.data, null, 2) : error.message;
 43 |         throw new Error(`MobSF API Error: ${errorData}`);
 44 |       }
 45 |       throw error;
 46 |     }
 47 |   }
 48 | 
 49 |   /**
 50 |   * Upload a file to MobSF for analysis
 51 |   * Supported file types: apk, zip, ipa, and appx
 52 |   * @param filePath Path to the file to upload
 53 |   * @returns Upload response containing file_name, hash, and scan_type
 54 |   */
 55 |   public async uploadFile(filePath: string): Promise<string> {
 56 |     const formData = new FormData();
 57 |     formData.append('file', fs.createReadStream(filePath));
 58 | 
 59 |     // When using FormData, we need to let Axios handle the Content-Type
 60 |     // to ensure proper multipart/form-data boundaries
 61 |     const config: AxiosRequestConfig = {
 62 |       url: `${this.baseUrl}/api/v1/upload`,
 63 |       method: 'POST',
 64 |       headers: {
 65 |         'Authorization': this.apiKey,
 66 |         'X-Mobsf-Api-Key': this.apiKey,
 67 |         ...formData.getHeaders()
 68 |       },
 69 |       data: formData
 70 |     };
 71 | 
 72 |     return this.sendRequest<string>(config);
 73 |   }
 74 | 
 75 |   /**
 76 |    * Scan a file that has already been uploaded to MobSF
 77 |    * @param hash Hash of the file to scan
 78 |    * @param reScan Set to true to force a rescan of the file
 79 |    * @returns Scan results
 80 |    */
 81 |   public async scanFile(hash: string, reScan: boolean = false): Promise<string> {
 82 |     const formData = new URLSearchParams();
 83 |     formData.append('hash', hash);
 84 |     formData.append('re_scan', reScan ? '1' : '0');
 85 | 
 86 |     const config: AxiosRequestConfig = {
 87 |       url: `${this.baseUrl}/api/v1/scan`,
 88 |       method: 'POST',
 89 |       headers: {
 90 |         'Authorization': this.apiKey,
 91 |         'X-Mobsf-Api-Key': this.apiKey,
 92 |         'Content-Type': 'application/x-www-form-urlencoded'
 93 |       },
 94 |       data: formData.toString()
 95 |     };
 96 | 
 97 |     return this.sendRequest<string>(config);
 98 |   }
 99 | 
100 |   /**
101 |  * Get scan logs for a specific file
102 |  * @param hash Hash of the file to get logs for
103 |  * @returns Scan logs as a string
104 |  */
105 |   public async getScanLogs(hash: string): Promise<string> {
106 |     const formData = new URLSearchParams();
107 |     formData.append('hash', hash);
108 | 
109 |     const config: AxiosRequestConfig = {
110 |       url: `${this.baseUrl}/api/v1/scan_logs`,
111 |       method: 'POST',
112 |       headers: {
113 |         'Authorization': this.apiKey,
114 |         'X-Mobsf-Api-Key': this.apiKey,
115 |         'Content-Type': 'application/x-www-form-urlencoded'
116 |       },
117 |       data: formData.toString()
118 |     };
119 | 
120 |     return this.sendRequest<string>(config);
121 |   }
122 |   /**
123 |    * Generate a detailed JSON report for a scanned file
124 |    * @param hash Hash of the file to generate a report for
125 |    * @returns Detailed JSON report
126 |    */
127 |   public async generateJsonReport(hash: string): Promise<string> {
128 |     const formData = new URLSearchParams();
129 |     formData.append('hash', hash);
130 | 
131 |     const config: AxiosRequestConfig = {
132 |       url: `${this.baseUrl}/api/v1/report_json`,
133 |       method: 'POST',
134 |       headers: {
135 |         'Authorization': this.apiKey,
136 |         'X-Mobsf-Api-Key': this.apiKey,
137 |         'Content-Type': 'application/x-www-form-urlencoded'
138 |       },
139 |       data: formData.toString()
140 |     };
141 | 
142 |     return this.sendRequest<string>(config);
143 |   }
144 | 
145 |   /**
146 |    * Get a list of recent scans
147 |    * @param page Page number for pagination
148 |    * @param pageSize Number of items per page
149 |    * @returns List of recent scans with pagination info
150 |    */
151 |   public async getRecentScans(page: number = 1, pageSize: number = 10): Promise<string> {
152 |     const config = this.createRequestConfig(
153 |       '/api/v1/scans',
154 |       'GET',
155 |       undefined,
156 |       {
157 |         'Authorization': this.apiKey,
158 |         'X-Mobsf-Api-Key': this.apiKey
159 |       },
160 |       {
161 |         page,
162 |         page_size: pageSize
163 |       }
164 |     );
165 | 
166 |     return this.sendRequest<string>(config);
167 |   }
168 | }
169 | 
170 | export const createMobSFClient = (baseUrl: string, apiKey: string): MobSFClient => {
171 |   return new MobSFClient(baseUrl, apiKey);
172 | };
```

--------------------------------------------------------------------------------
/mobsf-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { createMobSFClient } from './mobsf';
  5 | 
  6 | // Get command line arguments
  7 | const args = process.argv.slice(2);
  8 | if (args.length < 2) {
  9 |     console.error("Usage: mobfs <baseUrl> <apiKey>");
 10 |     process.exit(1);
 11 | }
 12 | 
 13 | const baseUrl = args[0];
 14 | const apiKey = args[1];
 15 | 
 16 | // Create MobSF client
 17 | const mobsfClient = createMobSFClient(baseUrl, apiKey);
 18 | 
 19 | // Create server instance
 20 | const server = new McpServer({
 21 |     name: "mobsf",
 22 |     version: "1.0.0",
 23 | });
 24 | 
 25 | // Define the scanFile tool
 26 | 
 27 | server.tool(
 28 |     "scanFile",
 29 |     "Scan a file that has already been uploaded to MobSF. This tool analyzes the uploaded mobile application for security vulnerabilities and provides a comprehensive security assessment report.",
 30 |     {
 31 |         hash: z.string().describe("Hash of the file to scan"),
 32 |         reScan: z.boolean().optional().describe("Set to true to force a rescan of the file")
 33 |     },
 34 |     async ({ hash,reScan }) => {
 35 |         // Handle process completion
 36 |         return new Promise((resolve, reject) => {
 37 |             mobsfClient.scanFile(hash,reScan).then(result => {
 38 |                 resolve({
 39 |                     content: [{
 40 |                         type: "text",
 41 |                         text: JSON.stringify(result, null, 2),
 42 |                     }]
 43 |                 });
 44 |             }).catch(error => {
 45 |                 reject(error);
 46 |             });
 47 |         });
 48 |     }
 49 | );
 50 | 
 51 | 
 52 | server.tool(
 53 |     "uploadFile",
 54 |     "Upload a mobile application file (APK, IPA, or APPX) to MobSF for security analysis. This is the first step before scanning and must be done prior to using other analysis functions.",
 55 |     {
 56 |         file: z.string().describe("Upload file path"),
 57 | 
 58 |     },
 59 |     async ({ file }) => {
 60 |         // Handle process completion
 61 |         return new Promise((resolve, reject) => {
 62 |             mobsfClient.uploadFile(file).then(result => {
 63 |                 resolve({
 64 |                     content: [{
 65 |                         type: "text",
 66 |                         text: JSON.stringify(result, null, 2),
 67 |                     }]
 68 |                 });
 69 |             }).catch(error => {
 70 |                 reject(error);
 71 |             });
 72 |         });
 73 |     }
 74 | )
 75 | 
 76 | 
 77 | server.tool(
 78 |     "getScanLogs",
 79 |     "Retrieve detailed scan logs for a previously analyzed mobile application using its hash value. These logs contain information about the scanning process and any issues encountered.",
 80 |     {
 81 |         hash: z.string().describe("Hash file to getting scan logs"),
 82 | 
 83 |     },
 84 |     async ({ hash }) => {
 85 |         // Handle process completion
 86 |         return new Promise((resolve, reject) => {
 87 |             mobsfClient.getScanLogs(hash).then(result => {
 88 |                 resolve({
 89 |                     content: [{
 90 |                         type: "text",
 91 |                         text: JSON.stringify(result, null, 2),
 92 |                     }]
 93 |                 });
 94 |             }).catch(error => {
 95 |                 reject(error);
 96 |             });
 97 |         });
 98 |     }
 99 | )
100 | 
101 | server.tool(
102 |     "getJsonReport",
103 |     "Generate and retrieve a comprehensive security analysis report in JSON format for a scanned mobile application. This report includes detailed findings about security vulnerabilities, permissions, API calls, and other security-relevant information.",
104 |     {
105 |         hash: z.string().describe("Hash file to getting scan logs"),
106 | 
107 |     },
108 |     async ({ hash }) => {
109 |         // Handle process completion
110 |         return new Promise((resolve, reject) => {
111 |             mobsfClient.generateJsonReport(hash).then(result => {
112 |                 resolve({
113 |                     content: [{
114 |                         type: "text",
115 |                         text: JSON.stringify(result, null, 2),
116 |                     }]
117 |                 });
118 |             }).catch(error => {
119 |                 reject(error);
120 |             });
121 |         });
122 |     }
123 | )
124 | 
125 | server.tool(
126 |     "getRecentScans",
127 |     "Retrieve a list of recently performed security scans on the MobSF server, showing mobile applications that have been analyzed, their statuses, and basic scan information.",
128 |     {
129 |         page: z.number().describe("Page number for result"),
130 |         pageSize: z.number().describe("Page size for result"),
131 | 
132 |     },
133 |     async ({ page,pageSize }) => {
134 |         // Handle process completion
135 |         return new Promise((resolve, reject) => {
136 |             mobsfClient.getRecentScans(page,pageSize).then(result => {
137 |                 resolve({
138 |                     content: [{
139 |                         type: "text",
140 |                         text: JSON.stringify(result, null, 2),
141 |                     }]
142 |                 });
143 |             }).catch(error => {
144 |                 reject(error);
145 |             });
146 |         });
147 |     }
148 | )
149 | 
150 | // Start the server
151 | async function main() {
152 |     const transport = new StdioServerTransport();
153 |     await server.connect(transport);
154 |     console.error("mobsf MCP Server running on stdio");
155 | }
156 | 
157 | main().catch((error) => {
158 |     console.error("Fatal error in main():", error);
159 |     process.exit(1);
160 | });
```

--------------------------------------------------------------------------------
/amass-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: amass-mcp <amass binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "amass",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "amass",
 20 |     "Advanced subdomain enumeration and reconnaissance tool",
 21 |     {
 22 |         subcommand: z.enum(["enum", "intel"]).describe(`Specify the Amass operation mode:
 23 |             - intel: Gather intelligence about target domains from various sources
 24 |             - enum: Perform subdomain enumeration and network mapping`),
 25 |         domain: z.string().optional().describe("Target domain to perform reconnaissance against (e.g., example.com)"),
 26 |         intel_whois: z.boolean().optional().describe("Whether to include WHOIS data in intelligence gathering (true/false)"),
 27 |         intel_organization: z.string().optional().describe("Organization name to search for during intelligence gathering (e.g., 'Example Corp')"),
 28 |         enum_type: z.enum(["active", "passive"]).optional().describe(`Enumeration approach type:
 29 |             - active: Includes DNS resolution and potential network interactions with target
 30 |             - passive: Only uses information from third-party sources without direct target interaction`),
 31 |         enum_brute: z.boolean().optional().describe("Whether to perform brute force subdomain discovery (true/false)"),
 32 |         enum_brute_wordlist: z.string().optional().describe("Path to custom wordlist file for brute force operations (e.g., '/path/to/wordlist.txt')")
 33 | 
 34 | 
 35 |     },
 36 |     async ({ subcommand, domain, intel_whois, intel_organization, enum_type, enum_brute, enum_brute_wordlist }) => {
 37 |         const amassCommand = "amass";
 38 |         let amassArgs: string[] = [subcommand];
 39 | 
 40 |         // Handle different subcommands
 41 |         if (subcommand === "enum") {
 42 |             if (!domain) {
 43 |                 throw new Error("Domain parameter is required for 'enum' subcommand");
 44 |             }
 45 | 
 46 |             amassArgs.push("-d", domain);
 47 | 
 48 |             // Handle enum type
 49 |             if (enum_type === "passive") {
 50 |                 amassArgs.push("-passive");
 51 |             } else if (enum_type === "active") {
 52 |                 // Active is default, but can be explicitly specified if needed
 53 |             }
 54 | 
 55 |             // Handle brute force options
 56 |             if (enum_brute === true) {
 57 |                 amassArgs.push("-brute");
 58 | 
 59 |                 // Add custom wordlist if provided
 60 |                 if (enum_brute_wordlist) {
 61 |                     amassArgs.push("-w", enum_brute_wordlist);
 62 |                 }
 63 |             }
 64 |         }
 65 |         else if (subcommand === "intel") {
 66 |             if (!domain && !intel_organization) {
 67 |                 throw new Error("Either domain or organization parameter is required for 'intel' subcommand");
 68 |             }
 69 | 
 70 |             // Add domain if provided
 71 |             if (domain) {
 72 |                 amassArgs.push("-d", domain);
 73 |                 // Add whois option if enabled
 74 |                 if (intel_whois !== true) {
 75 | 
 76 |                     throw new Error("For domain parameter whois is required");
 77 |                     amassArgs.push("-whois");
 78 |                 }
 79 |             }
 80 | 
 81 |             // Add organization if provided
 82 |             if (intel_organization) {
 83 |                 amassArgs.push("-org", "'"+intel_organization+"'");
 84 |             }
 85 |             if (intel_whois === true) {
 86 |                 amassArgs.push("-whois");
 87 |             }
 88 | 
 89 |         }
 90 | 
 91 |         console.log(`Executing: amass ${amassArgs.join(' ')}`);
 92 | 
 93 |         const amass = spawn(amassCommand, amassArgs);
 94 |         let output = '';
 95 | 
 96 |         // Handle stdout
 97 |         amass.stdout.on('data', (data) => {
 98 |             const chunk = data.toString();
 99 |             output += chunk;
100 |         });
101 | 
102 |         // Handle stderr
103 |         amass.stderr.on('data', (data) => {
104 |             const chunk = data.toString();
105 |             output += chunk;
106 |         });
107 | 
108 |         // Handle process completion
109 |         return new Promise((resolve, reject) => {
110 |             amass.on('close', (code) => {
111 |                 if (code === 0) {
112 |                     resolve({
113 |                         content: [{
114 |                             type: "text",
115 |                             text: output
116 |                         }]
117 |                     });
118 |                 } else {
119 |                     reject(new Error(`Amass exited with code ${code}. Output: ${output}. Args:${amassArgs}`));
120 |                 }
121 |             });
122 | 
123 |             amass.on('error', (error) => {
124 |                 reject(new Error(`Failed to start Amass: ${error.message}`));
125 |             });
126 |         });
127 |     },
128 | );
129 | 
130 | // Start the server
131 | async function main() {
132 |     const transport = new StdioServerTransport();
133 |     await server.connect(transport);
134 |     console.error("AMASS MCP Server running on stdio");
135 | }
136 | 
137 | main().catch((error) => {
138 |     console.error("Fatal error in main():", error);
139 |     process.exit(1);
140 | });
```

--------------------------------------------------------------------------------
/sslscan-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: sslscan-mcp <sslscan binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "sslscan",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-sslscan",
 20 |     "Execute SSLScan, a comprehensive SSL/TLS scanner that identifies supported cipher suites, SSL/TLS versions, certificate information, and security vulnerabilities in SSL/TLS configurations of web servers and other services. It helps security professionals assess the security posture of SSL/TLS implementations.",
 21 |     {
 22 |         target: z.string().url().describe("Target URL to scan (must begin with https:// for proper SSL/TLS scanning)"),
 23 |         sslscan_args: z.array(z.string()).describe(`--sni-name=<name>    Hostname for SNI
 24 |   --ipv4, -4           Only use IPv4
 25 |   --ipv6, -6           Only use IPv6
 26 | 
 27 |   --show-certificate   Show full certificate information
 28 |   --show-certificates  Show chain full certificates information
 29 |   --show-client-cas    Show trusted CAs for TLS client auth
 30 |   --no-check-certificate  Don't warn about weak certificate algorithm or keys
 31 |   --ocsp               Request OCSP response from server
 32 |   --pk=<file>          A file containing the private key or a PKCS#12 file
 33 |                        containing a private key/certificate pair
 34 |   --pkpass=<password>  The password for the private  key or PKCS#12 file
 35 |   --certs=<file>       A file containing PEM/ASN1 formatted client certificates
 36 | 
 37 |   --ssl2               Only check if SSLv2 is enabled
 38 |   --ssl3               Only check if SSLv3 is enabled
 39 |   --tls10              Only check TLSv1.0 ciphers
 40 |   --tls11              Only check TLSv1.1 ciphers
 41 |   --tls12              Only check TLSv1.2 ciphers
 42 |   --tls13              Only check TLSv1.3 ciphers
 43 |   --tlsall             Only check TLS ciphers (all versions)
 44 |   --show-ciphers       Show supported client ciphers
 45 |   --show-cipher-ids    Show cipher ids
 46 |   --iana-names         Use IANA/RFC cipher names rather than OpenSSL ones
 47 |   --show-times         Show handhake times in milliseconds
 48 | 
 49 |   --no-cipher-details  Disable EC curve names and EDH/RSA key lengths output
 50 |   --no-ciphersuites    Do not check for supported ciphersuites
 51 |   --no-compression     Do not check for TLS compression (CRIME)
 52 |   --no-fallback        Do not check for TLS Fallback SCSV
 53 |   --no-groups          Do not enumerate key exchange groups
 54 |   --no-heartbleed      Do not check for OpenSSL Heartbleed (CVE-2014-0160)
 55 |   --no-renegotiation   Do not check for TLS renegotiation
 56 |   --show-sigs          Enumerate signature algorithms
 57 | 
 58 |   --starttls-ftp       STARTTLS setup for FTP
 59 |   --starttls-imap      STARTTLS setup for IMAP
 60 |   --starttls-irc       STARTTLS setup for IRC
 61 |   --starttls-ldap      STARTTLS setup for LDAP
 62 |   --starttls-mysql     STARTTLS setup for MYSQL
 63 |   --starttls-pop3      STARTTLS setup for POP3
 64 |   --starttls-psql      STARTTLS setup for PostgreSQL
 65 |   --starttls-smtp      STARTTLS setup for SMTP
 66 |   --starttls-xmpp      STARTTLS setup for XMPP
 67 |   --xmpp-server        Use a server-to-server XMPP handshake
 68 |   --rdp                Send RDP preamble before starting scan
 69 | 
 70 |   --bugs               Enable SSL implementation bug work-arounds
 71 |   --no-colour          Disable coloured output
 72 |   --sleep=<msec>       Pause between connection request. Default is disabled
 73 |   --timeout=<sec>      Set socket timeout. Default is 3s
 74 |   --connect-timeout=<sec>  Set connect timeout. Default is 75s
 75 |   --verbose            Display verbose output
 76 |   --version            Display the program version
 77 |   --xml=<file>         Output results to an XML file. Use - for STDOUT.
 78 | `
 79 |         )
 80 |     },
 81 |     async ({ target, sslscan_args }) => {
 82 | 
 83 |         const sslscan = spawn(args[0], [...sslscan_args, target]);
 84 |         let output = '';
 85 | 
 86 |         // Handle stdout
 87 |         sslscan.stdout.on('data', (data: Buffer) => {
 88 |             output += data.toString();
 89 |         });
 90 | 
 91 |         // Handle stderr
 92 |         sslscan.stderr.on('data', (data) => {
 93 |             output += data.toString();
 94 |         });
 95 | 
 96 |         // Handle process completion
 97 |         return new Promise((resolve, reject) => {
 98 |             sslscan.on('close', (code) => {
 99 |                 if (code === 0) {
100 |                     resolve({
101 |                         content: [{
102 |                             type: "text",
103 |                             text: output + "\n sslscan completed successfully"
104 |                         }]
105 |                     });
106 |                 } else {
107 |                     reject(new Error(`sslscan exited with code ${code}`));
108 |                 }
109 |             });
110 | 
111 |             sslscan.on('error', (error) => {
112 |                 reject(new Error(`Failed to start sslscan: ${error.message}`));
113 |             });
114 |         });
115 |     },
116 | );
117 | 
118 | // Start the server
119 | async function main() {
120 |     const transport = new StdioServerTransport();
121 |     await server.connect(transport);
122 |     console.error("sslscan MCP Server running on stdio");
123 | }
124 | 
125 | main().catch((error) => {
126 |     console.error("Fatal error in main():", error);
127 |     process.exit(1);
128 | });
```

--------------------------------------------------------------------------------
/wpscan-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: wpscan-mcp <wpscan binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "wpscan",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-wpscan",
 20 |     "Run wpscan to analyze wordpress web sites",
 21 |     {
 22 |         url: z.string().url().describe("The target WordPress website URL to scan. Must be a valid URL starting with http:// or https://"),
 23 |         detection_mode: z.enum(["mixed", "passive", "aggressive"]).optional().describe("Scan detection mode: 'mixed' (default) combines passive and aggressive, 'passive' for non-intrusive scanning, 'aggressive' for thorough but potentially detectable scanning"),
 24 |         random_user_agent: z.boolean().optional().describe("Enable random user agent rotation for each request to avoid detection"),
 25 |         max_threads: z.number().optional().describe("Maximum number of concurrent scanning threads. Default is 5. Higher values increase speed but may trigger rate limiting"),
 26 |         disable_tls_checks: z.boolean().optional().describe("Disable SSL/TLS certificate verification and allow TLS 1.0+ connections. Requires cURL 7.66 or higher for TLS downgrade support"),
 27 |         proxy: z.string().optional().describe("Proxy server to route requests through. Format: protocol://IP:port (e.g., http://127.0.0.1:8080). Supported protocols depend on installed cURL version"),
 28 |         cookies: z.string().optional().describe("Custom cookies to include in requests. Format: name1=value1; name2=value2. Useful for authenticated scanning"),
 29 |         force: z.boolean().optional().describe("Skip WordPress detection and 403 response checks. Use when you're certain the target is WordPress"),
 30 |         enumerate: z.array(z.enum(["vp", "ap", "p", "vt", "at", "t", "tt", "cb", "dbe"])).describe(`
 31 |             WordPress enumeration options:
 32 |             - vp: Scan for vulnerable plugins
 33 |             - ap: Scan all installed plugins
 34 |             - p:  Scan only popular plugins
 35 |             - vt: Scan for vulnerable themes
 36 |             - at: Scan all installed themes
 37 |             - t:  Scan only popular themes
 38 |             - tt: Scan for timthumb vulnerabilities
 39 |             - cb: Scan for configuration backups
 40 |             - dbe: Scan for database exports
 41 | 
 42 |             Note: Some options are mutually exclusive:
 43 |             - Only one of vp, ap, p can be used
 44 |             - Only one of vt, at, t can be used
 45 | 
 46 |             Default behavior if not specified: vp,vt,tt,cb,dbe,u,m
 47 |             `),
 48 |     },
 49 |     async ({ url,detection_mode,random_user_agent,max_threads,disable_tls_checks,proxy,cookies,force,enumerate }) => {
 50 |         const wpscanArgs = ['-u', url];
 51 | 
 52 |         // Add detection mode if specified
 53 |         if (detection_mode) {
 54 |             wpscanArgs.push('--detection-mode', detection_mode);
 55 |         }
 56 | 
 57 |         // Add random user agent if specified
 58 |         if (random_user_agent) {
 59 |             wpscanArgs.push('--random-user-agent');
 60 |         }
 61 | 
 62 |         // Add max threads if specified
 63 |         if (max_threads) {
 64 |             wpscanArgs.push('-t', max_threads.toString());
 65 |         }
 66 | 
 67 |         // Add disable TLS checks if specified
 68 |         if (disable_tls_checks) {
 69 |             wpscanArgs.push('--disable-tls-checks');
 70 |         }
 71 | 
 72 |         // Add proxy if specified
 73 |         if (proxy) {
 74 |             wpscanArgs.push('--proxy', proxy);
 75 |         }
 76 | 
 77 |         // Add cookies if specified
 78 |         if (cookies) {
 79 |             wpscanArgs.push('--cookie-string', cookies);
 80 |         }
 81 | 
 82 |         // Add force if specified
 83 |         if (force) {
 84 |             wpscanArgs.push('--force');
 85 |         }
 86 | 
 87 |         // Add enumerate options if specified
 88 |         if (enumerate && enumerate.length > 0) {
 89 |             wpscanArgs.push('-e', enumerate.join(','));
 90 |         }
 91 | 
 92 | 
 93 |         const wpscan = spawn(args[0], wpscanArgs);
 94 |         let output = '';
 95 | 
 96 |         // Handle stdout
 97 |         wpscan.stdout.on('data', (data) => {
 98 |             output += data.toString();
 99 |         });
100 | 
101 |         // Handle stderr
102 |         wpscan.stderr.on('data', (data) => {
103 |             output += data.toString();
104 |         });
105 | 
106 |         // Handle process completion
107 |         return new Promise((resolve, reject) => {
108 |             wpscan.on('close', (code) => {
109 |                 if (code === 0) {
110 |                     resolve({
111 |                         content: [{
112 |                             type: "text",
113 |                             text: output + "\n wpscan completed successfully"
114 |                         }]
115 |                     });
116 |                 } else {
117 |                     reject(new Error(`wpscan exited with code ${code}`));
118 |                 }
119 |             });
120 | 
121 |             wpscan.on('error', (error) => {
122 |                 reject(new Error(`Failed to start wpscan: ${error.message}`));
123 |             });
124 |         });
125 |     },
126 | );
127 | 
128 | // Start the server
129 | async function main() {
130 |     const transport = new StdioServerTransport();
131 |     await server.connect(transport);
132 |     console.error("wpscan MCP Server running on stdio");
133 | }
134 | 
135 | main().catch((error) => {
136 |     console.error("Fatal error in main():", error);
137 |     process.exit(1);
138 | });
```

--------------------------------------------------------------------------------
/scoutsuite-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | const { getFindingsFromScoutSuite, extractReportJsPath } = require('./parser');
  4 | const z = require('zod');
  5 | const pty = require('node-pty');
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: scoutsuite-mcp <scoutsuite binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "scoutsuite",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-scoutsuite-aws",
 20 |     "Performs an AWS cloud security audit using Scout Suite for the given target settings, allowing service/region filtering and multiple authentication methods.",
 21 |     {
 22 |         full_report: z.boolean().default(false).optional().describe(""),
 23 |         max_workers: z.number().optional().describe("Maximum number of parallel worker threads used by Scout Suite (default: 10)"),
 24 |         services: z.array(z.string()).optional().describe("A list of AWS service names to include in scope (default: all services)"),
 25 |         skip_services: z.array(z.string()).optional().describe("A list of AWS service names to exclude from scope"),
 26 |         profile: z.string().optional().describe("Use a named AWS CLI profile for authentication"),
 27 |         acces_keys: z.string().optional().describe("Run using access keys instead of profile (use access_key_id, secret_access_key, and optionally session_token)"),
 28 |         access_key_id: z.string().optional().describe("AWS Access Key ID used for authentication"),
 29 |         secret_acces_key: z.string().optional().describe("AWS Secret Access Key used for authentication"),
 30 |         session_token: z.string().optional().describe("Temporary AWS session token (if using temporary credentials)"),
 31 |         regions: z.string().optional().describe("Comma-separated list of AWS regions to include in the scan (default: all regions)"),
 32 |         exclude_regions: z.string().optional().describe("Comma-separated list of AWS regions to exclude from the scan"),
 33 |         ip_ranges: z.string().optional().describe("Path to JSON file(s) containing known IP ranges to match findings against"),
 34 |         ip_ranges_name_key: z.string().optional().describe("Key in the IP ranges file that maps to the display name of a known CIDR")
 35 |     },
 36 |     async ({ full_report, max_workers, services, skip_services, profile, acces_keys, access_key_id, secret_acces_key, session_token, regions, exclude_regions, ip_ranges, ip_ranges_name_key }) => {
 37 | 
 38 |         const scoutSuiteArgs = ["aws", "--force", "--no-browser"];
 39 | 
 40 |         if (max_workers) scoutSuiteArgs.push("--max-workers", max_workers.toString());
 41 |         if (services?.length) {
 42 |             scoutSuiteArgs.push("--services");
 43 |             for (var i = 0; i < services.length; i++) {
 44 |                 scoutSuiteArgs.push(services[i])
 45 |             }
 46 |         }
 47 | 
 48 |         if (skip_services?.length) {
 49 |             scoutSuiteArgs.push("--skip");
 50 |             for (var i = 0; i < skip_services.length; i++) {
 51 |                 scoutSuiteArgs.push(skip_services[i])
 52 |             }
 53 |         }
 54 |         if (profile) scoutSuiteArgs.push("--profile", profile);
 55 |         if (acces_keys) scoutSuiteArgs.push("--access-keys"); // This is a flag, presence indicates manual credentials
 56 |         if (access_key_id) scoutSuiteArgs.push("--access-key-id", access_key_id);
 57 |         if (secret_acces_key) scoutSuiteArgs.push("--secret-access-key", secret_acces_key);
 58 |         if (session_token) scoutSuiteArgs.push("--session-token", session_token);
 59 |         if (regions) scoutSuiteArgs.push("--regions", regions);
 60 |         if (exclude_regions) scoutSuiteArgs.push("--exclude-regions", exclude_regions);
 61 |         if (ip_ranges) scoutSuiteArgs.push("--ip-ranges", ip_ranges);
 62 |         if (ip_ranges_name_key) scoutSuiteArgs.push("--ip-ranges-name-key", ip_ranges_name_key);
 63 | 
 64 |         let output = "";
 65 | 
 66 | 
 67 |         const scoutSuite = pty.spawn(args[0], scoutSuiteArgs, {
 68 |             name: 'xterm-color',
 69 |             cols: 80,
 70 |             rows: 30,
 71 |             cwd: process.cwd(),
 72 |             env: process.env
 73 |         });
 74 | 
 75 |         scoutSuite.on('data', function (data: string) {
 76 |             output += data.toString();
 77 |         });
 78 | 
 79 |         // Handle process completion
 80 |         return new Promise((resolve, reject) => {
 81 |             scoutSuite.on('close', function (code: number) {
 82 |                 if (code === 0 || typeof code === "undefined") {
 83 |                     let findings = getFindingsFromScoutSuite(extractReportJsPath(output), full_report)
 84 | 
 85 |                     const resolveData: any = {
 86 |                         content: [{
 87 |                             type: "text",
 88 |                             text: JSON.stringify(findings, null, 2)
 89 |                         }]
 90 |                     };
 91 |                     resolve(resolveData);
 92 |                 } else {
 93 |                     reject(new Error(`scoutsuite exited with code ${code}`));
 94 |                 }
 95 |             });
 96 |             scoutSuite.on('error', function (error: Error) {
 97 |                 if (typeof error.cause !== "undefined") {
 98 |                     reject(new Error(`Error to start scoutsuite: ${error.cause}`));
 99 |                 }
100 |             });
101 |         });
102 |     },
103 | );
104 | 
105 | // Start the server
106 | async function main() {
107 |     const transport = new StdioServerTransport();
108 |     await server.connect(transport);
109 |     console.error("scoutsuite MCP Server running on stdio");
110 | }
111 | 
112 | main().catch((error) => {
113 |     console.error("Fatal error in main():", error);
114 |     process.exit(1);
115 | });
```

--------------------------------------------------------------------------------
/nmap-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: nmap <nmap binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "nmap",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-nmap",
 20 |     "Run nmap with specified taget",
 21 |     {
 22 |         target: z.string().describe("Target ip to detect open ports"),
 23 |         nmap_args: z.array(z.string()).describe(`Additional nmap arguments 
 24 |             TARGET SPECIFICATION:
 25 |   Can pass hostnames, IP addresses, networks, etc.
 26 |   Ex: scanme.nmap.org, microsoft.com/24, 192.168.0.1; 10.0.0-255.1-254
 27 |   -iL <inputfilename>: Input from list of hosts/networks
 28 |   -iR <num hosts>: Choose random targets
 29 |   --exclude <host1[,host2][,host3],...>: Exclude hosts/networks
 30 |   --excludefile <exclude_file>: Exclude list from file
 31 | HOST DISCOVERY:
 32 |   -sL: List Scan - simply list targets to scan
 33 |   -sn: Ping Scan - disable port scan
 34 |   -Pn: Treat all hosts as online -- skip host discovery
 35 |   -PS/PA/PU/PY[portlist]: TCP SYN, TCP ACK, UDP or SCTP discovery to given ports
 36 |   -PE/PP/PM: ICMP echo, timestamp, and netmask request discovery probes
 37 |   -PO[protocol list]: IP Protocol Ping
 38 |   -n/-R: Never do DNS resolution/Always resolve [default: sometimes]
 39 |   --dns-servers <serv1[,serv2],...>: Specify custom DNS servers
 40 |   --system-dns: Use OS's DNS resolver
 41 |   --traceroute: Trace hop path to each host
 42 | SCAN TECHNIQUES:
 43 |   -sS/sT/sA/sW/sM: TCP SYN/Connect()/ACK/Window/Maimon scans
 44 |   -sU: UDP Scan
 45 |   -sN/sF/sX: TCP Null, FIN, and Xmas scans
 46 |   --scanflags <flags>: Customize TCP scan flags
 47 |   -sI <zombie host[:probeport]>: Idle scan
 48 |   -sY/sZ: SCTP INIT/COOKIE-ECHO scans
 49 |   -sO: IP protocol scan
 50 |   -b <FTP relay host>: FTP bounce scan
 51 | PORT SPECIFICATION AND SCAN ORDER:
 52 |   -p <port ranges>: Only scan specified ports
 53 |     Ex: -p22; -p1-65535; -p U:53,111,137,T:21-25,80,139,8080,S:9
 54 |   --exclude-ports <port ranges>: Exclude the specified ports from scanning
 55 |   -F: Fast mode - Scan fewer ports than the default scan
 56 |   -r: Scan ports sequentially - don't randomize
 57 |   --top-ports <number>: Scan <number> most common ports
 58 |   --port-ratio <ratio>: Scan ports more common than <ratio>
 59 | SERVICE/VERSION DETECTION:
 60 |   -sV: Probe open ports to determine service/version info
 61 |   --version-intensity <level>: Set from 0 (light) to 9 (try all probes)
 62 |   --version-light: Limit to most likely probes (intensity 2)
 63 |   --version-all: Try every single probe (intensity 9)
 64 |   --version-trace: Show detailed version scan activity (for debugging)
 65 | SCRIPT SCAN:
 66 |   -sC: equivalent to --script=default
 67 |   --script=<Lua scripts>: <Lua scripts> is a comma separated list of
 68 |            directories, script-files or script-categories
 69 |   --script-args=<n1=v1,[n2=v2,...]>: provide arguments to scripts
 70 |   --script-args-file=filename: provide NSE script args in a file
 71 |   --script-trace: Show all data sent and received
 72 |   --script-updatedb: Update the script database.
 73 |   --script-help=<Lua scripts>: Show help about scripts.
 74 |            <Lua scripts> is a comma-separated list of script-files or
 75 |            script-categories.
 76 | OS DETECTION:
 77 |   -O: Enable OS detection
 78 |   --osscan-limit: Limit OS detection to promising targets
 79 |   --osscan-guess: Guess OS more aggressively
 80 | TIMING AND PERFORMANCE:
 81 |   Options which take <time> are in seconds, or append 'ms' (milliseconds),
 82 |   's' (seconds), 'm' (minutes), or 'h' (hours) to the value (e.g. 30m).
 83 |   -T<0-5>: Set timing template (higher is faster)
 84 |   --min-hostgroup/max-hostgroup <size>: Parallel host scan group sizes
 85 |   --min-parallelism/max-parallelism <numprobes>: Probe parallelization
 86 |   --min-rtt-timeout/max-rtt-timeout/initial-rtt-timeout <time>: Specifies
 87 |       probe round trip time.
 88 |   --max-retries <tries>: Caps number of port scan probe retransmissions.
 89 |   --host-timeout <time>: Give up on target after this long
 90 |   --scan-delay/--max-scan-delay <time>: Adjust delay between probes
 91 |   --min-rate <number>: Send packets no slower than <number> per second
 92 |   --max-rate <number>: Send packets no faster than <number> per second
 93 | FIREWALL/IDS EVASION AND SPOOFING:
 94 |   -f; --mtu <val>: fragment packets (optionally w/given MTU)
 95 |   -D <decoy1,decoy2[,ME],...>: Cloak a scan with decoys
 96 |   -S <IP_Address>: Spoof source address
 97 |   -e <iface>: Use specified interface
 98 |   -g/--source-port <portnum>: Use given port number
 99 |   --proxies <url1,[url2],...>: Relay connections through HTTP/SOCKS4 proxies
100 |   --data <hex string>: Append a custom payload to sent packets
101 |   --data-string <string>: Append a custom ASCII string to sent packets
102 |   --data-length <num>: Append random data to sent packets
103 |   --ip-options <options>: Send packets with specified ip options
104 |   --ttl <val>: Set IP time-to-live field
105 |   --spoof-mac <mac address/prefix/vendor name>: Spoof your MAC address
106 |   --badsum: Send packets with a bogus TCP/UDP/SCTP checksum
107 | OUTPUT:
108 |   -oN/-oX/-oS/-oG <file>: Output scan in normal, XML, s|<rIpt kIddi3,
109 |      and Grepable format, respectively, to the given filename.
110 |   -oA <basename>: Output in the three major formats at once
111 |   -v: Increase verbosity level (use -vv or more for greater effect)
112 |   -d: Increase debugging level (use -dd or more for greater effect)
113 |   --reason: Display the reason a port is in a particular state
114 |   --open: Only show open (or possibly open) ports
115 |   --packet-trace: Show all packets sent and received
116 |   --iflist: Print host interfaces and routes (for debugging)
117 |   --append-output: Append to rather than clobber specified output files
118 |   --resume <filename>: Resume an aborted scan
119 |   --noninteractive: Disable runtime interactions via keyboard
120 |   --stylesheet <path/URL>: XSL stylesheet to transform XML output to HTML
121 |   --webxml: Reference stylesheet from Nmap.Org for more portable XML
122 |   --no-stylesheet: Prevent associating of XSL stylesheet w/XML output
123 | MISC:
124 |   -6: Enable IPv6 scanning
125 |   -A: Enable OS detection, version detection, script scanning, and traceroute
126 |   --datadir <dirname>: Specify custom Nmap data file location
127 |   --send-eth/--send-ip: Send using raw ethernet frames or IP packets
128 |   --privileged: Assume that the user is fully privileged
129 |   --unprivileged: Assume the user lacks raw socket privileges
130 |   -V: Print version number
131 |   -h: Print this help summary page.
132 |     `),
133 |     },
134 |     async ({ target, nmap_args }) => {
135 |         const nmap = spawn(args[0], [...nmap_args,target]);
136 |         let output = '';
137 | 
138 |         // Handle stdout
139 |         nmap.stdout.on('data', (data) => {
140 |             output += data.toString();
141 |         });
142 | 
143 |         // Handle stderr
144 |         nmap.stderr.on('data', (data) => {
145 |             output += data.toString();
146 |         });
147 | 
148 |         // Handle process completion
149 |         return new Promise((resolve, reject) => {
150 |             nmap.on('close', (code) => {
151 |                 if (code === 0) {
152 |                     resolve({
153 |                         content: [{
154 |                             type: "text",
155 |                             text: output + "\n nmap completed successfully"
156 |                         }]
157 |                     });
158 |                 } else {
159 |                     reject(new Error(`nmap exited with code ${code}`));
160 |                 }
161 |             });
162 | 
163 |             nmap.on('error', (error) => {
164 |                 reject(new Error(`Failed to start nmap: ${error.message}`));
165 |             });
166 |         });
167 |     },
168 | );
169 | 
170 | // Start the server
171 | async function main() {
172 |     const transport = new StdioServerTransport();
173 |     await server.connect(transport);
174 |     console.error("nmap MCP Server running on stdio");
175 | }
176 | 
177 | main().catch((error) => {
178 |     console.error("Fatal error in main():", error);
179 |     process.exit(1);
180 | });
```

--------------------------------------------------------------------------------
/ffuf-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from 'child_process';
  5 | 
  6 | const args = process.argv.slice(2);
  7 | if (args.length === 0) {
  8 |     console.error("Usage: ffuf-mcp <ffuf binary>");
  9 |     process.exit(1);
 10 | }
 11 | 
 12 | // Create server instance
 13 | const server = new McpServer({
 14 |     name: "ffuf",
 15 |     version: "1.0.0",
 16 | });
 17 | 
 18 | server.tool(
 19 |     "do-ffuf",
 20 |     "Run ffuf with specified URL",
 21 |     {
 22 |         url: z.string().url().describe("Target URL to fuzz"),
 23 |         ffuf_args: z.array(z.string()).describe(`Additional ffuf arguments 
 24 |  HTTP OPTIONS:
 25 |   -H                  Header \`"Name: Value"\`, separated by colon. Multiple -H flags are accepted.
 26 |   -X                  HTTP method to use
 27 |   -b                  Cookie data \`"NAME1=VALUE1; NAME2=VALUE2"\` for copy as curl functionality.
 28 |   -cc                 Client cert for authentication. Client key needs to be defined as well for this to work
 29 |   -ck                 Client key for authentication. Client certificate needs to be defined as well for this to work
 30 |   -d                  POST data
 31 |   -http2              Use HTTP2 protocol (default: false)
 32 |   -ignore-body        Do not fetch the response content. (default: false)
 33 |   -r                  Follow redirects (default: false)
 34 |   -raw                Do not encode URI (default: false)
 35 |   -recursion          Scan recursively. Only FUZZ keyword is supported, and URL (-u) has to end in it. (default: false)
 36 |   -recursion-depth    Maximum recursion depth. (default: 0)
 37 |   -recursion-strategy Recursion strategy: "default" for a redirect based, and "greedy" to recurse on all matches (default: default)
 38 |   -replay-proxy       Replay matched requests using this proxy.
 39 |   -sni                Target TLS SNI, does not support FUZZ keyword
 40 |   -timeout            HTTP request timeout in seconds. (default: 10)
 41 |   -u                  Target URL
 42 |   -x                  Proxy URL (SOCKS5 or HTTP). For example: http://127.0.0.1:8080 or socks5://127.0.0.1:8080
 43 | 
 44 | GENERAL OPTIONS:
 45 |   -V                  Show version information. (default: false)
 46 |   -ac                 Automatically calibrate filtering options (default: false)
 47 |   -acc                Custom auto-calibration string. Can be used multiple times. Implies -ac
 48 |   -ach                Per host autocalibration (default: false)
 49 |   -ack                Autocalibration keyword (default: FUZZ)
 50 |   -acs                Custom auto-calibration strategies. Can be used multiple times. Implies -ac
 51 |   -c                  Colorize output. (default: false)
 52 |   -config             Load configuration from a file
 53 |   -json               JSON output, printing newline-delimited JSON records (default: false)
 54 |   -maxtime            Maximum running time in seconds for entire process. (default: 0)
 55 |   -maxtime-job        Maximum running time in seconds per job. (default: 0)
 56 |   -noninteractive     Disable the interactive console functionality (default: false)
 57 |   -p                  Seconds of \`delay\` between requests, or a range of random delay. For example "0.1" or "0.1-2.0"
 58 |   -rate               Rate of requests per second (default: 0)
 59 |   -s                  Do not print additional information (silent mode) (default: false)
 60 |   -sa                 Stop on all error cases. Implies -sf and -se. (default: false)
 61 |   -scraperfile        Custom scraper file path
 62 |   -scrapers           Active scraper groups (default: all)
 63 |   -se                 Stop on spurious errors (default: false)
 64 |   -search             Search for a FFUFHASH payload from ffuf history
 65 |   -sf                 Stop when > 95% of responses return 403 Forbidden (default: false)
 66 |   -t                  Number of concurrent threads. (default: 40)
 67 |   -v                  Verbose output, printing full URL and redirect location (if any) with the results. (default: false)
 68 | 
 69 | MATCHER OPTIONS:
 70 |   -mc                 Match HTTP status codes, or "all" for everything. (default: 200-299,301,302,307,401,403,405,500)
 71 |   -ml                 Match amount of lines in response
 72 |   -mmode              Matcher set operator. Either of: and, or (default: or)
 73 |   -mr                 Match regexp
 74 |   -ms                 Match HTTP response size
 75 |   -mt                 Match how many milliseconds to the first response byte, either greater or less than. EG: >100 or <100
 76 |   -mw                 Match amount of words in response
 77 | 
 78 | FILTER OPTIONS:
 79 |   -fc                 Filter HTTP status codes from response. Comma separated list of codes and ranges
 80 |   -fl                 Filter by amount of lines in response. Comma separated list of line counts and ranges
 81 |   -fmode              Filter set operator. Either of: and, or (default: or)
 82 |   -fr                 Filter regexp
 83 |   -fs                 Filter HTTP response size. Comma separated list of sizes and ranges
 84 |   -ft                 Filter by number of milliseconds to the first response byte, either greater or less than. EG: >100 or <100
 85 |   -fw                 Filter by amount of words in response. Comma separated list of word counts and ranges
 86 | 
 87 | INPUT OPTIONS:
 88 |   -D                  DirSearch wordlist compatibility mode. Used in conjunction with -e flag. (default: false)
 89 |   -e                  Comma separated list of extensions. Extends FUZZ keyword.
 90 |   -enc                Encoders for keywords, eg. 'FUZZ:urlencode b64encode'
 91 |   -ic                 Ignore wordlist comments (default: false)
 92 |   -input-cmd          Command producing the input. --input-num is required when using this input method. Overrides -w.
 93 |   -input-num          Number of inputs to test. Used in conjunction with --input-cmd. (default: 100)
 94 |   -input-shell        Shell to be used for running command
 95 |   -mode               Multi-wordlist operation mode. Available modes: clusterbomb, pitchfork, sniper (default: clusterbomb)
 96 |   -request            File containing the raw http request
 97 |   -request-proto      Protocol to use along with raw request (default: https)
 98 |   -w                  Wordlist file path and (optional) keyword separated by colon. eg. '/path/to/wordlist:KEYWORD'
 99 | 
100 | OUTPUT OPTIONS:
101 |   -debug-log          Write all of the internal logging to the specified file.
102 |   -o                  Write output to file
103 |   -od                 Directory path to store matched results to.
104 |   -of                 Output file format. Available formats: json, ejson, html, md, csv, ecsv (or, 'all' for all formats) (default: json)
105 |   -or                 Don't create the output file if we don't have results (default: false)
106 |     `),
107 |     },
108 |     async ({ url, ffuf_args }) => {
109 |         const ffuf = spawn(args[0], ['-u', url, ...ffuf_args]);
110 |         let output = '';
111 | 
112 |         // Handle stdout
113 |         ffuf.stdout.on('data', (data) => {
114 |             output += data.toString();
115 |         });
116 | 
117 |         // Handle stderr
118 |         ffuf.stderr.on('data', (data) => {
119 |             output += data.toString();
120 |         });
121 | 
122 |         // Handle process completion
123 |         return new Promise((resolve, reject) => {
124 |             ffuf.on('close', (code) => {
125 |                 if (code === 0) {
126 |                     resolve({
127 |                         content: [{
128 |                             type: "text",
129 |                             text: output + "\n ffuf completed successfully"
130 |                         }]
131 |                     });
132 |                 } else {
133 |                     reject(new Error(`ffuf exited with code ${code}`));
134 |                 }
135 |             });
136 | 
137 |             ffuf.on('error', (error) => {
138 |                 reject(new Error(`Failed to start ffuf: ${error.message}`));
139 |             });
140 |         });
141 |     },
142 | );
143 | 
144 | // Start the server
145 | async function main() {
146 |     const transport = new StdioServerTransport();
147 |     await server.connect(transport);
148 |     console.error("ffuf MCP Server running on stdio");
149 | }
150 | 
151 | main().catch((error) => {
152 |     console.error("Fatal error in main():", error);
153 |     process.exit(1);
154 | });
```

--------------------------------------------------------------------------------
/gowitness-mcp/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
  2 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  3 | import { z } from "zod";
  4 | import { spawn } from "child_process";
  5 | import { readFile, access, readdir, writeFile, unlink, stat } from "fs/promises";
  6 | import { join } from "path";
  7 | 
  8 | // Get gowitness binary path
  9 | const args = process.argv.slice(2);
 10 | if (args.length === 0) {
 11 |     console.error("Usage: gowitness-mcp <gowitness binary>");
 12 |     process.exit(1);
 13 | }
 14 | 
 15 | const gowitnessPath = args[0];
 16 | 
 17 | // Create MCP Server
 18 | const server = new McpServer({
 19 |     name: "gowitness",
 20 |     version: "1.0.0",
 21 | });
 22 | 
 23 | // Tool: Enhanced 'screenshot' mode with binary return option
 24 | server.tool(
 25 |     "gowitness-screenshot",
 26 |     "Capture screenshot of the given URL using gowitness scan single. Can save to directory or return as binary data.",
 27 |     {
 28 |         url: z.string().url().describe("URL to take a screenshot of"),
 29 |         chrome_window_x: z.number().optional().describe("Chrome browser window width in pixels (default 1920)"),
 30 |         chrome_window_y: z.number().optional().describe("Chrome browser window height in pixels (default 1080)"),
 31 |         screenshot_path: z.string().optional().describe("Path to store screenshots (default ./screenshots)"),
 32 |         return_binary: z.boolean().optional().describe("If true, return screenshot as binary array instead of saving"),
 33 |         timeout: z.number().optional().describe("Number of seconds before considering a page timed out (default 60)"),
 34 |         delay: z.number().optional().describe("Number of seconds delay between navigation and screenshotting (default 3)"),
 35 |         fullpage: z.boolean().optional().describe("Do full-page screenshots, instead of just the viewport"),
 36 |         format: z.enum(["jpeg", "png"]).optional().describe("Screenshot format (default jpeg)"),
 37 |         threads: z.number().optional().describe("Number of concurrent threads (default 6)"),
 38 |         write_db: z.boolean().optional().describe("Write results to SQLite database"),
 39 |         write_jsonl: z.boolean().optional().describe("Write results as JSON lines"),
 40 |         user_agent: z.string().optional().describe("Custom user-agent string")
 41 |     },
 42 |     async ({ 
 43 |         url, 
 44 |         chrome_window_x, 
 45 |         chrome_window_y, 
 46 |         screenshot_path, 
 47 |         return_binary = false, 
 48 |         timeout, 
 49 |         delay, 
 50 |         fullpage, 
 51 |         format, 
 52 |         threads, 
 53 |         write_db, 
 54 |         write_jsonl,
 55 |         user_agent
 56 |     }: {
 57 |         url: string;
 58 |         chrome_window_x?: number;
 59 |         chrome_window_y?: number;
 60 |         screenshot_path?: string;
 61 |         return_binary?: boolean;
 62 |         timeout?: number;
 63 |         delay?: number;
 64 |         fullpage?: boolean;
 65 |         format?: "jpeg" | "png";
 66 |         threads?: number;
 67 |         write_db?: boolean;
 68 |         write_jsonl?: boolean;
 69 |         user_agent?: string;
 70 |     }) => {
 71 |         const args = ["scan", "single", "--url", url];
 72 | 
 73 |         // Add gowitness-specific parameters
 74 |         if (chrome_window_x) args.push("--chrome-window-x", chrome_window_x.toString());
 75 |         if (chrome_window_y) args.push("--chrome-window-y", chrome_window_y.toString());
 76 |         if (screenshot_path) args.push("--screenshot-path", screenshot_path);
 77 |         if (timeout) args.push("--timeout", timeout.toString());
 78 |         if (delay) args.push("--delay", delay.toString());
 79 |         if (fullpage) args.push("--screenshot-fullpage");
 80 |         if (format) args.push("--screenshot-format", format);
 81 |         if (threads) args.push("--threads", threads.toString());
 82 |         if (write_db) args.push("--write-db");
 83 |         if (write_jsonl) args.push("--write-jsonl");
 84 |         if (user_agent) args.push("--chrome-user-agent", user_agent);
 85 |         
 86 |         // Add default writer to avoid warnings if none specified
 87 |         if (!write_db && !write_jsonl) {
 88 |             args.push("--write-none");
 89 |         }
 90 | 
 91 |         const proc = spawn(gowitnessPath, args);
 92 |         let output = "";
 93 | 
 94 |         proc.stdout.on("data", (data) => {
 95 |             output += data.toString();
 96 |         });
 97 | 
 98 |         proc.stderr.on("data", (data) => {
 99 |             output += data.toString();
100 |         });
101 | 
102 |         return new Promise(async (resolve, reject) => {
103 |             proc.on("close", async (code) => {
104 |                 if (code === 0) {
105 |                 if (return_binary) {
106 |                     try {
107 |                         // gowitness creates files in the screenshot path directory
108 |                         const screenshotDir = screenshot_path || "./screenshots";
109 |                         const files = await readdir(screenshotDir);
110 |                         
111 |                         // First try to find exact match with hostname
112 |                         let screenshotFile = files.find(file => 
113 |                             (file.endsWith('.jpeg') || file.endsWith('.png') || file.endsWith('.jpg')) && 
114 |                             file.includes(getHostnameFromUrl(url))
115 |                         );
116 |                         
117 |                         // If not found, try partial domain matching
118 |                         if (!screenshotFile) {
119 |                             const hostname = getHostnameFromUrl(url);
120 |                             const domainParts = hostname.split('_').filter(part => part.length > 0);
121 |                             
122 |                             screenshotFile = files.find(file => 
123 |                                 (file.endsWith('.jpeg') || file.endsWith('.png') || file.endsWith('.jpg')) && 
124 |                                 domainParts.some(part => file.includes(part))
125 |                             );
126 |                         }
127 |                         
128 |                         // If still not found, take the most recently created screenshot
129 |                         if (!screenshotFile) {
130 |                             const imageFiles = files.filter(file => 
131 |                                 file.endsWith('.jpeg') || file.endsWith('.png') || file.endsWith('.jpg')
132 |                             );
133 |                             
134 |                             if (imageFiles.length > 0) {
135 |                                 // Sort by creation time and take the most recent one
136 |                                 screenshotFile = imageFiles[imageFiles.length - 1];
137 |                             }
138 |                         }
139 |                         
140 |                         if (!screenshotFile) {
141 |                             reject(new Error("Screenshot file not found after gowitness execution"));
142 |                             return;
143 |                         }
144 | 
145 |                         const screenshotPath = join(screenshotDir, screenshotFile);
146 |                         
147 |                         // Read the binary data
148 |                         const binaryData = await readFile(screenshotPath);
149 |                         
150 |                         resolve({
151 |                             content: [{
152 |                                 type: "text",
153 |                                 text: `Screenshot captured successfully. Binary data size: ${binaryData.length} bytes. Binary data: ${binaryData.toString('base64')} `, 
154 |                                 
155 |                             }],
156 |                             // Include binary data as base64 encoded string for transport
157 |                         });
158 |                     } catch (error) {
159 |                         reject(new Error(`Failed to read screenshot file: ${error instanceof Error ? error.message : String(error)}`));
160 |                         }
161 |                 } else {
162 |                     resolve({
163 |                         content: [{
164 |                             type: "text",
165 |                             text: output + "\nGowitness screenshot completed successfully" + 
166 |                                   (screenshot_path ? ` Screenshots saved to: ${screenshot_path}` : " Screenshots saved to: ./screenshots")
167 |                         }]
168 |                     });
169 |                 }
170 |                 } else {
171 |                     reject(new Error(`gowitness exited with code ${code}:\n${output}`));
172 |                 }
173 |             });
174 | 
175 |             proc.on("error", (error) => {
176 |                 reject(new Error(`Failed to start gowitness: ${error.message}`));
177 |             });
178 |         });
179 |     }
180 | );
181 | 
182 | // Tool: Enhanced 'report' mode
183 | server.tool(
184 |     "gowitness-report",
185 |     "Generate a report from gowitness screenshots and data",
186 |     {
187 |         screenshot_path: z.string().optional().describe("Path where gowitness stored screenshots"),
188 |         db_uri: z.string().optional().describe("Database URI to generate report from (e.g., sqlite://gowitness.sqlite3)"),
189 |         output_format: z.enum(["html", "csv", "json"]).optional().describe("Report output format"),
190 |     },
191 |     async ({ screenshot_path, db_uri, output_format = "html" }: {
192 |         screenshot_path?: string;
193 |         db_uri?: string;
194 |         output_format?: "html" | "csv" | "json";
195 |     }) => {
196 |         const args = ["report"];
197 |         
198 |         if (screenshot_path) args.push("--screenshot-path", screenshot_path);
199 |         if (db_uri) args.push("--write-db-uri", db_uri);
200 |         
201 |         // Note: gowitness report command may have different syntax
202 |         // This is a basic implementation - you may need to adjust based on actual gowitness report options
203 | 
204 |         const proc = spawn(gowitnessPath, args);
205 |         let output = "";
206 | 
207 |         proc.stdout.on("data", (data) => {
208 |             output += data.toString();
209 |         });
210 | 
211 |         proc.stderr.on("data", (data) => {
212 |             output += data.toString();
213 |         });
214 | 
215 |         return new Promise((resolve, reject) => {
216 |             proc.on("close", (code) => {
217 |                 if (code === 0) {
218 |                     resolve({
219 |                         content: [{
220 |                             type: "text",
221 |                             text: output + `\nGowitness report generated successfully`
222 |                         }]
223 |                     });
224 |                 } else {
225 |                     reject(new Error(`gowitness exited with code ${code}:\n${output}`));
226 |                 }
227 |             });
228 | 
229 |             proc.on("error", (error) => {
230 |                 reject(new Error(`Failed to start gowitness: ${error.message}`));
231 |             });
232 |         });
233 |     }
234 | );
235 | 
236 | // Tool: Batch screenshot with file-based approach
237 | server.tool(
238 |     "gowitness-batch-screenshot",
239 |     "Capture screenshots of multiple URLs using gowitness scan file command",
240 |     {
241 |         urls: z.array(z.string().url()).describe("Array of URLs to screenshot"),
242 |         screenshot_path: z.string().describe("Path to store screenshots"),
243 |         chrome_window_x: z.number().optional().describe("Chrome browser window width in pixels"),
244 |         chrome_window_y: z.number().optional().describe("Chrome browser window height in pixels"),
245 |         timeout: z.number().optional().describe("Number of seconds before considering a page timed out"),
246 |         delay: z.number().optional().describe("Number of seconds delay between navigation and screenshotting"),
247 |         threads: z.number().optional().describe("Number of concurrent threads"),
248 |         format: z.enum(["jpeg", "png"]).optional().describe("Screenshot format"),
249 |         write_db: z.boolean().optional().describe("Write results to SQLite database"),
250 |         write_jsonl: z.boolean().optional().describe("Write results as JSON lines")
251 |     },
252 |     async ({ 
253 |         urls, 
254 |         screenshot_path, 
255 |         chrome_window_x, 
256 |         chrome_window_y, 
257 |         timeout, 
258 |         delay, 
259 |         threads, 
260 |         format, 
261 |         write_db, 
262 |         write_jsonl 
263 |     }: {
264 |         urls: string[];
265 |         screenshot_path: string;
266 |         chrome_window_x?: number;
267 |         chrome_window_y?: number;
268 |         timeout?: number;
269 |         delay?: number;
270 |         threads?: number;
271 |         format?: "jpeg" | "png";
272 |         write_db?: boolean;
273 |         write_jsonl?: boolean;
274 |     }) => {
275 |         // Create a temporary URLs file
276 |         const urlsFile = join(screenshot_path, 'urls.txt');
277 |         const urlsContent = urls.join('\n');
278 |         
279 |         try {
280 |             // Write URLs to file
281 |             await writeFile(urlsFile, urlsContent);
282 |             
283 |             const args = ["scan", "file", "-f", urlsFile];
284 |             
285 |             // Add gowitness parameters
286 |             args.push("--screenshot-path", screenshot_path);
287 |             if (chrome_window_x) args.push("--chrome-window-x", chrome_window_x.toString());
288 |             if (chrome_window_y) args.push("--chrome-window-y", chrome_window_y.toString());
289 |             if (timeout) args.push("--timeout", timeout.toString());
290 |             if (delay) args.push("--delay", delay.toString());
291 |             if (threads) args.push("--threads", threads.toString());
292 |             if (format) args.push("--screenshot-format", format);
293 |             if (write_db) args.push("--write-db");
294 |             if (write_jsonl) args.push("--write-jsonl");
295 |             
296 |             // Add default writer to avoid warnings if none specified
297 |             if (!write_db && !write_jsonl) {
298 |                 args.push("--write-none");
299 |             }
300 | 
301 |             const proc = spawn(gowitnessPath, args);
302 |             let output = "";
303 | 
304 |             proc.stdout.on("data", (data) => {
305 |                 output += data.toString();
306 |             });
307 | 
308 |             proc.stderr.on("data", (data) => {
309 |                 output += data.toString();
310 |             });
311 | 
312 |             return new Promise((resolve, reject) => {
313 |                 proc.on("close", async (code) => {
314 |                     // Clean up the temporary URLs file
315 |                     try {
316 |                         await unlink(urlsFile);
317 |                     } catch (cleanupError) {
318 |                         // Ignore cleanup errors
319 |                     }
320 |                     
321 |                     if (code === 0) {
322 |                         resolve({
323 |                             content: [{
324 |                                 type: "text",
325 |                                 text: `Batch screenshot completed for ${urls.length} URLs.\nOutput: ${output}\n\nScreenshots saved to: ${screenshot_path}`
326 |                             }]
327 |                         });
328 |                     } else {
329 |                         reject(new Error(`gowitness exited with code ${code}:\n${output}`));
330 |                     }
331 |                 });
332 | 
333 |                 proc.on("error", (error) => {
334 |                     reject(new Error(`Failed to start gowitness: ${error.message}`));
335 |                 });
336 |             });
337 |         } catch (error) {
338 |             throw new Error(`Failed to create URLs file: ${error instanceof Error ? error.message : String(error)}`);
339 |         }
340 |     }
341 | );
342 | 
343 | // Tool: Read screenshot file as binary data
344 | server.tool(
345 |     "gowitness-read-binary",
346 |     "Read a screenshot file and return it as binary data",
347 |     {
348 |         file_path: z.string().describe("Path to the screenshot file to read"),
349 |         screenshot_dir: z.string().optional().describe("Directory to search for screenshot files (if file_path is not absolute)"),
350 |     },
351 |     async ({ file_path, screenshot_dir }: {
352 |         file_path: string;
353 |         screenshot_dir?: string;
354 |     }) => {
355 |         try {
356 |             let fullPath = file_path;
357 |             
358 |             // If it's not an absolute path, combine with screenshot_dir
359 |             if (!file_path.includes('\\') && !file_path.includes('/') && screenshot_dir) {
360 |                 fullPath = join(screenshot_dir, file_path);
361 |             }
362 |             
363 |             // Check if file exists
364 |             await access(fullPath);
365 |             
366 |             // Read the binary data
367 |             const binaryData = await readFile(fullPath);
368 |             const stats = await stat(fullPath);
369 |             
370 |             return {
371 |                 content: [{
372 |                     type: "text",
373 |                     text: `File read successfully. Binary data size: ${binaryData.length} bytes`
374 |                 }],
375 |                 binaryData: binaryData.toString('base64'),
376 |                 metadata: {
377 |                     filename: file_path,
378 |                     size: binaryData.length,
379 |                     path: fullPath,
380 |                     lastModified: stats.mtime.toISOString()
381 |                 }
382 |             };
383 |         } catch (error) {
384 |             throw new Error(`Failed to read file: ${error instanceof Error ? error.message : String(error)}`);
385 |         }
386 |     }
387 | );
388 | 
389 | // Tool: List screenshot files in directory
390 | server.tool(
391 |     "gowitness-list-screenshots",
392 |     "List all screenshot files in a directory",
393 |     {
394 |         screenshot_dir: z.string().optional().describe("Directory to search for screenshots (default: ./screenshots)"),
395 |     },
396 |     async ({ screenshot_dir = "./screenshots" }: {
397 |         screenshot_dir?: string;
398 |     }) => {
399 |         try {
400 |             await access(screenshot_dir);
401 |             const files = await readdir(screenshot_dir);
402 |             
403 |             const imageFiles = files.filter(file => 
404 |                 file.endsWith('.jpeg') || file.endsWith('.png') || file.endsWith('.jpg')
405 |             );
406 |             
407 |             const fileDetails = await Promise.all(
408 |                 imageFiles.map(async file => {
409 |                     const filePath = join(screenshot_dir, file);
410 |                     const stats = await stat(filePath);
411 |                     return {
412 |                         filename: file,
413 |                         path: filePath,
414 |                         size: stats.size,
415 |                         created: stats.mtime.toISOString()
416 |                     };
417 |                 })
418 |             );
419 |             
420 |             // Sort by creation time (newest first)
421 |             fileDetails.sort((a, b) => new Date(b.created).getTime() - new Date(a.created).getTime());
422 |             
423 |             return {
424 |                 content: [{
425 |                     type: "text",
426 |                     text: `Found ${fileDetails.length} screenshot files in ${screenshot_dir}:\n` +
427 |                           fileDetails.map(f => `• ${f.filename} (${f.size} bytes, ${f.created})`).join('\n')
428 |                 }],
429 |                 files: fileDetails
430 |             };
431 |         } catch (error) {
432 |             throw new Error(`Failed to list screenshots: ${error instanceof Error ? error.message : String(error)}`);
433 |         }
434 |     }
435 | );
436 | 
437 | 
438 | function getHostnameFromUrl(url: string): string {
439 |     try {
440 |         const urlObj = new URL(url);
441 |         return urlObj.hostname.replace(/[^a-zA-Z0-9]/g, '_');
442 |     } catch {
443 |         return 'unknown';
444 |     }
445 | }
446 | 
447 | // Start the server
448 | async function main() {
449 |     const transport = new StdioServerTransport();
450 |     await server.connect(transport);
451 |     console.error("Enhanced gowitness MCP Server running on stdio");
452 | }
453 | 
454 | main().catch((err) => {
455 |     console.error("Fatal error in main():", err);
456 |     process.exit(1);
457 | });
```
Page 2/2FirstPrevNextLast