name: company-check description: | Run a full due diligence check on a UK company or director. Cross-references Companies House, Gazette insolvency, HMRC VAT, and the Disqualified Directors register, then scores against a configurable risk profile (lender, journalist, acquirer, AML, or your own). Produces a CLEAR / WATCH / FLAG verdict with weighted reasons. Use when someone asks "check this company", "due diligence on X", "is this company legit", "who owns X Ltd", "is this director disqualified". Requires the UK Due Diligence MCP server. license: Apache-2.0 compatibility: "Requires UK Due Diligence MCP server." metadata: author: bouch version: "3.0" allowed-tools:
- mcp__claude_ai_uk-due-diligence__company_search
- mcp__claude_ai_uk-due-diligence__company_profile
- mcp__claude_ai_uk-due-diligence__company_officers
- mcp__claude_ai_uk-due-diligence__company_psc
- mcp__claude_ai_uk-due-diligence__gazette_insolvency
- mcp__claude_ai_uk-due-diligence__vat_validate
- mcp__claude_ai_uk-due-diligence__disqualified_search
- mcp__claude_ai_uk-due-diligence__disqualified_profile
- mcp__claude_ai_uk-due-diligence__charity_search
- mcp__claude_ai_uk-due-diligence__charity_profile
- mcp__claude_ai_uk-due-diligence__land_title_search
- Bash
- Read
- Write
Company Check — UK Due Diligence
Run a full due diligence check on a UK company or director using official government registers. The skill wraps the UK Due Diligence MCP in a deterministic pipeline: gather → enrich → score → report. Every verdict is traceable to the underlying register data, and the risk profile is a swappable JSON file (lender, journalist, acquirer, AML, or your own) so the same check produces the right answer for the right audience.
Data sources:
- Companies House (profile, officers, PSCs, filings)
- Companies House Register of Disqualified Directors
- The Gazette (insolvency notices: winding-up, administration, CVL, strike-off)
- HMRC VAT validation
- HM Land Registry (for asset checks, when relevant)
What this skill does NOT do: sanctions / PEP screening, credit scoring, trade references, forensic accounting, or legal advice. It supports those workflows; it does not replace them.
Setup
This skill depends on the UK Due Diligence MCP. Verify connection:
Call company_profile with company_number "00445790" (Tesco PLC).
You should get a full profile back in ~2 seconds. If not, the MCP isn't connected — fix that before proceeding.
Lane decision — pick one before calling any tool
Lane A — Full DD (default). User supplies a company name or number and a use case (or you infer the profile from context). Run the full pipeline: all MCP calls, risk scoring, rendered report. Takes 60–120 seconds end-to-end. This is the value case.
Lane B — Quick lookup. User wants a one-paragraph answer: "is Acme Ltd legit?" Skip enrichment and scoring. Run company_profile + gazette_insolvency + (if available) one disqualified_search on the first director. Return a single paragraph.
Lane C — Director check only. User gives a person's name, not a company. Run disqualified_search, then disqualified_profile on any hits. Optionally (if the name suggests an MP/Lord), offer to run parliament_member_interests via the legal-research skill. Return disqualification history, not a company report.
Always state which lane you're in at the start of your response so the user can redirect.
Lane A workflow — full DD
Step 1. Gather
If the user gave a name, resolve it to a company number first with company_search. Take the top match; ask the user to confirm if ambiguous.
Call these tools in parallel where possible, and save the combined response to /tmp/dd-raw.json:
company_profile(company_number)— status, filings, address, SIC codes, charges flagcompany_officers(company_number, include_resigned=true)— active + resigned officers, appointment countscompany_psc(company_number)— beneficial ownership chaingazette_insolvency(entity_name=company_name)— insolvency noticesvat_validate(vat_number)— only if a VAT number was supplied or appears in the profile
Then for each active director from step 2, call:
disqualified_search(query=director_name)— for each active director
For any disqualified search result that returns hits, call disqualified_profile(officer_id).
Structure the combined JSON with top-level keys matching the tool names:
{
"user_inputs": {"company_number": "...", "use_case": "lender"},
"company_profile": {...},
"company_officers": {...},
"company_psc": {...},
"gazette_insolvency": {...},
"vat_validate": {...},
"disqualified_lookups": {
"jane smith": {...disqualified_search result keyed by lowercased name...},
"john doe": {...}
},
"disqualified_profiles": {
"officer_id_1": {...disqualified_profile result...}
}
}
Use the Write tool (or Bash with heredoc) to save this to /tmp/dd-raw.json.
Step 2. Enrich
python scripts/cross_reference.py \
--input /tmp/dd-raw.json \
--output /tmp/dd-enriched.json
This computes: officer churn, high-appointment-count officers (nominee flags), overseas corporate PSC count, missing UBO flag, filing overdue days, insolvency signals by severity, VAT address match.
Step 3. Score against the chosen criteria profile
Pick the right criteria file for the user's context:
| Use case | Criteria file |
|---|---|
| Lender, invoice finance, credit, property finance | assets/dd-criteria-lender.json |
| Investigative journalism, beneficial ownership tracing | assets/dd-criteria-journalist.json |
| M&A, acquisitions, strategic investment | assets/dd-criteria-acquirer.json |
| KYB onboarding, AML compliance, counterparty screening | assets/dd-criteria-aml.json |
| Unclear / default | assets/dd-criteria-defaults.json |
If the user wants custom thresholds, copy a preset, edit it (see notes in the _notes field), and pass the path.
python scripts/risk_score.py \
--enriched /tmp/dd-enriched.json \
--raw /tmp/dd-raw.json \
--criteria assets/dd-criteria-lender.json \
--output /tmp/dd-verdict.json
Output is CLEAR, WATCH, or FLAG with a weighted score percentage and per-check reasons.
Step 4. Render
python scripts/render_check.py \
--raw /tmp/dd-raw.json \
--enriched /tmp/dd-enriched.json \
--verdict /tmp/dd-verdict.json \
--template assets/dd-report-template.md \
--output /tmp/dd-report.md
Step 5. Sanity gate
Before presenting, spot-check:
- Every
FLAGreason has a specific pointer (a Gazette notice, an officer name, a filing date). No vague "risk" language. - If disqualification returned a hit, confirm the match is real (date of birth or company-name overlap), not a namesake.
- If the verdict is
CLEARbut the user described a high-risk scenario (recent insolvency elsewhere, known bad actor), flag the tension — the scan missed something the user knows.
Step 6. Present and offer follow-on
Present the rendered markdown. Offer:
- Run the same data against a different profile: "want to see how this reads for an acquirer instead?"
- Pull the Land Registry for any properties owned by the company:
land_title_search - For charities:
charity_profileif relevant - Pull connected-officer companies: for any flagged director, run
company_searchon them to surface other active directorships
Lane B workflow — quick lookup
company_profile(company_number or company_search first result)gazette_insolvency(entity_name=company_name, start_date=24 months ago)- Optional:
disqualified_search(first_director_name)if profile returns officers; skip if time-pressed
Return one paragraph:
Acme Widgets Ltd (12345678) is an active private limited company, incorporated March 2018, with accounts currently 62 days overdue. No Gazette insolvency notices in the last 24 months. No disqualification hits on the named director. Verdict: low-risk with a filing-discipline caveat.
Do NOT run the full pipeline for Lane B. It's a one-paragraph answer.
Lane C workflow — director check
disqualified_search(person_name)- For each hit,
disqualified_profile(officer_id) - For each profile, check date of birth and company list against what the user told you
- Report matches and mismatches separately
Example output:
John Smith — 3 matches on the disqualified register, 1 of which appears to be the same person based on company overlap (Acme Ltd, Widget Co Ltd). That person was disqualified from 2019-03-15 to 2027-03-15 for causing Acme Ltd to trade to the detriment of HMRC. Two other "John Smith" matches are namesakes (different DOB, unrelated companies).
If user adds context ("John Smith the MP for Anytown"), consider whether legal-research skill's parliament tools are a better fit.
Configurable thresholds — the user-preference design
The six preset criteria JSONs in assets/ differ on these axes:
- Filing discipline weight: lenders care most (weight 3), journalists barely (0)
- Appointment-count threshold: journalists set it to 5 (surface nominees), lenders/AML use 10–15
- PSC opacity weight: AML cares most (weight 3), others 1–2
- Disqualification history window: journalists 20 years, acquirers 15, default 10
- Insolvency block windows: lenders 60 months on petitions, AML 24 months, journalists treat as history only
- VAT address discrepancy: AML blocks on it, others watch only
Users can edit any of these thresholds and re-run risk_score.py with their custom file. Same data, different verdict, different reasoning — the judgment is externalised in the JSON, not baked into the scripts.
Formatting rules
British spelling throughout. Company numbers as 8-digit zero-padded (01234567). Dates as YYYY-MM-DD in tables, D Month YYYY in prose. Director names with their residence country when overseas. Always state which registers were checked AND which were not (see "What was NOT checked" in the template).
Never assert something the registers don't support:
- Don't infer revenue from VAT registration
- Don't infer trading activity from "Active" company status (could be dormant)
- Don't infer solvency from absence of Gazette notices alone (notices lag events by weeks)
- Don't call a person disqualified without a date-of-birth or company-name match
When things go wrong
- Company not found: try name variations (Ltd ↔ Limited, ampersand ↔ "and"). Check for parent/subsidiary structures. Ask user to confirm trading name vs legal name.
- Multiple matches on company_search: present the top 3 with company numbers and status, ask user to pick.
- No PSC registered: this is itself a flag for a company incorporated post-2016. Include in report.
- Dissolved company: still useful — report dissolution date and whether Gazette notices preceded it.
- VAT number invalid: could be typo or fraud. Recommend user verify the number directly with the counterparty before escalating.
- Disqualified_search returns 50+ hits on a common name: filter by DOB or matched companies; report unique persons only.
- MCP timeout or 5xx: note the failure in the report under "What was NOT checked" and continue with what you have.
Files in this skill
scripts/cross_reference.py— enrich raw data with derived signals (churn, overseas %, disqualification matches)scripts/risk_score.py— score against criteria JSON, produce CLEAR/WATCH/FLAG verdictscripts/render_check.py— fill report template with raw + enriched + verdict datareferences/companies-house-filings.md— CS01/AA02 meaning, overdue signals, filing-address patternsreferences/insolvency-red-flags.md— Gazette codes by severity, winding-up vs CVL, phoenix patternsreferences/psc-opacity.md— nominee detection, overseas PSCs, UBO tracingreferences/director-disqualification.md— CDDA 1986, length-by-severity, match confidencereferences/vat-and-mtd.md— VAT validation signals, MTD April 2026, address discrepancy meaningassets/dd-criteria-defaults.json— balanced default thresholdsassets/dd-criteria-lender.json— lender preset (strict filings, charges, insolvency windows)assets/dd-criteria-journalist.json— investigative preset (PSC opacity weighted, broad history window)assets/dd-criteria-acquirer.json— M&A preset (strictest across all categories)assets/dd-criteria-aml.json— AML preset (ownership transparency + VAT validity)assets/dd-report-template.md— markdown template with{{dotted.path}}placeholdersreferences/uk-registers.md— legacy v2 reference, retained for compatibilityassets/dd-report-format.md— legacy v2 template, retained for compatibility
Scope
UK companies registered in England & Wales, Scotland, or Northern Ireland. Overseas companies appear only as PSCs of UK entities — their own filings are not accessible via this skill. No real-time sanctions or PEP screening. No credit scoring or Creditsafe-style predictive risk. No trade references or management interviews. Report is a scan, not an audit.