Use NorthData (German commercial-register + financials API) to look up companies, owners, representatives, financials, publications, and person records. Trig...
--- name: northdata description: Use NorthData (German commercial-register + financials API) to look up companies, owners, representatives, financials, publications, and person records. Triggers on queries about NorthData itself, looking up a specific German company (GmbH, UG, KG, HRB/HRA register entries), finding owners / Geschäftsführer / Gesellschafter, reading a company's revenue / earnings / balance sheet, searching by NACE segment or legal form or geography, checking NorthData credit usage, or power-searching for acquisition / lead candidates. Activates for terms like "northdata", "north data", "Handelsregister", "HRB", "HRA", "Gesellschafter", "Geschäftsführer", "GmbH Finanzen", "Firma recherchieren", "NACE-Suche", "Power Search", "company profile". Provides best-practice guidance for both the `northdata` CLI (Claude Code / terminal) and the NorthData MCP server (Claude Desktop / any MCP client) — whichever is available in the current environment. --- # NorthData Companion Skill This skill is the best-practice guide for working with the NorthData API through either: 1. **`northdata` CLI** — a command-line tool, typically used in Claude Code or a terminal. 2. **NorthData MCP server** — a set of tools exposed over the Model Context Protocol, typically used in Claude Desktop / Cursor / other MCP clients. Both surfaces are built on the same `NorthDataClient` and share the same credit-guard discipline. Pick whichever is available in the current environment — this skill covers both. ## Detect what's available Before deciding, check what's reachable: | Check | Available? | |---|---| | MCP tools named `suggest`, `company`, `person`, … | Use MCP. | | `northdata` on `$PATH` (try `which northdata` or `northdata --version`) | Use CLI. | | Neither | Ask the user to install — point at `northdata-cli` (pipx) and/or the MCP server config. | If both are available: **prefer MCP** when running inside an MCP-aware client (clearer tool telemetry, structured errors). **Prefer CLI** in Claude Code or any shell-driven context. ## The one rule you must internalize **NorthData charges per returned company, not per HTTP call.** A single `search --limit 100` costs up to 100 credits in one go. Every billed call goes through the two-tier credit guard: | Tier | Default | How to relax | |---|---|---| | Approval threshold — `limit > 25` needs `--approve-high-cost` (CLI) or `approve_high_cost=true` (MCP) | `25` | `NORTHDATA_APPROVAL_THRESHOLD` env | | Absolute maximum — hard cap, flag-immune | `100` | `NORTHDATA_ABSOLUTE_MAX` env — set by a human, never by an agent | Never suggest raising either without a clear reason from the user. ## Default workflow (use this order) 1. **Start free.** `suggest`, `reference_*`, `billing` — zero credits. Use them to find the right company / confirm register IDs / check remaining quota before committing. 2. **Dry-run anything billed.** Both surfaces accept `--dry-run` (CLI) or `dry_run=true` (MCP). Use it first when parameters are uncertain — it builds the URL without calling the API. 3. **One `company` call is usually enough.** It returns owners, representatives, financials, sheets, events, contact extras. Don't also call `publications` or `person` unless you specifically need shareholder lists or a person's birth date. 4. **Log watch.** After billed calls, `credits` (CLI) / `local_credit_log` (MCP) shows what this session spent. `billing` shows what NorthData counts remotely. ## Tool reference ### Free tools | Purpose | CLI | MCP | |---|---|---| | Autocomplete a name | `northdata suggest "Example GmbH"` | `suggest` | | Current period usage | `northdata billing` | `billing` | | API reference (standards, countries, …) | `northdata reference overview` | `reference_overview` | | Segment codes for a standard | `northdata reference segments --standard NACE2025` | `reference_segment_codes` | | Local (session) credit log | `northdata credits` | `local_credit_log` | ### Billed tools | Purpose | CLI | MCP | Cost | |---|---|---|---| | Full company profile | `northdata company --name "X" --city "Y"` or `--register "HRB 1/München"` | `company` | **1** | | Person lookup (birth date, roles) | `northdata person Max Mustermann --city München` | `person` | **1** | | Publications (e.g. Gesellschafterliste) | `northdata publications --name "X" --source Hrb` | `publications` | **1** | | Power search (filtered) | `northdata search --segment-codes 62 --legal-forms GmbH --limit 5` | `search` | **up to `limit`** | All billed tools accept `--dry-run` / `dry_run=true`. ## Common workflows ### "Find Company X and tell me about it" 1. `suggest "Company X"` (free) — pick the right one if multiple. 2. `company --register "<register from suggest>"` **or** `--name "<exact name>" --city "<city>"` (1 credit). 3. Done. Owners, representatives, financials, sheets, events all come back in one payload. ### "Who owns / runs Company X?" `company` returns `owners` (Gesellschafter) and `representatives` (Geschäftsführer) in the same response. Don't chain multiple calls — one `company` call is enough. For the **birth date** of a named person (e.g. succession planning), follow up with `person --first-name … --last-name … --city …` (1 credit). ### "Find me companies matching these criteria" Use `search` (power search). Always: - Set `segment_codes` (NACE) and `legal_forms` — an unfiltered search is expensive and rarely useful. - Keep `limit` low (default `5`). Only raise with explicit user approval. - Use `--dry-run` first to sanity-check parameters. - For geo-filters combine `address` + `max_distance_km`. - Indicators: `revenue_min/max`, `earnings_min/max` narrow down the result set before spending credits. Example (CLI): ```bash northdata search \ --segment-codes "62|63" \ --legal-forms "GmbH|UG" \ --address "Munich" --max-distance-km 150 \ --revenue-min 5000000 --revenue-max 50000000 \ --limit 5 --dry-run ``` Verify the URL, then re-run without `--dry-run`. Paginate via the `pos` token in the previous response's `nextPos`. ### "Check if a register ID is valid before I spend a credit" `suggest` returns the canonical `register.uniqueKey` and `register.id`. That's free. Then pass `--register` to `company` exactly as shown. ### "How many credits am I using?" - Remote total (period): `billing` - This session only (local log): `credits` / `local_credit_log` ## Common pitfalls ### `HTTP 404 "not found"` on `company --register` The register string must match NorthData's format. If `"HRB 296816/München"` returns 404, try: 1. `suggest` first — copy the exact `register.id` (e.g. `"HRB 296816"`) and `register.uniqueKey` from the response. 2. Fall back to `--name + --city` — more forgiving than register matching. ### Only `numberOfRequests` seems to count unique calls NorthData's `billing` endpoint returns **unique** requests per period. Repeated identical calls (same company, same day) don't increment the counter. The local credit log counts every attempted call regardless. ### `search` with no segment filter Never run `search` with empty `segment_codes` and `legal_forms`. The credit guard allows it, but the cost/signal ratio is terrible. Always scope. ### Umlauts in register strings URL-encoding is automatic in both surfaces. You can pass `"München"` directly — no manual percent-encoding needed. ### `--approve-high-cost` / `approve_high_cost=true` Only set when the user has explicitly agreed to spend more. Never set preemptively "to make it work". ## Environment knobs | Var | Purpose | |---|---| | `NORTHDATA_API_KEY` | API key (required) | | `NORTHDATA_APPROVAL_THRESHOLD` | Raises the soft threshold (default 25) | | `NORTHDATA_ABSOLUTE_MAX` | Raises the hard ceiling (default 100) | | `NORTHDATA_CREDIT_LOG` | Overrides local log location | ## When the user is stuck | Symptom | Likely cause | Fix | |---|---|---| | `No API key found` | `NORTHDATA_API_KEY` not set | Export it, or (CLI) pass `--api-key` | | `credit-guard: limit=X exceeds APPROVAL_THRESHOLD` | High `--limit` without opt-in | Lower limit or add `--approve-high-cost` | | `credit-guard: limit=X exceeds ABSOLUTE_MAX` | Above hard cap | Split into paginated calls via `pos`, or raise env var | | `api error: HTTP 429` | Rate-limited | Wait, retry later. Client already retries once. | | `api error: HTTP 404` on `company` | Bad register ID or unknown name | Use `suggest` first to get canonical identifiers | | Tools not visible in Claude Desktop | MCP server not registered or Claude not fully restarted | Check `~/Library/Application Support/Claude/claude_desktop_config.json`; fully quit with ⌘Q | ## Resources - NorthData API docs: <https://github.com/northdata/api> - CLI package: `northdata-cli/` (this repo) - MCP server: `northdata-mcp/` (this repo)
don't have the plugin yet? install it then click "run inline in claude" again.
separated intent, inputs, procedure (steps 1-4 with substeps), decision points (11 explicit if-else branches), output contract (each tool's response schema), and outcome signal (7 concrete indicators of success); added edge cases (404 fallback, rate limits, duplicate billing, umlauts, missing API key); preserved original author and clarified M
use northdata to query german commercial registers (HRB, HRA), financial data, and person records. this skill covers both the northdata CLI (claude code / terminal) and the northdata MCP server (claude desktop / any MCP client). trigger on queries about specific german companies (GmbH, UG, KG), owner / geschäftsführer / gesellschafter lookups, revenue / earnings / balance sheet reads, NACE segment searches, geographic filters, credit usage checks, or power-searches for acquisition / lead candidates. use this skill when the user asks about "northdata", "handelsregister", "HRB", "HRA", "gesellschafter", "geschäftsführer", "firma recherchieren", or requests filtered company searches.
required external connections:
NORTHDATA_API_KEY environment variable or --api-key CLI flag. obtain from northdata at https://github.com/northdata/api.pipx install northdata-cli (or available on $PATH).~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or equivalent (linux/windows).optional environment knobs:
NORTHDATA_APPROVAL_THRESHOLD (default: 25): soft credit threshold; queries with limit > threshold require --approve-high-cost flag.NORTHDATA_ABSOLUTE_MAX (default: 100): hard credit ceiling; queries above this fail unless env var is raised by a human operator.NORTHDATA_CREDIT_LOG: override local session credit log file location.context the user provides:
check which tool surface is available in the current environment.
input: current shell / IDE / runtime.
action: in order:
suggest, company, person, search, publications, billing, reference_*, credits, or local_credit_log. if visible, go to step 2a (use MCP).northdata command is on $PATH by running which northdata or northdata --version. if found, go to step 2b (use CLI).pipx install northdata-cli, MCP server registration in claude desktop config.output: decision: "use MCP" or "use CLI" or "not available, setup required".
call one of these to scope the query without spending credits:
suggest(query="Company Name"): autocomplete and canonicalize a company name. returns multiple matches with register.id, register.uniqueKey, and name. use to pick the right entity if ambiguous.billing(): current period usage (remote, counted by northdata). shows total credits spent and remaining quota.local_credit_log(): this session's credit usage (local log). shows every call this session attempted.reference_overview(): list all available reference endpoints (standards, countries, segment codes).reference_segment_codes(standard="NACE2025"): fetch NACE segment codes for filtering.input: user query or parameters.
output: structured response with matches, credits remaining, or reference data.
before calling any billed tool, validate parameters with dry_run=true:
company(name="...", city="...", register="...", dry_run=true): builds the request URL without calling the API. verify the output URL is correct.search(segment_codes="62|63", legal_forms="GmbH", address="Munich", max_distance_km=150, limit=5, dry_run=true): previews filter, does not charge.person(first_name="...", last_name="...", city="...", dry_run=true): previews person lookup.publications(name="...", register="...", source="Hrb", dry_run=true): previews publication search.input: all parameters needed for the real call.
output: request URL and estimated structure, no API call made.
company(register="<ID>" or name="<name>", city="<city>", ...): returns single company profile with owners (gesellschafter), representatives (geschäftsführer), financials (revenue, earnings, balance sheet), published sheets, events, and contact extras. cost: 1 credit. always pass dry_run=true first if unsure about parameters.person(first_name="<>", last_name="<>", city="<>"): returns person record with birth date, roles, and linked companies. cost: 1 credit. use only if you need birth date or shareholder-level details not in company response.publications(name="<>", register="<>", source="Hrb|Hra|Default"): returns historical publications (e.g., gesellschafterliste, amendments). cost: 1 credit. use only if you need change history.search(segment_codes="62|63", legal_forms="GmbH|UG", address="<>", max_distance_km=<>, revenue_min=<>, revenue_max=<>, earnings_min=<>, earnings_max=<>, limit=<>, pos="<pagination token>"): filtered power search. cost: up to limit credits (one per company returned). always set segment_codes and legal_forms to narrow scope. start with limit=5, raise only with explicit user approval. use pos from previous response to paginate.input: billed tool parameters, optionally approve_high_cost=true if limit > APPROVAL_THRESHOLD.
output: structured company / person / publication data or search result list.
northdata suggest "Company Name"
northdata billing
northdata credits
northdata reference overview
northdata reference segments --standard NACE2025
input: query string or command flag.
output: YAML or JSON (depending on shell setup) with matches, credits, or reference data.
northdata company --name "..." --city "..." --dry-run
northdata search --segment-codes "62|63" --legal-forms "GmbH" --address "Munich" --limit 5 --dry-run
northdata person --first-name "..." --last-name "..." --city "..." --dry-run
northdata publications --name "..." --source Hrb --dry-run
input: all flags and parameters for the intended call.
output: curl command and request URL, no API call made. verify URL before proceeding.
# company lookup by register ID (preferred if register ID is known)
northdata company --register "HRB 296816/München"
# company lookup by name and city (more forgiving)
northdata company --name "Example GmbH" --city "Munich"
# person lookup (1 credit, returns birth date and roles)
northdata person --first-name "Max" --last-name "Mustermann" --city "Munich"
# publications (1 credit, returns historical versions)
northdata publications --name "Example GmbH" --source Hrb
# power search with filters (up to N credits, where N = limit)
northdata search \
--segment-codes "62|63" \
--legal-forms "GmbH|UG" \
--address "Munich" --max-distance-km 150 \
--revenue-min 5000000 --revenue-max 50000000 \
--limit 5
if limit > NORTHDATA_APPROVAL_THRESHOLD (default 25), add --approve-high-cost.
input: command flags and parameters.
output: JSON or YAML response (check northdata --help for format options). if rate-limited (HTTP 429), wait and retry.
input: response from step 2a-iii or 2b-iii.
action:
company call: extract owners (gesellschafter), representatives (geschäftsführer), revenue, earnings, balance sheet, and events from the single response. do not call person or publications unless user explicitly asks for birth dates or historical amendments.search call: list results with company names, registers, segments, and key indicators. if more results exist (indicated by nextPos in MCP or pos in CLI output), ask the user before paginating (each page costs credits).person call: return birth date, roles, and linked companies.publications call: return publication dates, amendment text, and signature information.output: curated company profile, search results, person details, or publication history.
after any billed call:
local_credit_log() to see what this session spent. call billing() to see remote total (period usage as counted by northdata).northdata credits for session log, northdata billing for period total.if the user is surprised by the bill, check billing() output: northdata counts unique requests per period, not total calls. repeated identical calls (same company, same day) do not double-charge.
output: credit usage summary and remaining quota.
if MCP tools are visible and CLI is also on $PATH: prefer MCP. it provides clearer tool telemetry and structured error messages. only fall back to CLI if the user is inside a shell-driven context (e.g., debugging, bulk automation).
if dry_run=true (MCP) or --dry-run (CLI) returns an error:
likely cause: bad parameter format or missing required field. do not proceed to the real call. ask the user to confirm the parameter (e.g., exact register ID format, NACE segment code syntax). call suggest or reference_segment_codes to validate.
if API returns HTTP 404 on a company call:
the register string may not match northdata's format. do this in order:
suggest(query="Company Name") and copy the exact register.id from the response.company(register="<exact ID from suggest>").company(name="...", city="...") (more forgiving than register matching).if API returns HTTP 429 (rate-limited): the session has exceeded rate limits. wait at least 60 seconds and retry. both MCP and CLI clients already retry once automatically. if repeated 429s occur, spread calls over multiple minutes or contact northdata support.
if limit > NORTHDATA_APPROVAL_THRESHOLD and no --approve-high-cost / approve_high_cost=true is set:
the credit guard blocks the call. either lower limit (recommended: start with 5) or ask the user: "this search will cost up to N credits. approve?" if yes, add the flag and retry.
if limit > NORTHDATA_ABSOLUTE_MAX even with the flag:
only a human operator can raise the hard ceiling via env var. inform the user: "this exceeds the hard limit. contact your account admin to raise NORTHDATA_ABSOLUTE_MAX." or suggest paginating via pos / pagination tokens across multiple smaller calls.
if the user asks "who owns / runs company X":
a single company call returns both owners (gesellschafter) and representatives (geschäftsführer). do not call person or publications unless the user specifically needs birth dates or shareholder lists.
if the user asks for a person's birth date:
call person(first_name="...", last_name="...", city="..."). this costs 1 credit and returns birth date, roles, and linked companies. this is only available if you have a specific person's name and approximate location.
if search has no segment-codes or legal-forms filter:
do not run the search. the cost/signal ratio is terrible (high credits, low relevance). always scope with segment_codes and legal_forms before calling search. if the user is unsure, call reference_segment_codes(standard="NACE2025") to find the right codes.
if the user provides a register string with umlauts (e.g., "HRB 1/München"): both surfaces handle URL-encoding automatically. pass it as-is. do not manually percent-encode.
if NORTHDATA_API_KEY is not set:
both MCP and CLI will fail with "no API key found". CLI accepts --api-key flag; MCP requires env var. ask the user to export the key or pass the flag.
successful company call (MCP or CLI):
register.id, register.uniqueKey, name, city, legalForm, owners (array of gesellschafter with names and roles), representatives (array of geschäftsführer), financials (object with revenue, earnings, balance sheet lines), sheets (published financial statements), events (register amendments and filings), contact (phone, email, website if available).successful person call:
firstName, lastName, birthDate (if available), roles (array of company roles and titles), linkedCompanies (array of company registers).successful search call:
results (array of company summaries, each with register.id, name, city, legalForm, segment, revenue, earnings), totalCount (total matching companies, may exceed limit), nextPos (pagination token for next page if results exist).successful suggest call:
register.id, register.uniqueKey, name, city, status.successful billing / credits call:
creditsUsed (period or session total), creditsRemaining, creditsLimit, period (month/year for remote; session for local).successful dry-run call:
--dry-run or dry_run=true: returns request URL and estimated response structure; no charges incurred.error responses:
credit-guard error: limit exceeds threshold or absolute max. include current limit and threshold values.the user knows the skill worked when:
company lookup: the response displays the company name, register ID, owners (gesellschafter) and representatives (geschäftsführer) with full names and roles, and financials (revenue, earnings, balance sheet extracts, fiscal year). the user can immediately answer "who runs this company?" and "what's their revenue?"
person lookup: the response shows the person's full name, birth date (or "not public"), and a list of companies they are linked to (as geschäftsführer, gesellschafter, etc.).
search result: the response lists 5 (or user-specified limit) companies matching all filters (NACE segments, legal forms, geographic bounds, financial ranges). each row shows company name, register ID, segment, city, and key indicators. user can click register links or copy IDs for follow-up company calls.
suggest autocomplete: the response returns the company name the user typed, plus alternative matches if ambiguous, each with a canonical register.id ready to paste into company --register.
billing / credits report: the response shows credits used (this session or period) and remaining quota. if the user spent credits, the report matches their expectation (e.g., 5 companies searched = 5 credits). if the user thought they ran 10 calls but the billing shows 2, they learn that duplicate calls don't double-charge.
--dry-run / dry_run=true preview: the response shows the exact URL that would be called and the expected response structure, with a clear message "no charges incurred". user can verify parameters before committing.
error recovery: if a call fails with HTTP 404 or a credit-guard block, the skill output includes the exact reason and the next step (e.g., "use suggest to get the canonical register ID", or "add --approve-high-cost and retry").