Skip to main content
Glama
jkbngb

agentic-firmenbuch

Search Austrian companies

search_companies
Read-onlyIdempotent

Find and rank Austrian companies by name, location, industry, size or financials, returning compact summary cards with key metrics for deal sourcing or market research.

Instructions

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
    

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageNo
sortNo
afterNo
filtersNo
page_sizeNo
exact_countNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv1.0.0

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent, so the description's added depth is real value: it discloses credit metering (keyset = 1 credit per company vs 1 per 25 rows), that keyset is 'not combinable with query/near', that unknown sort fields are rejected, that missing-metric companies sort last, and that cards are compact rather than full records.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The critical routing statement is front-loaded and the parameter/recipe blocks are scannable, but there is internal duplication — the 'unknown sort field is rejected with the list of valid ones' rule appears twice in the same bullet — and the parameter bullet for sort is dense enough to be hard to parse in one pass.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-param tool with a rich nested filter object, an output schema (so return values needn't be spelled out), and heavy sibling overlap, the description covers strategy selection, paging modes, cost model, and error recovery. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% top-level schema coverage the description carries the full burden and does so: equity_ratio is defined as a fraction with percent auto-conversion, the sort field must be 'founded_year' not 'founded_year_min', 'after' is keyset paging with a ''-to-start protocol, and event_signal groups are enumerated. This adds meaning far beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states a specific verb+resource ('Find or look up Austrian companies by name') and declares itself the primary entry point, explicitly contrasting with named siblings (get_company_details, get_full_record, get_cohort_summary). An agent can distinguish this from every other lookup tool without opening a schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use ('START HERE', 'call THIS tool first'), a battery of named query strategies with selection rules, and routes to alternatives for events (list_events), aggregates (get_cohort_summary), and full records. The 'pick ONE primary strategy per user intent' plus the 'Zero hits? Read relaxations' guidance is unusually complete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.