Skip to main content
Glama
README.md
# Public Risk Intelligence MCP

An open-source public-evidence collection, entity-resolution, and risk-correlation toolkit for researching companies, people, and their connections. It combines official U.S. state business registries, selected free regulatory datasets, browser-assisted evidence collection, a CLI, an MCP server for AI agents, and a reusable JavaScript library into normalized investigation dossiers.

The project prefers a free official API where one is available. Otherwise it gives an MCP client a versioned browser recipe for the user's existing Chrome session, captures public registry evidence, and normalizes every source to the same result contract. Direct Playwright execution is also available for sites that accept a new browser profile.

It does not file documents, buy certificates, bypass CAPTCHA, access browser credentials, or turn registry, name-screening, or correlation evidence into a fraud verdict, AML determination, adverse decision, or clearance.

## Current coverage

- 35 live-verified Playwright browser recipes
- 4 official API routes
- 2 official bulk or export routes
- 6 human-verification boundaries
- 4 interactive automation-blocked routes
- 0 unmapped jurisdictions
- 3 anonymous official regulatory datasets: OFAC SDN, HHS OIG LEIE, and SEC company associations
- 1 cataloged free-with-key source: SAM.gov exclusions
- 1 normalized person/company investigation layer with evidence provenance, entity resolution, relationships, contradictions, coverage gaps, bounded review signals, and evidence-backed cross-entity correlations

Run `npm run audit:recipes` for the machine-readable current catalog and recipe signatures.

## How it works

```text
company + state
      |
      v
policy-aware route selection
   /        |          \
 API    browser recipe  explicit stop
   \        |          /
      public evidence
           |
           v
 normalized evidence + investigation schema 1.0
           |
           v
 evidence-backed correlations
           |
           v
 human investigator review
```

Trusted recipes contain exact fields, buttons, optional pre-submit actions, result-row selectors, column mappings, and safe detail behavior. When a known selector changes, the recipe engine returns `RECIPE_DRIFT_DETECTED` instead of guessing. New observations stay in a candidate store until two matching observations and human review.

See [Architecture](docs/ARCHITECTURE.md), [Host-browser protocol](docs/HOST_BROWSER_PROTOCOL.md), [Blocked-route alternatives](docs/BLOCKED_ROUTES.md), [Recipe format](docs/RECIPE_FORMAT.md), [Normalized results](docs/NORMALIZED_RESULTS.md), [Free regulatory screening](docs/REGULATORY_SCREENING.md), and [Investigation cases](docs/INVESTIGATION_CASES.md).

## Install

Requirements: Node.js 20 or newer and Chrome or Chromium for browser routes.

```bash
npm install
```

## CLI

```bash
# Free official API
npx --no-install public-risk-intelligence search "Microsoft Corporation" --state CO --json

# Prepare an exact recipe for an MCP client's existing Chrome session
npx --no-install public-risk-intelligence plan "Microsoft Corporation" --state TN --json

# Direct Playwright execution for a registry that accepts a fresh visible profile
npx --no-install public-risk-intelligence search "Example Company" --state OH --browser --json

# Inspect the exact Tennessee recipe and its signature
npx --no-install public-risk-intelligence recipe TN --json

# Produce a safe browser plan for another agent/browser host
npx --no-install public-risk-intelligence plan "Microsoft Corporation" --state TN --json

# Inspect policy and coverage
npx --no-install public-risk-intelligence state NC --json
npx --no-install public-risk-intelligence recipes --json

# Check exact names against free official regulatory datasets
npx --no-install public-risk-intelligence regulatory "Example Company LLC" --person "Example Person" --json

# Inspect source coverage and access requirements
npx --no-install public-risk-intelligence regulatory-sources --json

# Build an offline person/company research plan
npx --no-install public-risk-intelligence investigate "Example Company LLC" \
  --person "Example Person" --state NV --no-regulatory --json

# Run federal screening plus an available state-registry route
npx --no-install public-risk-intelligence investigate "Example Company LLC" \
  --person "Example Person" --state CO --registry \
  --purpose counterparty_due_diligence --json

# Validate all trusted recipes
npx --no-install public-risk-intelligence audit --json
```

