Skip to main content
Glama
README.md
# mcp-wl-vat

MCP server dla polskiej **białej listy podatników VAT** (Wykaz Podatników VAT) przez
oficjalne, bezpłatne API Ministerstwa Finansów (`wl-api.mf.gov.pl`). Zero kluczy API.

Autor: Piotr Waśniowski, Legal Link.

Zbudowany dla Legal Link, w konwencji tego samego fleetu co `mcp-saos` / `mcp-krs` /
`mcp-nsa` / `mcp-isap` / `mcp-eu-sparql` (MateMatic) — ten sam kontrakt
`structuredContent.citations`, ten sam wzorzec kodów błędów, ten sam `drift` test.

## Dlaczego własny, a nie istniejący `nip-checker-mcp`

Sprawdziliśmy istniejący projekt (`solverio-pl/nip-checker-mcp`) przed napisaniem tego.
Braki, które zdecydowały o budowie od zera:

- brak rozróżnienia kodów błędów — awaria sieci, błędny NIP i **wyczerpany dzienny limit
  zapytań MF** wszystkie zwracały identyczny, generyczny komunikat,
- brak jakiejkolwiek ochrony przed przekroczeniem dziennego limitu MF (100 zapytań/dzień
  metodą `search`, do 5000 metodą `check`) — po przekroczeniu MF blokuje **cały adres IP**
  do północy, co przy jednym IP biurowym oznacza blokadę dla całej kancelarii,
- brak wyszukiwania po REGON i po numerze konta,
- zero testów.

## Tools

- **`search_nip(nip, date?)`** — status VAT + dane podmiotu po NIP.
- **`search_regon(regon, date?)`** — jak wyżej, po REGON.
- **`search_bank_account(bank_account, date?)`** — jaki podmiot ma przypisany dany rachunek.
- **`check_nip_bank_account(nip, bank_account, date?)`** — TAK/NIE: czy dany rachunek jest
  przypisany do danego NIP. Wyższy dzienny limit (5000) niż metoda `search` (100) —
  preferowany, gdy znasz oba identyfikatory.

Każda odpowiedź zawiera `structuredContent.citations`:
`{ title, url, nip, regon, krs, status_vat, checked_date, request_id }`.

## Ochrona przed limitem dziennym

Ten serwer prowadzi **lokalny licznik w pamięci procesu** (nietrwały — restart = reset) i
sam odmawia wykonania zapytania (`rate_limit_daily`) z marginesem przed oficjalnym limitem
MF (90/100 dla `search`, 4800/5000 dla `check`). To siatka bezpieczeństwa, nie księgowość —
nie chroni przed przekroczeniem realnego limitu MF, jeśli kilka osób w biurze pyta
niezależnie z tego samego adresu IP.

Walidacja NIP/REGON/rachunku (z sumami kontrolnymi) odbywa się **przed** wysłaniem
zapytania — literówka nie zużywa slotu z dziennego budżetu.

## Potwierdzone empirycznie (2026-08-05, live test na produkcyjnym API)

- **WL-111** ("Nieprawidłowy numer konta bankowego") — realny kod błędu MF, zwracany gdy
  numer rachunku ma poprawną długość (26 cyfr) ale błędną sumę kontrolną NRB. Ten serwer
  **nie liczy sam** sumy kontrolnej NRB (mod 97 z formatowaniem liter PL) — poprawnie
  mapuje odpowiedź MF na kod `invalid_bank_account`, ale samo zapytanie już zużywa slot
  z dziennego limitu (w przeciwieństwie do błędów wykrytych czysto lokalnie, np. zła
  długość czy zły NIP).
- `search_nip` na prawdziwym NIP (ORLEN, 7740001454) zwraca poprawne dane, zgodne co do
  NIP/REGON/KRS z tym, co zwraca `mcp-krs`.

## Wciąż niezweryfikowane

Dokładny format błędu MF przy przekroczeniu **dziennego limitu zapytań** (spodziewany kod
`WL-191` wg wpisów na forach branżowych, nie potwierdzony na żywo — nikt jeszcze nie
uderzył w ten limit w testach). Detekcja (`looksLikeDailyLimitError` w `src/format.ts`)
działa na dopasowaniu frazy, nie sztywnego kodu. Jeśli kiedyś faktycznie zobaczysz ten
błąd w praktyce, sprawdź, czy wykrywanie zadziałało poprawnie — jeśli nie, popraw regex.

## Build + run
```
npm install
npm run build
npm start # stdio transport

npm run drift # offline - spójność INSTRUCTIONS/TOOLS/ErrorCode
npm run test:offline # offline - walidacja sum kontrolnych, formatowanie
npm run smoke # LIVE - wl-api.mf.gov.pl, zużywa realny dzienny limit
```
## Konfiguracja Claude Desktop

```json
{
  "mcpServers": {
    "wl-vat": {
      "command": "node",
      "args": ["<ścieżka>/mcp-wl-vat/dist/index.js"]
    }
  }
}
```

## Limity API (oficjalne, gov.pl, stan 01.01.2025)

- Metoda `search`: 100 zapytań/dzień z jednego IP, po max 30 podmiotów na zapytanie.
- Metoda `check`: do 5000 podmiotów/dzień.
- Po przekroczeniu: blokada IP do północy — obejmuje też ludzką wyszukiwarkę na
  podatki.gov.pl.

Dokumentacja MF: <https://www.gov.pl/web/kas/api-wykazu-podatnikow-vat>

## License

MIT.

TDQS

A4.4/5.0

Scored across 4 tools

Disambiguation5/5

Each tool targets a distinct identifier or combination: REGON, NIP, bank account, or NIP+account pair. There is no overlap or ambiguity in their purposes.

Naming Consistency4/5

Three tools follow the 'search_<identifier>' pattern, while the fourth uses 'check_<identifier1>_<identifier2>' to reflect its different validation action. The pattern is mostly consistent but with one justified deviation.

Tool Count5/5

Four tools are well-scoped for the server's narrow domain of Polish VAT registry lookups, covering the primary search and validation operations without redundancy.

Completeness5/5

The tool set covers all core query types: searching by NIP, REGON, bank account, and verifying a NIP-account pair. No obvious gaps exist for the intended white-list verification workflows.

Maintenance

ActivitySlowing
ResponsivenessNo issues