Skip to main content
Glama

Leadgen MCP — Romanian company data (ONRC, ANAF, financial statements)

A remote Model Context Protocol server for Romania's official business registry: 4.2M firms from ONRC, the ANAF fiscal layer (VAT, e-Factura, fiscal inactivity, phone) and 18 years of financial statements (Ministry of Finance, 2008–2025) with ratios and peer benchmarks.

This repository holds the public description of the server and an open-source local MCP client (below). The hosted server's source is not public.

Connect

Claude Code

claude mcp add --transport http leadgen https://leadgen-mcp.adrianhomelab.com/mcp --header "Authorization: Bearer <your key>"

or in .mcp.json:

{
  "mcpServers": {
    "leadgen": {
      "type": "http",
      "url": "https://leadgen-mcp.adrianhomelab.com/mcp",
      "headers": { "Authorization": "Bearer <your key>" }
    }
  }
}

Claude (claude.ai and Claude Desktop): Customize → Connectors → Add custom connector → URL https://leadgen-mcp.adrianhomelab.com/mcp, no sign-in; add the Authorization header with your key if your plan allows custom headers.

Cursor (~/.cursor/mcp.json or .cursor/mcp.json):

{ "mcpServers": { "leadgen": { "url": "https://leadgen-mcp.adrianhomelab.com/mcp", "headers": { "Authorization": "Bearer <your key>" } } } }

VS Code (.vscode/mcp.json):

{ "servers": { "leadgen": { "type": "http", "url": "https://leadgen-mcp.adrianhomelab.com/mcp", "headers": { "Authorization": "Bearer <your key>" } } } }

Without a key every client works for 30 calls a day; get_usage tells you what is left. Current limits: https://leadgen.adrianhomelab.com/en/docs.

Related MCP server: openregistry

Run locally (open client)

The hosted endpoint above is the main product and the simplest way in. If your client only speaks stdio, or you want to run the MCP server yourself, this repository also ships leadgen-mcp: a small open-source (MIT) local MCP server with the same 17 tools. It holds no data: every tool calls Leadgen's public REST API (https://leadgen.adrianhomelab.com/docs), so answers, limits and keys are the same as on the hosted server. Tool names, descriptions and schemas are a snapshot of the hosted server's tools/list (leadgen_mcp/tools.json, refreshed with scripts/sync_tools.py).

It is on PyPI as leadgen-mcp (Python 3.10 or newer):

uvx leadgen-mcp

or install it:

pip install leadgen-mcp
leadgen-mcp

To run the latest commit on main instead of the release: uvx --from git+https://github.com/darksider4all/leadgen-mcp leadgen-mcp.

or run it in Docker: docker build -t leadgen-mcp . then docker run -i --rm -e LEADGEN_API_KEY leadgen-mcp.

Variable

Default

What it does

LEADGEN_API_KEY

none

Your free key from https://leadgen.adrianhomelab.com/start (50 lookups a day instead of the REST API's 5). Optional; sent only when set.

LEADGEN_SOURCE

glama

A channel tag sent with each request (X-Leadgen-Source header and src parameter), so Leadgen knows where its users come from.

LEADGEN_API_URL

https://leadgen.adrianhomelab.com

REST API base URL.

LEADGEN_TIMEOUT

60

Seconds to wait for an answer (website crawls can take a while).

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "leadgen": {
      "command": "uvx",
      "args": ["leadgen-mcp"],
      "env": { "LEADGEN_API_KEY": "<your key>", "LEADGEN_SOURCE": "claude-desktop" }
    }
  }
}

Cursor (~/.cursor/mcp.json or .cursor/mcp.json):

{
  "mcpServers": {
    "leadgen": {
      "command": "uvx",
      "args": ["leadgen-mcp"],
      "env": { "LEADGEN_API_KEY": "<your key>", "LEADGEN_SOURCE": "cursor" }
    }
  }
}

Leave LEADGEN_API_KEY out to use the REST API's 5 anonymous lookups a day.

How it relates to the hosted server: same tools and same data. This client calls the REST API, whose anonymous allowance is smaller than the MCP endpoint's (5 a day against 30, counted per door and per IP); a free key gives 50 a day. A refusal (no key, daily limit, suspended key) comes back as a tool error that keeps the server's message and the link to a free key; for the daily limit it says when it resets (00:00 UTC). The key is sent as the X-API-Key header, only when it is set. Watches need a key.

Development: pip install -e ".[test]" && pytest (no network); LEADGEN_LIVE=1 pytest tests/test_live.py makes one real anonymous lookup; LEADGEN_DRIFT=1 pytest tests/test_drift.py compares tools.json with the live server card; python scripts/check_public.py checks that nothing private is committed.

Tools

Tool

What it does

lookup_business

Look up a Romanian company by name or CUI (tax code) in the official ONRC registry of 4.2M firms.

lookup_companies

Look up many Romanian companies by CUI in one call (up to 100): one result per input, in input order, each with found true/false and the company record.

find_company_by_domain

Find the Romanian firm behind a website domain (dedeman.ro).

match_companies

Match a list of up to 500 records (name, optional county, domain or CUI) to Romanian firms: each row gets match {cui, companyName, confidence, matchedOn} and the record, or no_match with up to 3 candidates.

lookup_by_category

Find companies by what they do, not by name: a curated topic ('software', 'retail'), plain words ('dentists', a CAEN class title; see matched) or CAEN codes ('4321,4322'; 6201 also finds Rev.3 6210).

lookup_director

Find Romanian companies by the name of a director or legal representative (ONRC).

extract_contacts

Crawl a company website and extract emails, phone numbers and social profiles.

enrich_company

A whole-firm profile in one call: the ONRC registry record plus the contacts discovered on that firm's website, each labelled with a confidence and a source.

lookup_domain

WHOIS plus DNS records (A, MX, NS, TXT) and an SPF/DMARC email-security audit for a domain.

lookup_financials

Annual financial statements for a Romanian company from Ministry of Finance filings, every fiscal year on record since 2008: revenue, profit, headcount and balance-sheet lines in RON with each year's ratios (growth, margins, equity ratio, liquidity), plus a summary (3/5/10-year CAGR, loss years, health score).

lookup_financial_ratios

Derived financial intelligence for a Romanian company: multi-year revenue trend (YoY, 3/5/10-year CAGR), margins, headcount, solvency and liquidity ratios, a 0-100 health score with its rule-by-rule breakdown, red flags, and peer percentiles within the same CAEN activity and county.

watch_company

Register a company (by CUI) to monitor.

watch_caen

Watch a CAEN activity code, optionally scoped to one county, for newly registered firms.

poll_watchlist

Collect everything the watch tools have found: call it to drain the changeset for every watch owned by your API key, most severe first.

unwatch

Stop watching a firm (cui) or a CAEN code (code, with its county if it had one). A watch you do not hold answers removed: 0.

get_usage

Show your own allowance: plan, daily limit, lookups used today, how many remain, when it resets (00:00 UTC) and any credit balance.

report_issue

Tell the Leadgen founder what is missing or wrong: a missing field, firm or source (kind 'gap'), a wrong company record ('wrong_record', pass its cui), a bug, an idea.

Every company-bearing answer carries asOf (registry snapshot, financial year, ANAF load date) — cite it.

Data and credit

Registry and financial statements: ONRC and the Ministry of Finance via data.gov.ro, licensed CC BY 4.0; fiscal data: ANAF. When you publish data obtained through Leadgen, credit it as: "Sursa: ONRC și Ministerul Finanțelor (data.gov.ro, CC BY 4.0) și ANAF, prin Leadgen".

Romanian

Server MCP pentru registrul oficial al firmelor din România (ONRC, ANAF, bilanțuri 2008–2025). Gratuit: 30 de interogări pe zi fără cheie (5 prin API-ul REST), 50 pe zi cu o cheie gratuită de la https://leadgen.adrianhomelab.com/start. Documentație: https://leadgen.adrianhomelab.com/docs.

Contact

Prices: https://leadgen-checkout.adrianhomelab.com/ · questions: through the website's contact link.

Available Tools

17 tools
enrich_companyCompany profile with website contactsA
Read-onlyIdempotent
Inspect

