Skip to main content
Glama

romania-mcp

tests PyPI

Check Romanian companies from an MCP client: ANAF status, filed financials, court cases, public contracts and EU VAT registration. Search imported ONRC data by name, keep local snapshots and check what changed. No API keys.

Verifici o firmă după nume sau CUI, îi vezi bilanțurile și dosarele, apoi păstrezi raportul pentru o comparație ulterioară. Dacă o sursă nu răspunde, raportul spune ce lipsește.

Install

Python 3.10 or newer:

pip install romania-mcp-server

For the code in this checkout, including changes not yet released on PyPI:

pip install -e .

For Claude Desktop, add this to claude_desktop_config.json:

{
  "mcpServers": {
    "romania": {
      "command": "uvx",
      "args": ["romania-mcp-server"]
    }
  }
}

If you installed the checkout with pip, use "command": "romania-mcp-server" and omit args. This runs your installed checkout instead of the published package. Cursor and other stdio MCP clients accept the same configuration.

For Claude Code:

claude mcp add romania -- romania-mcp-server

Related MCP server: ENTIA Entity Verification

Company checks

Tool

What it does

company_report

ANAF status, up to ten financial years, trends, court candidates and imported public contracts, with source receipts

company_search

Name search in an imported ONRC export, optionally filtered by county or CAEN

company_lookup

ANAF status for up to 500 CUIs, optionally on a past date

company_financials

Filed statements: revenue, profit or loss, employees, debts, equity and other reported figures

court_cases

Case search by company CUI, party name or case number, with roles and hearings

company_contracts

Contracts matched by supplier CUI in imported SEAP exports, with totals by currency

vat_check

A trading partner's current intra-EU VAT registration, through VIES

shop_check

Company details behind a shop, financials, court candidates and domain evidence

exchange_rate

BNR reference rates and conversion to RON

iban_check

Offline IBAN format and checksum validation, plus Romanian bank identification

Try:

  • „Găsește firma după numele acesta și arată-mi variantele din Cluj.”

  • „Fă un raport pentru CUI 14399840 pe ultimii cinci ani. Arată-mi și ce nu ai putut verifica.”

  • „Cum s-au schimbat cifra de afaceri, profitul și numărul de angajați?”

  • „Ce contracte publice găsești pentru firma asta în exporturile încărcate?”

  • „Verifică în VIES codul TVA al acestui partener din Germania.”

company_report returns figures and calculated trends, not a credit score. Percentage changes use consecutive financial years; missing years and zero denominators produce null. Amounts from ANAF are in RON.

Each report source has a status, URL, check time, cache flag and, when known, the oldest fetch time of its cached inputs. available means the request succeeded, no_data means the requested financial filing was not returned, and unavailable means the request failed. not_checked explains a check that could not be attempted. Missing filings and source failures remain distinct, and both keep coverage partial.

Court records do not contain CUIs. Exact normalized names, legal forms and the registered county help narrow the candidates, but do not establish identity. A company being a creditor or plaintiff is not in itself a problem. Capped searches remain marked incomplete.

Name search and public contracts

ANAF's public status service needs a CUI. Name search uses an ONRC export from data.gov.ro. Public contract search uses imported SEAP exports.

Tool

What it does

dataset_catalog

Find exports, resource IDs, publisher details and source links

dataset_import

Download a selected data.gov.ro CSV, XLSX or ODS file and index it locally

dataset_status

List sources, dates, covered periods, row counts, skipped rows and SHA-256 hashes

Find the files first:

romania-mcp-data catalog "organization:onrc"
romania-mcp-data catalog "achizitii publice"

Import OD_FIRME.CSV as onrc. Authorized CAEN activities are published separately in OD_CAEN_AUTORIZAT.CSV; import that as caen for the same snapshot date. They join through COD_INMATRICULARE. CAEN versions are retained in the index. Use caen_version (or --caen-version) to select revision 2 or 3. Filters use the same snapshot date as the company index.

romania-mcp-data sync RESOURCE_ID --kind onrc --published-on 2026-10-19
romania-mcp-data sync CAEN_RESOURCE_ID --kind caen --published-on 2026-10-19
romania-mcp-data search "numele firmei" --county Cluj

For a contract export, supply the dates stated by its publisher:

