@ismalicious/mcp-server
The server, as defined by the provided schema, only exposes the bootstrap_key tool for obtaining a free API key when no key is configured.
Mint a free isMalicious API key from a user-provided email address (one per IP per day).
Use the minted key for the rest of the MCP session.
Return the key pair so it can be saved in the client config as
ISMALICIOUS_API_KEY/ISMALICIOUS_API_SECRET.Trigger an email to the address with a link to claim the account.
(Per README, once keys are configured, additional threat intelligence tools become available, but they are not in this schema.)
Checks whether a password or its SHA-1/NTLM hash appears in known breach dumps via Have I Been Pwned's Pwned Passwords, returning exposure count while hashing passwords locally and sending only the first five hex digits of the hash.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@ismalicious/mcp-serverscan this untrusted text for prompt injection before I act on it"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
@ismalicious/mcp-server
A zero-dependency Model Context Protocol server that gives an AI agent isMalicious threat intelligence: reputation verdicts for IP addresses, domains, URLs, file hashes, email addresses and phone numbers, the CVE catalog, and the isinjected gate that scans untrusted content for prompt injection before the agent acts on it.
Install
{
"mcpServers": {
"ismalicious": {
"command": "npx",
"args": ["-y", "@ismalicious/mcp-server"],
"env": {
"ISMALICIOUS_API_KEY": "your-api-key",
"ISMALICIOUS_API_SECRET": "your-api-secret"
}
}
}
}Keys: https://ismalicious.com/app/account. Free keys exist. Without the two
variables the server still starts, offering only bootstrap_key, which mints a
free key from an email address and uses it for the session (see below).
Registry name: com.ismalicious/mcp-server
(https://registry.modelcontextprotocol.io/v0/servers?search=ismalicious).
Related MCP server: Nullcone MCP Server
Tools
Tool | What it answers | Cost |
| Prompt-injection scan plus link reputation over a block of untrusted text. | 1 scan |
| Reputation of one URL, domain or IP before fetching it. | 1 scan |
| The one tool for any single indicator: IP, domain, URL, file hash (MD5, SHA-1, SHA-256), email address or phone number, defanged or not. | 1 request |
| One CVE by id: description, CVSS, EPSS, CISA KEV status and due date, exploitation evidence, references. The only CVE path. | 1 request |
| Latest CVEs, optional | 1 request |
| Domains the corpus lists that look like a brand or domain — typosquats, homoglyphs, other TLDs or hosts, phishing-word combinations — most dangerous first. | 1 request on |
| Up to 100 indicators of any of the six kinds in one call: per row | 1 request per indicator |
| Whether a password, or its SHA-1 or NTLM hash, is in known breach dumps (Have I Been Pwned's Pwned Passwords) and how many times. A password is hashed locally; only the first 5 hex digits of the hash are sent. | 1 request |
| Only without a configured key: mint a free key from an email, one per IP per day. | — |
The default search API reads a bare keyword as its .com (paypal →
paypal.com) and returns at most 500 listed lookalikes. limit only reduces
that sample. Only listed domains are returned and a name buried in a longer
hostname is not matched, so an empty answer does not prove that no lookalike
exists.
The MCP result labels total_hits_scope as upstream_sample. Legacy or custom
API responses without completeness metadata produce truncated: null.
Scans and requests are two meters: https://ismalicious.com/api-docs.
Indicator types
check_indicator and check_indicators type each indicator before any
request, the way the API does:
Kind | Recognised as |
IP | IPv4, IPv6 (including |
URL | A scheme ( |
File hash | MD5 (32 hex), SHA-1 (40) or SHA-256 (64), bare or labelled ( |
Email address | One |
Phone number | Digits, spaces and |
Domain | Two or more labels of letters, digits, hyphens and underscores (non-ASCII letters too, when the label has a punycode form), an optional |
Every value is NFKC-normalised first, so full-width forms from CJK text
(090−1234−5678, user@evil.com, evil.com) read as their ASCII
selves, and an ideographic full stop (。) separates labels. Numbers are read
as typeset before the phone rule applies, and that form is what is sent:
no-break and thin spaces become spaces, typographic dashes and the minus sign
become -, (+33) 6 … becomes +33 6 …, +44 (0)20 … loses the national
(0), 030/1234567 its slash, tel: links their ;ext=… parameters, and a
trailing extension (x123, ext. 123) is dropped. A contact link is read as
the address or number it holds, with or without //: mailto:, tel:,
sms: (and its ?body=…), callto:, and sip: when its user part is a
number. So is a spreadsheet export's =+1…, ="+1…" or '+1….
Input that is none of these is refused before any request (invalid_params;
in a batch, a row with an error, not sent and not charged), never sent as a
domain: an @ the email rule rejects ("john doe"@example.com,
user@localhost, user@evil.com/), digits and separators the phone rule
rejects (12345), a number written with its keypad letters
(+1-800-FLOWERS), a URL whose host is not a dotted domain or an IP
(https://intranet/), and anything else that is not a hostname (localhost,
*.evil.com, spaces, quotes or brackets). Sent as a domain, each came back
"not listed", which read as clean / allow.
Defanged input is refanged first, and the refanged value is what is sent:
hxxp(s) in any case, [.] (.) {.} [dot], [:], [@] [at], [/],
surrounding brackets or quotes, a contact scheme, a display name around an
address, trailing sentence punctuation. The result carries input when it differs from indicator by
more than letter case.
SHA-512, SHA-384, TLSH, ssdeep and other hexadecimal strings of 32 characters
or more are refused before any request (invalid_params; in a batch, a row
with an error, not sent and not charged): the API indexes MD5, SHA-1 and
SHA-256 only.
An email address or a phone number is never clean. The API's email and
phone sources are a few feeds, so not being in them is unknown /
unverified, not evidence of safety. Its verdict comes from the address or
number's own listings and, for an email address, the sender domain. A listing
makes it malicious when its source's confidence is 70 or more, or when two
independent publishers at 60 or more agree; one list below that (the
consumer-complaint number feeds and the one address blacklist sit at 55) makes
it suspicious, because such lists name a displayed caller ID or From address,
often forged. For an email address, a
malicious domain that is not a shared mail provider makes the address
malicious; a domain with threat listings, a disposable domain or a domain
whose null MX says it accepts no mail makes it suspicious. Everything is read
from the API's dataset and cached DNS: mx is false only for a null MX,
and null when no DNS answer is cached or the cached one lists no MX. An API server
that predates email and phone support answers them as domains; the result is
then unknown / unverified with a note, never clean / allow.
check_indicator example
{
"indicator": "45.148.10.242",
"type": "ip",
"verdict": "malicious",
"headline": "45.148.10.242 is flagged malicious by 7 sources (scanner); risk 78/100; seen from 2026-06-02 to 2026-09-01.",
"recommendedAction": "block",
"malicious": true,
"risk": { "score": 78, "level": "high" },
"reputation": {
"malicious": 7,
"suspicious": 0,
"harmless": 0,
"undetected": 0
},
"blocklist": {
"hits": 7,
"listed": true,
"sources": [{ "name": "…", "category": "ip" }]
},
"network": { "countryCode": "NL", "asn": "AS…", "org": "…" },
"flags": {
"delisted": false,
"knownGood": false,
"microsoftTenant": false,
"ransomware": false,
"relatedInfrastructure": true
},
"reportUrl": "https://ismalicious.com/report?query=45.148.10.242"
}blocklist counts threat listings only. Listings whose threatClass is
infrastructure, policy or allowlist — a cloud provider's published
ranges, a Tor exit list, an ad-blocking list — say what the entity is or what
a customer may choose to block, not that it attacked anyone, so they never
reach the verdict. They are reported under infrastructure, which is absent
when there are none:
{
"indicator": "13.107.6.152",
"type": "ip",
"verdict": "clean",
"headline": "13.107.6.152 is not listed by any threat source; known infrastructure: cloud, saas; risk 12/100.",
"recommendedAction": "allow",
"malicious": false,
"risk": { "score": 12, "level": "low" },
"blocklist": { "hits": 0, "listed": false, "sources": [] },
"infrastructure": {
"attributes": ["cloud", "saas"],
"sources": [
{
"name": "Azure IP Ranges",
"category": "infrastructure",
"threatClass": "infrastructure"
},
{
"name": "Microsoft 365 endpoints",
"category": "infrastructure",
"threatClass": "infrastructure"
}
]
},
"network": {
"countryCode": "US",
"asn": "AS8075",
"org": "Microsoft Azure Cloud (eastus2)"
},
"reportUrl": "https://ismalicious.com/report?query=13.107.6.152"
}attributes is one or more of tor-exit, vpn, proxy, doh-resolver,
dns-resolver, sinkhole, cloud, cdn, crawler, scanner,
monitoring, disposable-email, dynamic-dns, url-shortener, bogon,
saas, allowlist; new ones may appear. An indicator cited by a honeypot
feed and sitting in a cloud range keeps its honeypot verdict.
Email address and phone number examples
{
"indicator": "billing@invoices-portal.example",
"type": "email",
"verdict": "suspicious",
"headline": "billing@invoices-portal.example is listed by 1 threat source (spam, scam); the domain invoices-portal.example is not in our dataset; risk 50/100.",
"recommendedAction": "review",
"malicious": false,
"lookupStatus": "found",
"risk": {
"score": 50,
"level": "medium",
"summary": "billing@invoices-portal.example is on a low-confidence list: review before trusting it"
},
"reasons": [
"Address listed by 1 threat feed: Sefinek - Blacklisted Emails (spam, scam, abuse)",
"Highest source confidence 55/100: below 70, one list is not enough for a malicious verdict"
],
"categories": ["spam", "scam", "abuse"],
"blocklist": {
"hits": 1,
"listed": true,
"sources": [{ "name": "Sefinek - Blacklisted Emails", "category": "spam" }]
},
"timeline": { "firstSeen": "2026-09-01", "lastSeen": "2026-09-29" },
"email": {
"domain": "invoices-portal.example",
"disposable": false,
"freeProvider": false,
"mx": true,
"domainReputation": {
"lookupStatus": "unknown",
"malicious": false,
"blocklistHits": 0,
"sources": []
}
},
"flags": { "delisted": false },
"meta": { "enrichment": "fast", "processingMs": 2, "latencyMs": 41 }
}check_indicator with { "indicator": "06 12 34 56 78", "country": "FR" }:
{
"indicator": "+33612345678",
"input": "06 12 34 56 78",
"type": "phone",
"verdict": "unknown",
"headline": "+33612345678 is not in any source we hold; absence is not evidence of safety.",
"recommendedAction": "unverified",
"malicious": false,
"lookupStatus": "unknown",
"risk": {
"summary": "No evidence about +33612345678: unverified, not a clean verdict"
},
"reasons": [
"No phone feed lists this number",
"Absence from our dataset is not evidence that the number is safe"
],
"blocklist": { "hits": 0, "listed": false, "sources": [] },
"phone": {
"e164": "+33612345678",
"countryCallingCode": "33",
"resolvedWith": "country"
},
"flags": { "delisted": false },
"meta": { "enrichment": "fast", "processingMs": 1, "latencyMs": 38 }
}resolvedWith is e164 (written with + or 00), country (resolved with
country), nanp-guess (10 digits read as North American) or digits (no
country could be told; e164 is then null).
A hash the dataset knows also carries file (family, file type, MIME type,
name, size, signature, tags, the file's other digests) and lookupStatus; a
citing source reached through another digest of the same file says
via: "alias", one reached through a listed range via: "cidr".
A hash NSRL knows (flags.knownGood) that a threat blocklist also lists comes
back suspicious with recommendedAction: "review", never malicious /
block: NSRL identifies known software, it does not clear it, and the two
sources disagree, which is a call for an analyst. The headline names the
conflict (<sha256> is known software (NSRL), yet 2 sources list it; review before blocking.) and blocklist still lists the citing sources.
check_indicators relays each row's recommendedAction from the API as it
comes; its rows carry no NSRL flag.
check_indicators returns its rows in input order. When the result would pass
48 KB, whole rows are dropped from the end and the result says so with
returned, omitted, truncated: true and a note; malicious still counts
every row, split into maliciousReturned and maliciousOmitted.
search_indicators does the same with indicators past 32 KB.
Errors
Every failure is a result with isError: true and this body:
{
"error": "rate_limited",
"status": 429,
"message": "Rate limit exceeded",
"quota": {
"kind": "burst",
"limit": 60,
"remaining": 0,
"plan": "FREE",
"retry_after": 30,
"resets_at": "…"
},
"hint": "Wait 30s before retrying."
}error is one of rate_limited, unauthorized, forbidden, not_found,
bad_request, upstream_error, timeout, network_error, invalid_params.
quota.kind is burst, monthly, daily, scans or issuance. A 401 says
whether no key is configured or the configured one was refused.
Timeouts and cancellation
Gate tools 15 s, check_indicator 25 s, CVE tools 10 s, search_indicators
20 s, check_indicators 60 s, check_password_exposure 10 s, bootstrap_key
15 s. ISMALICIOUS_TIMEOUT_MS
replaces all of them; ISMALICIOUS_TIMEOUT_<TOOL>_MS (for example
ISMALICIOUS_TIMEOUT_CHECK_INDICATOR_MS=3000) sets one tool's and wins. A
notifications/cancelled from the client aborts the HTTP call; the cancelled
request gets no response.
Latency
What the server itself does to answer sooner:
fastenrichment ischeck_indicator's default: the API answers from cached intelligence without calling a live upstream first. Facets it did not have cached are listed inmeta.pendingand fetched in the background; only then does the headline ask for one re-check after a few seconds, and it says that a facet still pending after it is not coming (the answer stands; each re-check is a billed request). A hash no source has cached may still wait a few seconds on CIRCL before the answer.standardmay call DNS, OTX or CIRCL before answering.fastneeds an API deploy from 2026-09-30 or later: an older server reads it asstandardfor an IP, a domain or a URL, but storesenrichmentLevel: "fast"in the hash document it caches, which is why this release follows that deploy. Email addresses and phone numbers are answered from cached data at every level.Connection reuse: one keep-alive pool per scheme (16 sockets, idle sockets kept 30 s), gzip or brotli responses, so a call a few seconds after the previous one does not pay a new TCP and TLS handshake. After
initialize, when a key is set, one unauthenticatedGET /healthopens the connection before the first tool call (ISMALICIOUS_PREWARM=0to skip).Result cache: a successful result is replayed to an identical call — same key, tool and normalised arguments — for 60 s (
check_indicator,check_indicators,check_url), 1 h (get_cve) or 5 min (recent_cves,search_indicators). A result that lists pending facets is never replayed: the re-check it invites goes to the API. A replay costs no request and says so (meta.cached,meta.ageSec, or a top-level_cache).scan_before_use,bootstrap_keyand errors are never cached.ISMALICIOUS_CACHE_TTL_Scaps or (with0) disables it.Shared calls: identical calls in flight share one request, a result with pending facets included. A defanged and a plain form of one indicator are one call; each caller still gets its own
input.
meta.latencyMs on a check_indicator result is the client-measured round
trip; meta.processingMs is the API's own time.
Calling the API host directly
By default the server calls https://ismalicious.com/api, which forwards to
the API. Setting ISMALICIOUS_API_BASE=https://api.ismalicious.com calls the
API host directly and skips that hop. bootstrap_key still goes to
https://ismalicious.com/api (its route exists only there; see
ISMALICIOUS_WEB_BASE). One billing difference: on the API host
search_indicators is charged one request of the monthly quota, where the
default base only counts it against the burst rate limit.
Resource
ismalicious://quota (application/json): the scan meter from
GET /gate/quota and the request-quota headers seen on the last billed call
of this session.
Environment
Variable | Meaning |
| Key pair; optional (bootstrap mode without them). |
| Defaults to |
| Base for |
| Overrides every tool timeout. |
| One tool's timeout, e.g. |
|
|
|
|
| Node's env-proxy mode ( |
Development
npm install
npm run typecheck && npm test && npm run build
node scripts/check-version.mjs # versions and server.json shape
node scripts/smoke.mjs # stdio end-to-end against a stub APIThe version is declared once in src/version.ts; CHANGELOG.md lists what changed.
This repository mirrors packages/mcp-server from the isMalicious monorepo, where
releases to npm and the MCP registry are cut. Issues and pull requests are welcome here.
The Dockerfile is the build Glama runs to list the server. It sets a
placeholder key pair so tools/list shows every tool; pass a real pair with
docker run -i -e ISMALICIOUS_API_KEY=… -e ISMALICIOUS_API_SECRET=…, or empty
values for bootstrap mode.
Available Tools
1 toolbootstrap_keyAInspect
No API key is configured. Mint a free isMalicious API key from an email address, use it for the rest of this session, and return it so it can be saved in the MCP client config (ISMALICIOUS_API_KEY / ISMALICIOUS_API_SECRET). One key per IP address per day; the address receives a link to claim the account. Ask the user for their email before calling.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | The email address that will own the key. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral burden, and it does well: it discloses the rate limit (one key per IP per day), the side effect (the address receives an account-claim link), the session lifetime, and the config keys the result feeds into. It stops short of stating key expiry, failure modes, or error behavior, which keeps it out of the top band.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the triggering condition, then action, then constraints. Every sentence carries distinct information — no restating of the name, no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description adequately signals the return (the key to be saved into MCP client config), plus the per-IP rate limit and email side effect. It omits error conditions and key longevity, a minor gap for a one-parameter bootstrap tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% for the single email parameter, so the baseline would be 3. The description adds meaning beyond the schema by mandating that the email come from the user before invocation, which is procedural guidance the schema cannot express.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Mint a free isMalicious API key from an email address') and frames the exact condition under which it applies ('No API key is configured'). No sibling tools exist, so no differentiation is required, and the purpose is unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use context (no key configured), a hard precondition ('Ask the user for their email before calling'), and the scope of the resulting key ('use it for the rest of this session'). Usage is fully specified with no inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
1 tool update
v0.3.0- First observed
bootstrap_key
TDQS
Scored across 1 tool
With only one tool in the set, there is no possibility of overlap or misselection between tools. The single tool has a single, clearly stated purpose (minting an API key).
The lone tool uses a readable snake_case verb_noun style (bootstrap_key), which is a sensible convention. However, a single name provides no evidence of a consistent pattern across the set, so it cannot be rated as exemplary.
One tool is far too few for a server fronting the isMalicious API, which implies a broader surface (e.g. checking URLs/domains/hashes). The server only exposes an onboarding/auth step rather than the API's actual functionality.
The surface covers only a one-time key bootstrap and none of the security-checking operations the isMalicious API presumably offers. There is no core CRUD/query capability at all, leaving the server severely incomplete for its stated purpose.
Maintenance
Related MCP Connectors
Threat-intelligence verdicts on a URL, domain or IP before a coding agent connects to it.
Security scanner for AI agents: prompt injection, leaked secrets, PII, and SSRF-risk URL detection.
Pay-per-call cybersecurity for AI agents: vuln scans, threat intel, compliance, code security.
Real-time threat intel for AI agents: 890K+ IOCs incl. prompt-injection & AI-skill threats
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceProvides CVE search enriched with EPSS exploit likelihood and CISA KEV status, plus live IP/domain reputation and a real-time threat feed for AI agents.MIT
- FlicenseNot gradedqualityDmaintenanceProvides real-time threat intelligence for AI agents, enabling checks on IPs, domains, URLs, hashes, CVEs, prompt-injection payloads, and malicious AI-skill/MCP-tool definitions against a free database of 890K+ IOCs.-

mlab.sh MCP serverofficial
AlicenseNot gradedqualityCmaintenanceEnables threat intelligence for SOC and DFIR workflows, including IOC enrichment, CVE and threat actor lookup, domain scanning, and account-based scan management.2MIT- AlicenseNot gradedqualityBmaintenanceEnables AI agents to inspect a URL before opening, following, or recommending it, by tracing redirect chains via headers, stripping tracking parameters, detecting phishing-style URL tricks, and cross-checking threat-intel feeds to return a SAFE, SUSPICIOUS, or DANGEROUS verdict with supporting evidence. It also scans text for embedded and defanged links and vets agent skills prior to installation.1MIT