A whole-firm profile in one call: the ONRC registry record plus the contacts discovered on that firm's website, each labelled with a confidence and a source. Prefer this over lookup_business followed by extract_contacts when you want everything about one company. cui is its tax code; website overrides the registered one; max_pages bounds the crawl; refresh=true crawls now instead of answering from the cache.

NameRequiredDescriptionDefault
cuiYesRomanian tax identification number (CUI), e.g. '2816464'; 'RO' and leading zeros are accepted.
refreshNotrue crawls now even if a cached result exists (default false: answer from the cache when there is one).
websiteNoOptional website override (domain or URL). When omitted, the firm's registered website is used (an error if none is on file).
max_pagesNoMaximum number of pages to crawl (1-20, default 5).

Output Schema

NameRequiredDescription
cuiNoThe firm's CUI.
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
companyNoA company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url).
crawledNotrue when the site was crawled for this answer.
messageNoA sentence for the caller.
websiteNoThe website crawled.
cacheHitNotrue when answered from the cache.
contactsNoContacts found, each with type, value, confidence and source.
crawlErrorNoWhy the crawl failed, if it did.
pagesCrawledNoPages read.
websiteSourceNoWhere the website came from: registry or override.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/openWorld/non-destructive, and the description goes further by disclosing cache-vs-live behavior ('refresh=true crawls now instead of answering from the cache') and that outputs carry confidence and source labels. It stops short of covering crawl cost, latency, or failure/partial-result behavior, so it is strong but not exhaustive.

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

Conciseness5/5

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

Front-loads the value proposition and the sibling routing rule, then compresses all four parameters into one dense clause each. No sentence is redundant or padded.

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?

An output schema exists, so return values need not be explained; the description still notes the confidence/source annotation on discovered contacts. With schema and annotations covering the rest, an agent has everything needed to call this correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so all four parameters are already documented with types, defaults and constraints (1-20 pages, RO-prefix acceptance). The description restates 'cui is its tax code', the website override, the crawl bound and refresh semantics without adding syntax or examples 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?

States a specific composite verb/resource ('whole-firm profile in one call: the ONRC registry record plus the contacts discovered on that firm's website') and explicitly names the two siblings it replaces. An agent can distinguish it from lookup_business and extract_contacts without opening either 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?

Gives an explicit when-to-use rule and names the alternatives: 'Prefer this over lookup_business followed by extract_contacts when you want everything about one company.' Both the condition and the competing tools are stated, leaving nothing to inference.

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

extract_contactsExtract contacts from a websiteA
Read-onlyIdempotent
Inspect

Crawl a company website and extract emails, phone numbers and social profiles. Accepts a bare domain or a full URL; max_pages (1-20, default 5) bounds the crawl.

NameRequiredDescriptionDefault
websiteYesThe website to crawl: a bare domain ('example.com') or a full URL ('https://example.com').
max_pagesNoMaximum number of pages to crawl (1-20, default 5).

Output Schema

NameRequiredDescription
urlNoThe start URL crawled.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
domainNoThe site's registrable domain.
emailsNoAddresses on the site's own domain.
githubNoGitHub profile.
phonesNoPhone numbers found.
messageNoA sentence for the caller.
twitterNoX / Twitter profile.
youtubeNoYouTube channel.
facebookNoFacebook profile.
linkedinNoLinkedIn page.
instagramNoInstagram profile.
otherEmailsNoOther addresses found on the site.
socialLinksNoEvery social link found, best first.
pagesCrawledNoPages read.

TDQS

A3.5/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, openWorldHint=true, idempotentHint=true and destructiveHint=false, so safety is covered. The description adds that this is a bounded crawl (max_pages controls scope), which usefully implies runtime/cost characteristics, but says nothing about latency, rate limits, or whether results are cached.

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?

Two tight sentences with the capability front-loaded and the input constraints trailing. The second sentence is largely a paraphrase of the schema, which is the only minor redundancy.

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

Completeness4/5

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

An output schema exists, so return values need no explanation, and annotations cover the safety profile. The description is nearly complete for this tool; only crawl-dynamics details (scope of crawling, subdomain behavior, expected duration) are absent.

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

Parameters3/5

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

Schema description coverage is 100% and both parameters already document the domain/URL format and the 1-20 default-5 range. The description simply restates that same information, adding no syntax, format, or edge-case guidance beyond the schema, so the baseline of 3 applies.

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

Purpose4/5

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

The description states a concrete verb+resource ('Crawl a company website') plus the extracted artifacts (emails, phone numbers, social profiles), so an agent knows exactly what it produces. It is clearly distinct from the lookup_* siblings in mechanism, but it never clarifies its relationship to overlapping tools like enrich_company, which could also surface contact data.

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

Usage Guidelines3/5

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

Usage is only implied: the agent can infer 'use this when you need contact details from a live site.' There is no explicit when-to-use trigger, no when-not, and no routing to or from alternatives such as enrich_company or lookup_domain.

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

find_company_by_domainFind the company behind a websiteA
Read-onlyIdempotent
Inspect

Find the Romanian firm behind a website domain (dedeman.ro). Uses the registry's website field, else reads the site's home and legal/contact pages for the CUI or registration number it shows (matchedOn: registry_website, site_cui). Without one, it says so and offers name candidates from the page title or the domain name, each with a confidence (at most 0.7, never a match). One lookup.

NameRequiredDescriptionDefault
domainYesThe website's domain ('dedeman.ro'); a URL or a www. host is reduced to it. Public domains only.
fieldsNoOptional: keep only these company fields in each row, comma-separated (companyName,cui,county,risk; dotted paths such as risk.level work). Without it the full record is returned.
compactNoOptional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url).

Output Schema

NameRequiredDescription
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
siteNoWhat was read from the site: url, pagesRead, title, cuis, registrationCodes, error.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
foundNoWhether a firm was identified.
matchNoThe identified firm: cui, companyName, matchedOn.
totalNoNumber of company records returned (at most 5).
domainNoThe normalised domain.
fieldsNoThe company fields kept when fields or compact trimmed the rows.
reasonNoWhen not found: no_cui_on_site or site_unreachable.
messageNoA sentence for the caller.
resultsNoThe company records, best first.
warningsNoNotes on how the request was read (a clamped limit, a widened CAEN code, an ignored field).
matchedOnNoregistry_website, site_cui or site_registration_code.
candidatesNoWhen not found (also when the site cannot be read): up to 3 firms whose name matches the page title or the domain name, each with a confidence (at most 0.7).
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).

TDQS

A4/5.0
Behavior5/5

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

Goes well beyond the annotations: it discloses the two lookup paths (registry website field vs. reading home/legal/contact pages), the matchedOn values, that name candidates are capped at 0.7 confidence and are 'never a match', and that it is a single lookup. This is exactly the behavioral detail annotations cannot convey.

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?

Dense and front-loaded with the core purpose first, then method, then fallback behavior. The middle sentence is packed but not redundant; a slightly shorter phrasing would improve scannability.

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?

With an output schema present and annotations covering the safety profile, the description supplies everything remaining an agent needs: input shape, resolution strategy, confidence semantics, and the fact that a non-match is reported rather than fabricated.

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

Parameters3/5

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

Schema coverage is 100%, so the domain, fields, and compact parameters are already fully documented in the schema. The description adds no parameter syntax or format detail of its own, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb and resource ('Find the Romanian firm behind a website domain') with a concrete example (dedeman.ro) and names the matching method used. It is clearly distinguishable in substance from lookup/enrich siblings, though it never names an alternative tool to contrast against.

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

Usage Guidelines3/5

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

Usage context is implied (you have a domain, you want the company) and the fallback chain tells the agent what will happen, but there is no explicit 'use this when X, use lookup_domain/lookup_business when Y' guidance despite many closely named siblings.

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

get_usageShow my daily allowanceA
Read-onlyIdempotent
Inspect

Show your own allowance: plan, daily limit, lookups used today, how many remain, when it resets (00:00 UTC) and any credit balance. Free and never counted as a lookup. Limits: 5 lookups a day anonymously, 25 with a free API key from https://leadgen.adrianhomelab.com/start (an email address, no payment).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
planNoPlan name (free, pro, business).
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
linksNoget_a_key, pricing, docs.
countedNoAlways false: this call is not counted.
messageNoA sentence for the caller.
identityNoWho is counted: kind (key or anonymous) and counted_as.
remainingNoLookups left today.
resets_atNoWhen the allowance resets (ISO 8601, 00:00 UTC).
suspendedNotrue when the key is suspended.
used_todayNoLookups used today.
daily_limitNoLookups allowed per UTC day.
entitlementsNoWhat the plan includes.
resets_in_secondsNoSeconds until the reset.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, but the description adds real behavioral context beyond them: it is free, never counted against the quota, reports both anonymous (5/day) and keyed (25/day) ceilings, and points to the key signup. Auth requirements and rate limits are disclosed, which is exactly what the annotations cannot convey.

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?