When installed as a package, `public-risk-intelligence` is the primary command. The legacy `sos-research` command remains an equivalent compatibility alias.

Browser launch is always opt-in with `--browser`. Use `--headless` only for a source that does not require visible human verification.

### Existing Chrome is preferred for protected registries

Some registries, including Tennessee during live verification on August 26, 2026, challenged a newly launched automated profile but worked in the user's existing Chrome session. For these sites, use the MCP pair:

1. `prepare_browser_search` returns the official URL, signed recipe, and exact controls.
2. The MCP client operates its already-connected Chrome browser.
3. `finalize_browser_search` validates the host and normalizes the public rows.
4. `build_investigation_report` combines that normalized result with subjects, reported relationships, regulatory screening results, other attributed evidence, and planned checks.

If the registry requests human verification, the client should prompt the user, pause, and resume after the user completes it. The normalized response uses `status: "manual_challenge_required"` and a structured `humanIntervention` object if the wait window expires. No CAPTCHA or security bypass is attempted.

Evidence supplied to the composition tool is treated as untrusted, source-attributed input. Its report is always marked `human_review_only`; it is not a fraud verdict, AML determination, or clearance.

### Attach through a local Chrome debugging port

The CLI can attach to a Chrome instance that exposes a local DevTools port. Connections are restricted to loopback hosts and the CLI opens and closes only its own page.

Chrome must be started with a debugging port before the CLI can attach; Playwright cannot attach to an arbitrary existing Chrome process. Start a dedicated persistent profile on macOS:

```bash
open -na "Google Chrome" --args \
  --remote-debugging-port=9222 \
  --user-data-dir=/tmp/public-risk-intelligence-chrome
```

Then run:

```bash
npx --no-install public-risk-intelligence search "Microsoft Corporation" \
  --state TN \
  --browser \
  --cdp-url http://127.0.0.1:9222 \
  --json
```

You may also set `SOS_CHROME_PATH` or `SOS_CHROME_CDP_URL`; see `.env.example`. These legacy environment-variable names remain supported to avoid breaking existing installations. This CDP route is optional—the host-browser MCP protocol is the portable existing-browser integration.

## MCP server

Start the stdio server with:

```bash
npm run start:mcp
```

Codex configuration:

```bash
codex mcp add public-risk-intelligence -- node /absolute/path/to/public-risk-intelligence-mcp/src/mcp-server.js
```

Claude Code configuration:

```bash
claude mcp add public-risk-intelligence --scope local -- node /absolute/path/to/public-risk-intelligence-mcp/src/mcp-server.js
```

Existing MCP client configurations may keep their locally assigned `sos-research` alias; the server now identifies itself as `public-risk-intelligence` and keeps all existing tool names compatible.

Tools:

- `search_business`: execute an official API or an explicitly authorized local browser search.
- `prepare_browser_search`: return the official URL and exact recipe for a host agent's browser.
- `finalize_browser_search`: validate the official host and normalize browser-observed rows.
- `build_investigation_report`: compose normalized registry and regulatory results with supplied subjects, relationships, evidence, planned checks, and evidence-backed correlations.
- `get_browser_recipe`: inspect one trusted recipe, validation result, and signature.
- `audit_browser_recipes`: validate and fingerprint the trusted catalog.
- `list_browser_recipe_coverage`: list verified, API, bulk, challenge, and blocked routes.
- `record_browser_recipe_observation`: store a sanitized structural candidate.
- `list_browser_recipe_candidates`: inspect candidates awaiting confirmation or review.
- `get_state_access` and `list_state_access`: inspect routing and policy boundaries.
- `screen_regulatory`: check company and person names against selected official regulatory datasets.
- `list_regulatory_sources`: inspect each regulatory source, subject coverage, and access requirement.
- `investigate_subjects`: build a normalized person/company investigation, optionally running regulatory and state-registry checks and deriving supported correlations.

## JavaScript library

