# recon (pypi · recon-tool)

Public DNS, certificate transparency, and identity observations.

- Trust score: 73/100 (medium)
- Change this week: −6
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- pypi · `recon-tool`: 73/100 (this document), [markdown](https://verifymcp.io/servers/blisspixel-recon/recon-tool.md), [page](https://verifymcp.io/servers/blisspixel-recon/recon-tool)

## Channel facts

- Registry: `pypi`
- Package: `recon-tool`
- Version: `2.27.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Supply Chain Security**: 99/100
  - No malware found by supply-chain analysis.
  - No known CVEs affecting this package version or its production dependencies.
  - Runs hatchling.build at install time, a recognised build step with no custom scripting around it.
  - 5 of 45 dependencies flagged as unhealthy.
- **Provenance & Transparency**: 74/100
  - Repository check failed: the declared repository URL redirects; it must resolve directly.
  - Cryptographically verified build provenance (signed, bound to blisspixel/recon).
  - Clear OSI-approved license (Apache-2.0).
  - Actively maintained (last published 1 days ago).
  - Publishes a security disclosure policy (SECURITY.md).
- **Schema Quality & AI Usability**: 73/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 8279 tokens (~285/item across 29 items; 23 tools + 6 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 0/100
  - Stability not yet verified: not enough scan history yet (needs a 30-day window).
- **Tool Coverage**: 71/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 0% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - All 1 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.
  - An AI judge read all 25 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).

**Unverified: 1 category.** A category scored 0 because we could not verify it: a data source with nothing on this package, evidence we could not reach, or a check we could not run. We only credit what we can confirm.

## Install

### How do I install the recon MCP server?

recon runs locally as a PyPI package, launched with uvx recon-tool. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add blisspixel-recon -- uvx recon-tool
```

### Cursor

```json
{
  "mcpServers": {
    "blisspixel-recon": {
      "command": "uvx",
      "args": [
        "recon-tool"
      ]
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "blisspixel-recon": {
      "command": "uvx",
      "args": [
        "recon-tool"
      ]
    }
  }
}
```

### Codex

```bash
codex mcp add blisspixel-recon -- uvx recon-tool
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "blisspixel-recon": {
      "type": "local",
      "command": [
        "uvx",
        "recon-tool"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add blisspixel-recon --command uvx --arg recon-tool
```

### Hermes

```yaml
mcp_servers:
  blisspixel-recon:
    command: "uvx"
    args: ["recon-tool"]
```

### Netclaw

```json
{
  "McpServers": {
    "blisspixel-recon": {
      "Transport": "stdio",
      "Command": "uvx",
      "Arguments": [
        "recon-tool"
      ]
    }
  }
}
```

### Vellum

```bash
assistant mcp add blisspixel-recon -t stdio -c uvx -a recon-tool
```

### Other

```json
{
  "mcpServers": {
    "blisspixel-recon": {
      "command": "uvx",
      "args": [
        "recon-tool"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-05 (score 73, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-10-30 (score 58, −21)

- [security regression] Malware scan: pass → unverified
- [security regression] Source repository: pass → fail

### 2026-10-29 (score 79, +15)

- [security improvement] Malware scan: unverified → pass

### 2026-10-28 (score 64)

First indexed and scored.

## MCP tools (23)

### `lookup_tenant` (~276 tokens)

Look up domain

Return compact text by default; JSON returns a detailed serialized record.

The default is agent-readable text. Use ``format="json"`` for serialized
JSON or ``markdown`` for a Markdown briefing. Public observations can include
display label, tenant ID, provider indicators, email-control records, and
signal correlations.

Works for any domain. Returns catalogued public SaaS and infrastructure
indicators plus claim-safe co-observations. A fingerprint match does not
establish active use, organizational intent, deployment scope, or maturity.

Queries only public DNS and unauthenticated endpoints. Authoritative DNS
may observe resolver traffic. MTA-STS is the only default target-owned HTTP
request; Google CSE and BIMI certificate probes require explicit opt-in.
No credentials or API keys are required.

Args:
    domain: A domain name to look up (e.g., alpha.invalid, gamma.invalid).
    format: Output format: "text" (default), "json" (structured), or "markdown" (briefing).
    explain: Include lineage-qualified explanations in the selected format.
        JSON also includes the structured provenance graph and conflicts.

Returns:
    Domain intelligence in the requested format, or an error message.

Input parameters:

- `domain` (string, required)
- `explain` (boolean)
- `format` (string)

Output parameters:

- `result` (string)

### `build_review_bundle` (~232 tokens)

Build review bundle

Build one fresh, evidence-linked NamespaceReviewBundle artifact.

The tool bypasses recon's lookup-result cache and performs exactly one
ordinary passive resolution for the caller-supplied namespace. Direct
probes are always disabled. Certificate-transparency collection remains on
by default and can be disabled with ``no_ct``. The explained lookup,
source-opportunity states, evidence ledger, and review candidates all
derive from the same in-memory result.

The returned artifact is a public-metadata handoff, not a security score,
vulnerability finding, compliance result, ownership conclusion, or proof
of active product use. Its digest detects modification but is not a digital
signature or collector authentication.

Args:
    domain: Namespace coordinate to reduce to its registrable apex.
    no_ct: Skip certificate-transparency providers when true.
    timeout_seconds: Aggregate resolution timeout, greater than zero and at
        most 600 seconds.

Returns:
    A schema-version-1 ReviewBundle success or typed collection failure.

Input parameters:

- `domain` (string, required)
- `no_ct` (boolean)
- `timeout_seconds` (number)

Output parameters:

- `collection` (object)
- `content_digest` (string)
- `generated_at` (string)
- `generator` (object)
- `interpretation_context` (object)
- `limitations` (array)
- `record_type` (string)
- `result` (object)
- `schema_version` (string)
- `scope` (object)
- `scope_statement` (string)
- `source_opportunities` (array)
- `workflow` (object)

### `analyze_posture` (~252 tokens)

Analyze posture

Analyze a domain's configuration posture and return neutral observations.

Returns factual observations about the domain's email security, identity,
infrastructure, SaaS footprint, certificate activity, and configuration
consistency. Observations are neutral - they describe what is, not what
should be.

Args:
    domain: A domain name to analyze (e.g., "gamma.invalid")
    explain: When true, include explanation data for each posture observation.
    profile: Optional profile name (e.g. "fintech", "healthcare",
        "saas-b2b", "high-value-target", "public-sector"). Reweights
        and filters observations to the profile's lens. It may add
        explicitly profile-relative expectations from already collected
        evidence, but withholds those expectations when collection is
        degraded.

Returns:
    A list of observation objects by default. Profile mode returns an
    envelope with ``observations`` and ``profile_note``. Explain mode
    returns an envelope with ``observations`` and ``explanations``, plus
    ``profile_note`` when a profile supplies one.

Input parameters:

- `domain` (string, required)
- `explain` (boolean)
- `profile`

Output parameters:

- `result`

### `assess_exposure` (~205 tokens)

Assess exposure

Summarize a domain's public configuration evidence for defensive review.

This is a model-bound public-evidence assessment, not an overall security
score or certification.

Returns a structured JSON object containing public email, identity,
infrastructure, configuration-consistency, and hardening observations. The
compatibility field ``posture_score`` is a 0-100 index based only on
publicly observable controls.

The score counts only controls with exact retained evidence, so it is a
floor. The ``observability`` block carries the complete weighted component
ledger, generation rule, basis state, typed predicates, bounded scope,
retained evidence, modeled ceiling, and unavailable controls. Report the
floor with its ceiling; a low floor can mean "quiet", not "weak".

Args:
    domain: A domain name to assess (e.g., "gamma.invalid")

Returns:
    JSON object with the full exposure assessment, or an error message.

Input parameters:

- `domain` (string, required)

Output parameters:

- `consistency_observations` (array)
- `disclaimer` (string)
- `domain` (string)
- `email_posture`
- `evidence` (array)
- `hardening_status`
- `identity_posture`
- `infrastructure_footprint`
- `observability`
- `posture_score` (integer)
- `posture_score_label` (string)

### `find_hardening_gaps` (~188 tokens)

Find hardening gaps

Identify hardening opportunities in a domain's public configuration.

This is a defensive review of public observations, not an overall security
assessment or certification.

Returns a gap-report object whose ``gaps`` array contains hardening prompts
with an exact generator rule, typed metadata predicates, bounded observation
scope, supporting evidence, and an ``observation_state``. The state
separates observed weak configuration, bounded non-observation, unresolved
hideable state, and an observed configuration inconsistency. The
compatibility field ``absence_confirmable`` remains present. Report an
unresolved hideable state as "not observed within the named scope", never
as a confirmed gap.

Args:
    domain: A domain name to analyze (e.g., "gamma.invalid")

Returns:
    JSON object with the gap report, or an error message.

Input parameters:

- `domain` (string, required)

Output parameters:

- `degraded_sources` (array)
- `disclaimer` (string)
- `domain` (string)
- `gaps` (array)
- `unavailable_controls` (array)

### `compare_postures` (~173 tokens)

Compare postures

Compare the public configuration evidence of two domains side by side.

This is a model-bound comparison of public observations, not an overall
security comparison or certification.

Returns a structured comparison with side-by-side metrics, control
differences, relative observations, and one exact component ledger per
namespace. Treat each public-evidence index as a floor and bounded ceiling,
never as an overall ranking of the two namespaces.

Args:
    domain_a: First domain to compare (e.g., "gamma.invalid")
    domain_b: Second domain to compare (e.g., "alpha.invalid")

Returns:
    A structured posture comparison. Raises ToolError (isError) when either
    domain is invalid or cannot be resolved (both must resolve to compare).

Input parameters:

- `domain_a` (string, required)
- `domain_b` (string, required)

Output parameters:

- `differences` (array)
- `disclaimer` (string)
- `domain_a` (string)
- `domain_a_observability`
- `domain_b` (string)
- `domain_b_observability`
- `metrics` (array)
- `relative_assessment` (array)

### `test_hypothesis` (~147 tokens)

Test hypothesis

Test a theory about a domain against signals and evidence.

Proposes a theory and receives related public observations; semantic
likelihood remains explicitly unresolved. Passive catalog matches cannot
validate active use, organizational intent, topology, or causal explanations.

Operates purely on cached pipeline data - zero additional network calls
beyond the initial domain resolution.

Args:
    domain: A domain name to test against (e.g., "gamma.invalid").
    hypothesis: A theory whose related public indicators should be listed.

Returns:
    JSON object with unresolved likelihood, related and contradicting
    observations, missing evidence, and collection confidence.

Input parameters:

- `domain` (string, required)
- `hypothesis` (string, required)

Output parameters:

- `confidence` (string)
- `contradicting_signals` (array)
- `disclaimer` (string)
- `domain` (string)
- `hypothesis` (string)
- `likelihood` (string)
- `missing_evidence` (array)
- `supporting_signals` (array)

### `simulate_hardening` (~175 tokens)

Simulate hardening

Re-compute the public-evidence index with hypothetical fixes.

Accepts a list of fix descriptions (e.g., "DMARC reject", "MTA-STS enforce")
and simulates how the model-bound compatibility index would change if those
fixes were applied. This is not a prediction of overall security change.

Operates purely on cached pipeline data - zero additional network calls
beyond the initial domain resolution.

Args:
    domain: A domain name to simulate against (e.g., "gamma.invalid").
    fixes: Array of fix descriptions or gap slugs to hypothetically apply.

Returns:
    JSON object with current_score, simulated_score, score_delta, both
    exact component ledgers, applied_fixes, and remaining_gaps.

Input parameters:

- `domain` (string, required)
- `fixes` (array, required)

Output parameters:

- `applied_fixes` (array)
- `current_observability`
- `current_score` (integer)
- `disclaimer` (string)
- `domain` (string)
- `remaining_gaps` (array)
- `score_delta` (integer)
- `simulated_observability`
- `simulated_score` (integer)

### `chain_lookup` (~221 tokens)

Follow related domains

Follow all `related_domains` observations; this does not establish ownership or a corporate relationship.

Recursively follows every ``related_domains`` observation returned by each
ordinary lookup, currently including CT, CNAME, Exchange/identity endpoint,
autodiscover, and DKIM tenant-domain breadcrumbs. Each queued name can
trigger another full public-metadata lookup. Co-occurrence does not
establish common control, company affiliation, or current product use.

Args:
    domain: Starting domain (e.g., "gamma.invalid")
    depth: Maximum recursion depth (1-3, default 1)
    result_limit: Optional compact-output cap. ``0`` returns the raw chain
        JSON. A positive value returns the first N domains in BFS chain
        order plus ``domains_omitted`` metadata.

Returns:
    JSON object with total_domains, max_depth_reached, truncated flag,
    and an array of domain intelligence objects with chain_depth.

Input parameters:

- `depth` (integer)
- `domain` (string, required)
- `result_limit` (integer)

Output parameters:

- `result` (string)

### `cluster_verification_tokens` (~357 tokens)

Cluster verification tokens

Cluster a list of domains by shared site-verification tokens.

For defensive OSINT and vendor due-diligence only.

Looks up each domain (using the TTL cache when available) and
computes a map of shared TXT verification tokens across the input
set. When two domains share a ``google-site-verification=``,
\``MS=``, Atlassian, Zoom, or similar token, it reports the exact
administrative token reuse and does not infer a relationship.

Exact token reuse is consistent with shared administration, copied
configuration, a managed-services provider, or stale residue. The public
record does not establish a shared account, operator, ownership, or current
product use. The tool reports the observation and leaves synthesis to the
caller.

Zero additional network calls beyond whatever initial resolves are
required to populate the cache. Every result is computed from
cached TenantInfo.

Args:
    domains: List of domain names to cluster. Must contain at
        least two distinct domains to be useful. Invalid domains
        are skipped with an error entry in the response.
    peer_limit_per_domain: Optional compact-output cap. ``0`` returns
        every observed peer entry. A positive value returns the first N
        entries per domain after deterministic ``(token, peer)`` sorting,
        plus ``peers_omitted`` counts.

Returns:
    JSON object with ``clusters`` (a map from each domain to its
    peers via shared tokens) and ``errors`` (a list of domains
    that could not be resolved). Empty ``clusters`` means no
    shared tokens were observed - not an error.

Input parameters:

- `domains` (array, required)
- `peer_limit_per_domain` (integer)

Output parameters:

- `clusters` (object)
- `disclaimer` (string)
- `errors` (array)
- `peer_limit_per_domain` (integer)
- `peers_omitted` (object)
- `raw_request` (string)
- `selection_rule` (string)

### `get_infrastructure_clusters` (~393 tokens)

List infrastructure clusters

Return the CT co-occurrence community-detection report for a domain.

Surfaces the same ``infrastructure_clusters`` envelope that ships in
the default ``--json`` output: cluster membership, modularity score,
algorithm path, and underlying graph metrics. The report describes
observable structure - names that co-occur on the same certificates,
grouped by the Louvain co-occurrence heuristic, never an ownership claim.

No new network surface: the report was already computed during the
last ``lookup_tenant`` (or implicit resolve). This tool just exposes
what the deterministic graph pass produced.

Args:
    domain: Domain to look up. Will use the existing TTL cache when
        available; otherwise resolves via the standard pipeline.
    member_limit_per_cluster: Optional compact-output cap. ``0`` returns
        every surfaced member from the already bounded raw report. A
        positive value returns the first N sorted members from each cluster
        plus ``members_omitted`` counts.

Returns:
    JSON object matching the ``InfrastructureClusterReport`` schema
    in ``docs/recon-schema.json``. The ``algorithm`` field reflects
    which path produced the partition (``louvain`` |
    ``connected_components`` | ``skipped``); ``skipped`` means the
    graph was empty or had no edges. ``partition_stability`` (2.2.0+)
    is the Louvain seed-sweep consensus (mean pairwise adjusted Rand
    index over ``stability_runs`` seeds; null outside the Louvain path).
    A value of 1.0 means every seed produced the identical partition;
    lower values show optimizer seed sensitivity on the same fixed graph.
    The field does not measure CT data stability, model stability,
    significance, or partition correctness.

Input parameters:

- `domain` (string, required)
- `member_limit_per_cluster` (integer)

Output parameters:

- `algorithm` (string)
- `clusters` (array)
- `domain` (string)
- `edge_count` (integer)
- `member_limit_per_cluster` (integer)
- `modularity` (number)
- `node_count` (integer)
- `partition_stability`
- `raw_request` (string)
- `selection_rule` (string)
- `stability_runs` (integer)

### `export_graph` (~377 tokens)

Export infrastructure graph

Return the raw CT co-occurrence graph (nodes + weighted edges).

Companion to ``get_infrastructure_clusters``: surfaces the underlying
graph that the Louvain pass partitioned. Nodes are SAN hostnames;
edges carry the shared-cert count between each pair. Useful for
Mermaid / GraphViz / CSV rendering pipelines that want to draw the
structure directly.

Edges are sorted by weight descending; both nodes and edges are
capped - see ``recon_tool/infra_graph.MAX_GRAPH_NODES`` and
\``MAX_EDGES_RETAINED`` for the bounds. ``cluster_assignment`` maps
every surfaced node to the cluster id from the same report so
downstream tools can colour the graph by community without re-
running detection.

No new network surface - the graph was already built during the
last ``lookup_tenant``. Read-only exposure of computed state.

Args:
    domain: Domain whose graph to export. Uses the TTL cache when
        available; otherwise resolves via the standard pipeline.
    node_limit: Optional compact-output cap. ``0`` returns every bounded
        node. A positive value selects top nodes by weighted degree
        descending, then hostname.
    edge_limit: Optional compact-output cap after node filtering. ``0``
        returns every retained edge among surfaced nodes.

Returns:
    JSON object with ``domain``, ``algorithm`` (mirroring the
    cluster report), ``node_count``, ``edge_count``, ``nodes`` (a
    sorted array of hostnames), ``edges`` (array of {source,
    target, shared_cert_count} records), and ``cluster_assignment``
    (object mapping each surfaced node to its cluster_id).

Input parameters:

- `domain` (string, required)
- `edge_limit` (integer)
- `node_limit` (integer)

Output parameters:

- `algorithm` (string)
- `cluster_assignment` (object)
- `cluster_assignment_omitted` (integer)
- `disclaimer` (string)
- `domain` (string)
- `edge_count` (integer)
- `edge_limit` (integer)
- `edges` (array)
- `edges_omitted` (integer)
- `node_count` (integer)
- `node_limit` (integer)
- `nodes` (array)
- `nodes_omitted` (integer)
- `raw_request` (string)
- `selection_rule` (string)

### `get_fingerprints` (~232 tokens)

List fingerprints

List all loaded fingerprints with slugs, categories, and detection types.

Returns a list of fingerprint summaries from both built-in and custom
sources. Each entry includes name, slug, category, confidence, match_mode,
provider_group, display_group, and the set of detection types used. The MCP
layer surfaces the list as navigable ``structuredContent`` with an
\``outputSchema``, alongside the serialized-JSON text block for compatibility.
These definitions are not evidence about any queried domain and do not
establish product use.

Args:
    category: Optional category filter using a word prefix or phrase.
    limit: Optional page size. With 800+ fingerprints loaded, an agent that
        only needs a slice can cap the response; omit (default) for the full
        list, which keeps the result shape backward-compatible.
    offset: Starting index for the page (default 0). Ignored without limit.

Returns:
    A list of fingerprint summaries (a page of it when limit is given).

Input parameters:

- `category`
- `limit`
- `offset` (integer)

Output parameters:

- `result` (array)

### `get_signals` (~207 tokens)

List signals

List reportable public signals with rules, layers, and conditions.

Returns the public projection of signal definitions from both built-in and
custom sources. Each entry includes name, category, confidence, description,
candidates, min_matches, metadata conditions, contradicts, requires_signals,
explain, and computed layer. The MCP layer surfaces the list as navigable
\``structuredContent`` with an ``outputSchema``, alongside the serialized-JSON
text block for compatibility.
These definitions are not evidence about any queried domain and do not
establish that a signal fired.

Layers: 1=basic, 2=composite (has metadata), 3=consistency, 4=meta (requires_signals).

Args:
    category: Optional category filter using a word prefix or phrase.
    layer: Optional layer filter (1, 2, 3, or 4).

Returns:
    A list of signal definitions.

Input parameters:

- `category`
- `layer`

Output parameters:

- `result` (array)

### `explain_signal` (~135 tokens)

Explain signal

Query a specific signal's trigger conditions and current state for a domain.

Without a domain: returns the signal's definition, trigger conditions,
and a list of conditions that would weaken or suppress the signal.

With a domain: resolves the domain (using cache if available), evaluates
the signal, and returns its current state with matched evidence and
specific weakening conditions.

Args:
    signal_name: Name of the signal to explain (required).
    domain: Optional domain to evaluate the signal against.

Returns:
    JSON object with signal definition and evaluation state, or an error.

Input parameters:

- `domain`
- `signal_name` (string, required)

Output parameters:

- `result`

### `reload_data` (~138 tokens)

Reload catalogs

Reload fingerprint, signal, and posture definitions for this server process.

Use this after updating the custom fingerprints.yaml / fingerprints/ or
signals.yaml overlay in recon's config directory, or the built-in data
files. The config directory is resolved, not fixed: an absolute
RECON_CONFIG_DIR, else an existing legacy ~/.recon/, else $XDG_CONFIG_HOME/recon
(default ~/.config/recon). Run `recon doctor` to print the resolved path.
Clears the process lookup cache so subsequent lookups use the new
definitions. Preserves the rate limiter and ephemeral catalog. No network
request is made by this tool.

Output parameters:

- `result` (string)

### `discover_fingerprint_candidates` (~409 tokens)

Discover fingerprint candidates

Mine unclassified CNAME candidates; each requires independent triage.

Bundles ``recon discover`` into one tool call: resolves the domain with
unclassified-CNAME-chain capture, applies intra-org and already-covered
filters, and returns a ranked candidate list ready for triage. A surviving
unclassified suffix does not establish a third-party service, ownership,
current use, or a reusable provider pattern. It may be first-party, shared,
unrelated, or noise. Require independent vendor documentation or repeated
validation evidence before proposing a new ``cname_target`` fingerprint.

Use after a regular ``lookup_tenant`` call when you notice unclassified
subdomains in the result, or proactively on any domain where you want
to grow the catalogue. Pair with the ``/recon-fingerprint-triage`` skill
(or apply the same triage rubric inline) to turn the
output into YAML stanzas for ``recon_tool/data/fingerprints/surface.yaml``.

Args:
    domain: A domain name to mine (e.g., ``alpha.invalid``).
    skip_ct: When true, skip cert-transparency providers (crt.sh,
        CertSpotter). Discovery falls back to common-subdomain probes
        and apex CNAME walks. Use for high-volume runs.
    keep_intra_org: When true, retain CNAME chains that look intra-
        organizational. Default ``false`` - false-positive prone but
        more inclusive when ``true``.
    min_count: Drop suffixes seen fewer than N times. Default 1 - for
        single-domain runs, every distinct chain matters.

Returns:
    JSON array of candidate dicts: ``[{suffix, count, samples: [{subdomain,
    terminal, chain}]}, ...]``. Sorted by count desc, then suffix.

Input parameters:

- `domain` (string, required)
- `keep_intra_org` (boolean)
- `min_count` (integer)
- `skip_ct` (boolean)

Output parameters:

- `result` (array)

### `get_posteriors` (~563 tokens)

Read posteriors

Compute v1.9 Bayesian-network posteriors over high-level claims.

Runs a normal recon lookup (cached + rate-limited like ``lookup_tenant``),
then layers the Bayesian network at
\``recon_tool/data/bayesian_network.yaml`` over the resulting evidence
set. Returns a JSON object with one entry per node:

  \``name`` (str), ``description`` (str),
  \``posterior`` (float in [0, 1], model-relative),
  \``interval_low`` / ``interval_high`` (float, 80% evidence-responsive
  uncertainty band, not a credible or confidence interval),
  \``evidence_used`` (list of slug/signal bindings that fired),
  \``n_eff`` (effective display mass used to derive the band),
  \``sparse`` (bool, True at the display-mass floor),
  \``entropy_reduction_nats`` (float, 2.2.0+, signed marginal entropy
  change, not pointwise information gain),
  \``unit_counterfactuals`` (list, 2.2.0+, exact leave-one-unit-out
  re-inference per informative evidence unit: ``unit``, ``kind``,
  \``observed`` ("fired"/"absent"), ``posterior_without``, ``delta``;
  an evidence counterfactual over the model, never a causal claim,
  and deltas are not additive across units).

The top level includes ``degraded_sources`` and
\``collection_masked_units`` so a standalone call preserves collection
provenance. A masked unit was structurally unobserved and contributed
neither fired evidence nor declarative absence.

The top level also carries ``sparse_count`` (how many nodes use the minimum
display mass) beside
\``evidence_count`` and ``conflict_count``.

How to read it: both the mean and band are model-relative diagnostics, not
facts. ``sparse=true`` means the display mass is at its floor. Absence of a
hideable signal is ignored by explicit policy, not treated as evidence of
absence. Inspect evidence and report unresolved when the public channel
does not support the claim.

Stable v2.0+. The CLI ``--fusion`` path can additionally compute a Beta
evidence-strength layer named ``slug_confidences`` over raw evidence
weights. This explicit MCP…

Input parameters:

- `domain` (string, required)

Output parameters:

- `collection_masked_units` (array)
- `conflict_count` (integer)
- `degraded_sources` (array)
- `domain` (string)
- `entropy_reduction_nats` (number)
- `evidence_count` (integer)
- `posteriors` (array)
- `sparse_count` (integer)

### `explain_dag` (~190 tokens)

Explain inference graph

Render the v1.9 Bayesian evidence DAG for a domain.

Produces a human-readable narrative of the inference: each node's
posterior, the evidence that fired, and the parent dependencies
that shaped it. Pair with ``get_posteriors`` when you want both
the structured posteriors and the prose explanation.

Stable v2.0+. Every posterior is a model-relative diagnostic, not a
calibrated probability or a truth claim. Sparse-evidence nodes are flagged
so the consumer does not over-interpret a confident-looking number.

Args:
    domain: Apex domain to evaluate.
    output_format: ``"text"`` (default, plain English) or ``"dot"``
        (Graphviz DOT for image rendering).

Returns:
    Rendered DAG as a string in the requested format.

Input parameters:

- `domain` (string, required)
- `output_format` (string)

Output parameters:

- `result` (string)

### `inject_ephemeral_fingerprint` (~273 tokens)

Inject ephemeral fingerprint

Inject a temporary fingerprint into this server process.

The fingerprint is validated through the same pipeline as built-in
fingerprints (regex compilation, ReDoS safety, valid detection types).
It lives in memory only and is discarded when the server process ends.

Scope: process-wide, not per conversation. MCP 2026-07-28 states that a
stdio process is not a session, so every request reaching this process sees
every injected fingerprint, including requests from a different conversation
with the same server. Treat this as server configuration you are changing
rather than as private scratch space, and call
\`clear_ephemeral_fingerprints()` when the experiment is done.

Args:
    name: Display name for the fingerprint (e.g., "Synthetic Delta Platform").
    slug: Unique identifier (e.g., "delta-platform").
    category: Category name (e.g., "SaaS").
    confidence: Detection confidence - "high", "medium", or "low".
    detections: List of detection rules, each with "type" and "pattern" keys.

Returns:
    Confirmation message or validation error.

Input parameters:

- `category` (string, required)
- `confidence` (string, required)
- `detections` (array, required)
- `name` (string, required)
- `slug` (string, required)

Output parameters:

- `detections_accepted` (integer)
- `name` (string)
- `slug` (string)
- `status` (string)

### `list_ephemeral_fingerprints` (~49 tokens)

List ephemeral fingerprints

List all ephemeral fingerprints loaded in this server process.

Returns a list of fingerprint summaries (navigable ``structuredContent``
plus the serialized-JSON text block at the MCP layer).

Output parameters:

- `result` (array)

### `clear_ephemeral_fingerprints` (~30 tokens)

Clear ephemeral fingerprints

Remove all ephemeral fingerprints from this server process.

Returns confirmation with the count of fingerprints removed.

Output parameters:

- `removed` (integer)
- `status` (string)

### `reevaluate_domain` (~148 tokens)

Reevaluate cached domain

Re-evaluate a previously looked-up domain against current fingerprints.

Uses cached raw DNS data from a prior lookup with zero network calls. Newly
loaded apex TXT/SPF, MX, NS, and apex/root CNAME rules are replayable. Rule
types whose owner-qualified observations are not retained in the cache must
be evaluated by a new lookup instead.
Useful after injecting ephemeral fingerprints to test detection hypotheses.

Args:
    domain: Domain to re-evaluate (must have been looked up previously).

Returns:
    Updated domain intelligence as a structured object. Raises ToolError
    (isError) when the domain is invalid or absent from the process lookup cache.

Input parameters:

- `domain` (string, required)

Output parameters:

- `auth_type`
- `bimi_identity`
- `cert_summary`
- `chain_motifs` (array)
- `cloud_instance`
- `confidence` (string)
- `ct_attempt_outcome`
- `ct_cache_age_days`
- `ct_provider_used`
- `ct_subdomain_count` (integer)
- `default_domain` (string)
- `degraded_sources` (array)
- `detection_scores` (object)
- `display_name` (string)
- `dmarc_pct`
- `dmarc_policy`
- `domain_count` (integer)
- `email_gateway`
- `email_security_score` (integer)
- `evidence` (array)
- `evidence_confidence` (string)
- `evidence_conflicts` (array)
- `fingerprint_metadata` (object)
- `fusion_enabled` (boolean)
- `google_auth_type`
- `google_idp_name`
- `inference_confidence` (string)
- `infrastructure_clusters`
- `insights` (array)
- `lexical_observations` (array)
- `likely_primary_email_provider`
- `msgraph_host`
- `mta_sts_mode`
- `partial` (boolean)
- `posterior_observations` (array)
- `primary_email_provider`
- `provider` (string)
- `queried_domain` (string)
- `record_type` (string)
- `region`
- `related_domains` (array)
- `schema_version` (string)
- `services` (array)
- `site_verification_tokens` (array)
- `slug_confidences` (object)
- `slugs` (array)
- `sources` (array)
- `surface_attributions` (array)
- `tenant_domains` (array)
- `tenant_id`
- `tenant_region_sub_scope`

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/blisspixel-recon/recon-tool#diagnostics

## Score history

- 2026-11-05: 73
- 2026-11-04: 58
- 2026-11-03: 58
- 2026-11-02: 58
- 2026-11-01: 58
- 2026-10-31: 58
- 2026-10-30: 58
- 2026-10-29: 79
- 2026-10-28: 64

## Common questions

### What is the recon MCP server?

recon is an MCP server listed in the public MCP registry as io.github.blisspixel/recon. Public DNS, certificate transparency, and identity observations. This page covers its PyPI package (recon-tool).

### Is the recon MCP server safe to use?

recon scores 73 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the recon MCP server expose?

recon exposes 23 tools: lookup_tenant, build_review_bundle, analyze_posture, assess_exposure, find_hardening_gaps, and 18 more. Their descriptions and schemas cost roughly 5,370 tokens of context every time the server is loaded.

### Is the recon MCP server still maintained?

recon is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

### What licence is the recon MCP server under?

recon declares the Apache-2.0 licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.

## Links

- PyPI project: https://pypi.org/project/recon-tool/
- Socket report: https://socket.dev/pypi/package/recon-tool
- Changelog RSS feed: https://verifymcp.io/servers/blisspixel-recon/recon-tool.xml
- Changelog JSON feed: https://verifymcp.io/servers/blisspixel-recon/recon-tool.json
- HTML version of this page: https://verifymcp.io/servers/blisspixel-recon/recon-tool