Two sentences, output contents front-loaded before the quota/auth caveats, with no filler. The trailing signup URL and parenthetical are slightly dense but genuinely actionable, so the trade-off is acceptable.

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?

An output schema exists, so return-value detail is optional; the description going further and enumerating the fields is a bonus. Auth needs, quota tiers, reset timing, and cost are all covered, leaving no gap an agent would need to guess at for this parameterless read tool.

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

Parameters4/5

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

The tool takes zero parameters, so the baseline is 4 and there is nothing further for the description to disambiguate. The statement that it costs no lookup is a useful semantic note about invocation but is not a parameter concern.

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?

Specific verb+resource ('Show your own allowance') followed by an enumerated list of what is returned: plan, daily limit, lookups used today, remaining, reset time, credit balance. It is unmistakably distinct from the lookup/enrich siblings, which all consume allowance rather than report it.

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

Usage Guidelines4/5

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

Gives clear context for when to call it (checking your allowance) and states the free/unmetered condition plus the anonymous-vs-key limits that shape usage. It does not explicitly name an alternative tool or a 'do not use when' case, but the sibling set contains no near-equivalent, so routing risk is low.

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

lookup_businessLook up a Romanian companyA
Read-onlyIdempotent
Inspect

Look up a Romanian company by name or CUI (tax code) in the official ONRC registry of 4.2M firms. Diacritic-insensitive ('paval' finds 'PAVAL'); a CUI matches exactly. The first call for a named Romanian company. Ranked with a score: live firms first (exact name, then words), closed ones after; county lifts. For 'firms that do X in Y', use lookup_by_category (an empty result may carry a hint naming it).

NameRequiredDescriptionDefault
queryYesCompany name or CUI (tax ID) to search for. Names are diacritic-insensitive ('paval' finds PAVĂL); a CUI ('2816464', 'RO2816464') matches exactly.
countyNoOptional county hint (diacritic-insensitive): firms registered there rank higher. Not a filter.
fieldsNoOptional: keep only these company fields in each row, comma-separated (companyName,cui,county,risk; dotted paths such as risk.level work). Without it the full record is returned.
compactNoOptional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url).
max_resultsNoMaximum number of companies to return (1-100, default 10).

Output Schema

NameRequiredDescription
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
hintNoWhen a name search finds nothing but reads like a category question: the lookup_by_category call that answers it.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
foundNofalse when a well-formed CUI is not in the snapshot.
queryNoThe query as given.
totalNoRows returned in this answer (at most max_results), not the number of firms that match.
countyNoThe county hint, if one was given.
fieldsNoThe company fields kept when fields or compact trimmed the rows.
reasonNoWhy nothing was found (not_found).
sourceNoData source: onrc (registry) or mfp (Ministry of Finance filings).
messageNoA sentence for the caller.
resultsNoThe company records, best first.
warningsNoNotes on how the request was read (a clamped limit, a widened CAEN code, an ignored field).
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, non-destructive and closed-world, so the safety profile is covered. The description adds genuinely non-derivable behavior: diacritic-insensitive matching, CUI exact-match semantics, live-before-closed ranking with county lift, and the empty-result hint. It stops short of stating result limits or pagination, but that is minor against the annotation coverage.

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?

Front-loaded with the core purpose, then ranking rules, then the sibling redirect. Dense but every clause carries information; the parenthetical examples are compact. Slightly packed with semicolon-separated ranking detail, but nothing is wasted.

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

Completeness4/5

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

With an output schema present, return values need no explanation, and the description covers matching rules, ranking order and the alternative path. A complex, highly-ranked lookup tool is adequately described; only the max_results/truncation boundary behavior is left implicit.

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

Parameters3/5

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

Schema description coverage is 100% and the parameter descriptions already cover diacritic-insensitivity, the county-as-hint-not-filter nuance, fields/compact behavior and the 1-100 bounds. The description largely restates the query semantics, so baseline 3 is correct – it adds little the schema does not already say.

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?

States a specific verb and resource ('Look up a Romanian company by name or CUI') and pins the data source ('official ONRC registry of 4.2M firms'). It also positions itself among siblings with 'The first call for a named Romanian company', so an agent can separate it from lookup_companies, lookup_by_category and match_companies 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?

Explicitly routes the disambiguating case: 'For firms that do X in Y, use lookup_by_category', and even explains the redirect an empty result may carry. Combined with the 'first call for a named Romanian company' framing, both when-to-use and when-to-use-something-else are stated.

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

lookup_by_categoryFind companies by activityA
Read-onlyIdempotent
Inspect

Find companies by what they do, not by name: a curated topic ('software', 'retail'), plain words ('dentists', a CAEN class title; see matched) or CAEN codes ('4321,4322'; 6201 also finds Rev.3 6210). Narrow by county; qualify by revenue, headcount, VAT, main activity. active_only (default) drops dead and ANAF-inactive firms.

NameRequiredDescriptionDefault
sortNoOrder of the results: 'newest' registrations first (default), 'revenue' (latest filing's turnover, biggest first) or 'employees' (headcount, biggest first); firms without a filing come last.newest
topicYesWhat the firms do: a curated topic ('software', 'retail'), plain words for a trade ('dentists', 'stomatologie'), a CAEN class title in Romanian or English, or CAEN codes ('6201' or '4321,4322'). Case-, space- and diacritic-insensitive. A number that names another activity in each revision takes a suffix: '4781r3' (Rev.3) or '4781r2' (Rev.2).
countyNoOptional county to narrow to (diacritic-insensitive: 'bucuresti', 'cluj'; a county town such as 'Cluj-Napoca' or a Bucharest sector is read as its county); omit for nationwide. An unknown county is an error (unknown_county) with suggestions, not 0 firms.
fieldsNoOptional: keep only these company fields in each row, comma-separated (companyName,cui,county,risk; dotted paths such as risk.level work). Without it the full record is returned.
compactNoOptional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url).
vat_payerNoOptional: true keeps VAT-registered firms only, false only non-VAT payers (ANAF data). Omit for both.
legal_formNoOptional legal form(s) to keep, comma-separated, case-insensitive: 'SRL', 'SA', 'PFA', 'II', or 'SRL,SA' (companies, no sole traders). Default: any form.
active_onlyNoDefault true: drop firms that are not a lead (struck off, dissolving, in liquidation, insolvent or bankrupt, activity suspended, or ANAF fiscally inactive). false returns every firm.
has_websiteNotrue keeps only firms with a website on file in the registry (default false).
max_resultsNoMaximum number of companies to return (1-100, default 10).
max_revenueNoOptional maximum net turnover in RON on the latest filing.
min_revenueNoOptional minimum net turnover in RON on the latest filing (FY2025, else FY2024). Firms without a filing never match a band.
max_employeesNoOptional maximum average headcount on the latest filing.
min_employeesNoOptional minimum average headcount on the latest filing.
main_activity_onlyNoDefault false: a firm matches when the code is ANY of its authorised activities (ONRC lists a dozen per firm, most never practised). true keeps only firms whose DECLARED main activity is one of the codes (ANAF main CAEN, else the CAEN on the latest filing): fewer, more relevant firms. The Leadgen app's lists use true by default.

Output Schema

