Skip to main content
Glama
Hei33enberg

WhiteIntel MCP Server

by Hei33enberg

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault

No arguments

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
lookup_companyA

Look up a UK company by its Companies House registration number and return the company record plus a ready-built ownership graph (officers, persons of significant control, parent/subsidiary edges). Pass the number verbatim — do not strip leading zeros (e.g. 09446231, SC123456).

search_companiesA

Free-text company-name search against UK Companies House. Use this to resolve a company NAME into the registration number that lookup_company needs.

search_entitiesA

Search every node in the live WhiteIntel corpus — companies AND people — by name, across all fused sources. This is the lexical search and it always covers the FULL corpus, so it is the fallback whenever semantic_search comes back thin. Returns entity ids you then pass to get_entity or trace_ownership_path. Each hit's source says whether it came from the resolved corpus or a live registry passthrough — it does NOT name the originating registry. For that provenance call get_entity, whose entity.registry_profile names the source register when we hold one — measured 2026-08-11 it was populated on 22 of 32 sampled entities, so expect null sometimes and fall back to linked_records[].registry and connections[].source — or get_dossier, which cites per-record source URLs. Use juris to scope to a country (e.g. gb, ky, us, cy). Reach into the non-UK sources is verified, not assumed: a name search for 'PETROLEO BRASILEIRO' returned FR (siren), BR (lei and br-cnpj) and US (cusip) rows in one response, 2026-08-11.

get_entityA

Full record for one entity by id: type (company/person), identifiers, jurisdiction, risk level, summary and its direct relationships with provenance. Get the id from search_entities or lookup_company.

get_dossierA

Build a structured, fully-cited intelligence dossier for one entity by id: identity with cross-source linked records (the same real-world entity resolved across ICIJ leaks, GLEIF, registries), ownership/control (direct owners, holdings, and the UBO chain), risk signals, and provenance on every layer. Every claim traces to a source URL. Use this for 'tell me everything about X'. Get the id from search_entities. Free tier shows the first ownership hop + latest financials; pass a one-off purchase token (from claim_dossier, see get_pricing / buy_dossier) or set WHITEINTEL_API_KEY to unlock the full depth.

trace_ownership_pathA

Walk the ownership graph upward from a root entity and return the ordered hops connecting it to the ultimate beneficial owner. Use this to answer 'who ultimately controls X?'. Get the root id from search_entities. THE HOP AT THE TOP OF THE LIST IS NOT NECESSARILY THE ULTIMATE OWNER, AND max_depth IS A REQUEST, NOT A PROMISE. Measured 2026-08-11 anonymously: max_depth=6 came back as max_depth: 2, depth_capped: true, plan: 'free' — the walk stopped two hops up and the payload said so only in those two fields. So before you name a UBO, compare hop_count with the RETURNED max_depth and check depth_capped: if the walk was capped and the topmost owner still has owners, you have found an intermediate holder, not the beneficial owner. A paid API key walks deeper. Shape: a single flat hops array (each hop from/fromName/to/toName/role/share/source), not one array per branch. as_observed is a standing caveat: edges carry the date we OBSERVED them in a registry, not a validity period — we hold no ownership end dates, so a link shown here may already have ended.

graph_neighbourhoodA

