Skip to main content
Glama
neflingcreations

Polish Business Intelligence MCP

🇵🇱 Polish Business Intelligence MCP

Language: English · 🇵🇱 Polski

An MCP (Model Context Protocol) server that gives any AI agent (Claude, Cursor, Copilot) instant, live access to two official Polish data sources: the Ministry of Finance VAT whitelist (Biała Lista) and the National Bank of Poland (NBP) exchange rates. No API keys, no signup, no scraping.

CI Python License


Why this exists

Large language models don't have live access to the Polish VAT registry or to official exchange rates. That data changes daily and sits behind government APIs the model was never trained on. This server closes the gap. Once it's connected, your agent can check whether a Polish company is a registered VAT payer, pull its registered address and bank accounts, and convert money at the official central-bank rate, all in real time.

It wraps two free, public, no-auth APIs:

Source

What it provides

Biała Lista (Ministry of Finance VAT whitelist)

Look up a company by NIP (tax ID): name, VAT status, address, registration date, bank accounts

NBP (National Bank of Poland)

Official PLN exchange rates (kurs średni) for around 40 currencies

Why live data matters AI models confidently produce plausible-looking data, a valid NIP in the right format, that can still be wrong. The only way to be sure is to ask the authoritative source. That's what this server does, on every call.


Related MCP server: ksef-mcp

Tools

Tool

What it does

Key inputs

lookup_company

Full company lookup on the VAT whitelist: name, VAT status, address, registration date, bank accounts

nip

check_vat_status

Quick yes / no / exempt answer to "is this NIP an active VAT payer?". Handy for "can I trust this invoice?"

nip

get_all_rates

All current PLN rates from NBP Table A (EUR, USD, GBP, CHF, JPY, CZK, and more)

optional date

get_currency_rate

Official NBP mid rate for one currency (Table A, falling back to Table B for exotics)

currency_code, optional date

convert_currency

Convert between PLN and any currency, or cross-rate two currencies through PLN

amount, from_currency, to_currency, optional date

Every tool returns clean, human-readable text (never raw JSON), and it never throws. Errors come back as friendly messages the agent can act on.


Quick install

Requires uv and Python 3.11+.

git clone https://github.com/neflingcreations/PBI-MCP.git
cd PBI-MCP
uv sync

Claude Desktop / Claude Code config

Add this to your MCP config (Claude Desktop: claude_desktop_config.json):

{
  "mcpServers": {
    "polish-business": {
      "command": "uv",
      "args": ["run", "polish-business-mcp"],
      "cwd": "/path/to/PBI-MCP"
    }
  }
}

Restart the client and the five tools show up automatically.


Example agent interactions

Once connected, your agent can answer questions it couldn't before:

"Is the company with NIP 951-238-16-07 a registered VAT payer?" → calls check_vat_status("9512381607")YES: BOOKSY INTERNATIONAL SPÓŁKA Z OGRANICZONĄ ODPOWIEDZIALNOŚCIĄ (NIP 9512381607) is an ACTIVE VAT payer (status: Czynny).

"Look up NIP 9512381607 and give me their address and bank accounts." → calls lookup_company("9512381607") → returns the company name, VAT status, registered address (UL. PROSTA 67, Warszawa), registration date, and the list of whitelisted bank accounts.

"What's today's EUR/PLN rate from the NBP?" → calls get_currency_rate("EUR")EUR (euro): 4.2531 PLN per 1 EUR. Effective date 2026-06-26. Official NBP mid-market rate.

"Convert 1500 PLN to GBP at the official rate." → calls convert_currency(1500, "PLN", "GBP") → returns the converted amount, the GBP rate used, and the effective date.


API sources

Both are free, public, and need no authentication. The Biała Lista lookup always sends today's date, which the API requires. NBP only publishes rates on banking days, so a weekend request comes back with the most recent rate, and the tool shows the actual effective date it used.


Local development

uv sync                                              # install deps (incl. dev group)
uv run pytest                                        # run tests (HTTP fully mocked, no network)
uv run ruff check .                                  # lint
uv run mcp dev src/polish_business_mcp/server.py     # open the MCP Inspector and call tools by hand
uv run polish-business-mcp                           # run the server over stdio (it waits on stdin, which is normal)

The test suite mocks every HTTP call with respx, so it runs offline and gives the same result every time.


Roadmap

  • lookup_by_regon: the Biała Lista API also accepts REGON (a 9- or 14-digit company ID).

  • lookup_companies_batch: the batch endpoint (/api/search/nips/) checks up to 30 NIPs in one call.

  • Historical VAT-status checks for a given date.


Development

Built with an AI-assisted workflow (Claude Code). The architecture, API integration, and verification decisions were all made and reviewed by hand, and every tool was tested live against the real Polish APIs before release.

License

MIT. See LICENSE.

Available Tools

5 tools
check_vat_statusA

Quick check: is this NIP registered as an active VAT payer in Poland? Returns a short, definitive yes / no / exempt answer plus the company name — useful for fast agent decisions such as "can I trust this invoice?".

Args: nip: 10-digit Polish NIP. Spaces and dashes are fine.