NameRequiredDescription
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
sortNoThe order of results: newest, revenue or employees.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
labelNoHuman label of what was matched.
queryNoThe topic as given.
topicNoThe curated topic matched, if any.
totalNoRows returned in this answer (at most max_results), not the size of the match set: a full page (total == max_results) may have more; narrow the filters or raise max_results.
appUrlNoThe same list opened in the Leadgen app (CAEN codes, county, legal form, active and main-activity filters), to share with the user; null when the app cannot open it (more than 10 codes, a legal form it does not offer).
countyNoThe county filter, if any.
fieldsNoThe company fields kept when fields or compact trimmed the rows.
sourceNoData source: onrc (registry) or mfp (Ministry of Finance filings).
filtersNoThe filters applied (legalForm, activeOnly, revenue and headcount bands, vatPayer, mainActivityOnly ...).
matchedNoHow plain words were read: by, niche or class title, codes.
messageNoA sentence for the caller.
resultsNoThe company records, best first.
warningsNoNotes on how the request was read (a clamped limit, a widened CAEN code, an ignored field).
caenCodesNoThe CAEN codes searched, when given or derived as codes.
caenNamesNoThe CAEN codes as asked, named: [{code, title (Romanian), titleEn}].
truncatedNotrue when max_results was cut to the list cap (and the list is full).
candidatesNoWhen the words fit several activities (ambiguous_topic): the ones to choose from.
codesAddedNoCAEN Rev.2/Rev.3 counterparts added to the search.
matchTotalNoHow many firms the whole list holds with every filter (active_only on; null when off): exact, or estimated when matchTotalApproximate is true.
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).
availableTopicsNoThe curated topic ids, when the topic is unknown or ambiguous.
matchTotalMarginNoThe 99% margin of an estimated matchTotal.
availableTopicNamesNoEach curated topic id with its name, e.g. {"agriculture": "Agriculture & Food"}, next to availableTopics.
inactiveFilteredOutNoFirms removed by active_only (null when off).
matchTotalApproximateNotrue when matchTotal is estimated (matchTotalMargin: its 99% margin).
inactiveFilteredOutApproximateNotrue when that count is estimated.

TDQS

A3.7/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive/openWorld=false, so the safety profile is covered. The description adds real behavioral context beyond that: the default active_only filter meaningfully changes result sets by dropping struck-off, dissolving, insolvent, suspended and ANAF-inactive firms, and it discloses that codes match ANY authorised activity unless main_activity_only narrows it. Return shape is left to the output schema, which is fine.

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?

Front-loaded with the core differentiator ('not by name') before the accepted input formats and filters; dense but every clause carries information. Minor waste and ambiguity in fragments like 'see matched' and the parenthetical CAEN examples.

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

Completeness4/5

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

For a 15-parameter tool with a full output schema, the description covers the essential decision points: what 'topic' accepts, the scoping/qualifying filters, and the default filtering behavior. It is slightly thin on how this tool relates to its closest siblings, but nothing needed to call it correctly is missing.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all 15 parameters, and the baseline is 3. The description mostly restates the filter categories rather than extending them, though the cross-revision note ('6201 also finds Rev.3 6210') and the 'a CAEN class title; see matched' hint add a little semantics the schema states only for the topic param.

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

Purpose4/5

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

A concrete verb+resource ('Find companies by what they do') with an explicit negative qualifier ('not by name') that separates it from name/domain lookups. However, it never names the close siblings (lookup_companies, match_companies) that an agent must choose between, so differentiation is by implication rather than by reference.

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

Usage Guidelines3/5

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

Usage context is implied through the accepted topic formats and the filter list ('narrow by county; qualify by revenue, headcount, VAT, main activity'), which tells the agent when the tool fits. But there are no explicit when-not conditions, prerequisites, or named alternatives among the many lookup_* siblings, and the fragment 'a CAEN class title; see matched' is puzzling rather than instructive.

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

lookup_companiesLook up many companies by CUIA
Read-onlyIdempotent
Inspect

Look up many Romanian companies by CUI in one call (up to 100): one result per input, in input order, each with found true/false and the company record. Each row counts as one lookup; a batch larger than what is left today is refused whole. fields or compact trims each record.

NameRequiredDescriptionDefault
cuisYesUp to 100 CUIs, as a list or one comma-separated string ('RO', spaces and leading zeros accepted, as in lookup_business).
fieldsNoOptional: keep only these company fields in each row, comma-separated (companyName,cui,county,risk; dotted paths such as risk.level work). Without it the full record is returned.
compactNoOptional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url).

Output Schema

NameRequiredDescription
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
foundNoRows that matched a firm.
totalNoNumber of input rows.
errorsNoRows that are input errors (empty, not a CUI, wrong control digit).
fieldsNoThe company fields kept when fields or compact trimmed the rows.
sourceNoData source: onrc (registry) or mfp (Ministry of Finance filings).
messageNoA sentence for the caller.
resultsNoPer input: input, cui, found, and company (the record) or error/reason.
meteringNoWhat the batch cost: rows, counted, notCounted (input-error rows are not counted) and the rule.
notFoundNoWell-formed CUIs not in the snapshot.
warningsNoNotes on how the request was read (a clamped limit, a widened CAEN code, an ignored field).
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already cover readOnly/idempotent/non-destructive, so the description's added value is the quota accounting ('each row counts as one lookup'), the atomic whole-batch refusal, the per-row found flag, and the input-order guarantee — real operational context beyond the schema. It doesn't say whether refused batches surface as an error vs a partial result.

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

Conciseness5/5

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

Dense but front-loaded: batch scope, per-row semantics, quota rule, and trimming flags in order of importance, with no filler sentences.

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

Completeness4/5

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

An output schema exists so return shapes need no explanation, and the description covers ordering, the found flag, and quota failure. The one gap is what happens on invalid or unknown CUIs within the batch, and how the whole-batch refusal is reported.

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

Parameters3/5

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

Schema description coverage is 100%, so cuis, fields, and compact are already fully documented, including accepted CUI formats and dotted paths. The description only echoes that fields/compact trim each record, adding no syntax beyond the schema; baseline 3 applies.

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?

States a specific verb (look up), resource (Romanian companies by CUI), and batch scope (up to 100, one result per input) that clearly separates it from the singular lookup_business sibling it references.

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

Usage Guidelines4/5

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

The 'many ... in one call' framing and the pointer to lookup_business for CUI formatting imply the batch-vs-single choice, and the quota/refusal rule tells the agent when a call will fail. It stops short of explicitly naming when to prefer this over match_companies or other siblings.

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

lookup_directorFind companies by directorA
Read-onlyIdempotent
Inspect

Find Romanian companies by the name of a director or legal representative (ONRC). Diacritic-insensitive. Whole words: 'pop maria' finds POP MARIA, not POPA MARIANA; prefix=true matches prefixes. The registry has no personal ID, so one name can be several people: homonyms and byCounty say so. Use this when you know a person rather than a firm.

NameRequiredDescriptionDefault
nameYesDirector / representative name to search for (e.g. 'Ion Popescu'); diacritic-insensitive, each word a whole word of the name.
fieldsNoOptional: keep only these company fields in each row, comma-separated (companyName,cui,county,risk; dotted paths such as risk.level work). Without it the full record is returned.
prefixNotrue matches each word as a prefix ('pop' also finds POPA, POPESCU); default false (whole words).
compactNoOptional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url).
max_resultsNoMaximum number of companies to return (1-100, default 10).

Output Schema

NameRequiredDescription
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
noteNoWhat homonyms means for this name.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
matchNowords (whole words) or prefix.
queryNoThe name as given.
totalNoEvery matching firm, not just the rows returned.
fieldsNoThe company fields kept when fields or compact trimmed the rows.
sourceNoData source: onrc (registry) or mfp (Ministry of Finance filings).
messageNoA sentence for the caller.
resultsNoThe company records, best first.
byCountyNoMatching firms per county.
homonymsNotrue when the matches span several counties (likely several people).
returnedNoNumber of companies returned.
warningsNoNotes on how the request was read (a clamped limit, a widened CAEN code, an ignored field).
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).
distinctCountiesNoNumber of counties the matches are in.
totalIsLowerBoundNotrue when the scan stopped early and total is a minimum.

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover the safety profile (readOnly, idempotent, non-destructive, closed-world), and the description usefully adds matching semantics (diacritic-insensitive, whole-word, prefix option) plus the key ambiguity that one name can map to several people due to no personal ID. It does not mention pagination or result-count behavior beyond the schema's max_results.

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?

Front-loaded with the core purpose and matching rules, and nearly every sentence carries distinct information. The dangling reference to 'byCounty' as a signal for homonyms is slightly confusing since no such parameter appears in the schema, costing a point.

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?

With an output schema present, return-value details are rightly omitted, and the description covers the tricky parts an agent needs: matching semantics, diacritics, prefix behavior, and the one-name-to-many-people caveat. Nothing essential for correct invocation is missing.

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

