MCP server
IVRE ships an MCP (Model Context
Protocol) server that exposes the database to LLM agents. It is
installed as the ivre mcp-server subcommand and communicates over
stdio, so it is meant to be launched by an MCP-capable client (Claude
Code, Claude Desktop, Cursor, OpenCode, …).
Once wired up, the LLM can answer questions like:
“How many hosts are running SSH?”
“Show me the top 10 products on port 443 in Germany.”
“Find all hosts in 192.168.1.0/24 with open port 80.”
“What operating systems are most common in AS13335?”
“List hosts affected by CVE-2021-44228.”
The server requires a configured, populated IVRE instance; it reads
the regular ivre.conf like the rest of IVRE.
Installation
The server depends on the mcp Python package, which is declared as
an optional dependency. Install IVRE with the [mcp] extra:
pip install 'ivre[mcp]'
The command can then be launched as:
ivre mcp-server
Without a connected client, the process starts and waits for MCP
JSON-RPC messages on stdin/stdout. Stop it with Ctrl+C.
Data purposes
Every tool takes a purpose parameter that selects the data source:
Purpose |
Description |
|---|---|
|
Consolidated, deduplicated merge of |
|
Active scan results (Nmap, Masscan, etc.) |
|
Passively collected network traffic data |
Default to view. Use nmap or passive only when you need
source-specific data or a tool is not available under view.
Tool reference
Filter builders
Filters are opaque tokens. Build them with these tools and combine
them with flt_and / flt_or.
Tool |
Filters by |
|---|---|
searchnet |
Network (CIDR) or host address |
searchhost |
Exact host address |
searchhostname |
Hostname (exact or regex) |
searchdomain |
Domain name |
searchport |
Open port (TCP/UDP) |
searchservice |
Detected service name |
searchproduct |
Detected product name |
searchdevicetype |
Device type |
searchcountry |
Country code (ISO 3166-1 alpha-2) |
searchasnum |
Autonomous System number or name |
searchos |
Detected operating system |
searchscript |
Nmap script name or output |
searchcve |
CVE identifier (matches “Vulnerable” tag info) |
searchcategory |
Category |
searchtag |
Tag value (and optionally tag info) |
searchrecontype |
Passive reconnaissance type |
searchsensor |
Passive sensor name |
Filter combinators
Tool |
Description |
|---|---|
flt_and |
Combine two filters with logical AND |
flt_or |
Combine two filters with logical OR |
flt_empty |
Return the empty filter (matches everything) |
Query tools
Tool |
Description |
|---|---|
count |
Count matching records |
get |
Retrieve matching records (paginated, sortable) |
topvalues |
Most frequent values of a field |
distinct |
Distinct values of a field |
describe_schema |
List available field paths for a given purpose |
nmap_service_values |
Known Nmap service / product values (discovery) |
A resource at ivre://guides/scope-discovery is also exposed; the
server’s top-level instructions point agents at it when they start
exploring a scope.
HTTP transport
In addition to stdio, the server can be exposed over HTTP using the Model Context Protocol Streamable HTTP transport. This is how remote or shared MCP deployments are typically served.
Starting the HTTP transport
ivre mcp-server --http \
--bind 127.0.0.1 \
--port 9100 \
--path /mcp
CLI flags:
Flag |
Description |
|---|---|
|
Switch from stdio to Streamable HTTP. |
|
Bind address. Default |
|
TCP port. Default |
|
HTTP path prefix for the MCP endpoint. Default |
|
Disable bearer-token auth. Required to bind a non-loopback address when the IVRE Web auth backend is not configured. |
Defaults can also be set from ivre.conf via MCP_HTTP_BIND,
MCP_HTTP_PORT, MCP_HTTP_PATH and MCP_HTTP_ALLOW_ANONYMOUS.
Authentication
The HTTP transport supports two authentication shapes against the same underlying Web Authentication user store. Both are bearer-token based; clients pick whichever fits the MCP integration they ship.
API-key bearer (always enabled)
MCP clients authenticate with Authorization: Bearer <api-key>;
the server verifies the token against db.auth.validate_api_key
(the same code path used by the Web UI) and refuses unauthenticated
requests when WEB_AUTH_ENABLED is set.
To create an API key, log in to the Web UI as the user, open Admin > API Keys and click Create. Keep the key secret – revoking it from the Web UI immediately invalidates MCP clients carrying it.
OAuth 2.1 consent flow (opt-in)
Recent MCP clients (Claude Desktop, Cursor, Claude Code, …)
drive an /authorize -> consent -> /token flow against
IVRE and receive a short-lived access token + refresh token.
Set MCP_OAUTH_AS_ENABLED = True in ivre.conf to enable
the AS side; this requires WEB_AUTH_ENABLED = True because
the consent screen reuses the existing login flow.
When enabled, the MCP HTTP server mounts the following OAuth 2.1 endpoints (per RFC 8414 / RFC 7591 / RFC 7009 / RFC 9728):
GET /.well-known/oauth-protected-resource– RFC 9728 protected-resource metadata; advertises the authorization server(s) for this MCP endpoint. Mounted unconditionally whenever bearer auth is enabled (i.e. also under API-key-only mode).GET /.well-known/oauth-authorization-server– RFC 8414 AS metadata (authorize/token/register/revokeendpoint URLs, supported grant types, PKCE methods).GET /authorize– the entry point that, after parsing the client’s PKCE authorization request, redirects the user-agent to/cgi/auth/oauth/consenton the Bottle Web app.POST /token– code-for-token exchange and refresh.POST /register– RFC 7591 dynamic client registration (gated onMCP_OAUTH_DCR_ENABLED; default on).POST /revoke– RFC 7009 token revocation.
The consent screen (rendered at /cgi/auth/oauth/consent) shows
the requesting client’s client_name plus the requested
scopes, then either redirects back to the client’s
redirect_uri with a one-shot authorization code, or with
error=access_denied on a “Deny” click.
Unauthenticated users are bounced through the regular IVRE
login page first, with the consent URL passed as a next=
query parameter so the user lands back on the consent screen
after signing in. The same next= plumbing is wired through
the OAuth login (/cgi/auth/login/<provider>), the
provider callback (/cgi/auth/callback/<provider>), the
magic-link request (POST /cgi/auth/magic-link) and the
magic-link verification (GET /cgi/auth/magic-link/verify).
The server validates every incoming next= value as a
same-origin relative path (rejecting absolute URLs,
protocol-relative URLs, \-prefixed variants, CR/LF
injection, and inputs longer than 2048 characters); anything
that does not parse cleanly is silently dropped and the
post-login redirect falls back to /. The OAuth-flow next= payload survives
the round-trip via the _ivre_login_next signed cookie
(HMAC’d with WEB_SECRET, HttpOnly, SameSite=Lax,
5 min TTL); the magic-link flow embeds the validated path in
the verification URL.
Issued access tokens (ivre_oat_*) and refresh tokens
(ivre_ort_*) are opaque random strings; only their SHA-256
hashes are persisted, mirroring the API-key storage posture.
Refresh tokens rotate on every exchange: the consumed refresh
token is revoked before the new pair is minted.
The OAuth knobs live alongside the HTTP transport knobs in
ivre.conf:
Knob |
Description |
|---|---|
|
Enable the OAuth AS endpoints. Default
|
|
Allow RFC 7591 dynamic client registration
at |
|
Public base URL used in the consent
redirect and AS metadata document. Falls
back to |
|
Lifetime of an in-flight |
|
Lifetime of an issued authorization code
awaiting exchange, in seconds. Default
|
|
Lifetime of an issued access token, in
seconds. Default |
|
Lifetime of an issued refresh token, in
seconds. |
The two authentication shapes coexist: when the AS is enabled, the MCP HTTP transport validates both OAuth-issued access tokens and pre-existing IVRE API keys on every tool call, so existing API-key users keep working while new clients drive the consent flow.
Per-user access controls
Per-user access controls (WEB_INIT_QUERIES,
WEB_DEFAULT_INIT_QUERY, group-based rules) are honoured for
every MCP tool call, regardless of which authentication shape
the client used: the authenticated user is resolved from the
bearer token and the resulting init filter is AND-ed with any
filter built by the client.
Safety defaults
When
--bindis not a loopback address and authentication is not configured,ivre mcp-server --httprefuses to start. Either bind to loopback, enableWEB_AUTH_ENABLED, or pass--allow-anonymousto acknowledge the risk.Anonymous mode disables all access control. Use it only for single-user local development.
Reverse proxy (nginx)
For production deployments, terminate TLS in nginx and reverse-proxy
to the MCP HTTP server. FastMCP registers the endpoint at exactly
/mcp (no trailing slash), so use an exact-match location: a
prefix location /mcp/ block would trigger nginx’s automatic
trailing-slash 301 and Starlette’s /mcp/ -> /mcp redirect,
producing a loop, and a regex location is incompatible with a
proxy_pass URI part. The Streamable-HTTP transport relies on
server-sent events, so disable response buffering and bump the read
timeout:
location = /mcp {
proxy_pass http://127.0.0.1:9100/mcp;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Authorization $http_authorization;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 1h;
proxy_send_timeout 1h;
chunked_transfer_encoding on;
}
The MCP server derives the externally-visible origin (used in
WWW-Authenticate: Bearer ..., resource_metadata="..." and in the
/.well-known/oauth-protected-resource/... JSON document) from each
request’s Host: and X-Forwarded-Proto: headers, the same trust
surface as the Web UI’s Referer: header check (see
WEB_ALLOWED_REFERERS in Configuration). The snippet
above forwards both correctly. The public path must match the
upstream --path (both default to /mcp); rewriting via
X-Forwarded-Prefix is not currently supported.
HTTP client configuration
Claude Desktop, Claude Code, Cursor, VS Code and Windsurf support
connecting to remote MCP servers. Example Claude Code snippet for
~/.claude/settings.json or a project-level .mcp.json:
{
"mcpServers": {
"IVRE": {
"type": "http",
"url": "https://ivre.example.com/mcp",
"headers": {
"Authorization": "Bearer IVRE_API_KEY_HERE"
}
}
}
}
The exact JSON schema differs slightly between clients; consult the client documentation for the precise key names.
Docker
The reference Docker deployment (see Docker) ships a
dedicated ivre/web-mcp image that runs ivre mcp-server --http
on port 9100 inside the Compose network. The ivre/web nginx
container reverse-proxies it at /mcp, so no extra configuration
is required to reach it from an MCP client at
http(s)://<host>/mcp.
The image starts with --allow-anonymous because the MCP port is
not published on the host. For any production use, enable the IVRE
Web auth backend (WEB_AUTH_ENABLED = True in ivre.conf),
create an API key from Admin > API Keys in the Web UI, and override
the ivremcp command: in docker-compose.yml to drop
--allow-anonymous.
Client setup
All snippets below assume ivre-mcp-server resolves to the console
script installed by the [mcp] extra. If it is installed in a
virtualenv that is not on the client’s PATH, use the absolute path
to the executable, or wrap the invocation in an activation script.
Note
These snippets configure the ivre mcp-server subcommand. A
convenience console-script entry for it is not installed; clients
below all call ivre with mcp-server as the first argument.
OpenCode
Add to your workspace opencode.json (or global
~/.config/opencode/opencode.json):
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"ivre": {
"type": "local",
"command": ["ivre", "mcp-server"],
"enabled": true
}
}
}
Claude Code
Add to ~/.claude/settings.json or to a project-level .mcp.json:
{
"mcpServers": {
"IVRE": {
"command": "ivre",
"args": ["mcp-server"]
}
}
}
Claude Desktop
Add to claude_desktop_config.json (accessible via
Settings > Developer > Edit Config):
{
"mcpServers": {
"IVRE": {
"command": "ivre",
"args": ["mcp-server"]
}
}
}
Cursor
Go to Settings > Tools & Integrations > New MCP Server, select
“command” type, and enter ivre mcp-server. Alternatively, add to
~/.cursor/mcp.json:
{
"mcpServers": {
"IVRE": {
"command": "ivre",
"args": ["mcp-server"]
}
}
}
VS Code (GitHub Copilot)
Requires the GitHub Copilot Chat extension. Add to your workspace
.vscode/mcp.json:
{
"servers": {
"IVRE": {
"type": "stdio",
"command": "ivre",
"args": ["mcp-server"]
}
}
}
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"IVRE": {
"command": "ivre",
"args": ["mcp-server"]
}
}
}
JetBrains IDEs
Requires IntelliJ IDEA 2025.1+ (or equivalent). Go to Settings > Tools > AI Assistant > MCP Servers, click +, and add:
{
"mcpServers": {
"IVRE": {
"command": "ivre",
"args": ["mcp-server"]
}
}
}
Extending the server
Third parties can add tools and resources via entry points in the
ivre.plugins.mcp_server group. See MCP server plugins for the plugin author guide.