ParametersJSON Schema
NameRequiredDescriptionDefault
nipYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior3/5

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

No annotations are provided, so the description carries the burden. It discloses the return format (yes/no/exempt answer plus company name) and describes the check as 'definitive', but it doesn't mention error handling for invalid NIPs, whether any side effects occur, or data source reliability. The description provides some transparency but leaves gaps.

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?

The description is concise and front-loaded, immediately answering 'what does this do?'. The return behavior, use case, and argument format are each explained in a short, purposeful way without any wasted words.

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?

Despite the tool's simplicity, the description covers purpose, return values, a concrete use case, and parameter format. An output schema exists, and the description already clarifies the return structure, making it complete for agent decision-making.

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 0%, so the description fully compensates for the single parameter 'nip' by specifying the format ('10-digit Polish NIP') and allowed formatting ('Spaces and dashes are fine'). This adds practical value beyond the schema's bare string type.

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 clearly states the tool's function with a specific verb ('check') and resource ('NIP registered as an active VAT payer in Poland'). It distinguishes itself from siblings like lookup_company and get_all_rates by focusing specifically on VAT status verification.

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?

Provides clear context for when to use the tool ('useful for fast agent decisions such as 'can I trust this invoice?''). While it doesn't explicitly name alternatives or exclusions, the use case is specific enough to guide selection among the sibling tools.

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

convert_currencyA

Convert an amount between PLN and another currency, or between two foreign currencies (via PLN as the pivot), using official NBP mid-market rates.

Args: amount: The amount to convert. from_currency: Source currency ISO code (e.g. "PLN", "EUR"). to_currency: Target currency ISO code (e.g. "GBP", "PLN"). date: Optional ISO date (YYYY-MM-DD) for historical rates.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNo
amountYes
to_currencyYes
from_currencyYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description bears full responsibility for disclosing behavior. It transparently states the use of NBP mid-market rates, the PLN pivot for foreign-to-foreign conversions, and the optional historical date. It does not mention potential edge cases like rate unavailability for certain currencies or errors, but it covers the core operational details beyond what a schema would show.

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?

The description is front-loaded with a clear single-sentence purpose, followed by a concise Args list. Every sentence adds necessary information, with no filler or repetition. The structure is easy to scan and immediately usable by an agent.

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?

The description covers the core functionality, parameter meanings, and the pivot mechanism. It has an output schema (though not shown), so return values are presumably handled there. Missing are notes on error handling or unsupported currency codes, but given the tool's moderate complexity, the description is sufficiently complete for an agent to invoke it correctly.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate, and it does. Each parameter (amount, from_currency, to_currency, date) is explained with examples for currencies and an explicit format for date. This adds all the semantic meaning missing from the schema, which only has titles.

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 clearly specifies the tool's function: converting an amount between PLN and another currency or between two foreign currencies using NBP mid-market rates. It distinguishes this from sibling tools like get_currency_rate by emphasizing conversion of an amount rather than just rate 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?

The description conveys when to use this tool (for conversions) and explains the PLN pivot mechanism, which is essential for understanding how conversions work. It does not explicitly name alternatives or exclusions, but the sibling tool names (get_currency_rate, get_all_rates) imply those are for rate-only tasks, providing implicit differentiation.

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

get_all_ratesA

Get all current PLN exchange rates from the National Bank of Poland (Table A — EUR, USD, GBP, CHF, JPY, CZK and ~30 others).

Args: date: Optional ISO date (YYYY-MM-DD) for historical rates. NBP publishes rates only on banking days; a weekend date returns the most recent available table (the actual effective date is shown).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations provided, the description carries the full burden. It discloses a key behavioral nuance: NBP publishes rates only on banking days, so weekend dates return the most recent available table and the effective date is shown. This goes beyond the schema and helps the agent interpret results.

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?

The description is two concise sentences plus a compact Args block. It front-loads the core purpose and only adds necessary detail about the parameter. No redundant or filler content.

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 the tool's simplicity (one optional parameter, output schema available), the description is highly complete. It covers purpose, parameter semantics, and a real-world edge case. It does not list every currency or error handling, but that exceeds what's needed for selection and invocation.

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

Parameters5/5

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

The schema has only a 'date' parameter with zero description coverage, so the description must compensate fully. It does: explains the ISO format, marks it optional, and describes what happens with weekend dates. This gives the agent everything needed to invoke the tool correctly.

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 clearly states the tool's function: 'Get all current PLN exchange rates from the National Bank of Poland' with specific scope (Table A, list of currencies). It differentiates from siblings like get_currency_rate, which likely returns a single rate, by emphasizing 'all' rates.

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 description provides useful context (optional historical date, weekend behavior) but does not explicitly mention when to use this tool versus alternatives like get_currency_rate or convert_currency. The usage guidance is implied by the 'all' phrasing, not stated directly.

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

get_currency_rateA

Get the official NBP mid-market exchange rate for a single currency against PLN. Tries Table A first and falls back to Table B for exotic currencies.

