polish-mcp-servers 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,6 +25,8 @@ Each call returns at most 100 dataset items and at most 256 KiB of JSON. Pass `m
25
25
  | `polish-developer-apartment-prices` | Developer apartment and house offers, with price per m², from dane.gov.pl. | [Store](https://apify.com/enterprising_hamster/polish-developer-apartment-prices) |
26
26
  | `polish-electricity-market-pse` | PSE electricity prices and grid rows (RCE, day-ahead, imbalance, load, generation). | [Store](https://apify.com/enterprising_hamster/polish-electricity-market-pse) |
27
27
 
28
+ The full tool and parameter descriptions that clients see live in [`catalog/tool-descriptions.json`](catalog/tool-descriptions.json). Every tool is annotated `readOnlyHint: true`, `destructiveHint: false`, `idempotentHint: true`, `openWorldHint: true`: it only reads the public source, but each `tools/call` starts a paid Apify Actor run, billed pay-per-event to the Apify account behind `APIFY_TOKEN`, and waits up to 300 s for it.
29
+
28
30
  `polish-mcp-servers` and `polish-mcp` list all 12. `polish-law-mcp` lists only `polish-law-mcp-server`. `polish-public-registers` lists the other 11, including `cee-public-tenders`.
29
31
 
30
32
  ## Install
@@ -0,0 +1,42 @@
1
+ {
2
+ "polish-law-mcp-server": {
3
+ "description": "Makes one call to the Polish Law MCP Actor, which reads the official Sejm ELI API (Dziennik Ustaw, Monitor Polski) and the SAOS court judgments API live: set tool to search_legal_acts, get_legal_act, get_legal_act_text (current consolidated wording, optionally one article), list_changed_legal_acts, search_court_judgments or get_court_judgment, and pass that tool's arguments. Use it to find or read one specific act, article or judgment; for bulk filtered lists or onlyNew feeds use polish-legal-acts-eli or polish-court-judgments-saos. Read-only: it only queries the public sources and never writes to them. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-law-mcp-server on your Apify account, billed pay-per-event per successful tool call (calls returning full text cost more; failed or empty calls are free) plus any Apify platform usage. The server waits up to 300 s; ELI answers in about a second, SAOS searches take 1-20 s and one full SAOS judgment 15-60 s.",
4
+ "parameters": {
5
+ "tool": "Which law tool to run once. search_legal_acts: find acts by title stem, publisher (DU or MP), year, type, keywords, in-force status or date range. get_legal_act: metadata, status and references of one act. get_legal_act_text: plain text of an act or one article (newest consolidated text), paged. list_changed_legal_acts: acts whose ELI record changed since a time. search_court_judgments: find SAOS judgments. get_court_judgment: full text and metadata of one judgment.",
6
+ "arguments": "Arguments object for the chosen tool, exactly as the hosted Polish Law MCP server takes them, e.g. {\"title\": \"ochron danych\", \"limit\": 5} for search_legal_acts, {\"eli\": \"DU/1964/93\", \"article\": \"415\"} for get_legal_act_text (an ELI id or a Dz.U. citation), or {\"query\": \"art. 415 k.c.\", \"court_type\": \"SUPREME\", \"limit\": 5} for search_court_judgments. Full argument lists: https://apify.com/enterprising_hamster/polish-law-mcp-server"
7
+ }
8
+ },
9
+ "polish-legal-acts-eli": {
10
+ "description": "Lists Polish legal acts from the official Sejm ELI API (Dziennik Ustaw or Monitor Polski), filtered by year or date range, title stem, ELI keywords, act type and in-force status; each item is act metadata, with includeDetails adding keywords, references, issuing bodies and inForce, and includeText adding extracted HTML/PDF text (no OCR, charged at a higher rate). Use it for bulk lists or monitoring of acts; to read one act or article interactively use polish-law-mcp-server. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-legal-acts-eli on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
11
+ },
12
+ "polish-court-judgments-saos": {
13
+ "description": "Searches Polish court judgments in the official SAOS database (System Analizy Orzeczeń Sądowych) by court type, date range, SAOS query phrase, subject keywords and judgment type; each item has case numbers, judges and keywords, and includeFullText adds the published anonymised text (charged at a higher rate). Coverage is uneven: common courts are current, Supreme Court data ends in 2016-06, the Constitutional Tribunal in 2015-12 and KIO in 2018-09, and administrative courts return nothing. Use it for bulk lists or onlyNew feeds; to read one judgment interactively use polish-law-mcp-server. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-court-judgments-saos on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
14
+ },
15
+ "polish-eu-funds-tenders-baza-konkurencyjnosci": {
16
+ "description": "Lists procurement notices (zapytania ofertowe) published by EU-grant beneficiaries on the official Baza Konkurencyjności portal (archive from 2014-01-01), filtered by publication date, status, search query, category, CPV, region, beneficiary name or NIP and submission deadline; includeDetails adds orders, conditions, evaluation criteria, estimated values and attachments (charged at a higher rate). Use it for Polish EU-funded procurement; for Czech, Slovak, Hungarian or Ukrainian tenders use cee-public-tenders. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-eu-funds-tenders-baza-konkurencyjnosci on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
17
+ },
18
+ "cee-public-tenders": {
19
+ "description": "Lists public tenders from Czechia, Slovakia, Hungary and Ukraine in one normalised schema, collected from the official Prozorro, Slovak Vestník and TED sources: title, CPV codes, value, deadline and status, with includeDetails adding lots, places of performance, document links and an EU-funding flag (charged at a higher rate). Filter by country, lastDays, keywords, CPV prefixes and onlyOpen. It does not cover Poland; for Polish EU-funded procurement use polish-eu-funds-tenders-baza-konkurencyjnosci. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/cee-public-tenders on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
20
+ },
21
+ "polish-ev-charging-stations-eipa": {
22
+ "description": "Returns EV, CNG/LNG and hydrogen stations in Poland from the official EIPA register run by UDT: operator, address, GPS, power in kW and connectors, with includeLiveData adding live point status and ad-hoc prices; stations of possibly private operators are anonymised or skipped. Without eipaToken it uses a shared EIPA demo account limited to 10 static downloads an hour, so it may be refused when busy; pass your own free EIPA reader token for regular use. Use it for charging infrastructure; for vehicle fleet statistics use polish-vehicle-registrations-cepik. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-ev-charging-stations-eipa on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
23
+ },
24
+ "polish-vehicle-registrations-cepik": {
25
+ "description": "Returns monthly vehicle registration counts from the official CEPiK open data API, grouped by brand, model, fuel, powertrain, origin, production year or county and filtered by vehicle type, fuel, origin, voivodeship and month range (at most 60 months per run); aggregates only, no VINs or owners. Defaults are electric passenger cars in Mazowieckie for the last complete month; all of Poland can take several minutes when CEPiK is busy. Use it for fleet and EV adoption statistics; for charging infrastructure use polish-ev-charging-stations-eipa. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-vehicle-registrations-cepik on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
26
+ },
27
+ "polish-building-permits-gunb": {
28
+ "description": "Returns building permit decisions (pozwolenia na budowę) and construction notifications (zgłoszenia) from the official GUNB register (RWDZ), newest first: project name, Construction Law category, cubature, location and dates; investors are named only when they are organisations, never private persons. Defaults to permits in Mazowieckie; set voivodeships to ALL or pass TERYT codes for other areas. Use it for construction projects and leads; for parcel boundaries and zoning use polish-land-parcels-uldk-zoning. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-building-permits-gunb on your Apify account, billed pay-per-event per delivered project (named organisation investors cost more) plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
29
+ },
30
+ "polish-land-parcels-uldk-zoning": {
31
+ "description": "Looks up Polish land parcels (działki) in the official GUGiK ULDK service by full parcel ID, precinct name plus number, or GPS point, returning location, area and an optional GeoJSON boundary; includeZoning adds local zoning plans (MPZP) and general plan zones (POG) with building limits from Rejestr Urbanistyczny (charged at a higher rate). No owner data; with no input it looks up three example parcels. Use it for one parcel's geometry and zoning; for building permits use polish-building-permits-gunb. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-land-parcels-uldk-zoning on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
32
+ },
33
+ "polish-healthcare-facilities-rpwdl": {
34
+ "description": "Returns Polish healthcare facilities from the official RPWDL register (Rejestr Podmiotów Wykonujących Działalność Leczniczą): address, phone, organisation e-mail, website, NIP/REGON, specialties and beds. Filter by voivodeship, TERYT code, city, facility kind, ownership, specialty code or keyword, name, NIP, available contacts and minimum beds; the whole register is about 24,000 facilities. Use it for hospital and clinic lookups or lead lists; no sibling tool covers healthcare. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-healthcare-facilities-rpwdl on your Apify account, billed pay-per-event per delivered item plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
35
+ },
36
+ "polish-developer-apartment-prices": {
37
+ "description": "Returns new-build apartment and house offers from the developer price lists published on dane.gov.pl under the price transparency rules (jawność cen): one record per unit with price, price per m² and location, or, in priceChanges mode, only the differences from the developer's previous list. Filter by publication window (lastDays, or a date range of at most 14 days), voivodeship, city, developer, property type and availability. Use it for primary-market housing prices from developers; no sibling tool covers real estate. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-developer-apartment-prices on your Apify account, billed pay-per-event per delivered record (price changes cost more) plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
38
+ },
39
+ "polish-electricity-market-pse": {
40
+ "description": "Returns Polish electricity market and grid data from the official PSE API (Polskie Sieci Elektroenergetyczne): RCE market price, day-ahead and imbalance prices, Kompas Energetyczny, load and generation mix, as 15-minute, hourly or daily rows. Filter by business-date range (history from 2024-06-14) or lastDays; next-day data appears once PSE publishes it, about 14:00 Europe/Warsaw. Use it for energy prices and grid statistics; no sibling tool covers electricity. Read-only: it only queries the public source and never writes to the registry; onlyNew merely keeps a stateKey memory in your own Apify account. Each call needs the APIFY_TOKEN env var and starts one paid run of the Apify Actor enterprising_hamster/polish-electricity-market-pse on your Apify account, billed pay-per-event per delivered data row plus any Apify platform usage; the server waits up to 300 s for the run and returns JSON {items, truncated} with at most maxItems (max 100) items and 256 KiB."
41
+ }
42
+ }
package/dist/server.js CHANGED
@@ -4,6 +4,8 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
4
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
5
  import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
6
6
  const CATALOG_URL = new URL("../catalog/actors.json", import.meta.url);
7
+ const DESCRIPTIONS_URL = new URL("../catalog/tool-descriptions.json", import.meta.url);
8
+ const PACKAGE_URL = new URL("../package.json", import.meta.url);
7
9
  const TOKEN_URL = "https://console.apify.com/settings/integrations";
8
10
  const MISSING_TOKEN = `Missing APIFY_TOKEN. Create a token at ${TOKEN_URL} and set APIFY_TOKEN.`;
9
11
  const DEFAULT_MAX_ITEMS = 20;
@@ -11,19 +13,26 @@ const ITEM_CEILING = 100;
11
13
  const RESPONSE_BYTE_CAP = 256 * 1024;
12
14
  const SYNC_TIMEOUT_SECS = 300;
13
15
  const FETCH_ABORT_MS = 320_000;
14
- const SERVER_VERSION = "0.1.0";
15
16
  const LAW_INSTRUCTIONS = "One tool runs the law actor. Set tool to an enum value and pass arguments. maxItems caps returned dataset rows.";
16
17
  const REGISTERS_INSTRUCTIONS = "Each tool runs one actor with that actor's input. maxItems caps dataset rows.";
18
+ // Every tool proxies a public read of an official register through an Apify Actor run.
19
+ const TOOL_ANNOTATIONS = {
20
+ readOnlyHint: true,
21
+ destructiveHint: false,
22
+ idempotentHint: true,
23
+ openWorldHint: true,
24
+ };
17
25
  export async function serve(profile) {
18
- const tools = selectProfile(loadCatalog(CATALOG_URL), profile);
26
+ const tools = selectProfile(loadCatalog(CATALOG_URL, DESCRIPTIONS_URL), profile);
19
27
  const label = serverLabel(profile);
20
- const server = new Server({ name: label.name, version: SERVER_VERSION }, { capabilities: { tools: {} }, instructions: label.instructions });
28
+ const server = new Server({ name: label.name, version: readVersion(PACKAGE_URL) }, { capabilities: { tools: {} }, instructions: label.instructions });
21
29
  server.setRequestHandler(ListToolsRequestSchema, async () => ({
22
30
  tools: tools.map((tool) => ({
23
31
  name: tool.name,
24
32
  title: tool.title,
25
33
  description: tool.description,
26
34
  inputSchema: tool.inputSchema,
35
+ annotations: { title: tool.title, ...TOOL_ANNOTATIONS },
27
36
  })),
28
37
  }));
29
38
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
@@ -46,7 +55,38 @@ function serverLabel(profile) {
46
55
  }
47
56
  }
48
57
  }
49
- function loadCatalog(url) {
58
+ function readVersion(url) {
59
+ const parsed = JSON.parse(readFileSync(fileURLToPath(url), "utf8"));
60
+ if (!isObject(parsed)) {
61
+ throw new Error("package.json must be a JSON object.");
62
+ }
63
+ return requiredString(parsed.version, "version");
64
+ }
65
+ function loadToolTexts(url) {
66
+ const parsed = JSON.parse(readFileSync(fileURLToPath(url), "utf8"));
67
+ if (!isObject(parsed)) {
68
+ throw new Error("Tool descriptions must be a JSON object keyed by tool name.");
69
+ }
70
+ const texts = new Map();
71
+ for (const [name, entry] of Object.entries(parsed)) {
72
+ if (!isObject(entry)) {
73
+ throw new Error(`Tool description for ${name} must be an object.`);
74
+ }
75
+ const parameters = {};
76
+ if (entry.parameters !== undefined) {
77
+ if (!isObject(entry.parameters)) {
78
+ throw new Error(`Tool ${name} parameters must be an object.`);
79
+ }
80
+ for (const [key, text] of Object.entries(entry.parameters)) {
81
+ parameters[key] = requiredString(text, `${name}.parameters.${key}`);
82
+ }
83
+ }
84
+ texts.set(name, { description: requiredString(entry.description, `${name}.description`), parameters });
85
+ }
86
+ return texts;
87
+ }
88
+ function loadCatalog(url, descriptionsUrl) {
89
+ const texts = loadToolTexts(descriptionsUrl);
50
90
  const parsed = JSON.parse(readFileSync(fileURLToPath(url), "utf8"));
51
91
  if (!Array.isArray(parsed)) {
52
92
  throw new Error("Actor catalog must be a JSON array.");
@@ -57,7 +97,7 @@ function loadCatalog(url) {
57
97
  if (!isObject(row) || row.isPublic !== true) {
58
98
  continue;
59
99
  }
60
- const tool = bindTool(row);
100
+ const tool = bindTool(row, texts);
61
101
  if (names.has(tool.name)) {
62
102
  throw new Error(`Duplicate actor name ${tool.name}.`);
63
103
  }
@@ -66,7 +106,7 @@ function loadCatalog(url) {
66
106
  }
67
107
  return tools;
68
108
  }
69
- function bindTool(row) {
109
+ function bindTool(row, texts) {
70
110
  const name = requiredString(row.name, "name");
71
111
  const actorId = requiredString(row.actorId, "actorId");
72
112
  const slash = actorId.indexOf("/");
@@ -74,15 +114,34 @@ function bindTool(row) {
74
114
  throw new Error(`Actor id ${actorId} must look like owner/name.`);
75
115
  }
76
116
  const title = requiredString(row.title, "title");
77
- const description = requiredString(row.description, "description");
117
+ const text = texts.get(name);
118
+ if (text === undefined) {
119
+ throw new Error(`Tool ${name} has no entry in catalog/tool-descriptions.json.`);
120
+ }
121
+ const description = text.description;
78
122
  const buildNumber = requiredString(row.buildNumber, "buildNumber");
79
123
  if (!isObject(row.inputSchema) || row.inputSchema.type !== "object") {
80
124
  throw new Error(`Actor ${name} inputSchema must be a JSON object schema.`);
81
125
  }
82
126
  const router = isLawRouter(row.inputSchema);
83
- const { inputSchema, cap } = listSchema(row.inputSchema);
127
+ const { inputSchema, cap } = listSchema(describeParameters(name, row.inputSchema, text.parameters));
84
128
  return { name, title, description, inputSchema, actorId, buildNumber, router, cap };
85
129
  }
130
+ function describeParameters(name, schema, texts) {
131
+ const properties = schema.properties;
132
+ if (!isObject(properties)) {
133
+ throw new Error(`Actor ${name} inputSchema.properties must be an object.`);
134
+ }
135
+ const described = { ...properties };
136
+ for (const [key, description] of Object.entries(texts)) {
137
+ const property = properties[key];
138
+ if (!isObject(property)) {
139
+ throw new Error(`Tool ${name} describes unknown parameter ${key}.`);
140
+ }
141
+ described[key] = { ...property, description };
142
+ }
143
+ return { ...schema, properties: described };
144
+ }
86
145
  function isLawRouter(schema) {
87
146
  if (!isObject(schema.properties)) {
88
147
  return false;
@@ -118,7 +177,7 @@ function listSchema(schema) {
118
177
  maxItems: {
119
178
  type: "integer",
120
179
  title: "Maximum items",
121
- description: "Maximum dataset items returned to the client.",
180
+ description: "Maximum dataset items returned to the client (1-100), applied by this server to the run's dataset.",
122
181
  default: cap.fallback,
123
182
  minimum: cap.min,
124
183
  maximum: cap.max,
@@ -7,6 +7,8 @@ import { fileURLToPath } from "node:url";
7
7
  const TOKEN_URL = "https://console.apify.com/settings/integrations";
8
8
  const LAW_TOOL = "polish-law-mcp-server";
9
9
  const root = fileURLToPath(new URL("..", import.meta.url));
10
+ const descriptions = JSON.parse(readFileSync(new URL("../catalog/tool-descriptions.json", import.meta.url), "utf8"));
11
+ const packageVersion = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
10
12
  const catalog = JSON.parse(readFileSync(new URL("../catalog/actors.json", import.meta.url), "utf8"))
11
13
  .filter((row) => row.isPublic);
12
14
  function childEnv(token) {
@@ -56,11 +58,22 @@ function schemaOf(tool) {
56
58
  test("tools/list works without a token", async () => {
57
59
  await withClient("dist/main.js", childEnv(), async (client) => {
58
60
  assert.equal(client.getServerVersion()?.name, "polish-mcp");
61
+ assert.equal(client.getServerVersion()?.version, packageVersion);
59
62
  const listed = await client.listTools();
60
63
  assert.deepEqual(listed.tools.map((tool) => tool.name), catalog.map((row) => row.name));
61
64
  for (const tool of listed.tools) {
62
65
  const row = catalog.find((entry) => entry.name === tool.name);
63
66
  assert.ok(row);
67
+ const text = descriptions[tool.name];
68
+ assert.ok(text, `${tool.name} has a description entry`);
69
+ assert.equal(tool.description, text.description);
70
+ for (const phrase of ["Read-only", "APIFY_TOKEN", "paid run", "300 s"]) {
71
+ assert.equal(tool.description?.includes(phrase), true, `${tool.name} description mentions ${phrase}`);
72
+ }
73
+ assert.equal(tool.annotations?.readOnlyHint, true);
74
+ assert.equal(tool.annotations?.destructiveHint, false);
75
+ assert.equal(tool.annotations?.idempotentHint, true);
76
+ assert.equal(tool.annotations?.openWorldHint, true);
64
77
  const listedProperties = schemaOf(tool).properties ?? {};
65
78
  const catalogProperties = row.inputSchema.properties ?? {};
66
79
  assert.equal(listedProperties.maxItems !== undefined, true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polish-mcp-servers",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "MCP stdio server for Polish public law and registers. Lists 12 Apify Actor tools without a token and runs them with APIFY_TOKEN.",
5
5
  "license": "MIT",
6
6
  "author": "Kamil Kaczmarek",
@@ -28,10 +28,10 @@
28
28
  "node": ">=20"
29
29
  },
30
30
  "bin": {
31
- "polish-mcp-servers": "./dist/main.js",
32
- "polish-mcp": "./dist/main.js",
33
- "polish-law-mcp": "./dist/law.js",
34
- "polish-public-registers": "./dist/registers.js"
31
+ "polish-mcp-servers": "dist/main.js",
32
+ "polish-mcp": "dist/main.js",
33
+ "polish-law-mcp": "dist/law.js",
34
+ "polish-public-registers": "dist/registers.js"
35
35
  },
36
36
  "files": [
37
37
  "dist",