agentic-firmenbuch
Query Austria's official Firmenbuch (company register) in plain language over MCP — search ~341k companies, pull full financial profiles and ratios, read filings, and track register changes.
Find companies (
search_companies): filter/rank by name, region (Bundesland, city, PLZ, radius), ÖNACE industry, legal form, size class, balance-sheet total, revenue, equity ratio, EBIT/EBITDA, employees, growth, founding year, management age, filing year, status, and register-event signals; supports relevance queries, keyset paging and sort by any metric.Inspect one company (
get_company_details): identity, location, multi-year balance sheet + P&L, computed ratios, growth, employees, management, filings — with optional section/history trimming.Get the raw complete record (
get_full_record): full 317-position UGB taxonomy, unknown-code passthrough, completeness flags, GuV years, signatories, lineage.Analyze time series (
get_company_history): per-metric yearly values for one company or a batch of up to 50 FNRs.Compare and benchmark (
find_peers,benchmark_company): nearest same-size/same-industry peers and percentile ranks within a size class.Aggregate (
get_cohort_summary,get_coverage,get_event_stats): cohort statistics, dataset coverage breakdown, and register-change counts by type/region.Follow register changes (
list_events): cross-company feed of name/seat/form/capital/management changes plus M&A, restructuring, founding, deletion events — for deal sourcing and watchlists.Read the source documents (
list_documents,get_document,get_document_text): newest-first document chronology, signed download links for XML/PDF filings, and extracted text of Anhang/Lagebericht.Explore the schema and codes (
describe_fields,list_sectors,list_sectors(query=…)): field dictionary with types/null rules, plus valid legal-form, size-class and ÖNACE codes with counts.People search (
search_persons): find companies by an officer/representative's name.Export and account (
export_companies_csv,get_my_usage): semicolon-separated CSV lead lists up to 10k rows with a time-limited link, and your own usage/plan/credit balance.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@agentic-firmenbuch Find active GmbHs in Vienna with revenue over 1 million."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
agentic-firmenbuch
Austria's entire company register, queryable by AI agents in plain language. Official master data, annual accounts and key ratios for every firm – served over MCP, answered on real numbers instead of hallucinations.
Try the playground · Start free: 50 credits, 7 days · Quickstart ↓
A live, automated data product over the Austrian Firmenbuch (free EU HVD / High Value Datasets), served through a multi-tenant MCP server. A deterministic Azure pipeline pulls the published Jahresabschluss (annual financial statement) filings from the official register, parses them, consolidates per company, computes ratios/growth/trends, and serves the result to MCP clients. The whole register holds ~640k legal entities; the served slice is currently ~341k and grows as the backfill progresses. Version 1 = facts + clean derivations only (no scoring, no third-party enrichment, no NACE, no AI summaries).
Also available: Germany and the wider DACH region. Alongside this Austrian product, a unified
agentic-registerendpoint serves both the Austrian Firmenbuch and the German Handelsregister / Unternehmensregister over a single MCP. It is listed in the official MCP registry asio.github.jkbngb/handelsregister(spec:handelsregister.server.json) and reachable athttps://register.agentic-firmenbuch.at/mcpwith the same account and the same access rules (free trial, then Pro). A search returns matches from both countries, tagged bycountry(AT/DE).
Quickstart
Use the hosted service – query official Firmenbuch data from an MCP client that accepts an HTTP header key (Claude Code, VS Code with GitHub Copilot, Cursor, …):
Get an API key at agentic-firmenbuch.at. Every new account starts with 50 free credits, valid for 7 days (1 credit per company, so about 50 companies), one allowance shared by the web console and Claude. After the trial, access from Claude, Cursor or any MCP/API client needs Pro at €79/month plus VAT: unlimited queries within fair-use limits (10,000 calls per day, 20,000 export rows and 50 documents per month), cancel monthly. Credit packs are a web-console product and do not unlock MCP/API access. (Connecting via a sandboxed client like Claude Cowork/claude.ai grants the 50 credits on first connect, no key needed, see below.)
Add the server. Claude Code (terminal), one line:
claude mcp add --scope user --transport http agentic-firmenbuch https://mcp.agentic-firmenbuch.at/mcp --header "X-API-Key: <your-key>"GitHub Copilot / VS Code:
code --add-mcp "{\"name\":\"agentic-firmenbuch\",\"type\":\"http\",\"url\":\"https://mcp.agentic-firmenbuch.at/mcp\",\"headers\":{\"X-API-Key\":\"<your-key>\"}}". Any other HTTP-MCP-Header client: URLhttps://mcp.agentic-firmenbuch.at/mcp, headerX-API-Key: <your-key>.Ask in natural language, e.g. "Aktive GmbHs in Oberösterreich mit Bilanzsumme über 5 Mio. €, sortiert nach Umsatz." The agent calls
search_companies/get_company_detailsand answers with official data – no SDK required.
Claude Cowork & claude.ai (sandboxed clients) don't take the API-key header – they connect via
Settings → Connectors → Add custom connectorwith the URLhttps://mcp.agentic-firmenbuch.at/mcpand a one-time email login (OAuth, no key). Step-by-step with screenshots: agentic-firmenbuch.at/cowork.html.
Prefer to try before signing up? Use the playground.
Or run the pipeline yourself – clone, uv sync, uv run pytest (offline, no Azure). See Develop.
Related MCP server: companylens-mcp
Available MCP tools
Tool | Purpose |
| Filter / rank Austrian companies by region, size, balance-sheet total, equity ratio, revenue, growth profile, management age, last filing year, status. Returns a compact result card per match. |
| Full served profile of one company: identity, location, founding/filing years, size class, multi-year balance sheet + P&L, 13 computed ratios, growth, management, list of filings. |
| Superset of |
| Filing-by-filing time series of every reported position — one company, or a batch via |
| K-nearest peer set for a company within its size class / region. |
| Aggregate statistics (counts, percentiles, distributions) for a filtered cohort. |
| Per-Bundesland / per-Rechtsform / per-size-class coverage statistics for the served dataset. |
| Available legal-form ( |
| Self-describing field dictionary with type + null-rules + EBIT/EBITDA definition. |
| Fetch the URL/blob key for an original filed annual statement (XML or PDF). |
| Return the extracted text of a filed annual statement (parsed XML/PDF) for direct reading. |
| One newest-first chronology of a company's Abschluss documents: filed annual statements plus register-held PDFs (Konzernabschluss, HV-Protokoll) with their Dokumentart. |
| Find companies by an officer / representative (managing directors, board members, signatories) by name. |
| Position one company against its peer cohort (percentile ranks on key metrics). |
| Register-change events (name/seat/legal-form/capital/management changes, derived daily since 2026-07) for a company or cohort. |
| Aggregate event statistics (counts by type/period) across a filtered cohort. |
| Export a filtered company set as a CSV download (server-generated, time-limited link). |
| The caller's own usage, plan, remaining trial credits and the upgrade link. |
| Connection test; always free. |
All tools return a processed derivative of official Austrian Firmenbuch data (source: BMJ – Justiz, CC BY 4.0). Concretely: we ingest the published filings from the register, parse and consolidate them, compute ratios, and serve that from our own database — no web scraping, no LLM-generated summaries, no third-party data mixed in (V1). Every response carries provenance.data_version + built_at and names the original source, so the agent can attribute it correctly; for the authoritative record, the official Firmenbuch always governs.
Currently served: ~341,000 active legal entities across all Rechtsformen (GmbH, AG, KG, OG, EU, Genossenschaft, Privatstiftung, SE …). The full register has ~640,000 entities; the gap is companies without a published Jahresabschluss plus inactive/deleted entries, which are added step by step.
Documentation
Full index with the versioning convention (shipped _v1 specs vs. the forward
ROADMAP.md + V2 design spec): docs/README.md.
The headline documents:
Doc | What it is |
File format + golden sample for every pipeline stage. | |
Served field dictionary – every field each MCP tool returns, with type + null rules. Public page: felder.html. | |
Forward plan – status/priorities and the V2 direction (banks/insurers, GISA, Ediktsdatei). | |
Full 317-entry canonical position taxonomy → copied into | |
Official source material (API reference, JAb 4.0 XSDs/Excel). |
Monorepo layout (agentic-first)
This repository is the agentic-first monorepo umbrella. It separates source-agnostic
shared code from per-source products, so another source-specific product can be added without
touching the Austrian pipeline:
agentic-first/ (this repo)
├── packages/ SHARED — source-agnostic, zero Firmenbuch/UGB knowledge
│ ├── core/ (fbl_core) lineage/meta + metric contracts, config, storage clients
│ └── auth/ (fbl_auth) signup, token issue/validate, metering, 00_accounts
└── products/
└── agentic-firmenbuch/ AUSTRIA product (live) — README below
├── packages/
│ ├── core_at/ (fbl_core_at) UGB taxonomy, Firmenbuch domain models, ÖNACE, FI dirs
│ ├── firmenbuch_client, 99_registry, 90_ingest, 70_parse,
│ │ 50_consolidate, 30_derive, 10_present, mcp_server, orchestration
│ └── …
└── tests/ AT integration tests + golden fixturesAdditional source-specific products are added in their own separate repositories that consume
packages/{core,auth} as a dependency (they are not scaffolded here). The precise
1:1 / adapt / product-local reuse boundary is the reuse table (Appendix R) of the technical spec, and the generic recipe is in
docs/monorepo/ADDING_A_PRODUCT.md.
Product READMEs: agentic-firmenbuch · shared core · auth
Pipeline (numbered layers, 90 → 10)
99_registry (foundation: all companies) → 90_raw (Blob) → 70_parsed (Blob) → 50_consolidated → 30_derived → 10_presentation → MCP
(Cosmos) (Cosmos) (Cosmos)
side: 00_accounts (MCP signup) · 00_directories (register-based FI flag, OeNB) reserved for v2: 40_enriched, 20_scored90_raw is the immutable source of truth (every downloaded XML/PDF, kept forever). 70_parsed
is a write-through cache of the per-filing ParsedFiling JSON – always re-derivable from raw,
so safe to drop/rebuild; it exists so a reprocess (re-consolidate/derive after a logic change)
skips re-parsing all filings, and so the lineage inputs[] in each consolidated doc resolve to a
real parsed document. 50/30/10 are the queryable Cosmos layers; 10_presentation is what the MCP
serves.
LAYER_MAP – which code owns which layer
Each pipeline-stage package directory is prefixed with its layer number so the
owner of every data layer is obvious. (Python module names can't start with a digit, so
the importable package keeps its fbl_* name; the number is also exposed as a LAYER
constant in each stage package.)
All AT stage packages live under products/agentic-firmenbuch/packages/ (abbreviated …/ below).
Layer | Package (dir) | import | Store / container | Pydantic model | Sample |
|
| Cosmos |
| §15a.0 doc | |
|
| Blob | raw | ||
|
| Blob |
| ||
|
| Cosmos |
| ||
|
| Cosmos |
| ||
|
| Cosmos |
|
Un-numbered. Shared (in packages/): core (fbl_core,
source-agnostic lineage/meta + metric contracts, config, storage) and
auth (fbl_auth, 00_accounts). AT-specific (in
products/agentic-firmenbuch/packages/): core_at
(fbl_core_at, UGB taxonomy + Firmenbuch domain models + ÖNACE + FI directories),
firmenbuch_client
(fbl_firmenbuch_client, HVD SOAP adapter),
orchestration
(fbl_orchestration, the --mode Job entrypoint),
mcp_server
(fbl_mcp_server, serving). Plus products/agentic-firmenbuch/tests/ (fixtures),
docs/ (incl. API probe findings).
Build status – live in production ✅
All build stages are implemented and the service is live in production: the multi-tenant MCP server is
deployed, the daily pipeline runs on a cron, and the backfill keeps growing the served slice. Since the V1
launch the register has gained semantic vector search, ÖNACE/WZ industry classification, register-change
events, German Handelsregister coverage through the unified endpoint, and the trial-then-Pro access model
described above. ruff + mypy --strict + pytest (with an 80% coverage gate) are green in CI;
deployment of the backend is manual after review.
Develop
uv sync # create the workspace venv
uv run pytest # all fixture/unit/integration tests (offline)
uv run mypy packages products # strict types (shared + products)
uv run ruff check packages products # lintTrue end-to-end (live): a separate, env-flag-guarded test runs a few real FNRs
through every layer (API → 90_raw → … → 10_presentation → MCP). Skipped by default.
FBL_E2E=1 uv run pytest products/agentic-firmenbuch/tests/e2e -q # needs FIRMENBUCH_API_KEYSee products/agentic-firmenbuch/tests/e2e/. It uses in-memory stores + a tiny real pull –
no Azure, no full backfill (deployment is manual after review).
License & data
Licensed under the MIT License (see LICENSE).
The data originates from the Austrian Firmenbuch (BMJ – Justiz), an EU High Value Dataset
licensed under CC BY 4.0. Any redistribution of the data must keep the attribution
"Quelle: Österreichisches Firmenbuch / BMJ – Justiz (CC BY 4.0)" (see NOTICE).
Disclaimer – no warranty, use at your own risk
This software and any data it produces are provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or implied (see the MIT License). The processed data is derived automatically from the public Firmenbuch and is provided without any guarantee of correctness, completeness, timeliness, or fitness for a particular purpose. It is not legal, tax, or financial advice and does not replace an official Firmenbuch extract – the official register always prevails.
Use of this software and the data is entirely at your own risk. To the maximum extent permitted by law, the authors and copyright holders accept no liability for any direct, indirect, incidental, or consequential damages arising from its use. You are responsible for complying with the CC BY 4.0 attribution requirement and all applicable data-protection, competition, and copyright law when using or redistributing the data.
Available Tools
18 toolsbenchmark_companyBenchmark a company vs peersARead-onlyIdempotentInspect
Where one company stands in its peer group — a composite over find_peers + the company's precomputed size-peer percentiles. Read-only. Pro.
Parameters:
- fnr (required): the company's Firmenbuchnummer, e.g. "123456a" (an "AT:" prefix is
tolerated).
- n (optional, default 10, clamped 1..50): how many peers to include.
Returns the company's headline metrics (bilanzsumme, revenue, equity_ratio, growth_profile),
its `percentiles` WITHIN its UGB size class (100 = top of the class; available for
bilanzsumme and equity_ratio), and the nearest peers (same size class, same ÖNACE section
preferred, recent filers only: last Jahresabschluss within 3 years, widened once to 5 when
too few exist, see `peer_recency` + `peers_note`; each peer carries `latest_year`). Use for
"how does X compare to its peers"; for the raw peer list use find_peers, for whole-cohort
aggregates use get_cohort_summary.
Inputs: fnr (required), n. Returns: object
describe_fieldsDescribe available fieldsARead-onlyIdempotentInspect
Catalog of every field the server can return, by tool tier (search card -> full profile -> full record), with code tables and availability/null rules. Read-only, no parameters.
This describes the SCHEMA only (field names, types, code tables, null rules) so you can
pick the right tool and interpret its output. It returns no company data itself; for that
call search_companies (many) or get_company_details / get_full_record (one). Call this
once up front when unsure what a field means or which tool to use.
Human-readable version: https://www.agentic-firmenbuch.at/felder.htmlInputs: no named parameters. Returns: object
export_companies_csvExport companies to CSVARead-onlyInspect
Export a whole search result set as ONE downloadable CSV file (a lead list) instead of paging through search_companies 25 rows at a time. Read-only over company data; each call writes a new short-lived export file (auto-deleted after ~1 day).
Use this when the user wants a list to open in Excel / import elsewhere ("exportiere",
"als CSV/Liste", "alle GmbHs in … herunterladen"). For browsing or ranking on screen use
search_companies; for one company's full profile use get_company_details.
Parameters:
- filters (optional): a SearchFilters object — EXACTLY the same filters as search_companies
(name; legal_form; bundesland/city/postal_code; near radius; oenace_division/group /
geschaeftszweig; size_gkl; bilanzsumme / revenue / equity_ratio / employees ranges
(equity_ratio as a fraction, 0.35 = 35 %; percent values auto-converted);
growth_profile; founded/last-filing years; gf_age_min; manager_name; status). AND-joined.
- sort (optional): {field, descending}, same fields as search_companies (default bilanzsumme
descending; "distance" with a near filter).
- max_rows (optional, default 1000, hard maximum 10000): row ceiling. Free plan is capped at
100 rows with basic columns only. For a set larger than 10000, refine the filters
(Bundesland/Branche/Größe) and export in parts.
CSV format: semicolon-separated, UTF-8 with BOM (opens cleanly in Excel-DE, umlauts intact).
Columns are exactly the search card fields: fnr, name, legal_form, street, postal_code,
city, bundesland, industry_section, oenace_division(+label), geschaeftszweig, size_gkl,
bilanzsumme_latest, equity_ratio_latest, revenue_latest, growth_profile, manager_name, and
distance_km when a near filter is used. Empty values are blank cells. No fields beyond the
card — the same personal-data gating applies.
Returns {rows, download_url, expires_minutes (60), columns, truncated, note}. The
download_url is a signed link valid for 60 minutes (3600 s; exact expiry in
`download.expires_at` — open it promptly, don't expect bytes inline); the underlying
file is deleted after about one day. When the result was capped (truncated=true), the
note says so and asks you to refine.
Field reference: https://www.agentic-firmenbuch.at/felder.html
Inputs: sort, filters, max_rows. Returns: object
find_peersFind peer companiesARead-onlyIdempotentInspect
Find the companies most similar in size to a given one. Read-only.
Parameters:
- fnr (required): the reference company's Firmenbuchnummer, e.g. "123456a".
- n (optional, default 10, clamped to 1..50): how many peers to return.
Returns up to `n` companies in the SAME size class (`gkl`) as the reference, preferring
the same ÖNACE industry as SPECIFICALLY as possible: the cascade class -> group ->
division -> section widens only when a level has too few companies, and any remaining
slots are filled with the nearest same-size companies from other industries — closest by
Bilanzsumme within the class and group levels; on broader levels a reference with a
registered activity text gets the most similar activities first. Each is a compact card
like search_companies. The response
carries `same_sector_level` ("class"/"group"/"division"/"section"/null: how specific the
industry match is), `same_sector_count`, and an explicit `note` when the match is only
section-wide or the list is (partly) a pure size-neighbourhood — so you never mistake
same-size-different-industry rows for a sector benchmark (e.g. holdings whose stated
industry differs from the group's). The reference company is excluded; an empty list means
the FNR is unknown or has no Bilanzsumme to rank against. Recency: only companies whose
last Jahresabschluss is from the current year minus 3 or later qualify; when fewer than
`n` class/group-level peers exist in that window it widens once to minus 5 and the `note`
says so (`peer_recency` = {years, min_year, widened}); every peer row carries
`latest_year`. For a strict industry benchmark, filter search_companies by oenace_* + size
instead; for group aggregates use get_cohort_summary.
Inputs: fnr (required), n. Returns: object
get_cohort_summaryCohort statisticsARead-onlyIdempotentInspect
Aggregate statistics for a cohort of companies. Read-only.
Parameters:
- dimension (required): which axis defines the cohort, one of "gkl" (size class),
"bundesland" (federal state), or "legal_form" (Rechtsform). The search-filter alias
"size_gkl" is accepted for "gkl".
- value (required): the cohort value on that axis, e.g. dimension="bundesland",
value="Wien" (full name or the code "W" both work); dimension="gkl", value="M".
Use list_sectors to see valid legal_form / gkl values.
Returns cohort counts plus distribution statistics (e.g. Bilanzsumme median; the exact
median is skipped for very large cohorts to keep the request fast), NOT per-company rows.
Use for "what does group X look like in aggregate"; for the individual companies use
search_companies, for one company use get_company_details.
Inputs: value (required), dimension (required). Returns: object
get_company_detailsCompany profileARead-onlyIdempotentInspect
Full served profile for one company by FNR. Read-only.
Parameters:
- fnr (required): Firmenbuchnummer, e.g. "123456a" (the `fnr` from a search card).
- include (optional): which optional sections to serve, subset of
["bilanz", "guv", "ratios", "management", "events", "industry"]; omit for ALL sections
(the full profile). Identity, location, company, size, filings and the financials
scalars (latest values) are always included. Use this to keep the response small when
you only need part of the profile.
- history (optional, default true): false drops the per-metric year series (the latest
values stay) — use get_company_history when you later need a specific trend.
Null fields are omitted from the response (a missing key means "no data for this
company"; describe_fields documents every field that CAN exist). Returns one company's
identity, location, financials (per-year Bilanz + GuV), all computed ratios, growth,
employees, filings, and management. Use when you already know the company
(from search_companies); for the complete record (full position taxonomy, unknown-code
passthrough, per-year lineage) use get_full_record; for specific metric trends use
get_company_history.
Field reference: https://www.agentic-firmenbuch.at/felder.html
Inputs: fnr (required), history, include. Returns: object
get_company_historyCompany financial historyARead-onlyIdempotentInspect
Per-metric multi-year time series for one company — or a whole cohort. Read-only.
Parameters:
- fnr: Firmenbuchnummer, e.g. "123456a" (the `fnr` from a search card) — one company.
- fnrs: list of up to 50 Firmenbuchnummern for a BATCH in one call (a Branchenradar
over a 30-200 cohort pages through this instead of one call per company). Unknown
numbers land in `result.not_found`; billing stays per company (1 credit each),
only companies actually returned are charged. Pass fnr OR fnrs.
- metrics (optional): list of metric names to return, e.g.
["bilanzsumme", "umsatzerloese", "eigenkapital"]; omit to get every available series.
The card alias "revenue" is accepted for "umsatzerloese".
Returns, per requested metric, the yearly values (year -> value) plus latest/latest_year
(batch: the same shape per company under `result.companies`). Use when you need the
trend of specific figures; for a full one-shot profile use get_company_details, for
the complete record (all positions) use get_full_record.
Inputs: fnr, fnrs, metrics. Returns: object
get_coverageDataset coverageARead-onlyIdempotentInspect
How much of the register we actually serve, as an aggregate dashboard. Read-only, no parameters.
Returns coverage counts broken down by data availability — companies with parsed XML
financials vs PDF-only (linked but not machine-readable) vs none — and by format/status, so
you can gauge what share of the universe has usable financials. It is a dataset-wide
overview (served O(1) from a precomputed stats doc), NOT per-company data, no filters. Use
for "how complete is the data"; for the valid filter values use list_sectors, for one
group's aggregate figures use get_cohort_summary.
Inputs: no named parameters. Returns: object
get_documentDownload annual filingARead-onlyIdempotentInspect
Get a time-limited download link to a company's official Jahresabschluss document. Read-only.
Parameter:
- doc_key (required): a filing's `document_ref` ("{fnr}:{stichtag}") from
get_company_details, a bare FNR (-> latest filing), or a legacy doc_key.
Returns `download.url`, a signed link valid for 15 minutes (900 s; the exact expiry is
`download.expires_at` / `expires_in_seconds` in the response — open it promptly, don't
expect bytes inline), plus the `financial_institution` flag + caveat for banks/insurers,
whose figures live only in the PDF. If the PDF is not in the archive yet it is fetched
on demand from the register (the first call for a year can take up to ~1 minute);
`download` is null only when the register itself holds no document for that filing. Use to
fetch the original filing artifact; for the already-parsed figures use
get_company_details / get_full_record instead of downloading.Inputs: doc_key (required). Returns: object
get_document_textRead annual filing textARead-onlyIdempotentInspect
Return the TEXT of a company's official Jahresabschluss filing so you can read the Anhang, Lagebericht and positions directly (XML filings are flattened to "label: value" lines, PDF filings are text-extracted). Read-only.
Parameters:
- doc_key (required): a filing's `document_ref` ("{fnr}:{stichtag}") from
list_documents / get_company_details, or a bare FNR (-> latest filing).
- max_chars (optional, default 40000, max 120000): cap on the returned text;
`truncated` tells you when the document is longer.
Use for questions about the wording of a filing ("Was steht im Lagebericht zum
Ausblick?", "Welche Risiken nennt der Anhang?"). For the parsed figures use
get_company_details; for a download link use get_document. Cite the Stichtag.Inputs: doc_key (required), max_chars. Returns: object
get_event_statsRegister change statisticsARead-onlyIdempotentInspect
Aggregate counts of register changes by type and by Bundesland over a window. Read-only. Pro. Use for market-watch dashboards ("how many capital increases in OÖ this month"); for the individual changes use list_events.
Parameters (all optional): since / until (default last 30 days); bundesland; oenace_section;
oenace_division; legal_form — same facets as list_events. Returns {since, until, total,
by_type, by_bundesland}. Forward-only from 2026-07-01.
Inputs: since, until, bundesland, legal_form, +2 more. Returns: object
get_full_recordFull company recordARead-onlyIdempotentInspect
Complete per-company record, the full superset we hold for one company. Read-only.
Parameter:
- fnr (required): Firmenbuchnummer, e.g. "123456a" (the `fnr` from a search card).
Returns everything: every position's full per-year history, unknown-code passthrough
(nothing dropped), completeness flags, guv_years, and lineage (§5.1). This is the heaviest
read. Use it when you need raw completeness; for the normal curated profile use
get_company_details, for a single metric's trend use get_company_history.
Inputs: fnr (required). Returns: object
get_my_usageMy API usageARead-onlyIdempotentInspect
Your own API-key usage: call count and weighted compute-units, per tool. Read-only.
Parameter:
- window (optional, default "today"): one of "today", "yesterday", "month_to_date",
"last_30_days", "all".
Returns only the calling key's own usage (totals + per-tool breakdown) for that window,
plus `plan` (the plan in force). Credit-metered accounts additionally get `credits_used`
(credits charged in the window), `credits_remaining` (current balance) and the `credits`
block with per-lot detail — for them, Credits are the billing unit (calls/compute_units
are internal telemetry; failed attempts cost 0). Free-plan keys use this to check their
consumption against the monthly free quotas. Never another user's data and never the
e-mail behind the key.Inputs: window. Returns: object
list_documentsList company documentsARead-onlyIdempotentInspect
List a company's available official documents, newest first. Read-only, metadata only.
Parameter:
- fnr (required): Firmenbuchnummer, e.g. "123456a" (an "AT:" prefix is tolerated).
Returns ONE merged chronology, strictly newest-first: every entry is
{type, stichtag, financial_year, document_ref, format, parsed, note?}. Two types:
`annual_financial_statement` (a filed Jahresabschluss; `parsed=true` means figures are
served) and `abschluss_document_pdf` (an Abschluss-carrying PDF the register holds beyond
the plain filing — Konzernabschluss, HV-Protokoll m. Jahresabschluss, Lagebericht — with
its `dokumentart` label; always `parsed=false`). A Konzernabschluss next to the same
year's Jahresabschluss is a DIFFERENT document, not a duplicate. Years held only as PDF
appear with `parsed=false` + a `note` — no extracted figures, but the original stays
downloadable (an honest gap, never silent). Pass any entry's `document_ref`
("{fnr}:{stichtag}") to get_document for a signed download link. No download link and no
personal data here — use get_document for the file, get_company_details for the figures.
Inputs: fnr (required). Returns: object
list_eventsRegister change feedARead-onlyIdempotentInspect
Cross-company feed of register CHANGES (Vollzuege), newest first — the market-watch / deal-sourcing surface. Read-only. Pro.
Answers "which companies changed X, where, since when" in one call — e.g. management
changes, capital increases, relocations across a region or industry, or a watchlist of FNs.
For the change history of ONE known company, use get_company_details (its `events[]`).
Parameters (all optional, AND-combined):
- types: DETAILED (with before/after values), forward from 2026-07-01: "name_change",
"seat_change", "legal_form_change", "capital_change", "management_change". COARSE
historical (type + date only, source=change_feed, back to ~2020): "founding", "deletion",
"merger",
"split", "conversion", "contribution", "consolidation", "division",
"shareholder_capital_change", "management_join", "management_leave". Omit for all. The
M&A/restructuring types (merger/split/conversion/…) + capital_change + deletion are the
deal- and distress-signal surface.
- since / until: ISO dates ("2024-01-01"). Default window: the last 30 days.
- bundesland: full name ("Wien") or code; oenace_section (letter) / oenace_division
(2-digit); legal_form ("GmbH" or a Firmenbuch code) — same facets as search_companies.
- fnrs: restrict to these Firmenbuchnummern (a watchlist).
- page (1), page_size (25, max 100).
Returns {total, page, page_size, since, until, events:[{fnr, name, date, type, description,
source, capital_from, capital_to, managers_added, managers_removed, bundesland,
industry_section}]}. `source` is "change_feed" for the coarse historical events (no
before/after values) vs the detailed daily-diff events. An empty result means no matching
change in the window (not missing data).
Field reference: https://www.agentic-firmenbuch.at/felder.html
Inputs: fnrs, page, since, types, +6 more. Returns: object
list_sectorsList sectors & legal formsARead-onlyIdempotentInspect
Valid filter values for search_companies, with company counts. Read-only.
Optional `query`: a German category word or phrase ("Brauereien", "Steuerberater",
"Softwarefirma") -> `matches` with the ÖNACE level, code, official label, an activity
concept and the search_companies filter to use (oenace_section/division/group). Use this
instead of guessing a code; a concept-only match means "use filters.query".
Returns the legal-form (Rechtsform) codes and the size-class (`gkl`: W/K/M/G) values
present in the served dataset, each with its count. Call this first to discover the real
`legal_form` / `size_gkl` values to pass to search_companies or get_cohort_summary, instead
of guessing codes. For region/format coverage instead, use get_coverage.
Inputs: query. Returns: object
search_companiesSearch Austrian companiesARead-onlyIdempotentInspect
Find or look up Austrian companies by name — START HERE for any company lookup.
This is the primary entry point: search/find/look up companies by NAME (substring) or
filter by location, industry, legal form, size or financials, ranked. Whenever the user
names a company or wants a list of companies, call THIS tool first (you do not need the
Firmenbuchnummer/FNR to search by name). Read-only.
Parameters:
- filters (optional): a SearchFilters object; every field is optional and AND-combined
(name substring; legal_form; bundesland; oenace_section/division/group and the
4-digit oenace_class for one exact activity (11.05 = breweries; list_sectors(query=…)
resolves a category word to the code); size_gkl W/K/M/G; bilanzsumme / anlagevermoegen
/ revenue / equity_ratio / employees min+max ranges; growth_profile; has_guv;
last_filing_year_min;
founded_year_min/max; gf_age_min; status active/inactive/all). Omit for an unfiltered
list. Full-name inputs like "Wien" or "GmbH" are mapped to stored codes automatically.
equity_ratio_min/max are FRACTIONS of the Bilanzsumme (0.35 = 35 % Eigenkapitalquote);
percent-style values (>1.5, up to 100) are auto-converted /100, so 35 and 0.35 both
mean 35 %.
- sort (optional): {field, descending}; the sort field for the founding year is
"founded_year" (never founded_year_min); an unknown field is rejected with the list
of valid ones. field in {bilanzsumme, anlagevermoegen, revenue, equity_ratio,
employees, last_filing_year, founded_year, revenue_growth_1y, revenue_growth_3y,
revenue_growth_5y}
(Umsatzwachstum: 1y YoY, 3y/5y CAGR; only companies with a multi-year GuV have them, the
rest sort last) (or "distance" with a near filter); default bilanzsumme
descending. Companies missing the sort field sort last. An unknown sort field is
rejected with the list of valid ones. With a `query`, the matched companies are
relevance-ranked by DEFAULT; pass an explicit sort to order them by that metric instead
(e.g. "die größten Medienhäuser" -> query + sort bilanzsumme). For an exhaustive
"largest in sector X" ranking prefer a structured filter (oenace_*) over query, since a
query returns a relevance shortlist, not the whole sector.
- page (optional, default 1) and page_size (optional, default 25, clamped to 1..100).
- after (optional): KEYSET paging for bulk extraction — pass "" to start, then feed the
response's `next_after` back here for each next page (FNR-ordered, no offset ceiling); an
empty page means done. Not combinable with `query`/`near` (ranking has no stable cursor).
Prefer this over deep `page` for exporting a whole segment. Credit-metered accounts:
keyset pages are EXTRACTION and cost 1 credit per returned company (same rate as
export_companies_csv); normal `page` browsing costs 1 credit per started 25 rows.
- exact_count (optional, default false): force an exact `total` in keyset mode (a full COUNT
scan). In normal (offset) mode `total` is always exact already; `total_semantics` reports
"exact" vs "page_only".
Returns the total match count plus a COMPACT summary card per company on the page (name,
legal_form, bundesland, size, Bilanzsumme, equity ratio, revenue, growth, has_guv, industry)
— NOT the full record. Use to find/rank companies; for one company's full profile call
get_company_details, for the complete record call get_full_record, for aggregates over a
whole group call get_cohort_summary.
Query recipes (pick ONE primary strategy per user intent):
- Specific company by name: filters={"name": "<name>"} — substring, case-insensitive.
Results are relevance-ordered (exact/prefix matches first) when the hit set is small
(≤200); a broader name acts as a market screen and keeps the numeric sort.
- Industry as a CONCEPT ("tech companies", "Metallverarbeiter"): use oenace_division /
oenace_group (codes + German labels via describe_fields), NOT geschaeftszweig.
- Industry by literal ACTIVITY TEXT: geschaeftszweig matches the Firmenbuch free-text
description as substring ("anlagenbau" works; "technisch" won't — it's not semantic).
- Free-text query: filters={"query": "<text>"} searches name + activity and combines with
all structured filters; cards carry match_reason. Semantic activity recall is live — a
concept query surfaces companies by what they DO even without the literal words, and the
matched pool is relevance-ranked by default (pass an explicit sort to override).
- Region: bundesland (broad) > city (exact town) > postal_code prefix. Radius: use
near={"place":"Gmunden","radius_km":25} or near={"postal_code":"4810","radius_km":25};
cards get distance_km and sort by distance. An ambiguous town name is rejected with the
candidate PLZs.
- Recent corporate EVENT ("companies that raised capital / changed management / were
acquired / changed owners"): add event_signal + event_since to filters, e.g.
filters={"oenace_division":"41","bilanzsumme_min":5000000,"event_signal":["capital_raise"],
"event_since":"2024-01-01"}. Signal groups: "ownership_change" (Gesellschafter-
Kapitaländerung, often a share transfer), "leadership_change", "capital_raise",
"restructuring" (Verschmelzung/Spaltung/…), "new_company", "closure", "rebrand",
"relocation". Combines with EVERY financial/profile filter; each returned card gains
`events` (the triggering register changes, rich values on forward events) +
latest_event_date. Default window 365 days. This is the deal-sourcing / sales-trigger
surface. Pro. (For the raw cross-company event log use list_events; for counts
get_event_stats.)
- Zero hits? Read `relaxations` in the response and adjust THAT filter; do not retry
blind variations. `applied_filters` echoes how your inputs were normalized.
The response also carries has_more (another page exists) and, when total==0 with ≥2
filters, relaxations (which single filter to drop, most-permissive first).
Field reference: https://www.agentic-firmenbuch.at/felder.html
Inputs: page, sort, after, filters, +2 more. Returns: object
search_personsSearch companies by representativeARead-onlyIdempotentInspect
Find the companies a person represents (Geschäftsführung, Vorstand, Prokura, Aufsichtsrat) by NAME over the official register roster. Read-only, public data only.
Parameters:
- name (required, min. 3 characters): part of the person's name, case-insensitive
("Pöpperl", "Christian Pöpperl").
- limit (optional, default 50, max 200): maximum companies scanned.
Returns `persons[]` grouped by the exact name found, each with `companies[]`
({fnr, name, city, role}). Name equality is not identity: say so when several people
share a name. Use for "Welche Firmen führt X?"; for a company's own officers use
get_company_details.Inputs: name (required), limit. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 18 tools
The set covers distinct operations (search, profile, history, documents, events, peers, aggregates), but the three company-record tools get_full_record, get_company_details, and get_company_history overlap in scope, requiring careful reading to choose correctly. The descriptions explicitly disambiguate, so an attentive agent can avoid misselection.
All 18 tools use snake_case with a predictable verb_noun pattern (get_, list_, search_, find_, export_, describe_, benchmark_). No camelCase or mixed conventions; the naming is consistent throughout.
18 tools for a rich read-only register API with search, profile, documents, events, persons, benchmarks, and meta endpoints is slightly above the typical 3–15 range but each tool appears to serve a distinct capability. No obvious redundant tools, though the number is on the heavy side.
The surface covers company lookup, detailed profiles, full records, multi-year histories, document metadata, text extraction, download links, person search, sector filters, cohort aggregates, peer benchmarks, event feeds/stats, coverage, and usage. For a read-only Firmenbuch API, this is comprehensive with no obvious dead ends.
Maintenance
Related MCP Connectors
CompanyLens is a remote MCP server giving AI agents instant access to official company registry data across 19 jurisdictions in Europe, the Americas, and Asia-Pacific. Eighteen read-only tools let you search companies and people, look up officers and beneficial owners, map corporate networks through shared directors, screen names against the UK disqualified directors register, find every company at a registered address, and pull filing history — all from a single connector. Visit our website: https://companylens.io
Agent-native API for Finnish public company data via YTJ. Pay-per-call $0.01 USDC over x402.
KVK Handelsregister AI Connect: hosted MCP server for the Dutch business register.
Verified Swiss company profiles for AI agents: search, read and contact firms via allowed actions.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server for Slovak business registers (RPO) — AI agents can query 1.4M+ Slovak legal entities via Slovakia's official Statistical Office API. Search companies by name, IČO, or get full entity details including legal form, address, and statutory representatives.21MIT
- AlicenseAqualityCmaintenanceCompanyLens MCP gives your AI assistant access to real corporate data from official government sources. No web scraping, no hallucinations — verified data from SEC EDGAR, UK Companies House, OpenSanctions, and USAspending.gov.5201 npm4MIT
- AlicenseNot gradedqualityDmaintenanceGives any MCP-compatible AI agent instant access to the Australian Business Register (ABR) — plus AI-powered business intelligence. Search 8M+ registered Australian entities by name or ABN, get full profiles, check GST status, and get an AI-generated opportunity assessment for any business.38 npmMIT
- AlicenseAqualityDmaintenanceAn MCP server that gives AI agents access to US business entity data, enabling searches across 9 state registries, SEC EDGAR filings, federal contracts, and lobbying disclosures.61MIT