romania-mcp-data sync CONTRACT_RESOURCE_ID --kind procurement --published-on 2026-10-06 --period-start 2026-07-01 --period-end 2026-09-30

The IDs above are placeholders. Use the catalog results and read the source description: a metadata modification time is not automatically the file's publication or coverage date.

You can also import a file you have already downloaded:

romania-mcp-data import ./OD_FIRME.CSV --kind onrc --published-on 2026-10-19 --source-url https://data.gov.ro/URL-OF-THE-EXPORT

Imports stream CSV rows and read workbooks without loading them all into memory. Reimporting the same source replaces its rows in one transaction; an empty or invalid import keeps the old index. Downloads are limited to 2 GB. Large ONRC exports can take minutes, so the CLI is usually more convenient than an interactive tool call. Legacy binary XLS needs conversion to CSV or XLSX first.

Contract totals cover imported records only. They are contract values, not payments or proof of revenue. Overlapping copies of an identifiable contract are deduplicated. Rows without a single valid supplier CUI, including some joint bids and foreign suppliers, are skipped and counted. An empty result does not prove a company has no public contracts.

Snapshots and monitoring

Tool

What it does

company_snapshot

Fetch a fresh report and save it locally

company_history

Read saved observations

company_changes

Compare the latest two snapshots

company_watch

Add, update or pause a local watch

company_watchlist

List watches and their next due times

monitor_run

Check due watches, save reports and return changes

History starts with your first saved report. A failed source is an availability change, not a deleted company or a closed case. Changes to check timestamps alone do not trigger an event. Cases falling outside a result page are not reported as closed.

romania-mcp-data report 14399840 --years 5 --save
romania-mcp-data watch 14399840 --interval-hours 24
romania-mcp-data monitor

monitor performs one pass and writes JSON lines only for changes or a first incomplete check. A successful first check establishes the baseline quietly. Unchanged checks produce no stdout. Run it periodically with Task Scheduler, cron or a service you already use. Adding a watch does not install a scheduler or send messages anywhere.

For a process that stays running:

romania-mcp-data monitor --loop --poll-seconds 60

The poll interval decides when to look for due work; each company's interval decides when it is actually checked. Monitoring fetches fresh source data. Pause a watch with romania-mcp-data watch 14399840 --disable.

Supplier lists

supplier_check starts a job or resumes it by job_id. Each completed supplier is saved before the next starts. supplier_results returns JSON or CSV, with findings first, then incomplete checks, then checks with no flags. CSV exports include source receipts and neutralize formula prefixes in external text.

romania-mcp-data suppliers 14399840 18547290 --years 3 --limit 1
romania-mcp-data suppliers --job-id JOB_ID --limit 3
romania-mcp-data export JOB_ID --format csv > suppliers.csv

Continue until pending is zero. Each job accepts up to 500 CUIs and removes duplicates. Invalid input is rejected before creating a job. A partial supplier report stays visibly partial. MCP results are paginated with offset and next_offset; the CLI exports the whole job.

Storage and source limits

HTTP responses are cached in ~/.cache/romania-mcp/cache.sqlite3. Company status lasts six hours, financials one day, court searches three hours and current BNR rates one hour. Past BNR years last thirty days. Use refresh=true for a report that must query sources again.

Snapshots, watchlists, supplier jobs and dataset indexes live separately in ~/.local/share/romania-mcp/data.sqlite3. Configure other locations with:

ROMANIA_MCP_CACHE=off
ROMANIA_MCP_CACHE_PATH=/path/to/cache.sqlite3
ROMANIA_MCP_DATA_PATH=/path/to/data.sqlite3

The CLI also accepts --data-path PATH before the command. Data stays on the machine running the server. The CUI, VAT number, company name or domain needed for a check is sent to the relevant public service. Imports, snapshots, watches and supplier checks are marked as local writes in MCP annotations.

  • ANAF requests are spaced one second apart. Public services can still reject or delay requests.

  • Financials describe the indicated year, not today's cash position. Sector-specific layouts can contain unmapped fields.

  • Portal Just's endpoint currently uses plain HTTP and caps searches at 1,000 candidates. Transport and matching limitations are visible in reports.

  • VIES checks current intra-EU VAT registration for a trading partner. A service fault is not an invalid registration; the tool does not reconstruct historical status.

  • IBAN validation does not establish that an account exists or who owns it.

  • A missing Wayback capture does not establish a site's age. No automated ROTLD WHOIS is used for .ro domains.

  • Shop results are signals, not proof of fraud or reliability. Source outages keep coverage partial. A known red flag can still be shown alongside an outage.

  • Page downloads have content-type and size limits. DNS answers must be public; connections use the checked IP while keeping the original TLS hostname. Redirect connections go through the same checks. Environment proxies are disabled for source requests.