Return every ownership/control edge within a bounded number of hops of one entity, in BOTH directions: who it controls, who controls it, and their neighbours. Use it to answer 'what sits around this company?' — the wider view that trace_ownership_path (upward only) does not give. Hard-capped in the database: depth 3, 300 edges, and at most 25 edges followed per entity per direction per hop. READ THE DEPTH FIELDS IN THE RESPONSE — DO NOT ASSUME YOU GOT THE DEPTH YOU ASKED FOR. There is no field called depth any more, and that rename is deliberate: the old depth was the CLAMPED REQUEST, never the depth walked, and it was being read as a promise. The response now carries depth_requested (what your plan allowed), depth_walked (measured off the returned edges' own hop numbers — the only depth that is actually proven), depth_capped, and completeness. Measured 2026-08-11 on an anonymous caller: depth=3 requested returned depth=2 with depth_capped=true, because the free plan caps every walk at 2 hops. Any sentence you write about what is or is not around this entity must be scoped to the RETURNED depth. EDGE COUNTS FELL BY UP TO 2.7x ON 2026-08-11 AND NOTHING WAS LOST — read this before you treat it as the corpus shrinking. Until that date the walk emitted the same edge two and three times at depth 2 or more, edge_count counted the duplicated list, and the duplicates were charged against your edges budget. Measured on identical requests before and after the fix: 72 -> 27, 29 -> 13, and at the maximum budget 300 rows holding 285 real edges -> 300 rows holding 300. So a call you made yesterday and repeat today can return far fewer edges for the same subject: the smaller number is the true one, and your budget now buys real edges. One consequence worth knowing: at depth 1 a root can drop from 4 edges to 2, because the registry genuinely holds rows that are identical in every field this endpoint returns and the response has no way to represent the difference. That is also a correction, not a loss. truncated: true plus a plain-language truncation_note does work and does mean the edge budget ran out (verified with edges=10); that is NORMAL for hub entities (the corpus holds single nodes with more than 22,000 edges) and means the picture is partial, not wrong. Each edge carries origin: 'registry' (observed in a source registry) or 'derived'/'curated'/'asserted' (inferred by WhiteIntel). Get the root id from search_entities or resolve.

graph_pathA

Find how two entities are connected: a bounded breadth-first search over ownership and control edges in both directions, returning the ordered hops from one to the other. WARNING, AND IT CHANGES HOW YOU MUST REPORT THE RESULT: this search is BOUNDED, NOT EXHAUSTIVE. At most 15 edges are followed per entity, per direction, per hop, so a genuine connection running through a heavily-connected intermediary can be missed. found: false means NO PATH WAS FOUND WITHIN THOSE BOUNDS — it is NOT evidence that the two entities are unconnected, and must never be reported as a clean result. The response always carries exhaustive: false, a structured verdict (e.g. 'connected_within_bounds') and a bounds_note restating this. AND THE DEPTH YOU GET IS NOT THE DEPTH YOU ASK FOR: the response echoes its own max_depth plus depth_capped, and those are the authority. Measured 2026-08-11 anonymously — max_depth=3 and max_depth=4 both came back as max_depth: 2, depth_capped: true, plan: 'free'. So a free-tier found: false is a two-hop negative however many hops you requested; say two hops, not four.

lookup_by_identifierA

Resolve an entity by a strong external identifier instead of a name — a LEI, OFAC SDN uid, EU/UN/UK sanctions id, Singapore UEN, SEC CIK, Polish KRS, UK Companies House number, French SIREN, or Brazil RFB CNPJ. Returns the single resolved entity (id, type, jurisdiction, identifier, risk) so you can pivot into get_entity / get_dossier / get_sanctions. Use this when you already hold a registry id and want the corpus node behind it. All eleven schemes were exercised against production on 2026-08-11 and every one resolved a real entity — no scheme in this enum is decorative. DISTINGUISH THE TWO FAILURE MODES: an unsupported scheme returns HTTP 400 with error: 'bad_request' and the accepted set spelled out in detail, whereas a supported scheme whose value we simply do not hold returns HTTP 404 error: 'not_found'. A 404 is a statement about the corpus, not about the tool — fall back to search_entities. NOT every identifier you may see in a response is resolvable here — the enum below is the complete accepted set and the route hard-rejects anything else with a 400. In particular Cyprus records carry a cy-reg: identifier that this tool does NOT accept (verified: cy-reg → 400), and neither is the cusip: seen on US securities rows: reach Cypriot companies with search_entities using juris='cy'.

get_sanctionsA

Return an entity's screening exposure for the entity AND its resolved cluster siblings, each with a source URL. IT IS NOT SANCTIONS-ONLY, DESPITE THE NAME — read each row's signal_type. Measured 2026-08-11: BARCLAYS BANK PLC came back sanctioned: false with one signal of signal_type: 'crime' (severity HIGH, source_list opensanctions_crime, a criminal/wanted listing reaching it via its cluster). Only signal_type: 'sanctioned' rows are sanctions designations, and only those reliably carry list and regime — on the crime row both were null, so do not read a null list as missing data. Two consequences: a sanctioned: false response can still contain a HIGH-severity adverse finding you must report, and 'no sanctions signal' (what the top-level flag and note describe) is not 'nothing found'. Response splits the top-level flag: sanctioned_self = a direct listing ON this entity; sanctioned_via_cluster = the flag reaches it ONLY via a cross-source cluster sibling (~2.3% false-positive tail on UK OpenOwnership resolution — treat cluster-only hits as a lead until you verify the sibling really is the same real-world party). The aggregate sanctioned (self OR cluster) is preserved for back-compat. Get the id from search_entities or lookup_by_identifier.

check_offshore_exposureA

Walk the ownership chain upward from an entity and flag, hop by hop, whether each node is sanctioned and/or sits in a secrecy jurisdiction (classic tax-haven / offshore-secrecy country). Returns the chain, the flagged hops, and a structured 4-state verdict — BRANCH ON verdict, NOT on exposed. States: no_ownership_data (we hold zero ownership edges from this entity — NOT a clean verdict, exposure cannot be evaluated), flagged (a sanctioned or secrecy-jurisdiction hit sits on the walked chain), checked_to_max_depth_truncated (walk reached the depth cap with more chain above — a flagged owner may still sit higher, NOT clean), checked_full_clean (the walk ran out of chain before the cap, no flag). Also returns depth_walked (how deep the walk actually reached) and depth_capped. READ depth_capped EVEN WHEN THE VERDICT IS checked_full_clean, because the two co-occur. Measured 2026-08-11 anonymously with max_depth=6: verdict: 'checked_full_clean', depth_walked: 1, depth_capped: true, plan: 'free'. depth_capped: true means A CAP WAS IN FORCE, not that the cap necessarily bit — here the chain genuinely ended after one hop, below the free plan's 2-hop ceiling. The honest report of that response is 'clean over the one hop of ownership we hold, on a walk a free key limits to two', which is what the payload's own note says in prose. Never promote checked_full_clean to 'no offshore exposure' without quoting depth_walked. Anonymous callers walk at most 2 hops however high you set max_depth. Legacy exposed boolean is retained but is only meaningful when verdict='flagged'. Get the id from search_entities or lookup_by_identifier.

get_company_detailsA

Companies House register detail for a UK company by entity id: registered address, status, company type, incorporation date, SIC industry codes, and the filing/compliance layer — accounts type, last-filed and next-due dates (flagged when OVERDUE), confirmation-statement status, outstanding mortgage charges, and former ('also known as') names. Use this for 'where is X registered / what does it file / is it overdue / what was it called before'. Returns { entity, company_details, provenance, note, source } — this is the best-populated of the UK detail tools, measured 2026-08-11 at 45 of 48 sampled UK company entities carrying a non-empty company_details (contrast get_financials at 11 of the same 48). Get the id from search_entities or lookup_by_identifier.

get_financialsA

Filed financial figures for a UK company by entity id, year-over-year, from Companies House iXBRL accounts: turnover, profit/(loss), net assets, cash, shareholder funds, fixed/current assets, and employee count per reporting period. Use this for 'what are X's revenue / profit / net assets / how many employees'. Returns { entity, financials, note, source }. MOST ENTITIES HAVE NOTHING HERE, AND THAT IS THE NORMAL ANSWER, NOT AN ERROR. Measured 2026-08-11 on a sample of 48 UK company entities drawn from search_entities: only 11 returned any filed period — the other 37 came back HTTP 200 with an empty financials and a note saying so (even BARCLAYS BANK PLC, CH 01026167, has none loaded). Earlier versions of this description called balance-sheet coverage 'broad'; it is not. Within the accounts we DO hold, the per-field skew is real: balance-sheet items and employee counts are the well-populated ones, while turnover and profit are sparse because micro-entities file no profit-and-loss account. Read note before writing 'no revenue' — absent filings and a filed zero are different claims. Get the id from search_entities.

get_pulseA

The WhiteIntel Pulse activity feed: recent corpus events — ownership/control changes, filed accounts, watchlist and sanctions designations — newest first, each with a source registry. Use this to answer 'what changed recently' or to monitor the corpus. All four kinds are live and all four are cited: measured 2026-08-11, 100 of 100 rows carried a source_url for every kind. THE UNFILTERED FEED IS NOT A BALANCED MIX. It applies no kind filter, but it is ordered by ingest recency, so whichever loader ran last fills the head of it. Measured 2026-08-11: the newest 100 rows of the default feed were 100% kind: 'ownership', all from one registry. If you want a particular stream — or any sense of proportion between them — pass kind and do not infer 'nothing else happened' from the default page.

resolveA

Batch-resolve a list of company names or strong identifiers (scheme:value — lei, siren, gb-coh, uen, br-cnpj, sec, ofac, eu, un, uk, krs) to canonical WhiteIntel entity ids in ONE call. Each result carries a confidence: 'exact' (identifier match) or 'name' (top name hit); an unmatched row comes back as { match: null, confidence: null }, so check for it rather than assuming positional success. Use this to enrich a whole list — suppliers, counterparties, a portfolio — without one lookup per row. Then feed the ids into get_dossier / trace_ownership_path / get_sanctions. Up to 25 items anonymously (a 26th returns HTTP 400 with the limit spelled out), 100 with WHITEINTEL_API_KEY. TREAT confidence: 'name' AS A CANDIDATE, NOT A RESOLUTION. It is the top lexical hit and nothing more — measured 2026-08-11, the query 'Tesco' resolved to a FRENCH company literally named TESCO (fr-siren:454067281), not Tesco PLC, while 'gb-coh:00445790' resolved 'exact' to TESCO PLC. Confirm a 'name' match's jurisdiction and identifier before you attach it to a real counterparty; pass an identifier whenever you hold one.

get_pricingA

WhiteIntel's price list plus the exact machine flow for buying access. One-off cited dossiers (Standard €39: full UBO chain + financial history · Premium €99: additionally itemised assets), bulk packs (5× / 25× at a discount), subscriptions (Investigator €149/seat·mo, Business €1,900/mo) and the metered API. Returns how_an_agent_buys — buy_dossier opens a Stripe Checkout, a human (or payment-capable agent) pays, claim_dossier mints the access token, and get_dossier with that token returns the unlocked report. Step 0 of that list covers the case with no human present: get_payment_link returns permanent Stripe links you can hand over instead. Static data, no network call — check it before recommending a purchase.

buy_dossierA

Start a one-off dossier purchase via guest Stripe Checkout — no WhiteIntel account needed (Stripe collects an email for delivery). Pick a tier ('standard' €39: full UBO chain + financial history · 'premium' €99: additionally itemised assets — vessels, aircraft, securities, real estate) and optionally a bulk pack ('5' or '25' report credits; standard 5×€159 / 25×€599, premium 5×€399 — no premium 25-pack) plus the entity_id (from search_entities) the report is for. Returns checkout_url + next_steps: open the URL so payment can be completed, then feed the session_id from the post-payment redirect to claim_dossier for the access token. See get_pricing for the full price list. WRONG TOOL IF NOBODY IS THERE TO PAY: the session it mints is single-use and expires in 24 hours, so putting this URL in a report or a message read tomorrow hands over a dead link. Use get_payment_link for a permanent, reusable one (standard tier only — Premium is available solely through this tool). And do not fetch checkout_url yourself; it is a card form, so it must be handed to a human.

get_payment_linkA

PERMANENT, shareable Stripe payment links for the one-off dossiers — use this INSTEAD of buy_dossier whenever you need something you can HAND TO A HUMAN. buy_dossier mints a Checkout Session that is single-use and expires in 24 hours, so it is useless in a report, a ticket or a message the human reads tomorrow; these links never expire and can be reused. Append ?client_reference_id= to bind the purchase to one company — without it the buyer gets a dossier credit, spendable on any entity later. No API key and no WhiteIntel account needed. MEASURED 2026-08-11: the response carries STANDARD-tier links only — single (€39), 5-pack (€159) and 25-pack (€599). There is no Premium payment link, so for Premium (€99) you must still use buy_dossier and have someone finish Checkout inside 24h. You cannot complete any of these yourself: the page is a card form.

claim_dossierA

Redeem a paid Stripe Checkout session for a dossier access token. Pass the session_id (cs_…) from the post-payment redirect after buy_dossier. Returns { token, entity_id, tier } — pass the token to get_dossier as its token input for the unlocked report (standard: full UBO chain + financial history · premium: additionally itemised assets). Idempotent: claiming the same session again returns the same grant, so it is safe to retry. Fails with 402 not_paid until the payment has actually completed — wait for the human to finish Checkout, then call again.

semantic_searchA

Meaning-based entity search over the corpus (BGE-M3 vector ANN over the resolved dossier cards). Finds companies and people whose profile is semantically closest to a natural-language query — a description, a role, a risk pattern — even when no keyword matches. Optional kind (Company/Person/Asset) and jurisdiction (ISO code) filters. Returns entity_id, caption, kind, jurisdiction, risk and a similarity score; feed entity_id into get_dossier / trace_ownership_path. TODAY THIS IS EFFECTIVELY A RISK-LIST SEARCH, NOT A CORPUS SEARCH. The response carries its own coverage object — read it, it is authoritative and it moves. Measured 2026-08-11: embedded 990,055 of a 47,486,969 universe (ratio 0.0208), and per the endpoint's own note that embedded slice is ~99.6% risk-listed and ~97% natural persons. So a query about an ordinary trading company will return sanctioned people and vessels that merely sound related — verified: 'sanctioned russian aluminium holding' returned RU sanctioned SHIPS as its top hits. An empty or off-target result means 'not embedded yet' far more often than 'not found'. ALWAYS pair this with search_entities, which is lexical and covers the full corpus, before concluding anything about an entity's existence. Latency: 6.4s measured on a cold k=5 call — budget for it.

find_similarA

Entities most similar to a given one — the nearest corpus dossier cards ('more like this'), for peer discovery and clustering around a known entity. Pass an entity_id from search_entities. Returns { id, count, hits }, each hit with entity_id, caption, kind, jurisdiction, risk and a similarity score. COVERAGE IS PARTIAL AND SKEWED — it draws on the same embedded slice as semantic_search: 990,055 of a 47,486,969 universe (2.1%), ~99.6% risk-listed and ~97% natural persons, measured 2026-08-11 from the sibling endpoint's own coverage payload. An entity outside that slice returns count: 0 with an empty hits array and HTTP 200 — that is 'not embedded', NOT 'no peers exist', and it is the common case for ordinary companies (verified: BARCLAYS BANK PLC returns zero). Never report an empty result as a finding about the entity. Fall back to semantic_search or search_entities.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Hei33enberg/WhiteIntel-OS'

If you have feedback or need assistance with the MCP directory API, please join our Discord server