Args: currency_code: ISO 4217 code, e.g. "EUR", "USD", "GBP". date: Optional ISO date (YYYY-MM-DD) for a historical rate.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateNo
currency_codeYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the transparency burden. It discloses a meaningful behavioral detail: 'Tries Table A first and falls back to Table B for exotic currencies.' This explains why different currencies may be resolved via different NBP tables. It does not cover failure modes or error handling, but the disclosed fallback logic adds important context beyond the schema.

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?

The description is front-loaded with the primary function in the first sentence, followed by a compact and clear Args block. There is no fluff, and every sentence adds value.

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?

The tool is simple (2 parameters, 1 required), and the description covers the data source (NBP), the currency pair (vs PLN), the fallback behavior, and parameter formats. Since an output schema exists, return value details are not needed. Minor gaps like error cases are not covered, but the core usage is fully specified.

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

Parameters5/5

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

The schema has no descriptions for its parameters (0% coverage). The description compensates fully by defining currency_code as an ISO 4217 code with examples ('EUR', 'USD', 'GBP') and date as an optional ISO date (YYYY-MM-DD) for historical rates, providing formats and semantics beyond the raw field names.

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 clearly states the tool's function: 'Get the official NBP mid-market exchange rate for a single currency against PLN.' It uses a specific verb and resource, and the phrase 'single currency' differentiates it from the sibling tool 'get_all_rates'.

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 indicates the tool is specifically for retrieving a single exchange rate against PLN and optionally for historical dates. It provides clear context but does not explicitly rule out alternatives like 'convert_currency' or state when not to use it, though the single-currency framing implicitly guides selection.

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

lookup_companyA

Look up a Polish company by NIP (tax ID) on the Ministry of Finance VAT whitelist (Biała Lista). Returns the company name, VAT status, registered address, registration date and bank account numbers.

Args: nip: 10-digit Polish NIP. Spaces and dashes are fine — they are stripped.

ParametersJSON Schema
NameRequiredDescriptionDefault
nipYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.1/5.0
Behavior3/5

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

With no annotations, the description carries the burden of behavioral disclosure. It does disclose input normalization ('Spaces and dashes are fine — they are stripped') and the list of returned fields, which is useful. However, it omits potential error conditions (e.g., NIP not found on the whitelist), rate limits, or any explicit statement that this is a read-only operation, leaving gaps in transparency.

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?

The description is extremely concise: two short sentences explaining the main purpose and one argument explanation. It is front-loaded with the core action and contains no redundant or filler words, making it efficient and easy to parse.

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 the tool's simplicity (single parameter, read-only lookup) and the presence of an output schema, the description covers the essentials well—purpose, result fields, and input format. The only notable gap is the lack of explicit guidance on when to use this tool over sibling check_vat_status, but this is a minor omission for such a straightforward operation.

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

Parameters5/5

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

The schema only provides the parameter name and type, while the description adds critical semantics: it specifies that the NIP must be a 10-digit Polish NIP and that spaces/dashes are stripped. This fully compensates for the absent schema description, providing an agent with all necessary input details.

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 clearly states a specific action ('Look up a Polish company by NIP'), identifies the authoritative source ('Ministry of Finance VAT whitelist'), and enumerates the returned data (company name, VAT status, address, registration date, bank accounts). This differentiates it from sibling tools like check_vat_status by implying a full profile rather than a single status check.

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 description provides contextual information about the target (Polish company, NIP) but does not explicitly explain when to use this tool versus the sibling check_vat_status or other alternatives. Usage is implied rather than stated, so some ambiguity remains for an agent deciding between tools.

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. 5 tool updatesv0.1.0
    • First observedcheck_vat_status
    • First observedconvert_currency
    • First observedget_all_rates
    • First observedget_currency_rate
    • First observedlookup_company

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation4/5

lookup_company and check_vat_status both operate on NIP numbers and return VAT-related information, which could cause initial confusion, but their scope is clearly different: full company details vs. a quick yes/no status. The three exchange-rate tools are each well-differentiated.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern: lookup_company, check_vat_status, get_all_rates, get_currency_rate, convert_currency. The verbs are all actions and the nouns clearly indicate the target, making the naming predictable and readable.

Tool Count5/5

With 5 tools across two related but distinct subdomains (VAT whitelist and exchange rates), the set is well-scoped. Each tool serves a clear purpose, and the count is neither bloated nor too sparse for the apparent functionality.

Completeness5/5

The VAT domain is covered with a full lookup and a fast status check; the exchange-rate domain is covered with all rates, a single rate, and conversion. Historical date support is included, and there are no obvious missing operations for the stated business intelligence purpose.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Look up Polish companies from any AI assistant: registry data (KRS, REGON, CEIDG), VAT white list checks before payments, and financial statements of 4.4M businesses. Read-only tools backed by official public registers.
    4
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to interact with the Polish National e-Invoice System (KSeF) for authentication, invoice creation, validation, and retrieval via 30 tools.
    32
    4
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables real-time verification of Polish NIP (Tax Identification Numbers) using the official Ministry of Finance API. Also supports checking if a bank account belongs to a specific NIP.
    2
    6 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to issue Poland structured e-invoices (faktura ustrukturyzowana) through KSeF 2.0, handling FA(3) XML building, encrypted session flow, and KSeF number retrieval.
    MIT