ShyHurricane is an MCP server to assist AI in offensive security testing of web applications. It aims to solve a few problems observed with LLMs:
- Spidering and directory busting commands can be quite noisy and long-running. LLMs will go through a few iterations to pick a suitable command and options. The server provides spidering and busting tools to consistently provide the LLM with usable results.
- Models will also enumerate websites with many curl commands. The server saves and indexes responses to return data without contacting the website repeatedly. Large sites, common with bug bounty programs, are not efficiently enumerated with individual curl commands.
- Port scans may take a long time causing the LLM to assume the scan has failed and issue a repeated scan. The port_scan tool provided by the server addresses this.
An important feature of the server is the indexing of website content using embedding models. The find_web_resources tool uses LLM prompts to find vulnerabilities specific to content type: html, javascript, css, xml, HTTP headers. The content is indexed when found by the tools. Content may also be indexed by feeding external data into the /index endpoint. Formats supported are katana jsonl, hal json and Burp Suite Logger++ CSV. Extensions exist for Burp Suite, ZAP, Firefox and Chrome to send requests to the server as the site is browsed.
The following tools are provided:
| Tool | Description | Open World? |
|---|---|---|
| port_scan | Performs a port scan and service identification on the target(s), similar to the functions of nmap. | Yes |
| spider_website | Spider the website at the url and index the results for further analysis | Yes |
| directory_buster | Search a website for hidden directories and files. | Yes |
| index_http_url | Index an HTTP URL to allow for further analysis. (aka curl) | Yes |
| find_wordlists | Find available word lists for spidering and directory_buster | No |
| find_web_resources | Query indexed resources about a website using natural language . | No |
| fetch_web_resource_content | Fetch the content of a web resource that has already been indexed. | No |
| find_domains | Query indexed resources for a list of domains. | No |
| find_hosts | Query indexed resources for a list of hosts for the given domain. | No |
| find_netloc | Query indexed resources for a list of network locations, i.e. host:port, for a given domain. | No |
| find_urls | Query indexed resources for a list of URLs for the given host or domain. | No |
| register_hostname_address | Registers a hostname with an IP address. | No |
| register_http_headers | Register HTTP headers that should be sent on every request. | No |
| save_finding | Save findings as a markdown. | No |
| query_findings | Query for previous findings for a target. | No |
| deobfuscate_javascript | De-obfuscate JavaScript content (automatically done during indexing) | No |
The MCP server itself uses an LLM for light tasks such that the llama3.2:3b model is sufficient. Ollama is recommended but not required. OpenAI and Google AI models are also supported. Docker is required for tool specific commands such as spidering and directory busting.
Docker is required and the quality of the networking stack is important. Docker Desktop is acceptable. On macOS, Apple Virtualization networking has issues. Use colima with qemu virtualization for better results.
If you use Homebrew, brew bundle may be used for installation. Otherwise, use your operating system to install colima, qemu, docker, and docker-compose.
Start colima with a command such as the following:
colima start --runtime docker --cpu 4 --disk 50 -m 4 --vm-type qemuIt is best to run nmap on the host. If not installed on the host, the docker container will be used.
Configure your desired provider and model in .env:
OLLAMA_MODEL=llama3.2:3b
OLLAMA_HOST=192.168.253.100:11434
GEMINI_API_KEY=
GEMINI_MODEL=
OPENAI_MODEL=
OPENAI_API_KEY=
BEDROCK_MODEL=
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=Run the MCP server:
docker compose up -dor to build the images from source:
docker compose -f docker-compose.dev.yml up -dAdd the MCP server to your client of choice at http://127.0.0.1:8000/mcp.
$(command -v python3.12) -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtInstall Ollama and the llama3.2:3b model:
Ubuntu:
apt-get install ollama
ollama pull llama3.2:3bmacOS:
brew install ollama
brew services start ollama
ollama pull llama3.2:3bdocker build -t ghcr.io/double16/shyhurricane_unix_command:main src/docker/unix_commandOllama with llama3.2:3b:
python3 mcp_service.pyOpenAI:
export OPENAI_API_KEY=xxxx
python3 mcp_service.py --openai-model gpt-4-turboGoogle AI:
export GOOGLE_API_KEY=xxxx
python3 mcp_service.py --gemini-model gemini-2.0-flashAWS Bedrock:
python3 mcp_service.py --bedrock-model us.meta.llama3-2-3b-instruct-v1:0Open-world tools allow the LLM to reach out to the Internet for spidering, directory busting, etc. There are use cases where this is undesired and only indexed content should be used.
Configure .env:
OPEN_WORLD=falseRestart Docker:
docker compose up -dOR
Start the MCP server with --open-world false:
python3 mcp_service.py --open-world falseThe MCP tools will index data if appropriate. For example, spidering and directory busting. Data can be indexed by external means using the /index endpoint. The endpoint is not part of an MCP tool or protocol.
The ingest.py script makes using this endpoint more convenient. It isn't complicated to use directly. The supported data formats are inferred. Katana JSON is the preferred format.
curl -X POST -H "Content-Type: application/json" http://127.0.0.1:8000/index @katana.jsoncat katana.jsonl | python3 ingest.py --mcp-url http://127.0.0.1:8000/ --katana
# live ingestion:
tail -f katana.jsonl | python3 ingest.py --mcp-url http://127.0.0.1:8000/ --katanaMinimum fields to export:
- Request.AsBase64
- Request.Time
- Request.URL
- Response.AsBase64
- Response.RTT
cat LoggerPlusPlus.csv | python3 ingest.py --mcp-url http://127.0.0.1:8000/ --csv
# live ingestion using the auto-export feature of Logger++:
tail -f LoggerPlusPlus.csv | python3 ingest.py --mcp-url http://127.0.0.1:8000/ --csvBrowser and intercepting proxy extensions are available at the following GitHub repos:
- https://github.com/double16/shyhurricane-chrome
- https://github.com/double16/shyhurricane-firefox
- https://github.com/double16/shyhurricane-burpsuite
- https://github.com/double16/shyhurricane-zap
The browser extensions will forward requests and responses made in Chrome and Firefox to the MCP server for indexing. There are controls for setting in-scope domains.
The Burp Suite and ZAP extensions will forward both requests/responses and alerts/findings. The alerts are used by the LLM to improve effectiveness.
The /status endpoint is an HTTP POST endpoint and is not part of the MCP server protocol.
curl -X POST http://127.0.0.1:8000/statusThe MCP server exposes a proxy port, 8010 by default, that serves the indexed content. The intent is to use tools on
the indexed content after the fact. For example, to run nuclei and feed the findings into the MCP server.
The proxy supports HTTP and HTTPS with self-signed certs. Look for a log line like the following to find the CA cert or
POST an empty body to /status. Either your tools can be configured to ignore certificate validation or trust this cert.
replay proxy listening on ('127.0.0.1', 8010), CA cert is at /home/user/.local/state/shyhurricane/shyhurricane.db/certs/ca.pem (CONNECT→TLS ALPN: h2/http1.1)
An example curl call:
curl -x 127.0.0.1:8010 -k https://example.comHere is an example of using Nuclei on indexed content to submit findings passively:
nuclei -proxy http://127.0.0.1:8010 -target https://example.com -j | curl http://127.0.0.1:8000/findings -H "Content-Type: text/json" --data-binary @-If a URL or domain isn't indexed, the 404 page will include links to URLs that have been indexed. A tool that spiders links may use this to find the indexed content.
