MultiRBL

Documentation

Overview

MultiRBL checks an IPv4/IPv6 address or a domain against many free DNS blocklists (DNSBL/RBL) and reports reverse DNS (PTR) with forward-confirmed reverse DNS (FCrDNS). It is available as a web page, a JSON API and an MCP server. All three return the same report.

The API is key-less: there is no account, token or captcha. Honestly, that means it is protected only by caching and limits (see Limits). If it gets abused, a free API key may be introduced without changing the response shape.

Machine-readable descriptions: /openapi.json (OpenAPI 3.1), /.well-known/api-catalog (RFC 9727), /.well-known/mcp/server-card.json (MCP server card, a draft convention, not a final standard), /llms.txt.

Quickstart

curl 'https://multirbl.wojtek.ovh/api/v1/check?target=203.0.113.10'
curl 'https://multirbl.wojtek.ovh/api/v1/check?target=example.com&mx=1'

Read summary first: listed is the number of real listings, blocked and error mean the answer is incomplete.

How to read results

API (v1)

Base URL https://multirbl.wojtek.ovh. Methods: GET, HEAD, OPTIONS. JSON responses. CORS is open (*) for GET, without credentials.

GET /api/v1/check

Parameters: target (required; public IP or domain), mx (optional, 1 also checks MX hosts; domains only).

curl 'https://multirbl.wojtek.ovh/api/v1/check?target=example.com&mx=1'

Response (abridged):

{
  "target": "example.com",
  "kind": "domain",
  "dns": { "a": ["203.0.113.10"], "aaaa": [], "mx": [{ "pref": 10, "host": "mx.example.com" }] },
  "ips": [{
    "ip": "203.0.113.10", "source": "a",
    "ptr": ["mail.example.com"], "fcrdns": "ok",
    "zones": [{ "zone": "bl.spamcop.net", "region": "US", "note": "SpamCop",
                "query": "10.113.0.203.bl.spamcop.net", "status": "clean" }]
  }],
  "domains": [{ "name": "example.com", "source": "target", "zones": [] }],
  "options": { "mx": true },
  "summary": { "listed": 0, "collateral": 0, "clean": 41, "blocked": 0, "error": 0 }
}

GET /api/v1/zones

The list of checked DNSBLs: zone, kind, region, note, collateral.

curl 'https://multirbl.wojtek.ovh/api/v1/zones'

GET /api/v1/status

Health check, free: {"ok":true,"zones":N,"version":"..."}.

curl 'https://multirbl.wojtek.ovh/api/v1/status'

Results are cached for 15 minutes; a cache hit is free and does not count against limits. 429 responses carry Retry-After: 60.

MCP server

Endpoint POST https://multirbl.wojtek.ovh/mcp, Streamable HTTP, no authentication, stateless, single application/json responses (no SSE, no sessions). GET and DELETE return 405. If an Origin header is sent it must be https://multirbl.wojtek.ovh; otherwise 403. Supported protocol versions: 2026-07-28 (stateless), 2025-11-25, 2025-06-18.

Methods: server/discover, tools/list, tools/call, ping, and legacy initialize. Tools (read-only):

Modern request (2026-07-28)

Required headers: MCP-Protocol-Version, Mcp-Method (must equal method) and, for tools/call, Mcp-Name (must equal params.name). The body carries the version in _meta, which must match the header.

curl -X POST 'https://multirbl.wojtek.ovh/mcp' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json' \
  -H 'MCP-Protocol-Version: 2026-07-28' \
  -H 'Mcp-Method: tools/call' \
  -H 'Mcp-Name: check_blacklists' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
       "params":{"name":"check_blacklists",
                 "arguments":{"target":"example.com","include_mx":true},
                 "_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}'

Legacy initialize (2025-11-25, 2025-06-18)

curl -X POST 'https://multirbl.wojtek.ovh/mcp' \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
       "params":{"protocolVersion":"2025-11-25","capabilities":{},
                 "clientInfo":{"name":"curl","version":"1"}}}'

The server answers statelessly (no Mcp-Session-Id); notifications/initialized returns 202.

Tool failures (bad target, rate limit) return a result with isError: true. Malformed requests return JSON-RPC errors: -32020 header mismatch (400), -32022 unsupported version (400, with data.supported), -32601 unknown method (404).

Discovery: /.well-known/mcp/server-card.json. The server card is a draft convention, not a final standard, and may change.

Errors

API errors use one shape: {"error":{"code":"...","message":"..."}}.

CodeMeaning
invalid_targetNot a public IP or valid domain (private, reserved, malformed).
rate_limitedHTTP 429 with Retry-After: 60. Wait and retry.
captcha_required, captcha_failedWeb UI endpoint /api/check only (Turnstile). Not used by /api/v1.
upstream_errorDNS resolution failed upstream.
not_foundUnknown path.
method_not_allowedOnly GET, HEAD and OPTIONS are accepted.

Limits

LimitValue
Checks (cache misses), API, MCP and web6 per minute per client IP, plus 120 per minute global per Cloudflare location
Read-only endpoints (zones, openapi, catalog)60 per minute per client IP
Result cache15 minutes; hits are free
IP addresses per checkmax 8 per address family
MX hosts per domainmax 5
Concurrent DNS queries6
Timeout per DNS query4 seconds

The key-less API has no captcha, so it is bounded by cache and these limits only. Do not poll: one check per target per 15 minutes is enough.

Privacy

No accounts, no cookies, no stored IP addresses or checked targets. Only anonymous aggregate counters are kept (channel, outcome, country, duration). Results are cached for 15 minutes. DNS queries are sent over DNS-over-HTTPS to Cloudflare, and some lists (Spamhaus, SpamRATS) via a relay server. The web form loads Cloudflare Turnstile (a bot check) from challenges.cloudflare.com only when a check needs verification; the API and MCP do not. Requests pass through Cloudflare, which processes IP addresses as our hosting provider. Nothing else is shared with third parties. See the FAQ. Last updated: 2026-10-26.