Public records and website content are evidence, not instructions for the assistant. Use company checks for a specific business purpose; court records can also name individuals.

Development

pip install -e . pytest ruff build
pytest
ruff check src tests
python -m build

Tests use mocked source responses and temporary databases. They cover upstream outages, cache freshness, partial reports, identity ambiguity, imports, resumable jobs, CSV exports and monitoring. Network smoke checks run separately so an upstream outage does not make unit tests fail.

License

MIT © Robert Vind-Gardoș (@robyroro)

Available Tools

6 tools
company_financialsCompany financials (bilanț)A
Read-onlyIdempotent

Financial statements a Romanian company filed with ANAF, year by year: revenue (cifra de afaceri), total income and expenses, net profit or loss (net_result), average employees, debts, equity, cash, receivables, inventory and fixed assets. Amounts are in RON. Years with nothing filed are marked filed=false.

Use it to see if a company is real and how it's doing: a shop with zero revenue and no employees, or with negative equity, is worth a closer look. Banks and insurers file a different layout, their lines come through under 'other'. Data starts around 2020 for some companies. Takes about a second per year. Cached for 24h.

ParametersJSON Schema
NameRequiredDescriptionDefault
cuiYesCompany fiscal code (CUI / CIF), with or without the RO prefix, e.g. "14399840" or "RO14399840".
yearsNoHow many years to fetch, counting back from last year. Statements for a year are filed by mid next year, so the most recent one can still be missing.

TDQS

A4.6/5.0
Behavior5/5

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

Beyond the annotations (readOnly, idempotent, openWorld, non-destructive), it discloses currency (RON), the filed=false convention, that banks/insurers use a different layout surfaced under 'other', the ~2020 data horizon, ~1s per year latency, and 24h caching. That is unusually complete behavioral context.

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 resource and contents, then caveats and performance notes in short sentences. It is slightly long, but each sentence (currency, field list, layout exception, latency, caching) carries distinct information.

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 no output schema, the description compensates by enumerating returned fields, the currency, and the filed=false marker, and it flags layout exceptions. An agent has everything needed to call and interpret the result.

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 coverage is 100%, so the baseline is 3, but the description adds meaning the schema lacks: the data horizon around 2020 and the caveat that the most recent year may be missing. The 'years' semantics are largely already in the schema, so it lands above baseline without being fully additive.

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?

