mcp-wl-vat
by pwasniowski
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