ketch
Web search, public code search, library docs and page-to-markdown scraping from one Go binary
Dark web OSINT over Tor: query onion search engines, read .onion pages and save reports
By Apurv Singh Gautam (individual) Python Local · stdio SecurityWeb searchBrowser automation
69 popularity score ★ 7.9k ⇣ 68k pulls
Opens the app, which asks before it adds the server.
claude mcp add robin -- docker run -i --rm -v robin-investigations:/app/investigations apurvsg/robin mcp{
"mcpServers": {
"robin": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-v",
"robin-investigations:/app/investigations",
"apurvsg/robin",
"mcp"
]
}
}
}{
"mcpServers": {
"robin": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-v",
"robin-investigations:/app/investigations",
"apurvsg/robin",
"mcp"
]
}
}
}{
"servers": {
"robin": {
"type": "stdio",
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-v",
"robin-investigations:/app/investigations",
"apurvsg/robin",
"mcp"
]
}
}
}[mcp_servers.robin]
command = "docker"
args = ["run", "-i", "--rm", "-v", "robin-investigations:/app/investigations", "apurvsg/robin", "mcp"]gemini mcp add --scope user robin docker -- run -i --rm -v robin-investigations:/app/investigations apurvsg/robin mcpROBIN_MODEL |
Optional: Model robin_investigate uses when the client offers no sampling. |
|---|---|
OPENAI_API_KEY |
Optional: OpenAI key; ANTHROPIC_API_KEY, GOOGLE_API_KEY, MISTRAL_API_KEY or OPENROUTER_API_KEY work instead. |
OLLAMA_BASE_URL |
Optional: Ollama address; defaults to http://host.docker.internal:11434. |
ROBIN_DEFAULT_PRESET |
Optional: Default research domain; threat_intel unless set. |
ROBIN_DEFAULT_MAX_RESULTS |
Optional: Default result count, 10 to 100 (50 if unset). |
ROBIN_DEFAULT_MAX_SCRAPE |
Optional: Default pages to read, 3 to 20 (10 if unset). |
In a container, a setting goes in with -e NAME=value after docker run.
Robin is a dark web research tool that ships as one Docker image with two modes: a Streamlit web UI on port 8501, and an MCP server on stdio started with the `mcp` argument. The container starts its own Tor daemon, and every search and page fetch goes out through it, so the MCP client never loads an onion page itself.
In MCP mode the assistant works through the steps of an investigation: turn a question into a short search query, send it to sixteen onion search engines, drop off-topic hits, fetch the remaining pages as text, then write a report and save it as JSON in a Docker volume the web UI can also open. Scraped text comes back wrapped in marked untrusted-data delimiters, with control and invisible characters stripped first. The refine, filter and investigate steps run on the client's own model through MCP sampling when the client supports it. Otherwise they need ROBIN_MODEL and a provider key. Without either, the step-by-step tools still work, because the assistant writes the report itself.
The server has nine tools in v3.1 (listed in TOOL_NAMES in mcp_server.py). A search does not run until the user has picked a research domain (preset) and the call passes `user_chose=true`. Saving is rate-limited to 30 saves per 10 minutes, and a saved report is capped at 200,000 characters, 100 sources and 10 pivots (mcp_server.py, v3.1).
| Runtime | Docker |
|---|
Docker, with the image apurvsg/robin pulled first so the first start is not a download. Tor runs inside the container. No key is needed when the MCP client supports sampling or you drive the tools step by step. For robin_investigate without sampling, pass ROBIN_MODEL plus one provider key (OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, MISTRAL_API_KEY or OPENROUTER_API_KEY) into the container, or point it at a local Ollama.
Its makers say it is for educational and lawful investigation only, and that opening some dark web content may be illegal where you live. A Tor investigation takes minutes, so the README raises client tool timeouts to 600 seconds. Until Tor has finished bootstrapping, search tools return a Tor-not-ready message. robin_scrape rejects hosts that are not onion services unless `allow_clearweb` is set. robin_investigate defaults to 50 results, 10 pages and 8,000 characters per page (config.py). For Claude Code, scrape output is capped at 60,000 characters unless `max_chars` is given.
Suits threat-intelligence and OSINT analysts who want an assistant to search onion sites and gather dark web evidence without opening Tor themselves. It works with clients that can run a local Docker command. The README says an ordinary ChatGPT chat cannot run it, only Codex sessions. Not suited to clearweb research or to people who cannot run Docker. Teams that must not send scraped dark web text to an outside model provider should use the client's own model or a local Ollama.
robin_refinerobin_searchrobin_filterrobin_scraperobin_investigaterobin_save_investigationrobin_list_investigationsrobin_list_modelsrobin_health