It states a specific resource (Romanian company financial statements filed with ANAF) and enumerates the actual line items returned (revenue, net result, employees, debts, equity, etc.). This is clearly distinguishable from company_lookup, court_cases, exchange_rate and shop_check.

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 explicit usage context ('use it to see if a company is real and how it's doing') plus interpretation heuristics (zero revenue, no employees, negative equity). It doesn't name sibling alternatives for the basic-identity case, 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.

company_lookupCompany lookup (ANAF)A
Read-onlyIdempotent

Official status of Romanian companies from ANAF's public registry: name, address, registration number (J...), CAEN code, registration date, whether it's deregistered (radiată), VAT registered (and since when), VAT on collection, split VAT, declared fiscally inactive, and in the RO e-Factura registry. Each company comes with a 'warnings' list (deregistered, fiscally inactive, suspended).

Use it to vet suppliers or clients, e.g. checking a list of suppliers for fiscally inactive ones, since buyers generally can't deduct expenses or VAT on their invoices. Only searches by CUI, not by name. CUIs with a wrong control digit are returned under 'invalid' without asking ANAF. ANAF allows about one request per second, so every 100 CUIs take a second. Cached for 6h.

ParametersJSON Schema
NameRequiredDescriptionDefault
cuisYesOne or more CUIs, with or without RO, e.g. ["14399840", "RO18547290"]. Up to 500 in one call.
dateNoCheck the status as it was on this day (YYYY-MM-DD or DD.MM.YYYY), e.g. an invoice date to see if the supplier was VAT registered then. Defaults to today.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnly/idempotent/non-destructive/openWorld, and the description adds substantial non-obvious behavior: ~1 request/second rate limit with the practical '100 CUIs take a second' translation, 6h caching, local control-digit validation returning invalid CUIs without hitting ANAF, and the semantics of the warnings list.

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-loads the highest-value information (what registry, what fields) then moves to usage, constraints, and rate limits. The returned-field enumeration is long but each item earns its place since there is no output schema. Minor density cost.

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 no output schema, the description compensates by enumerating return fields and warning values, plus rate limits, caching, and edge-case handling — everything an agent needs to call this correctly and interpret results.

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 coverage is 100%, so the baseline is 3, but the description adds meaning the schema lacks: the CUI-only restriction (no name search) and the purpose of the date parameter (e.g. an invoice date to see whether the supplier was VAT registered then). It stops short of explaining the invalid-CUI return shape.

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 — official status of Romanian companies from ANAF's public registry — and enumerates exactly what is returned (name, address, J number, CAEN, VAT status, warnings). This is clearly distinguishable from sibling company_financials, court_cases, or iban_check.

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 a concrete use case (vetting suppliers/clients, e.g. screening a supplier list for fiscally inactive companies) with the business rationale. It also states a hard constraint: only searches by CUI, not by name. It does not explicitly name sibling alternatives for other lookup styles, 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.

court_casesCourt cases (Portal Just)A
Read-onlyIdempotent

Court cases from Portal Just, the public portal of every Romanian court: case number, court, category (civil, criminal, insolvency...), stage, subject, parties and their roles, latest outcome and next hearing. For a party it also counts its roles (defendant, creditor...) and lists insolvency cases where it's the debtor, the strongest red flag for a company.

Prefer cui for companies: the portal has no fiscal codes, so a name search also returns other companies with similar names. A big company being creditor or plaintiff in many cases is normal, look at the roles. Portal Just caps a search at 1000 cases. Usually answers in 1-5s. Cached for 3h.

ParametersJSON Schema
NameRequiredDescriptionDefault
cuiNoA company's CUI. Its exact name and county come from ANAF, so only that company's cases are kept and insolvency is checked at the right court. Best for companies.
courtNoOnly cases at this court, e.g. "Tribunalul Cluj" or "Judecatoria Sectorul 4". Ambiguous names return an error listing the matching courts.
limitNoHow many cases to return in detail, most recently updated first. Counts cover all of them.
partyNoName of a party to search for, e.g. "Dante International". "SC" and the legal form (SRL, SA) are dropped so different spellings match. Diacritics don't matter.
sinceNoOnly cases registered on or after this day (YYYY-MM-DD or DD.MM.YYYY).
case_numberNoCase number, e.g. "17902/3/2023". Use instead of or together with party.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare read-only, idempotent, non-destructive and open-world behavior, but the description adds operational traits those don't cover: a 1000-case search cap, typical 1-5s latency, and 3h caching. It also explains the noise profile of name searches and why names may mismatch, which materially affects how an agent interprets 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?

It is front-loaded with the returned data set before moving to usage advice and operational notes, and every sentence carries information (cui preference, role interpretation, cap, latency, caching). It is dense and slightly longer than minimal, but no sentence is filler.

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?

There is no output schema, so the description carries the burden of describing returns — it lists the fields, the party role counts, and the insolvency-debtor listing. Combined with the 100%-documented parameter schema and the operational notes (cap, cache, latency), an agent has everything needed to call and interpret this 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?

Schema coverage is 100%, so the schema already documents all six parameters in detail (cui, court, limit, party, since, case_number). The description adds selection meaning beyond the schema by explaining why cui is preferred over party and how to read party roles, which is genuine guidance rather than repetition.

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 names a specific resource (court cases from Portal Just, the Romanian courts portal) and enumerates what each record contains — case number, court, category, stage, subject, parties/roles, outcome, next hearing. It also scopes the tool's special behavior (role counting and insolvency-as-debtor detection), so an agent knows exactly what this tool returns without opening a schema. No sibling covers court data, so no differentiation gap exists.

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 an explicit routing preference ("Prefer cui for companies") with the reason (portal has no fiscal codes, so name searches return similar-named companies), and interpretive guidance ("A big company being creditor or plaintiff in many cases is normal, look at the roles"). It does not say when to reach for this tool rather than company_lookup or company_financials, so it stops short of full alternative-routing guidance.

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

exchange_rateBNR exchange rateA
Read-onlyIdempotent

Official National Bank of Romania (BNR) reference rate: how many RON one unit of a currency is worth on a day, and optionally an amount converted to RON. rate_date is the day of the fixing that was used.

BNR publishes once per working day around 13:00. For a VAT invoice in foreign currency the usual rule is the last rate published before the invoice date, so ask for the day before. Cached for 1h (past years for 30 days).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNoDay to get the rate for (YYYY-MM-DD or DD.MM.YYYY), from 2005 on. Weekends and holidays give the last rate before. Defaults to the latest rate.
amountNoAmount in that currency to convert to RON, e.g. 1500 for 1500 EUR.
currencyNoISO code like "EUR", "USD", "GBP", or "ALL" for every currency BNR publishes.EUR

TDQS

A4.4/5.0
Behavior5/5

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

Annotations declare readOnly/openWorld/idempotent, and the description adds traits they do not cover: BNR publishes once per working day around 13:00, results are cached for 1h (past years for 30 days), and weekends/holidays resolve to the last prior rate. Timing, staleness, and fallback behavior are exactly the non-obvious facts an agent needs.

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 core definition is front-loaded in the first sentence, followed by publication timing and the practical invoice rule. Four compact sentences with no redundancy, though the caching/parenthetical detail is slightly dense for its position.

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 no output schema, the description still conveys what the result means (RON per unit of currency, optionally an converted amount) and which day the fixing came from, plus freshness and holiday behavior. An agent has everything needed to call it and interpret the response.

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 date formats, the 'ALL' currency sentinel, and the amount semantics; baseline is 3. The description's only addition, 'rate_date is the day of the fixing that was used', concerns a return field rather than clarifying a parameter 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+resource: returning the official BNR reference rate for a currency on a given day, plus optional conversion to RON. It also defines the domain term 'rate_date' and would not be confused with any sibling (court_cases, iban_check, shop_check, company_financials, company_lookup).

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 concrete conditional guidance: for a VAT invoice in foreign currency, the usual rule is the last rate published before the invoice date, 'so ask for the day before'. This is real when-to-use context rather than restatement. It stops short of naming explicit exclusions or alternatives (none of the siblings overlap, so the cost is low).

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

iban_checkIBAN checkA
Read-onlyIdempotent

Check that an IBAN is well formed (length and mod-97 check digits, catches typos) and, for Romanian IBANs, which bank issued it and whether it's a State Treasury account. Works for any country's IBAN, offline, nothing is sent anywhere.

A valid IBAN only means the number is well formed: it doesn't prove the account exists or who owns it. Use company_lookup to check the company you're paying.

ParametersJSON Schema
NameRequiredDescriptionDefault
ibanYesIBAN to check, spaces allowed, e.g. "RO49 AAAA 1B31 0075 9384 0000".

TDQS

A4.4/5.0
Behavior4/5

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

Annotations already cover read-only/idempotent/non-destructive, but the description adds genuinely new context: the check is fully offline with nothing transmitted, and it discloses the semantics of a 'valid' result as only well-formedness, not account existence. That is meaningful beyond the annotations. Only minor gap: it doesn't say what is returned for an invalid IBAN (error vs. negative result), and 'offline' sits slightly awkwardly against openWorldHint=true, though that is a data-locality statement rather than a read/write contradiction.

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 tight paragraphs with no filler: the validation scope comes first, then the enrichment, then the caveat and the routing hint. Every sentence carries information an agent needs.

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?

There is no output schema, and the description compensates by describing what a result contains (well-formedness plus, for Romanian IBANs, issuing bank and State Treasury status) and the limits of that result. The only omission is the shape of a failure response (error vs. invalid flag), which a caller would benefit from knowing.

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?

With one required parameter and 100% schema description coverage including a concrete spaced-IBAN example, the schema fully documents the argument. The description explains what 'check' means (length + mod-97) but adds no syntax, format, or edge-case detail about the iban field itself, 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 ('check that an IBAN is well formed') plus the exact validation methods (length, mod-97 check digits) and the extra Romanian-bank/Treasury enrichment. It also explicitly differentiates itself from the sibling company_lookup, so an agent can route 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 Guidelines5/5

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

It states when the tool applies (any country's IBAN, offline), when it is insufficient ('a valid IBAN only means the number is well formed: it doesn't prove the account exists or who owns it'), and names the alternative to use for that gap (company_lookup). When-to-use, when-not, and the alternative are all explicit.

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

shop_checkOnline shop checkA
Read-onlyIdempotent

Is an online shop legit? Reads the CUI off the site (homepage, then terms / contact pages), then checks the company at ANAF, its last two years of financials, insolvency and other cases on Portal Just, and how long the site has been online (Wayback Machine). Returns a risk level (high / medium / low / unknown) with red_flags, warnings and good_signs, plus all the data behind them.

Use this first for "e țeapă?" questions, then the other tools to dig deeper. The result is signals, not proof: a scam can copy a real company's CUI, which is why it checks that the company name appears on the site. Fetches a few pages of the shop like a browser would. Takes 5-20s.

ParametersJSON Schema
NameRequiredDescriptionDefault
cuiNoThe company's CUI, if you already know it or the site hides it from bots.
urlYesThe shop's address, e.g. "https://example.ro" or just "example.ro".

TDQS

A4.5/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, openWorld), so the description correctly focuses on what they don't say: it fetches several pages like a browser, takes 5-20s, and returns signals rather than proof, including the specific caveat about CUI copying. The remaining gap is minor since annotations carry the read-only story and no output schema is promised.

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-loaded with the core question, then the data sources, then the output, then the routing and caveats. Dense but every sentence carries operational content; nothing is restated filler.

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 no output schema, the description must describe returns and does: a risk level (high/medium/low/unknown) with red_flags, warnings, good_signs, plus the underlying data. The latency and evidence-limitation caveats round out what an agent needs before calling it.

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 are documented in the schema itself, so the baseline is 3. The description mentions reading the CUI off the site, which loosely motivates the optional cui parameter, but adds no syntax or fallback detail the schema lacks.

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 question it answers ('Is an online shop legit?') plus the concrete resources it consults (ANAF, Portal Just, Wayback Machine) and the verdict shape it returns. Clearly distinguishable from siblings like company_lookup and court_cases, which cover single facets of the same investigation.

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 agent: 'Use this first for "e țeapă?" questions, then the other tools to dig deeper.' This gives both the trigger condition and the ordering relative to the sibling tools, 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.