```js
import {
  buildInvestigationReport,
  createBrowserSearchPlan,
  getRecipeRecord,
  investigateSubjects,
  listRegulatorySources,
  normalizeRecord,
  screenRegulatory,
  searchBusiness,
} from "public-risk-intelligence-mcp";

const plan = createBrowserSearchPlan({
  state: "TN",
  query: "Microsoft Corporation",
});

const recipe = getRecipeRecord("TN");
const sources = listRegulatorySources();
const screening = await screenRegulatory({
  companyName: "Example Company LLC",
  personName: "Example Person",
});
const investigation = await investigateSubjects({
  companyName: "Example Company LLC",
  personName: "Example Person",
  state: "CO",
  relationship: "reported_owner",
  purpose: "counterparty_due_diligence",
  runRegistry: true,
});
for (const correlation of investigation.analysis.correlations) {
  console.log(correlation.title, correlation.subjectIds, correlation.basisEvidenceIds);
}
const normalized = normalizeRecord({
  fields: {
    "Control No.": "000000000",
    Name: "EXAMPLE CORPORATION",
    Status: "Active",
    "Formed In": "TENNESSEE",
  },
});
```

## Normalized output

Registry and regulatory source results retain `schemaVersion: "1.0"`. Investigation reports default to `schemaVersion: "2.0"`, which adds bounded evidence-backed correlations. Library and MCP callers can request `outputSchemaVersion: "1.0"` or `output_schema_version: "1.0"` when consuming the strict legacy report contract.

The registry-result JSON Schema is at `schemas/normalized-result.schema.json`. The current person/company investigation schema is at `schemas/investigation-report.schema.json`; the retained strict legacy contract is at `schemas/investigation-report-v1.schema.json`.

### Evidence-backed risk correlations

The investigation layer can correlate verified facts and relationships across distinct subjects. Supported correlation types are:

- `shared_identifier_across_subjects`: two or more strongly attributed subjects share a verified address, registered agent, phone, email, domain, bank-account reference, or beneficiary fact;
- `multiple_company_affiliations`: a person has evidence-backed, verified relationships to multiple companies;
- `repeated_adverse_company_statuses`: a person has verified relationships to multiple companies with strongly attributed adverse official registry or license statuses.

Every correlation contains subject IDs, supporting evidence and/or relationship IDs, `strong` or `confirmed` identity confidence, and a limitation describing benign alternatives. Shared-fact correlations add a SHA-256 fingerprint and evidence/fact paths so investigators can distinguish the matched fact without exposing raw bank-account values. Sentinel, masked, partial, and low-information values are excluded. Output is deterministically limited to 500 correlations and `analysis.correlationSummary` reports any truncation.

Affiliation correlations use only these relationship types: `owner`, `reported_owner`, `beneficial_owner`, `member`, `manager`, `director`, `officer`, `founder`, `partner`, `principal`, `shareholder`, `employee`, `authorized_person`, and `registered_agent`. Each verified relationship must cite a verified, strongly attributed relationship evidence item whose facts explicitly contain compatible `fromSubjectId`, `toSubjectId`, and `relationshipType` values. Other relationship types remain in the dossier but do not create affiliation correlations.

Shared details can reflect a service provider, household, coworking site, reassignment, ordinary closure, restructuring, or stale data. A correlation is therefore a traceable review lead—not proof of common control, stolen identity, fraud, money laundering, or wrongdoing. Investigators must review source records, dates, roles, identity attributes, and alternative explanations before using it in any decision.

## Access boundaries

State sites and terms change. The project records this explicitly:

- `manual_challenge_required` means human verification prevented completion; no bypass was attempted.
- `automation_blocked` means the published policy or current access boundary prohibits the interactive route.
- `no_matches_or_unparsed` means the browser did not produce normalized rows; it is not a definitive statement that the company does not exist.

Registry results are informational. They are not certificates of good standing, legal conclusions, or sufficient evidence for an adverse risk decision.

Regulatory matches are name-only screening leads until identifying fields and the official record are reviewed. No match in a checked snapshot is not a clearance.

## Contributing

Read [CONTRIBUTING.md](CONTRIBUTING.md) before adding a source or recipe. Never commit credentials, session artifacts, personal investigation results, or CAPTCHA bypasses.

```bash
npm run ci
```

## License

MIT