mcp-krs
This server provides access to the Polish National Court Register (KRS) via the Ministry of Justice API, allowing you to query data about registered companies and associations.
get_entity(krs, rejestr?)– Retrieve a current extract including name, legal form, NIP, REGON, address, share capital, board composition, representation rules, commercial proxies (prokurenci), primary PKD code, and status (active/liquidation/bankruptcy).get_entity_full(krs, rejestr?)– Retrieve a full historical extract with all past changes, deletions, and previous board compositions.get_board(krs, rejestr?)– Retrieve a condensed view of board composition, representation rules, and commercial proxies — ideal for quickly determining who can legally represent an entity.
Additional notes:
Supports the entrepreneurs register (
P, default) and associations register (S)KRS numbers are auto-padded to 10 digits (e.g.,
28860→0000028860)All responses include structured citation metadata and a URL to the official Ministry of Justice search tool
Board member personal data may be partially masked per 2023 Polish law
mcp-krs
Installation (one command)
Published on npm + MCP Registry (io.github.matematicsolutions/mcp-krs). Run without cloning:
npx -y @matematicsolutions/mcp-krsMCP client configuration (stdio):
{ "mcpServers": { "mcp-krs": { "command": "npx", "args": ["-y", "@matematicsolutions/mcp-krs"] } } }(Building from source - below.)
MCP server for the Krajowy Rejestr Sadowy / KRS (National Court Register) via the official, free
Ministerstwo Sprawiedliwosci (Ministry of Justice) API (api-krs.ms.gov.pl/api/krs).
Related MCP server: KRS Poland MCP Server
Why
A law firm asks about a counterparty -> Patron returns full register data: name, legal form, NIP, REGON, address, share capital, board composition, representation rules, commercial proxies (prokurenci), primary PKD code, status (active / liquidation / bankruptcy). Plus a URL to the Ministry of Justice search tool.
Critical for contract work: the question "can this person sign this contract
for company X on their own" reduces to two moves -
krs__get_board with the KRS number, then comparing the representation rules
against the signing party.
Tools
get_entity(krs, rejestr?)- current extract (full entity data).get_entity_full(krs, rejestr?)- full extract (with entry history).get_board(krs, rejestr?)- short form: representation only (rules + composition) + commercial proxies (prokurenci).
Parameters:
krs- 1-10 digits, leading zeros padded automatically (28860->0000028860).rejestr-P(entrepreneurs register, default) orS(associations register).
Every response contains structuredContent.citations with fields:
title, url (Ministry of Justice search), krs, nazwa, nip, regon,
forma_prawna, status, miejscowosc, sad_rejestrowy, rejestr.
Patron reads the field automatically and renders it in the UI panel as a "Krajowy Rejestr Sadowy (KRS - MS)" section.
Stack
Node 18+ (built-in
fetch)@modelcontextprotocol/sdkStdio transport
Throttle 500 ms (2 req/s) - the Ministry of Justice API is tolerant, but be polite
Build + run
npm install
npm run build
node dist/index.jsWiring into Patron
In patron/backend/mcp-servers.json:
{
"name": "krs",
"transport": "stdio",
"command": "node",
"args": ["C:/Users/<YOUR-USER>/mcp-krs/dist/index.js"],
"enabled": true
}Smoke test
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"s","version":"0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_board","arguments":{"krs":"28860"}}}' \
| node dist/index.jsShould return ORLEN SA, representation rules "two board members acting jointly", board composition, commercial proxies (prokurenci) + URL.
GDPR notes
The Ministry of Justice API returns masked personal data of board members in its responses (asterisks in surnames after the 2023 amendment). Patron passes this through raw and does not unmask it. For full surnames, the law-firm user opens the Ministry of Justice link in a browser after logging in.
Lineage
API contract from the official documentation MS api-krs.ms.gov.pl. TypeScript implementation from scratch.
License
MIT.
Part of the MateMatic legal stack
This server is one of five MCP connectors covering Polish jurisdiction + EU law, used by Patron (AGPL-3.0) and any other MCP-aware legal AI agent.
mcp-krs (this repo) - Polish company registry (official MS API)
mcp-saos - common courts, SN, TK, KIO
mcp-nsa - NSA + 16 WSA administrative courts
mcp-isap - Polish legislation (Dz.U. + M.P.)
mcp-eu-sparql - EU law + CJEU (EUR-Lex)
All five MCP servers share the same structuredContent.citations
contract: each tool returns an array of {title, url, snippet?, ...metadata}
that legal agents can render directly in their citation panel.
See matematicsolutions/.github for the full org profile.
Available Tools
3 toolsget_boardARead-onlyIdempotent
SKROCONA wersja: tylko sklad zarzadu + sposob reprezentacji + prokurenci. Szybciej niz get_entity gdy potrzebujesz tylko 'kto reprezentuje X'. Bazuje na odpisie aktualnym.
| Name | Required | Description | Default |
|---|---|---|---|
| krs | Yes | Numer KRS (1-10 cyfr). | |
| rejestr | No | Rejestr: 'P' (default) lub 'S'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds behavioral context by stating it is based on a current extract and is faster. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no wasted words. Front-loaded with the core purpose and key differentiator.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the simple input schema and presence of annotations, the description adequately covers what the tool returns, its data source, and performance advantage. No output schema needed explanation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters with descriptions. The description does not add additional meaning to parameters beyond what the schema provides, so baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states this tool returns board composition, representation method, and proxies. It distinguishes itself from get_entity by being faster and more focused, and the name 'get_board' aligns with the described scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says to use this when you need 'who represents X' and that it's faster than get_entity. However, it does not mention when not to use it or address the sibling get_entity_full, leaving some gaps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_entityARead-onlyIdempotent
Pobiera ODPIS AKTUALNY z Krajowego Rejestru Sadowego po numerze KRS. Zwraca pelne dane podmiotu: nazwa, forma prawna, NIP, REGON, adres, kapital zakladowy, reprezentacja (zarzad + sposob reprezentacji), prokurenci, glowny PKD, status (aktywny/likwidacja/upadlosc) + URL do wyszukiwarki KRS. Numer KRS uzupelnij zerami wiodacymi (lub podaj krotszy - zostanie wyrównany do 10 cyfr).
| Name | Required | Description | Default |
|---|---|---|---|
| krs | Yes | Numer KRS (1-10 cyfr, np. '28860' -> automatyczne '0000028860'). | |
| rejestr | No | Rejestr: 'P' = przedsiebiorcow (domyslnie), 'S' = stowarzyszen. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as read-only and idempotent. Description adds behavioral details like automatic zero-padding of KRS to 10 digits and inclusion of a URL to the KRS search engine.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is a single paragraph that front-loads the main purpose. It is informative but slightly verbose; could be tightened.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, description comprehensively lists returned fields, including URL. For a read-only tool with two parameters, this provides complete context for use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all parameters, but description adds behavior for 'krs' (zero-padding) and clarifies enum values for 'rejestr' (default and alternatives).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the tool retrieves a current extract from the National Court Register by KRS number, listing specific data returned. It uses a specific verb and resource, distinguishing it from siblings like get_board and get_entity_full by focusing on a single entity's full details.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to use this tool versus alternatives. No mention of prerequisites or context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_entity_fullARead-onlyIdempotent
Pobiera ODPIS PELNY z KRS (z historia wpisow - kazda zmiana, kazde wykreslenie, wszystkie poprzednie sklady zarzadu). Wieksza odpowiedz, uzywaj kiedy potrzebujesz historii zmian, nie tylko stanu aktualnego.
| Name | Required | Description | Default |
|---|---|---|---|
| krs | Yes | Numer KRS (1-10 cyfr). | |
| rejestr | No | Rejestr: 'P' (default) lub 'S'. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description discloses behavioral traits beyond annotations: returns history including each change, deletion, previous management boards, and larger response. Annotations already indicate readOnlyHint=true, destructiveHint=false, idempotentHint=true, and description aligns and adds detail.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no fluff, front-loaded with purpose and key differentiator. Every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with good annotations and no output schema, description covers what the tool returns and when to use it. Could mention output format explicitly but not required given clarity. Slight room for improvement.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. Description does not add additional parameter insights beyond what is already in schema (krs number, rejestr with enum). No contradiction, but no extra value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states verb 'Pobiera' (retrieves) and resource 'ODPIS PELNY z KRS' with history. It distinguishes from siblings by specifying it provides full history of changes, not just current state, which contrasts with likely simpler tools like get_entity and get_board.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use: 'uzywaj kiedy potrzebujesz historii zmian, nie tylko stanu aktualnego' (use when you need history of changes, not just current state). This implies alternative for current state, providing clear context.
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.
3 tool updates
v1.1.0- First observed
get_board - First observed
get_entity - First observed
get_entity_full
TDQS
Scored across 3 tools
Each tool targets a distinct use case: get_board for quick board composition summary, get_entity for current full entity data, and get_entity_full for historical records. There is no ambiguity or overlap between them.
All tool names follow a consistent get_ prefix pattern with snake_case (get_board, get_entity, get_entity_full), making the naming predictable and easy to understand.
Three tools is an appropriate number for a specialized KRS data retrieval server. Each tool serves a distinct purpose covering the main query needs without being excessive or too sparse.
The tools cover the main read operations for KRS entities (current data, full history, board summary). However, a search tool by name or NIP is missing, which would be a natural complement for a complete data retrieval surface.
Maintenance
Related MCP Connectors
MCP server for 3M+ Polish companies — KRS & CEIDG financials, ownership, and industry search.
Polish company records from the official KRS register API, with alerts on new registry entries.
1Polish company registry: 4.4M firms, KRS/REGON data, VAT white list checks, financial statements
Hosted MCP server for real-world data: business registries, sanctions, companies, domains, crypto.
Related MCP Servers
- AlicenseAqualityDmaintenanceMCP server providing AI assistants access to Polish public registries (KRS, CEIDG) and statistical data (GUS BDL) for querying companies, sole proprietorships, and regional statistics.147MIT
- AlicenseCqualityDmaintenanceEnables querying the Polish National Court Register (KRS) to retrieve current and historical entity data.257 npm4MIT
- AlicenseNot gradedqualityCmaintenanceMCP server for verifying Polish business entities from the National Court Register (KRS) and VAT White List. Allows querying by KRS, NIP, or REGON to retrieve official company data including name, address, board, and capital.Apache 2.0
- AlicenseAqualityBmaintenanceMCP server for Polish company registries that enables looking up companies by NIP or KRS using public government APIs with no authentication required.2MIT