Tool Schema Changelog

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

  1. 6 tool updatesv0.1.0
    • First observedcompany_financials
    • First observedcompany_lookup
    • First observedcourt_cases
    • First observedexchange_rate
    • First observediban_check
    • First observedshop_check

TDQS

A4.5/5.0

Scored across 6 tools

Disambiguation5/5

Each tool targets a distinct domain object: company_financials (filings), company_lookup (registry status), court_cases (litigation), exchange_rate (FX), iban_check (bank validation), and shop_check (composite first-pass). company_financials vs company_lookup could be blurred but the descriptions clearly separate financials from registry/VAT status, and shop_check is explicitly positioned as a wrapper over the others.

Naming Consistency4/5

All names are consistently snake_case with a domain_entity or verb_noun shape, which reads predictably. There is slight variation between noun_noun (court_cases, exchange_rate) and verb_noun (company_lookup, shop_check, iban_check), but the convention is readable and uniform.

Tool Count5/5

Six tools is well-scoped for a Romanian company-vetting server, with each tool earning a clear place. No redundancy or filler: the composite shop_check and the granular primitives complement rather than duplicate each other.

Completeness4/5

The surface covers the core vetting lifecycle: identity/status, financials, litigation, FX for invoices, IBAN sanity, and an aggregate risk check. The notable gap is that company_lookup only accepts CUI, so name-based discovery is a dead end (though this is a real ANAF constraint, not a design omission).

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    MCP server for EU company and business data. 9 tools: company search (GLEIF, 2M+ entities), LEI lookup, corporate structures (parent/subsidiaries), trade register search, EU VAT validation (VIES), GDP, unemployment, inflation, and business demography (Eurostat). All APIs free, no keys required.
    9
    6
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables querying Spain's official company registry (BORME) for company events such as incorporations, director appointments, insolvencies, and capital changes, supporting filters by date, province, and act type.
    7
    MIT