Parameters4/5

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

Schema description coverage is 100%, so the schema already carries parameter meaning and the baseline would be 3. The description earns a point by reinforcing matching behavior with a concrete example ('pop maria' finds POP MARIA, not POPA MARIANA) and explaining the homonym ambiguity that no schema field conveys.

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?

States a specific verb and resource with its scope: 'Find Romanian companies by the name of a director or legal representative (ONRC).' This clearly separates it from sibling firm-oriented tools such as find_company_by_domain, lookup_companies, and match_companies.

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

Usage Guidelines4/5

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

'Use this when you know a person rather than a firm' gives a clear selection condition and implicitly excludes firm/domain-based siblings. It does not name a specific alternative tool to switch to, so it stops short of full when/when-not routing.

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

lookup_domainDomain WHOIS, DNS and email auditA
Read-onlyIdempotent
Inspect

WHOIS plus DNS records (A, MX, NS, TXT) and an SPF/DMARC email-security audit for a domain. Use it to profile a company's web estate or check its email posture. include_dns and include_security toggle the two halves.

NameRequiredDescriptionDefault
domainYesDomain name to look up (e.g. 'example.com'); a URL is reduced to its host.
include_dnsNoInclude DNS records (A, AAAA, MX, NS, TXT, SOA); default true.
include_securityNoInclude the SPF/DMARC email-security check; default true.

Output Schema

NameRequiredDescription
dnsNoRecords by type: A, AAAA, MX, NS, TXT, SOA.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
whoisNoregistrar, creationDate, expirationDate, updatedDate, nameServers, registrantOrg, registrantCountry.
domainNoThe normalised domain.
messageNoA sentence for the caller.
securityNohasSPF, spf, hasDMARC, dmarc.
resolvedIPNoAn address the domain resolves to.

TDQS

A3.9/5.0
Behavior3/5

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

Annotations already declare this a read-only, idempotent, open-world, non-destructive operation, so the safety profile is covered. The description adds that the lookup is split into DNS and email-security halves, but discloses nothing about rate limits, failures on non-existent domains, or external source variability that an agent would find useful.

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?

Three tight sentences with the payload list front-loaded and the toggles noted last. Nothing is padded, though the final toggle sentence is largely redundant with the schema.

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

Completeness4/5

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

An output schema exists, so return values need no explanation here, and the description covers scope, toggles, and intended use. A note on behavior for non-existent or malformed domains would complete it, but it is otherwise sufficient for correct invocation.

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

Parameters3/5

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

Schema coverage is 100%, so all three parameters are fully documented in the schema, including defaults and the URL-to-host normalization. The description's note that include_dns/include_security toggle the two halves restates what the schema already conveys, so the baseline 3 applies.

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?

States a specific verb (lookup) and resource (domain) and enumerates the concrete payloads: WHOIS, DNS records, and an SPF/DMARC email audit. This distinguishes it from the sibling company-lookup tools, which fetch entity data rather than domain infrastructure.

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

Usage Guidelines4/5

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

"Use it to profile a company's web estate or check its email posture" gives clear context for when to reach for this tool. It stops short of naming an alternative or exclusion (e.g., when to prefer find_company_by_domain or enrich_company instead), so it is not a full when/when-not statement.

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

lookup_financial_ratiosFinancial ratios and health scoreA
Read-onlyIdempotent
Inspect

Derived financial intelligence for a Romanian company: multi-year revenue trend (YoY, 3/5/10-year CAGR), margins, headcount, solvency and liquidity ratios, a 0-100 health score with its rule-by-rule breakdown, red flags, and peer percentiles within the same CAEN activity and county. Verdict: 'growing', 'stable' or 'distressed'. Use lookup_financials for the raw figures.

NameRequiredDescriptionDefault
cuiYesRomanian tax identification number (CUI), e.g. '2816464'; 'RO' and leading zeros are accepted.

Output Schema

NameRequiredDescription
cuiNoThe firm's CUI.
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
flagsNoRed flags.
foundNoWhether any filing is on record.
peersNoPercentiles within the same CAEN activity and county.
totalNoNumber of fiscal years used.
yearsNoPer fiscal year figures and margins.
ratiosNoMargins, equity ratio, debt to equity, liquidity, returns.
sourceNoData source: onrc (registry) or mfp (Ministry of Finance filings).
historyNoYears on record, loss years, revenue peak.
messageNoA sentence for the caller.
signalsNoThe distress signals found.
verdictNogrowing, stable or distressed.
distressNotrue when the distress signals fire.
headcountNoLatest headcount and its change.
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).
healthScoreNo0-100 score, band and its rule-by-rule components.
revenueTrendNoLatest revenue, YoY growth, 3/5/10-year CAGR, trend label.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive/non-open-world, so safety is covered. The description adds real behavioral value beyond that: the discrete verdict enum ('growing'/'stable'/'distressed'), the presence of a rule-by-rule health-score breakdown, red flags and peer-percentile benchmarking. It omits any note on data freshness or what happens for companies with sparse filings.

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?

Front-loaded: the payload of the tool is stated first, with the sibling routing instruction last. The opening sentence is a long comma-separated enumeration, but each item is a distinct returned artifact rather than filler, so it stays efficient.

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?

An output schema exists so return values need not be restated, yet the description still gives the agent the semantic shape (verdict enum, health-score breakdown, peer grouping by CAEN and county) plus scope and the alternative tool. Nothing needed to select or call this correctly is missing.

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

Parameters3/5

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

Only one parameter and schema coverage is 100%, with the schema itself documenting the CUI format and the 'RO'/leading-zero tolerance. The description adds no further meaning about the identifier, so the baseline 3 for schema-covered params applies.

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?

States a precise verb+resource and enumerates exactly what 'derived financial intelligence' means: YoY/3-5-10y CAGR, margins, headcount, solvency/liquidity ratios, a 0-100 health score, red flags, peer percentiles. It explicitly distinguishes itself from the sibling lookup_financials ('raw figures'), so an agent can separate the two without opening either schema.

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

Usage Guidelines4/5

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

Names the alternative (lookup_financials) and the condition that selects it ('for the raw figures'), and scopes the tool to Romanian companies via the CUI input. It does not state prerequisites, failure modes (e.g. company with no filed statements), or exclusions beyond that one routing sentence, so it stops short of a full when/when-not map.

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

lookup_financialsAnnual financial statementsA
Read-onlyIdempotent
Inspect

Annual financial statements for a Romanian company from Ministry of Finance filings, every fiscal year on record since 2008: revenue, profit, headcount and balance-sheet lines in RON with each year's ratios (growth, margins, equity ratio, liquidity), plus a summary (3/5/10-year CAGR, loss years, health score). Resolve the firm with lookup_business first if you only have a name.

NameRequiredDescriptionDefault
cuiYesRomanian tax identification number (CUI), e.g. '2816464'; 'RO' and leading zeros are accepted.

Output Schema

NameRequiredDescription
cuiNoThe firm's CUI.
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
foundNoWhether any filing is on record.
totalNoNumber of fiscal years returned.
yearsNoPer fiscal year: revenue, profit, loss, netResult, employees, assets, debt, equity (RON) and that year's ratios.
sourceNoData source: onrc (registry) or mfp (Ministry of Finance filings).
messageNoA sentence for the caller.
summaryNoHistory, revenue growth (3/5/10-year CAGR), latest ratios, health score and band, flags.
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, destructiveHint=false and a closed world, so the safety profile is covered. The description adds genuine value beyond that: the data source (Ministry of Finance filings), historical depth (every fiscal year since 2008), currency (RON), and the name-resolution prerequisite. Rate limits, auth, and coverage gaps (e.g. missing years, firms never filing) are unmentioned.

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 payload is front-loaded into one dense sentence and the routing rule is a short second sentence, so nothing is buried. The enumerated field list is long but each item is informative rather than filler.

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

Completeness4/5

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

With an output schema present, the return format need not be explained, and annotations cover the safety profile; the description still supplies source, currency, and historical coverage. The remaining gap is the unresolved overlap with lookup_financial_ratios, which an agent facing both tools would need to disambiguate.

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

Parameters3/5

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

There is a single parameter and the schema description coverage is 100%, with the schema itself documenting the CUI format, examples, and acceptance of 'RO' and leading zeros. The description adds no parameter-level meaning, so the baseline 3 applies.

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

Purpose4/5

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

States a specific verb+resource with unusually concrete scope: annual statements for a Romanian company sourced from Ministry of Finance filings, every fiscal year since 2008, including named line items in RON. It stops short of drawing the boundary against the sibling lookup_financial_ratios, whose territory (ratios) this description also claims, so an agent must guess which to call for ratio-only needs.

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

Usage Guidelines4/5

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

Explicitly gives the prerequisite path: resolve the firm with lookup_business first when only a name is available, which is real routing guidance. It offers no when-to-use versus lookup_financial_ratios or the other lookup_* siblings, so selection among overlapping tools is left to inference.

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

match_companiesMatch a list of records to firmsA
Read-onlyIdempotent
Inspect

Match a list of up to 500 records (name, optional county, domain or CUI) to Romanian firms: each row gets match {cui, companyName, confidence, matchedOn} and the record, or no_match with up to 3 candidates. A valid CUI wins (confidence 1.0). Each row counts as one lookup; a batch larger than what is left today is refused whole.

NameRequiredDescriptionDefault
rowsYesUp to 500 records, each {name, county, domain, cui, ref} (any of them; ref is your own id, echoed back), or a bare string (a CUI, a domain or a name).
fieldsNoOptional: keep only these company fields in each row, comma-separated (companyName,cui,county,risk; dotted paths such as risk.level work). Without it the full record is returned.
compactNoOptional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url).

Output Schema

NameRequiredDescription
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
totalNoNumber of input rows.
errorsNoRows that are input errors (nothing to match on).
fieldsNoThe company fields kept when fields or compact trimmed the rows.
sourceNoData source: onrc (registry) or mfp (Ministry of Finance filings).
matchedNoRows matched to a firm.
messageNoA sentence for the caller.
noMatchNoRows with no match above the threshold.
resultsNoPer row: row, input, status (matched or no_match), match {cui, companyName, confidence, matchedOn}, company, or candidates.
meteringNoWhat the batch cost: rows, counted, notCounted (input-error rows are not counted) and the rule.
warningsNoNotes on how the request was read (a clamped limit, a widened CAEN code, an ignored field).
thresholdNoConfidence a row needs to be matched (0-1).
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).

TDQS

A3.9/5.0
Behavior4/5

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

Annotations already cover safety (readOnly, idempotent, non-destructive, closed-world), so the bar is lower, yet the description adds real operational context: each row consumes one lookup, an over-quota batch is refused atomically, and a valid CUI forces confidence 1.0. It stops short of covering rate limits or partial-failure behavior in detail.

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?

Three dense sentences, front-loaded with the core action and the 500-row cap. The inline {cui, companyName, confidence, matchedOn} output spec is slightly heavy but each sentence carries information.

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

Completeness4/5

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

Given a 3-parameter tool with a full schema and an output schema, the description covers the matching rules, quota cost, and all-or-nothing batch refusal. The main gap is sibling routing, which contextual completeness does not fully resolve.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents rows, fields, and compact fully. The description's field list and CUI rule largely restate schema content, earning the baseline 3 rather than adding new parameter meaning.

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?

States a specific verb (match) and resource (a list of up to 500 records) against Romanian firms, and makes the batch nature explicit. It is clearly distinguishable from single-record siblings like find_company_by_domain or lookup_companies.

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

Usage Guidelines3/5

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

The batch use case is implied and the row-quota mechanics are explained, but the description never states when to choose this tool over siblings such as lookup_companies or enrich_company. Usage is inferable rather than guided.

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

poll_watchlistCollect watchlist changesAInspect

Collect everything the watch tools have found: call it to drain the changeset for every watch owned by your API key, most severe first. Company watches return an 'updated' entry with the changed fields and risk; CAEN and county watches return the 'new' firms registered since the last poll (200 a poll, the rest next).

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
okNotrue when the poll ran.
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
ownerNoWhose watches these are (key prefix or IP).
totalNoNumber of watches with news.
activeNoEvery watch you hold, changed or not: kind (company or caen), target (CUI or code), county, since, name. Remove one with unwatch.
messageNoA sentence for the caller.
watchesNoPer watch: an 'updated' company with its changed fields and risk, or the 'new' firms registered in a watched activity.
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).
email_alertsNoHow to get the same changes by email.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations declare readOnlyHint=false, idempotentHint=false and destructiveHint=false, and the description explains exactly why: 'drain the changeset' discloses that collection consumes/mutates the pending changeset state, and 'since the last poll (200 a poll, the rest next)' discloses the non-idempotent pagination cap. It also describes ordering ('most severe first') and the differing output shapes for company vs CAEN/county watches, which is well beyond what the annotations convey.

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

Conciseness5/5

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

Two sentences, tightly front-loaded with what the tool does and why, followed by the output and pagination details. Every clause earns its place with no filler or repetition of the title.

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?

An output schema exists so return values need not be explained, yet the description still summarizes the two result shapes ('updated' entries with fields and risk, 'new' firms for CAEN/county) and the 200-per-poll limit. For a zero-parameter polling tool, 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.

Parameters4/5

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

The tool takes zero parameters, so per the baseline the description carries no parameter burden beyond baseline 4. Schema coverage is 100% (empty object), and there is nothing in the parameter surface for the description to compensate for.

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 description uses a specific verb ('Collect... drain the changeset') and resource ('every watch owned by your API key'), and it explicitly frames itself against the sibling watch tools that create the watches. An agent can distinguish this from watch_company/watch_caen/unwatch without opening any schema.

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

Usage Guidelines4/5

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

It clearly establishes the context of use: call this to drain what the watch tools have found for your API key. It implies the setup/consume relationship with the watch_* siblings, but it never states when not to call it or names an explicit alternative (e.g., unwatch to stop collection).

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

report_issueReport missing or wrong dataAInspect

Tell the Leadgen founder what is missing or wrong: a missing field, firm or source (kind 'gap'), a wrong company record ('wrong_record', pass its cui), a bug, an idea. Free, never counted as a lookup. contact is optional (an address for a reply); nothing is mailed to it automatically. Registry records are corrected at the source (ONRC) and arrive with the next snapshot.

NameRequiredDescriptionDefault
cuiNoOptional CUI of the firm the report is about (for 'wrong_record').
kindNoOne of 'gap' (a missing field, firm or source; the default), 'wrong_record' (pass its cui), 'bug', 'idea', 'other'.gap
contactNoOptional email address for a reply; nothing is mailed to it automatically.
messageYesThe report, in plain words: what is missing or wrong.

Output Schema

NameRequiredDescription
idNoThe report's id.
kindNoThe kind filed.
noteNoFor wrong_record: how registry records get corrected.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
statusNoreceived.
messageNoA sentence for the caller.

TDQS

A4.5/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, destructiveHint=false, idempotentHint=false) by disclosing cost (free, not counted as a lookup), notification behavior ('nothing is mailed to it automatically'), and downstream latency/workflow ('Registry records are corrected at the source (ONRC) and arrive with the next snapshot'). These are exactly the side-effect and expectation-setting details an agent cannot infer from structured fields.

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

Conciseness5/5

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

Front-loads the core action, then compresses the kind taxonomy, the cost guarantee, the contact caveat and the correction cadence into minimal prose. Every clause earns its place with no redundancy.

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?

An output schema exists, so return values need no explanation. For a free-text report submission tool the description covers what to send, how to classify it, what it costs and what happens afterward, leaving no material gap for correct invocation.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents cui, kind, contact and message. The description restates the kind taxonomy and cui usage and adds only the 'nothing is mailed automatically' clause, which is behavioral rather than semantic. Baseline 3 is appropriate when the schema carries the parameter burden.

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?

States a specific verb and resource ('Tell the Leadgen founder what is missing or wrong') and immediately enumerates the report categories, making it unmistakable against the sibling lookup/enrichment tools. An agent can tell this is a feedback channel, not a data-retrieval call, without opening the schema.

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

Usage Guidelines4/5

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

Gives clear per-case routing: 'gap' for missing field/firm/source, 'wrong_record' plus its cui for a bad company record, plus bug and idea. It also supplies the incentive condition ('Free, never counted as a lookup'), which steers an agent away from treating it as a billable lookup. No explicit when-not-to-use or named alternative, so it falls short of a 5.

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

unwatchStop watching a company or activityA
Idempotent
Inspect

Stop watching a company (cui) or a CAEN activity code (code, plus the county it was watched in, if any), on your API key: the watch and its baseline are removed. Unwatching something you do not watch changes nothing (removed: 0). poll_watchlist lists your active watches.

NameRequiredDescriptionDefault
cuiNoCUI of a watched firm (e.g. '2816464'); give this or code.
codeNoA watched CAEN activity code (e.g. '6210'); give this or cui.
countyNoWith code: the county the code was watched in (diacritic-insensitive); omit for a nationwide watch.

Output Schema

NameRequiredDescription
okNotrue when the request was valid.
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
kindNocompany or caen.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
ownerNoWhose watches these are (key prefix or IP).
activeNoThe watches you still hold (as in poll_watchlist).
countyNoThe CAEN watch's county; null for nationwide or a company.
targetNoThe CUI or CAEN code.
messageNoA sentence for the caller.
removedNo1 when the watch was removed, 0 when you did not hold it.
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).

TDQS

A3.7/5.0
Behavior1/5

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

The description contradicts the destructiveHint: false annotation by stating that "the watch and its baseline are removed." Removing state is not an additive update, so the annotation and description are inconsistent. It also adds useful idempotence context ("removed: 0"), but the contradiction forces a 1 under the rules.

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

Conciseness5/5

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

It is front-loaded with the core action, packs relevant scope and behavior into three short sentences, and none of the text is wasted.

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?

Given an output schema exists, the description need not explain return values. It covers the key inputs, removal semantics, idempotence, API key scope, and the related poll_watchlist alternative, so an agent has enough context to call it correctly.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all three parameters. The description adds only a light mapping (cui=company, code=CAEN activity code, county conditional), which does not go meaningfully 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 description states a specific verb ("Stop watching") and resources ("a company (cui) or a CAEN activity code (code, plus the county...)"), and distinguishes itself from the opposite watch_* siblings and from poll_watchlist. An agent can identify the tool's scope without opening the schema.

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

Usage Guidelines4/5

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

It gives clear context: stop watching a company or activity, on your API key, with a no-op if not watched, and points to poll_watchlist for active watches. It does not explicitly state when to use this versus watch_company/watch_caen, so it stops short of a 5.

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

watch_caenWatch an activity for new firmsA
Idempotent
Inspect

Watch a CAEN activity code, optionally scoped to one county, for newly registered firms. A registration-date cutoff is the baseline: only firms registered after it are reported, and poll_watchlist slides the cutoff forward so each new firm surfaces once. A retired CAEN Rev.2 code (6201) also watches its Rev.3 successor (6210), with a warning.

NameRequiredDescriptionDefault
codeYesCAEN activity code to watch (e.g. '6210'); a retired Rev.2 code also watches its Rev.3 successor.
countyNoOptional county name to scope the watch to (diacritic-insensitive); omit to watch nationwide.

Output Schema

NameRequiredDescription
okNotrue when the watch is in place.
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
watchNokind, target, owner (key prefix), county, baseline.
messageNoA sentence for the caller.
warningsNoNotes on how the request was read (a clamped limit, a widened CAEN code, an ignored field).
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).
alreadyWatchingNotrue when you already held this watch (nothing changed).

TDQS

A4.2/5.0
Behavior4/5

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

Annotations cover the safety profile (readOnlyHint=false, destructiveHint=false, idempotentHint=true), so the bar is lower. The description still adds real behavior beyond them: the registration-date baseline cutoff, the dedup guarantee that each firm surfaces once, and the retired Rev.2 → Rev.3 alias with a warning. It doesn't cover watch lifetime or how to remove the watch, hence not a 5.

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

Conciseness5/5

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

Three tight sentences: purpose first, then the cutoff/polling mechanics, then the edge case alias. No filler and the most important information is front-loaded.

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

Completeness4/5

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

An output schema exists, so return values need not be described, and annotations carry the safety profile. The description covers scope, cutoff semantics, dedup, and the alias edge case; only watch lifecycle/auth requirements are unaddressed, which is a minor gap.

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

Parameters3/5

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

Schema description coverage is 100% — both 'code' and 'county' are documented, including diacritic-insensitivity and nationwide default. The description's note about retired Rev.2 codes restates what the schema already says, adding no new parameter semantics, so the baseline 3 applies.

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?

States a specific verb and resource ('Watch a CAEN activity code') plus the scope ('for newly registered firms'), which cleanly separates it from watch_company (single firm) and unwatch. An agent can identify what is being created without opening the schema.

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

Usage Guidelines4/5

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

The description explains the workflow relationship to poll_watchlist ('slides the cutoff forward so each new firm surfaces once'), which tells the agent when this tool's output will be consumed. It stops short of an explicit when-not/exclusion rule against the sibling watch tools, so it lands at clear context without routing guidance.

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

watch_companyWatch a company for changesA
Idempotent
Inspect

Register a company (by CUI) to monitor. Stores a fingerprint of its current registry record as the baseline; poll_watchlist then reports changes between monthly ONRC snapshots - a new director, a new CAEN activity, an address or status change - and when ANAF declares it fiscally inactive or its VAT status flips.

NameRequiredDescriptionDefault
cuiYesRomanian tax identification number (CUI) of the firm to watch, e.g. '2816464'. Watching a firm you already watch changes nothing.

Output Schema

NameRequiredDescription
okNotrue when the watch is in place.
asOfNoWhat to cite: registry (ONRC snapshot date), financialYear (fiscal year of the figures), anaf (day of the ANAF data), snapshot, published, source.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
watchNokind, target, owner (key prefix), county, baseline.
messageNoA sentence for the caller.
attributionNoThe credit line to keep when redistributing the data (CC BY 4.0).
alreadyWatchingNotrue when you already held this watch (nothing changed).

TDQS

A4.5/5.0
Behavior5/5

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

Adds substantial behavior beyond the annotations: it stores a fingerprint of the current registry record as a baseline, changes are computed between monthly ONRC snapshots, and it enumerates the change classes detected (director, CAEN activity, address, status, ANAF fiscal-inactivity, VAT flip). It also reinforces idempotency ('watching a firm you already watch changes nothing'), consistent with idempotentHint=true.

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

Conciseness5/5

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

A single dense sentence, front-loaded with the action, then the baseline mechanism, then the reported outcomes and cadence. No filler sentences and nothing repeated from the schema.

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?

With one required parameter, full schema coverage, an output schema, and annotations covering the safety profile, the description supplies everything else an agent needs: what registration stores, when results appear (monthly snapshots), and via which sibling.

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

Parameters3/5

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

Schema description coverage is 100% and the schema already defines CUI with an example plus the idempotency note. The description only restates 'by CUI', adding no format or constraint detail beyond the schema, so the baseline 3 applies.

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?

States a concrete verb+resource ('Register a company ... to monitor') and immediately names the downstream consumer (poll_watchlist), which separates it from siblings like watch_caen and unwatch. An agent can pick it without opening the schema.

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

Usage Guidelines4/5

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

Explains the workflow context clearly: register here, then poll_watchlist reports changes. It does not state exclusions or explicitly contrast with watch_caen (CAEN-specific watching) or unwatch, so it stops short of full when/when-not guidance.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 11 tool updatesv0.1.3
    • Changedenrich_company1 field changed
      • changedOutput schema / properties / company / description
        Previous value: -"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity}], directors, status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, and score/match on name searches. With fields or compact, only the requested keys."New value: +"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url)."
    • Changedfind_company_by_domain3 fields changed
      • changedInput schema / properties / compact / description
        Previous value: -"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level, phone, website, latest revenue and headcount)."New value: +"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url)."
      • changedOutput schema / properties / candidates / description
        Previous value: -"When not found: up to 3 firms whose name matches the page title."New value: +"When not found (also when the site cannot be read): up to 3 firms whose name matches the page title or the domain name, each with a confidence (at most 0.7)."
      • changedOutput schema / properties / results / items / description
        Previous value: -"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity}], directors, status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, and score/match on name searches. With fields or compact, only the requested keys."New value: +"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url)."
    • Changedlookup_business3 fields changed
      • changedInput schema / properties / compact / description
        Previous value: -"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level, phone, website, latest revenue and headcount)."New value: +"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url)."
      • changedOutput schema / properties / results / items / description
        Previous value: -"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity}], directors, status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, and score/match on name searches. With fields or compact, only the requested keys."New value: +"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url)."
      • changedOutput schema / properties / total / description
        Previous value: -"Number of companies returned."New value: +"Rows returned in this answer (at most max_results), not the number of firms that match."
    • Changedlookup_by_category16 fields changed
      • changedInput schema / properties / compact / description
        Previous value: -"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level, phone, website, latest revenue and headcount)."New value: +"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url)."
      • changedInput schema / properties / county / description
        Previous value: -"Optional county name to narrow to (diacritic-insensitive: 'bucuresti', 'cluj'); omit for nationwide."New value: +"Optional county to narrow to (diacritic-insensitive: 'bucuresti', 'cluj'; a county town such as 'Cluj-Napoca' or a Bucharest sector is read as its county); omit for nationwide. An unknown county is an error (unknown_county) with suggestions, not 0 firms."
      • changedInput schema / properties / main_activity_only / description
        Previous value: -"true keeps firms whose declared main activity (ANAF main CAEN, else the CAEN on the latest filing) is one of the codes, instead of any authorised activity (default false)."New value: +"Default false: a firm matches when the code is ANY of its authorised activities (ONRC lists a dozen per firm, most never practised). true keeps only firms whose DECLARED main activity is one of the codes (ANAF main CAEN, else the CAEN on the latest filing): fewer, more relevant firms. The Leadgen app's lists use true by default."
      • addedInput schema / properties / sort
        Added value: +{
        +  "default": "newest",
        +  "description": "Order of the results: 'newest' registrations first (default), 'revenue' (latest filing's turnover, biggest first) or 'employees' (headcount, biggest first); firms without a filing come last.",
        +  "enum": [
        +    "newest",
        +    "revenue",
        +    "employees"
        +  ],
        +  "title": "Sort",
        +  "type": "string"
        +}
      • changedOutput schema / description
        Previous value: -"A lead list: firms in an activity, newest registration first."New value: +"A lead list: firms in an activity, newest registration first (or by turnover / headcount: sort)."
      • addedOutput schema / properties / appUrl
        Added value: +{
        +  "description": "The same list opened in the Leadgen app (CAEN codes, county, legal form, active and main-activity filters), to share with the user; null when the app cannot open it (more than 10 codes, a legal form it does not offer).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / availableTopicNames
        Added value: +{
        +  "description": "Each curated topic id with its name, e.g. {\"agriculture\": \"Agriculture & Food\"}, next to availableTopics.",
        +  "type": [
        +    "object",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / availableTopics / description
        Previous value: -"The curated topics, when the topic is unknown."New value: +"The curated topic ids, when the topic is unknown or ambiguous."
      • addedOutput schema / properties / caenNames
        Added value: +{
        +  "description": "The CAEN codes as asked, named: [{code, title (Romanian), titleEn}].",
        +  "type": [
        +    "array",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matchTotal
        Added value: +{
        +  "description": "How many firms the whole list holds with every filter (active_only on; null when off): exact, or estimated when matchTotalApproximate is true.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matchTotalApproximate
        Added value: +{
        +  "description": "true when matchTotal is estimated (matchTotalMargin: its 99% margin).",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / matchTotalMargin
        Added value: +{
        +  "description": "The 99% margin of an estimated matchTotal.",
        +  "type": [
        +    "integer",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / results / items / description
        Previous value: -"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity}], directors, status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, and score/match on name searches. With fields or compact, only the requested keys."New value: +"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url)."
      • addedOutput schema / properties / sort
        Added value: +{
        +  "description": "The order of results: newest, revenue or employees.",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
      • changedOutput schema / properties / total / description
        Previous value: -"Number of companies returned."New value: +"Rows returned in this answer (at most max_results), not the size of the match set: a full page (total == max_results) may have more; narrow the filters or raise max_results."
      • changedOutput schema / properties / truncated / description
        Previous value: -"true when more firms match than were returned."New value: +"true when max_results was cut to the list cap (and the list is full)."
    • Changedlookup_companies2 fields changed
      • changedInput schema / properties / compact / description
        Previous value: -"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level, phone, website, latest revenue and headcount)."New value: +"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url)."
      • changedOutput schema / properties / results / items / properties / company / description
        Previous value: -"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity}], directors, status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, and score/match on name searches. With fields or compact, only the requested keys."New value: +"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url)."
    • Changedlookup_director2 fields changed
      • changedInput schema / properties / compact / description
        Previous value: -"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level, phone, website, latest revenue and headcount)."New value: +"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url)."
      • changedOutput schema / properties / results / items / description
        Previous value: -"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity}], directors, status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, and score/match on name searches. With fields or compact, only the requested keys."New value: +"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url)."
    • Changedmatch_companies2 fields changed
      • changedInput schema / properties / compact / description
        Previous value: -"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level, phone, website, latest revenue and headcount)."New value: +"Optional: true keeps a short preset per row (name, CUI, county, city, legal form, risk level and what it did not check, phone, website, latest revenue and headcount, record url)."
      • changedOutput schema / properties / results / items / properties / company / description
        Previous value: -"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity}], directors, status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, and score/match on name searches. With fields or compact, only the requested keys."New value: +"A company record: companyName, cui, registrationCode, registrationDate (DD/MM/YYYY), legalForm, euid, address, county, city, website, phone, caenActivities [{code, activity (RO), activityEn}], directors, representatives [{name, role}], status [{code, name}], latestFinancials {year, revenue, netResult, employees; RON}, anaf {mainCaen, vatPayer, eFactura, inactive}, risk {level, label, reasons, isLead}, source, asOf, url (the firm's public record page to share with the user; null for sole traders and other natural persons), and score/match on name searches. With fields or compact, only the requested keys (compact keeps url)."
    • Changedpoll_watchlist2 fields changed
      • addedOutput schema / properties / active
        Added value: +{
        +  "description": "Every watch you hold, changed or not: kind (company or caen), target (CUI or code), county, since, name. Remove one with unwatch.",
        +  "type": [
        +    "array",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / attribution
        Added value: +{
        +  "description": "The credit line to keep when redistributing the data (CC BY 4.0).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Addedunwatch
    • Changedwatch_caen1 field changed
      • addedOutput schema / properties / attribution
        Added value: +{
        +  "description": "The credit line to keep when redistributing the data (CC BY 4.0).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedwatch_company1 field changed
      • addedOutput schema / properties / attribution
        Added value: +{
        +  "description": "The credit line to keep when redistributing the data (CC BY 4.0).",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
  2. 16 tool updatesv0.1.0
    • First observedenrich_company
    • First observedextract_contacts
    • First observedfind_company_by_domain
    • First observedget_usage
    • First observedlookup_business
    • First observedlookup_by_category
    • First observedlookup_companies
    • First observedlookup_director
    • First observedlookup_domain
    • First observedlookup_financial_ratios
    • First observedlookup_financials
    • First observedmatch_companies
    • First observedpoll_watchlist
    • First observedreport_issue
    • First observedwatch_caen
    • First observedwatch_company

TDQS

A3.9/5.0

Scored across 17 tools

Disambiguation4/5

Most tools target distinct resources or actions, and the detailed descriptions clarify boundaries well. However, lookup_business vs enrich_company, lookup_financials vs lookup_financial_ratios, and lookup_companies vs match_companies have adjacent purposes that could occasionally cause misselection.

Naming Consistency4/5

All tool names use snake_case with clear verb/object structure, making the set predictable. Minor deviations exist, such as lookup_by_category and find_company_by_domain using prepositions, and unwatch lacking an explicit object.

Tool Count4/5

17 tools is slightly above the ideal 3–15 range, but the server covers a broad leadgen domain including lookup, matching, enrichment, financials, monitoring, and utilities. Each tool has a plausible role, though a few adjacent lookup tools could be consolidated.

Completeness4/5

The surface covers core Romanian company workflows: search by category/name/director/domain, batch lookup and matching, enrichment, financial statements and ratios, contact extraction, domain profiling, monitoring, usage, and issue reporting. Minor gaps remain, such as no explicit address/phone search or bulk financial retrieval, but there are no major dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers