MCP server for ProjectDiscovery's Interactsh OOB testing platform
Project description
interactsh-mcp
An MCP server that gives LLMs first-class access to ProjectDiscovery's Interactsh — the out-of-band (OOB) interaction collector behind tools like Nuclei.
Use it to let an agent validate OOB-style vulnerabilities end-to-end: blind SSRF, log4shell-style JNDI callbacks, blind XXE, blind SQLi exfil, DNS exfiltration, command-injection callbacks, blind XSS, etc. The agent gets a fresh payload URL, embeds it in a request to the target, and polls for the callback to confirm the bug.
Works against the public Interactsh service (the public oast.*
rotation) out of the box, and against any self-hosted server — with or
without a token.
Install
From PyPI (recommended)
pip install interactsh-mcp
# or, with uv:
uv tool install interactsh-mcp
After install the interactsh-mcp command starts the MCP server on stdio.
From GitHub (latest, no PyPI release needed)
pip install git+https://github.com/rek7/interactsh-mcp.git
# or, run without installing:
uvx --from git+https://github.com/rek7/interactsh-mcp.git interactsh-mcp
From source
git clone https://github.com/rek7/interactsh-mcp.git
cd interactsh-mcp
pip install .
Docker
# Build locally
docker build -t interactsh-mcp .
docker run --rm -i interactsh-mcp # smoke test; Ctrl-D to exit
The image runs as a non-root user and only needs outbound HTTPS to the Interactsh server.
Configure your client
Claude Code
Claude Code reads MCP servers from ~/.claude.json (or a project-local
.mcp.json). Add an entry under "mcpServers":
Local Python install — public servers
{
"mcpServers": {
"interactsh": {
"command": "interactsh-mcp"
}
}
}
Local Python install — self-hosted server
{
"mcpServers": {
"interactsh": {
"command": "interactsh-mcp",
"env": {
"INTERACTSH_SERVER": "interact.example.com",
"INTERACTSH_TOKEN": "your-server-token"
}
}
}
}
Omit INTERACTSH_TOKEN if your self-hosted server was started without
-auth.
Docker
{
"mcpServers": {
"interactsh": {
"command": "docker",
"args": [
"run", "--rm", "-i",
"-e", "INTERACTSH_SERVER",
"-e", "INTERACTSH_TOKEN",
"interactsh-mcp"
],
"env": {
"INTERACTSH_SERVER": "interact.example.com",
"INTERACTSH_TOKEN": "your-server-token"
}
}
}
}
You can also register the server with the CLI:
claude mcp add interactsh -- interactsh-mcp
# with env vars:
claude mcp add interactsh \
-e INTERACTSH_SERVER=interact.example.com \
-e INTERACTSH_TOKEN=your-server-token \
-- interactsh-mcp
Codex CLI
Codex CLI (OpenAI's terminal coding agent) reads MCP servers from
~/.codex/config.toml:
Public servers
[mcp_servers.interactsh]
command = "interactsh-mcp"
Self-hosted with token
[mcp_servers.interactsh]
command = "interactsh-mcp"
env = { INTERACTSH_SERVER = "interact.example.com", INTERACTSH_TOKEN = "your-server-token" }
Docker
[mcp_servers.interactsh]
command = "docker"
args = ["run", "--rm", "-i", "-e", "INTERACTSH_SERVER", "-e", "INTERACTSH_TOKEN", "interactsh-mcp"]
env = { INTERACTSH_SERVER = "interact.example.com", INTERACTSH_TOKEN = "your-server-token" }
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json on macOS,
%APPDATA%\Claude\claude_desktop_config.json on Windows. Same shape as the
Claude Code example above.
Environment variables
| Variable | Purpose |
|---|---|
INTERACTSH_SERVER |
Default hostname (e.g. interact.example.com). If unset, a random host from the public oast.* rotation is used. Per-call server argument overrides. |
INTERACTSH_TOKEN |
Default Authorization token for -auth-protected servers. Per-call token argument overrides. |
INTERACTSH_LOG_LEVEL |
Python log level (default WARNING). |
Tools the LLM sees
| Tool | What it does |
|---|---|
create_session |
Registers a new Interactsh session, starts background polling, and returns session_id + payload_url. Optional args: server, token, poll_interval, scheme, correlation_id_length. |
list_sessions |
Lists active sessions with their buffer counts. |
poll_interactions |
Drains buffered interactions for a session. wait (seconds) blocks until the first event arrives; clear=false peeks without consuming. |
new_payload |
Vends an additional payload URL on an existing session (different nonce, same correlation-id — all routed back to the same session). |
destroy_session |
Deregisters and frees the session. |
get_default_servers |
Returns the public oast.* host list. |
Typical agent workflow
- Agent calls
create_session→ getspayload_urle.g.c7lci09s8mts0o3og0g0abc12.oast.pro. - Agent crafts an exploit that uses
payload_url— a JNDI string in a User-Agent header, a?url=http://payload_url/SSRF, a DNS subdomain in a SQL payload, etc. - Agent sends the request to the target.
- Agent calls
poll_interactions(session_id, wait=10)and, if interactions come back, reports the vuln as confirmed (with the source IP / raw request from the callback as evidence). - Agent calls
destroy_sessionwhen done.
For multiple test variants in one conversation the agent can either call
create_session per variant or call new_payload to get distinct URLs that
share a session.
Self-hosting Interactsh
Quick reminder of how to stand up a server you can point this MCP at:
# Public, no auth:
interactsh-server -domain interact.example.com
# Token-protected (server prints a random token; pass it as INTERACTSH_TOKEN):
interactsh-server -domain interact.example.com -auth
See the interactsh server docs for DNS, TLS, and infra setup.
Development
git clone https://github.com/rek7/interactsh-mcp.git
cd interactsh-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e '.[test]'
pytest
Live integration tests (DNS-callback against a real server) are opt-in:
INTERACTSH_LIVE=1 pytest tests/test_live.py
# or against a self-hosted server:
INTERACTSH_LIVE=1 INTERACTSH_SERVER=interact.example.com INTERACTSH_TOKEN=... pytest tests/test_live.py
The mocked test suite exercises the full register → poll → decrypt → drain path against an in-process fake server, so the crypto and HTTP wiring are covered without network access.
License
MIT. Interactsh itself is MIT-licensed and developed by ProjectDiscovery.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file interactsh_mcp-0.1.0.tar.gz.
File metadata
- Download URL: interactsh_mcp-0.1.0.tar.gz
- Upload date:
- Size: 16.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b9008dbb8d7a7c06c5d917927135d9d51a3290ec9eeaccf9e05752ba9341fa5
|
|
| MD5 |
0d19893910db7155842025020018ca40
|
|
| BLAKE2b-256 |
129b16754bdee0337bd18f76727fbdbb0f8025c83cd9117bfd1274e245674a30
|
Provenance
The following attestation bundles were made for interactsh_mcp-0.1.0.tar.gz:
Publisher:
release.yml on rek7/interactsh-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
interactsh_mcp-0.1.0.tar.gz -
Subject digest:
8b9008dbb8d7a7c06c5d917927135d9d51a3290ec9eeaccf9e05752ba9341fa5 - Sigstore transparency entry: 1564335574
- Sigstore integration time:
-
Permalink:
rek7/interactsh-mcp@bd804bc44ea8a63b8ed57410fefbb794d2969e7d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/rek7
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bd804bc44ea8a63b8ed57410fefbb794d2969e7d -
Trigger Event:
push
-
Statement type:
File details
Details for the file interactsh_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: interactsh_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b5b00a187fa6dc28d2001b6f21a8aace23b6487efad7c7f81bb36799a2b79d9
|
|
| MD5 |
74fbfb955ed33d5dc4eeed69d5878237
|
|
| BLAKE2b-256 |
893428a6b22dab2b3ef520044a48ca640b91b6788252750fe885e28266397a74
|
Provenance
The following attestation bundles were made for interactsh_mcp-0.1.0-py3-none-any.whl:
Publisher:
release.yml on rek7/interactsh-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
interactsh_mcp-0.1.0-py3-none-any.whl -
Subject digest:
1b5b00a187fa6dc28d2001b6f21a8aace23b6487efad7c7f81bb36799a2b79d9 - Sigstore transparency entry: 1564335870
- Sigstore integration time:
-
Permalink:
rek7/interactsh-mcp@bd804bc44ea8a63b8ed57410fefbb794d2969e7d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/rek7
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@bd804bc44ea8a63b8ed57410fefbb794d2969e7d -
Trigger Event:
push
-
Statement type: