getregdata-mcp 1.1.0 → 1.2.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 +19 -2
- package/actors.js +161 -36
- package/index.js +108 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,11 +13,27 @@ every beneficial owner, returned as a single verdict. The per-registry tools are
|
|
|
13
13
|
depth behind that answer, and the way to run the same jobs elsewhere.
|
|
14
14
|
|
|
15
15
|
Each registry is exposed as its own tool (e.g. `regdata_crbr_beneficial_owners`,
|
|
16
|
-
`regdata_germany_handelsregister`, `regdata_adverse_media`), plus
|
|
16
|
+
`regdata_germany_handelsregister`, `regdata_adverse_media`), plus three helpers:
|
|
17
17
|
|
|
18
18
|
- `regdata_catalog` - list every registry tool and what it returns.
|
|
19
19
|
- `regdata_describe` - fetch a specific actor's live input schema so the agent
|
|
20
20
|
builds a correct call.
|
|
21
|
+
- `regdata_run_result` - collect a check that was still running when its tool call
|
|
22
|
+
returned.
|
|
23
|
+
|
|
24
|
+
## Long checks return a handle, not a failure
|
|
25
|
+
|
|
26
|
+
Most calls return dataset items directly. If a run is still going after ~45 seconds,
|
|
27
|
+
the tool returns `{status, runId, datasetId, note}` instead. That run is still going
|
|
28
|
+
and is **already billed**, so call `regdata_run_result` with the `runId` to collect it -
|
|
29
|
+
re-running the check to "retry" charges the user twice.
|
|
30
|
+
|
|
31
|
+
This matters most for the Poland KYB composite: 20-30 seconds typically, up to ~2.5
|
|
32
|
+
minutes for a company with many beneficial owners. Set `"timeout": 600000` on the
|
|
33
|
+
server in your MCP config so the common case still returns inline.
|
|
34
|
+
|
|
35
|
+
Treat a `runId` as a secret: Apify resolves run and dataset IDs without checking
|
|
36
|
+
ownership, so anyone holding the ID can read that check's result.
|
|
21
37
|
|
|
22
38
|
## Setup
|
|
23
39
|
|
|
@@ -34,7 +50,8 @@ Add to your MCP config (`claude_desktop_config.json`, or `.mcp.json` for Claude
|
|
|
34
50
|
"getregdata": {
|
|
35
51
|
"command": "npx",
|
|
36
52
|
"args": ["-y", "getregdata-mcp"],
|
|
37
|
-
"env": { "APIFY_TOKEN": "apify_api_xxxxx" }
|
|
53
|
+
"env": { "APIFY_TOKEN": "apify_api_xxxxx" },
|
|
54
|
+
"timeout": 600000
|
|
38
55
|
}
|
|
39
56
|
}
|
|
40
57
|
}
|
package/actors.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// Auto-generated from the live Apify fleet (deployed builds). 35 regdata actors.
|
|
2
2
|
// Regenerate with: APIFY_TOKEN=... node scripts/gen-manifest.mjs
|
|
3
|
-
// Generated 2026-
|
|
3
|
+
// Generated 2026-10-27. Do not edit inputSchema by hand.
|
|
4
4
|
export const ACTORS = [
|
|
5
5
|
{
|
|
6
6
|
"slug": "poland-kyb-check",
|
|
7
7
|
"tool": "regdata_poland_kyb_check",
|
|
8
8
|
"title": "Poland KYB Risk Check - one call, one verdict",
|
|
9
|
-
"description": "Run a COMPLETE Polish KYB check from a single NIP or KRS - start here for Poland instead of chaining the individual registry tools. Resolves official company identity, pulls beneficial owners from the national UBO register, and screens the national debtor register for insolvency, restructuring and enforcement proceedings against the company AND every beneficial owner by exact identifier. Returns one normalized verdict - clear, findings, not_found or partial - plus machine-readable risk flags and the underlying registry entries (case signature, classification, court, dates, source). A \"partial\" verdict means a source could not be reached, not that the company is clean, and is not billed. Poland only; use the per-registry tools for other jurisdictions or for deeper single-source detail.",
|
|
9
|
+
"description": "Run a COMPLETE Polish KYB check from a single NIP or KRS - start here for Poland instead of chaining the individual registry tools. Resolves official company identity, pulls beneficial owners from the national UBO register, and screens the national debtor register for insolvency, restructuring and enforcement proceedings against the company AND every beneficial owner by exact identifier. Returns one normalized verdict - clear, findings, not_found or partial - plus machine-readable risk flags and the underlying registry entries (case signature, classification, court, dates, source). A \"partial\" verdict means a source could not be reached, not that the company is clean, and is not billed. Poland only; use the per-registry tools for other jurisdictions or for deeper single-source detail. TIMING: this check typically takes 20-30 seconds, but scales with the number of beneficial owners and has been measured up to ~2.5 minutes. If it has not finished in time, the tool returns {status, runId, note} instead of results - the check is running and already billed, so call regdata_run_result with that runId to collect it. Never re-run the check to 'retry': that bills twice.",
|
|
10
10
|
"inputSchema": {
|
|
11
11
|
"type": "object",
|
|
12
12
|
"properties": {
|
|
@@ -15,6 +15,12 @@ export const ACTORS = [
|
|
|
15
15
|
"title": "Company identifiers (NIP or KRS)",
|
|
16
16
|
"description": "The Polish companies to check, by NIP (10 digits) or KRS (10 digits, leading zeros). Each identifier returns one complete KYB check: identity, beneficial owners, and insolvency proceedings against the company and every beneficial owner."
|
|
17
17
|
},
|
|
18
|
+
"includeManagement": {
|
|
19
|
+
"type": "boolean",
|
|
20
|
+
"title": "Include management board (KRS)",
|
|
21
|
+
"description": "Also read the current KRS extract and return the sitting management board (or representing partners), representation rule, prokurenci (proxies), supervisory board, shareholders/partners and share capital. Companies without a KRS number are reported as not applicable. The board is billed by the board-members actor it runs, on top of the check.",
|
|
22
|
+
"default": false
|
|
23
|
+
},
|
|
18
24
|
"krzConcurrency": {
|
|
19
25
|
"type": "integer",
|
|
20
26
|
"title": "Beneficial-owner screening concurrency",
|
|
@@ -158,12 +164,12 @@ export const ACTORS = [
|
|
|
158
164
|
"dateFrom": {
|
|
159
165
|
"type": "string",
|
|
160
166
|
"title": "Published Since (Date From)",
|
|
161
|
-
"description": "Only return
|
|
167
|
+
"description": "Only return edicts published on or after this date (YYYY-MM-DD). Setting it is strongly recommended: it is the only filter the register applies server-side, so it is what keeps a browse-style run short, and it removes the need for the GmbH fallback query - without it a run with no searchQuery returns ONLY debtors whose name contains 'GmbH'. | Nur Veroeffentlichungen ab diesem Datum."
|
|
162
168
|
},
|
|
163
169
|
"dateTo": {
|
|
164
170
|
"type": "string",
|
|
165
171
|
"title": "Published Until (Date To)",
|
|
166
|
-
"description": "Only return
|
|
172
|
+
"description": "Only return edicts published up to this date (YYYY-MM-DD). Applied per edict, not by the register, so a narrow window costs one page fetch per candidate. | Nur Veroeffentlichungen bis zu diesem Datum."
|
|
167
173
|
},
|
|
168
174
|
"entryType": {
|
|
169
175
|
"type": "string",
|
|
@@ -179,7 +185,7 @@ export const ACTORS = [
|
|
|
179
185
|
"maxResults": {
|
|
180
186
|
"type": "integer",
|
|
181
187
|
"title": "Max Results",
|
|
182
|
-
"description": "Maximum number of
|
|
188
|
+
"description": "Maximum number of matching records to return. Default: 100. Set to 0 for unlimited. This caps matches, not work: dateTo and proceedingType are checked per edict, so reaching the cap can require many more page fetches than the cap itself. | Maximale Anzahl der Ergebnisse.",
|
|
183
189
|
"default": 100
|
|
184
190
|
}
|
|
185
191
|
},
|
|
@@ -350,6 +356,17 @@ export const ACTORS = [
|
|
|
350
356
|
"inputSchema": {
|
|
351
357
|
"type": "object",
|
|
352
358
|
"properties": {
|
|
359
|
+
"mode": {
|
|
360
|
+
"type": "string",
|
|
361
|
+
"title": "What to do",
|
|
362
|
+
"description": "<b>Search</b> looks up the names or entity numbers you list below. <b>New filings</b> delivers every newly approved California entity since the last run - schedule it daily and each run picks up where the previous one stopped. <b>Add addresses</b> takes the results of an earlier run and completes each record with its principal address, mailing address and the registered agent's address.",
|
|
363
|
+
"enum": [
|
|
364
|
+
"search",
|
|
365
|
+
"newFilings",
|
|
366
|
+
"addresses"
|
|
367
|
+
],
|
|
368
|
+
"default": "search"
|
|
369
|
+
},
|
|
353
370
|
"searchQueries": {
|
|
354
371
|
"type": "array",
|
|
355
372
|
"title": "Search queries",
|
|
@@ -360,12 +377,60 @@ export const ACTORS = [
|
|
|
360
377
|
"title": "Max results per query",
|
|
361
378
|
"description": "Maximum number of entities to keep per query (default 50 to avoid surprise charges on broad searches). Set 0 for no limit (all matches, typically up to ~500 per search).",
|
|
362
379
|
"default": 50
|
|
380
|
+
},
|
|
381
|
+
"startEntityNumber": {
|
|
382
|
+
"type": "string",
|
|
383
|
+
"title": "Start from entity number",
|
|
384
|
+
"description": "New filings only, first run only: the California entity number to start from, e.g. <code>B20260403469</code>. Later runs continue automatically from the saved position."
|
|
385
|
+
},
|
|
386
|
+
"maxNumbersPerRun": {
|
|
387
|
+
"type": "integer",
|
|
388
|
+
"title": "Entity numbers to check per run",
|
|
389
|
+
"description": "Upper bound on how many entity numbers one run checks. California issues roughly 1,500-2,000 per business day; a daily schedule at the default keeps up, and whatever is not reached is picked up next run.",
|
|
390
|
+
"default": 2500
|
|
391
|
+
},
|
|
392
|
+
"includeNameReservations": {
|
|
393
|
+
"type": "boolean",
|
|
394
|
+
"title": "Include name reservations",
|
|
395
|
+
"description": "Name reservations share the number sequence but are not formed businesses. Off by default: they are skipped and not billed.",
|
|
396
|
+
"default": false
|
|
397
|
+
},
|
|
398
|
+
"restartFromStartNumber": {
|
|
399
|
+
"type": "boolean",
|
|
400
|
+
"title": "Restart from the start number",
|
|
401
|
+
"description": "Discard the saved position and start again from \"Start from entity number\". Use it to re-run a range; every record in it is delivered (and billed) again.",
|
|
402
|
+
"default": false
|
|
403
|
+
},
|
|
404
|
+
"stateStoreName": {
|
|
405
|
+
"type": "string",
|
|
406
|
+
"title": "Progress store name",
|
|
407
|
+
"description": "Name of the key-value store in your Apify account that keeps the scan position between runs. Use a different name to run several independent feeds.",
|
|
408
|
+
"default": "california-new-filings"
|
|
409
|
+
},
|
|
410
|
+
"stopAfterConsecutiveMisses": {
|
|
411
|
+
"type": "integer",
|
|
412
|
+
"title": "Stop after consecutive unanswered numbers",
|
|
413
|
+
"description": "How many consecutive entity numbers with no approved filing yet mark the end of what the registry has processed so far. Leave at the default unless a run stops too early.",
|
|
414
|
+
"default": 300
|
|
415
|
+
},
|
|
416
|
+
"reserveForNewNumbers": {
|
|
417
|
+
"type": "integer",
|
|
418
|
+
"title": "Look-ups reserved for new entity numbers",
|
|
419
|
+
"description": "Every run re-checks numbers that had no record yet before it moves on to new ones. This reserves part of the run's budget for new numbers so the scan always moves forward, even when the re-check queue is long. Leave at the default unless a run reports a growing backlog.",
|
|
420
|
+
"default": 1800
|
|
421
|
+
},
|
|
422
|
+
"sourceDatasetId": {
|
|
423
|
+
"type": "string",
|
|
424
|
+
"title": "Results to complete (dataset ID)",
|
|
425
|
+
"description": "The dataset ID of an earlier run of this actor. Every record in it is looked up once and returned with <code>principalAddress</code>, <code>mailingAddress</code>, <code>agentType</code>, <code>agentName</code> and <code>agentAddress</code> added. Commercial registered agents have no address of their own on the entity's record, so <code>agentAddress</code> is empty for those."
|
|
426
|
+
},
|
|
427
|
+
"sourceRunId": {
|
|
428
|
+
"type": "string",
|
|
429
|
+
"title": "...or the run ID",
|
|
430
|
+
"description": "Alternative to the dataset ID: the ID of the earlier run whose results should be completed."
|
|
363
431
|
}
|
|
364
432
|
},
|
|
365
|
-
"additionalProperties": true
|
|
366
|
-
"required": [
|
|
367
|
-
"searchQueries"
|
|
368
|
-
]
|
|
433
|
+
"additionalProperties": true
|
|
369
434
|
}
|
|
370
435
|
},
|
|
371
436
|
{
|
|
@@ -512,7 +577,7 @@ export const ACTORS = [
|
|
|
512
577
|
"kwNumbers": {
|
|
513
578
|
"type": "array",
|
|
514
579
|
"title": "KW Numbers",
|
|
515
|
-
"description": "List of KW numbers to look up. Format: 'CODE/NUMBER/DIGIT' (e.g., '
|
|
580
|
+
"description": "List of KW numbers to look up. Format: 'CODE/NUMBER/DIGIT' (e.g., 'WA4M/00160286/2'). The check digit (last part) is optional - it will be auto-calculated if omitted. You can also provide just 'CODE/NUMBER'. Note: users on the Apify Free plan get a preview allowance of 25 KW numbers per 30 days; upgrade to any paid Apify plan to run unlimited batches."
|
|
516
581
|
},
|
|
517
582
|
"viewType": {
|
|
518
583
|
"type": "string",
|
|
@@ -546,8 +611,8 @@ export const ACTORS = [
|
|
|
546
611
|
"maxConcurrency": {
|
|
547
612
|
"type": "integer",
|
|
548
613
|
"title": "Max parallel lookups",
|
|
549
|
-
"description": "How many KW numbers to process in parallel
|
|
550
|
-
"default":
|
|
614
|
+
"description": "How many KW numbers to process in parallel. Default 4; values above 4 are accepted but run at 4, so one access slot always stays free for other runs.",
|
|
615
|
+
"default": 4
|
|
551
616
|
}
|
|
552
617
|
},
|
|
553
618
|
"additionalProperties": true,
|
|
@@ -567,7 +632,7 @@ export const ACTORS = [
|
|
|
567
632
|
"searchQuery": {
|
|
568
633
|
"type": "string",
|
|
569
634
|
"title": "Company name / keyword",
|
|
570
|
-
"description": "Company name or keyword(s) to search for (Schlagwörter). E.g. \"Zalando SE\" or \"BioNTech\"."
|
|
635
|
+
"description": "Company name or keyword(s) to search for (Schlagwörter). E.g. \"Zalando SE\" or \"BioNTech\". The register accepts at most 5 keywords - send the company name only, not a website title or description. Legal forms (GmbH, AG, KG, e.V., ...), \"und\", \"mit\" and repeated words do not count; \"der\", \"für\", \"von\" do. Single letters and legal forms alone are ignored: \"K&F\" searches for nothing - add a word from the name (\"K & F Kältetechnik\") or write the letters together (\"KF\")."
|
|
571
636
|
},
|
|
572
637
|
"exactMatch": {
|
|
573
638
|
"type": "boolean",
|
|
@@ -578,13 +643,24 @@ export const ACTORS = [
|
|
|
578
643
|
"registerNumber": {
|
|
579
644
|
"type": "string",
|
|
580
645
|
"title": "Register number (optional)",
|
|
581
|
-
"description": "Optional
|
|
646
|
+
"description": "Optional register number to narrow the search. The number on its own (\"215511\") or with its register type (\"HRB 6684\", \"HRB 215511 B\") - both work, and the type is selected for you. Must be combined with a company name/keyword: the portal does not allow number-only searches."
|
|
582
647
|
},
|
|
583
648
|
"maxResults": {
|
|
584
649
|
"type": "integer",
|
|
585
650
|
"title": "Max results",
|
|
586
651
|
"description": "Maximum number of matching companies to return structured data for (from the first results page). 1-30.",
|
|
587
652
|
"default": 10
|
|
653
|
+
},
|
|
654
|
+
"onlyNew": {
|
|
655
|
+
"type": "boolean",
|
|
656
|
+
"title": "Monitor mode - only new or changed companies",
|
|
657
|
+
"description": "For scheduled checks of the same company or search. The first run returns every company found and remembers it; every later run of the SAME search returns only companies that are new to it, or whose status, name, seat, share capital or officers changed - each with changeType, changedFields and previousValues. When the register cannot serve a company's structured document on a run, its capital and officers are not compared that time (they are never reported as changed on missing data). A run with nothing new succeeds with an empty dataset and a status message, and is billed like any run. The memory is kept in your own Apify account (a key-value store named regdata-handelsregister-monitor); delete it to start again.",
|
|
658
|
+
"default": false
|
|
659
|
+
},
|
|
660
|
+
"monitorKey": {
|
|
661
|
+
"type": "string",
|
|
662
|
+
"title": "Monitor name (optional)",
|
|
663
|
+
"description": "Just a label for your watchlist history, not a password or API key - it is shown masked. Optional name for this monitor's memory, e.g. 'supplier-acme'. Leave empty and the search itself is the name."
|
|
588
664
|
}
|
|
589
665
|
},
|
|
590
666
|
"additionalProperties": true
|
|
@@ -606,7 +682,7 @@ export const ACTORS = [
|
|
|
606
682
|
"watchlist": {
|
|
607
683
|
"type": "array",
|
|
608
684
|
"title": "Watchlist (bulk / monitoring)",
|
|
609
|
-
"description": "A list of company names or surnames to check in one run. Ideal for scheduled monitoring - run this Actor daily against your counterparties and get any new insolvency publications. Overrides the single \"name\" field when set."
|
|
685
|
+
"description": "A list of company names or surnames to check in one run (up to 100). Ideal for scheduled monitoring - run this Actor daily against your counterparties and get any new insolvency publications. Overrides the single \"name\" field when set. For more than 100 names, split them across several runs or scheduled tasks."
|
|
610
686
|
},
|
|
611
687
|
"firstName": {
|
|
612
688
|
"type": "string",
|
|
@@ -680,7 +756,7 @@ export const ACTORS = [
|
|
|
680
756
|
"maxResults": {
|
|
681
757
|
"type": "integer",
|
|
682
758
|
"title": "Max results",
|
|
683
|
-
"description": "Maximum publications to export across all queries in this run.",
|
|
759
|
+
"description": "Maximum publications to export across all queries in this run. Each publication returned is billed, so this also caps the per-publication cost.",
|
|
684
760
|
"default": 200
|
|
685
761
|
}
|
|
686
762
|
},
|
|
@@ -872,12 +948,28 @@ export const ACTORS = [
|
|
|
872
948
|
"dateFrom": {
|
|
873
949
|
"type": "string",
|
|
874
950
|
"title": "Date From",
|
|
875
|
-
"description": "Start date for announcement search (YYYY-MM-DD). Only used in announcements mode."
|
|
951
|
+
"description": "Start date for announcement search (YYYY-MM-DD). Only used in announcements mode. A date range of up to 366 days is returned in full, even when it holds more than 1000 announcements; the run says so if a single day exceeds what the register will return."
|
|
876
952
|
},
|
|
877
953
|
"dateTo": {
|
|
878
954
|
"type": "string",
|
|
879
955
|
"title": "Date To",
|
|
880
|
-
"description": "End date for announcement search (YYYY-MM-DD). Only used in announcements mode."
|
|
956
|
+
"description": "End date for announcement search (YYYY-MM-DD), inclusive. Only used in announcements mode. A malformed date, or a dateFrom after dateTo, stops the run before any search and nothing is charged."
|
|
957
|
+
},
|
|
958
|
+
"proceedingType": {
|
|
959
|
+
"type": "array",
|
|
960
|
+
"title": "Proceeding type filter (announcements)",
|
|
961
|
+
"description": "Optional, announcements mode only. Keep only announcements of these proceeding types; leave empty for all. 'appeal' = second-instance rulings on a bankruptcy or restructuring case (e.g. on an arrangement or a repayment plan) - choosing 'restructuring' alone does NOT include appeal rulings on restructuring cases, so add 'appeal' too if you need them. Left-out rows are not exported and not charged.",
|
|
962
|
+
"items": {
|
|
963
|
+
"type": "string"
|
|
964
|
+
}
|
|
965
|
+
},
|
|
966
|
+
"proceedingKinds": {
|
|
967
|
+
"type": "array",
|
|
968
|
+
"title": "Proceeding kind filter (entity search)",
|
|
969
|
+
"description": "Optional, entity mode only. A company search returns one row per proceeding the register holds for it. Keep only these kinds; leave empty for all. Left-out rows are not exported and not charged.",
|
|
970
|
+
"items": {
|
|
971
|
+
"type": "string"
|
|
972
|
+
}
|
|
881
973
|
},
|
|
882
974
|
"maxResults": {
|
|
883
975
|
"type": "integer",
|
|
@@ -885,6 +977,17 @@ export const ACTORS = [
|
|
|
885
977
|
"description": "Maximum number of results to return. Default: 100. Set to 0 for unlimited.",
|
|
886
978
|
"default": 100
|
|
887
979
|
},
|
|
980
|
+
"onlyNew": {
|
|
981
|
+
"type": "boolean",
|
|
982
|
+
"title": "Monitor mode - only new or changed",
|
|
983
|
+
"description": "For scheduled checks of the same company or search. The first run returns everything and remembers it; every later run of the SAME search returns only proceedings that are new to it. Case-signature searches, where the register returns status and type, also report a status or type change (changeType, changedFields, previousValues); company-name searches carry no status, so they report new proceedings only. A run with nothing new succeeds with an empty dataset and a status message, and is billed like any search - 'nothing new' is the answer. The memory is kept in your own Apify account (a key-value store named regdata-krz-monitor); delete it to start again. Not available for proceedingDetails. Dates are not part of the memory, so a rolling announcements window keeps one history.",
|
|
984
|
+
"default": false
|
|
985
|
+
},
|
|
986
|
+
"monitorKey": {
|
|
987
|
+
"type": "string",
|
|
988
|
+
"title": "Monitor name (optional)",
|
|
989
|
+
"description": "Just a label for your watchlist history, not a password or API key - it is shown masked. Optional name for this monitor's memory, e.g. 'client-acme'. Leave empty and the search itself is the name. Use it to keep two separate histories of the same search."
|
|
990
|
+
},
|
|
888
991
|
"disableSessionCache": {
|
|
889
992
|
"type": "boolean",
|
|
890
993
|
"title": "Disable session cache (advanced)",
|
|
@@ -931,12 +1034,12 @@ export const ACTORS = [
|
|
|
931
1034
|
"textInBody": {
|
|
932
1035
|
"type": "string",
|
|
933
1036
|
"title": "Text in Body",
|
|
934
|
-
"description": "Full-text search
|
|
1037
|
+
"description": "Full-text search inside the announcement body (max 1000 chars). MATCHES LITERALLY, SO POLISH DIACRITICS ARE REQUIRED: \"upadłości\" returns hundreds of notices a month, \"upadlosci\" returns none. Case does not matter and phrases work. Try: upadłości, likwidacji, wierzycieli, syndyk, restrukturyzacji."
|
|
935
1038
|
},
|
|
936
1039
|
"textInPosition": {
|
|
937
1040
|
"type": "string",
|
|
938
1041
|
"title": "Text in Position",
|
|
939
|
-
"description": "Search
|
|
1042
|
+
"description": "Search the announcement header line - the \"Poz. NNNNN. NAME. KRS ... COURT ...\" summary (max 1000 chars). Same literal matching as Text in Body, so Polish diacritics are required. Try: LIKWIDACJI, REJONOWY, GOSPODARCZY."
|
|
940
1043
|
},
|
|
941
1044
|
"signatureOfCase": {
|
|
942
1045
|
"type": "string",
|
|
@@ -945,13 +1048,13 @@ export const ACTORS = [
|
|
|
945
1048
|
},
|
|
946
1049
|
"dateFrom": {
|
|
947
1050
|
"type": "string",
|
|
948
|
-
"title": "
|
|
949
|
-
"description": "
|
|
1051
|
+
"title": "Published from",
|
|
1052
|
+
"description": "Start of the publication date range. Required by the gazette - a search without both dates is rejected. Pick a date, or type a relative one such as \"3 months\"."
|
|
950
1053
|
},
|
|
951
1054
|
"dateTo": {
|
|
952
1055
|
"type": "string",
|
|
953
|
-
"title": "
|
|
954
|
-
"description": "
|
|
1056
|
+
"title": "Published to",
|
|
1057
|
+
"description": "End of the publication date range. Required by the gazette - a search without both dates is rejected. Pick a date, or type a relative one such as \"1 week\"."
|
|
955
1058
|
},
|
|
956
1059
|
"fetchDetails": {
|
|
957
1060
|
"type": "boolean",
|
|
@@ -962,8 +1065,19 @@ export const ACTORS = [
|
|
|
962
1065
|
"maxResults": {
|
|
963
1066
|
"type": "integer",
|
|
964
1067
|
"title": "Max Results",
|
|
965
|
-
"description": "Maximum number of
|
|
966
|
-
"default":
|
|
1068
|
+
"description": "Maximum number of announcements to return. Set to 0 for every match. Starts at 10 so a first run is cheap to try - raise it once the search looks right.",
|
|
1069
|
+
"default": 10
|
|
1070
|
+
},
|
|
1071
|
+
"onlyNew": {
|
|
1072
|
+
"type": "boolean",
|
|
1073
|
+
"title": "Monitor mode - only new notices",
|
|
1074
|
+
"description": "For scheduled checks of the same company or search. The first run returns every matching notice and remembers it; every later run of the SAME search returns only notices published since, each with changeType 'new'. Gazette notices never change once published, so nothing is reported as changed. A run with nothing new succeeds with an empty dataset and a status message. Use a rolling window such as Published from '1 month' and Published to '0 days' - the dates are not part of the memory. Set Max results to 0 so the first run records every match. The memory is kept in your own Apify account (a key-value store named regdata-msig-monitor); delete it to start again.",
|
|
1075
|
+
"default": false
|
|
1076
|
+
},
|
|
1077
|
+
"monitorKey": {
|
|
1078
|
+
"type": "string",
|
|
1079
|
+
"title": "Monitor name (optional)",
|
|
1080
|
+
"description": "Just a label for your watchlist history, not a password or API key - it is shown masked. Optional name for this monitor's memory, e.g. 'client-acme'. Leave empty and the search itself is the name."
|
|
967
1081
|
}
|
|
968
1082
|
},
|
|
969
1083
|
"additionalProperties": true,
|
|
@@ -1002,6 +1116,17 @@ export const ACTORS = [
|
|
|
1002
1116
|
"title": "Include raw statement file",
|
|
1003
1117
|
"description": "Include the raw XML/XHTML (iXBRL) statement in the output. Files over 5 MB are linked via the key-value store (rawXmlUrl) instead of inlined.",
|
|
1004
1118
|
"default": true
|
|
1119
|
+
},
|
|
1120
|
+
"onlyNew": {
|
|
1121
|
+
"type": "boolean",
|
|
1122
|
+
"title": "Monitor mode - only new statements",
|
|
1123
|
+
"description": "For scheduled checks of the same company. The first run returns the latest filed statement and remembers it; every later run returns a row only when a NEWER statement has been filed (changeType 'new'). When nothing new has been filed, nothing is downloaded, the dataset stays empty and the status message says which statement is still the latest - you pay only the run start. The memory is kept in your own Apify account (a key-value store named regdata-krs-financial-monitor); delete it to start again.",
|
|
1124
|
+
"default": false
|
|
1125
|
+
},
|
|
1126
|
+
"monitorKey": {
|
|
1127
|
+
"type": "string",
|
|
1128
|
+
"title": "Monitor name (optional)",
|
|
1129
|
+
"description": "Just a label for your watchlist history, not a password or API key - it is shown masked. Optional name for this monitor's memory. Leave empty and the KRS / NIP number is the name."
|
|
1005
1130
|
}
|
|
1006
1131
|
},
|
|
1007
1132
|
"additionalProperties": true
|
|
@@ -1052,7 +1177,7 @@ export const ACTORS = [
|
|
|
1052
1177
|
"seedIdentifiers": {
|
|
1053
1178
|
"type": "array",
|
|
1054
1179
|
"title": "Seed identifiers (NIP / REGON / KRS)",
|
|
1055
|
-
"description": "List of company identifiers to expand. Auto-detected by shape: 9 or 14 digits = REGON, 10 digits = NIP (override with Seed identifier type).
|
|
1180
|
+
"description": "List of company identifiers to expand. Auto-detected by shape: 9 or 14 digits = REGON, 10 digits = NIP (override with Seed identifier type). This actor expands companies you already know into their local units (jednostki lokalne) - it does not discover companies by area, so seed them here (or via Seed dataset)."
|
|
1056
1181
|
},
|
|
1057
1182
|
"seedDatasetId": {
|
|
1058
1183
|
"type": "string",
|
|
@@ -1248,7 +1373,7 @@ export const ACTORS = [
|
|
|
1248
1373
|
"minIntervalMs": {
|
|
1249
1374
|
"type": "integer",
|
|
1250
1375
|
"title": "Min interval between requests (ms)",
|
|
1251
|
-
"description": "
|
|
1376
|
+
"description": "Delay between requests in milliseconds. Keep the default for reliable runs.",
|
|
1252
1377
|
"default": 350
|
|
1253
1378
|
}
|
|
1254
1379
|
},
|
|
@@ -1395,8 +1520,8 @@ export const ACTORS = [
|
|
|
1395
1520
|
},
|
|
1396
1521
|
"province": {
|
|
1397
1522
|
"type": "string",
|
|
1398
|
-
"title": "Province",
|
|
1399
|
-
"description": "
|
|
1523
|
+
"title": "Province or region",
|
|
1524
|
+
"description": "Limit results to one Spanish province or one autonomous community (region). A province: its name in Spanish or the local language, common older spellings, or the INE code (1-52) - 'Madrid', 'Navarra', 'Bizkaia' or 'Vizcaya', 'A Coruña' or 'La Coruña', 'Illes Balears' or 'Baleares', '31'. A region: its Spanish, local or English name - 'Catalonia' or 'Cataluña', 'Andalucía', 'Basque Country' or 'Euskadi', 'Comunitat Valenciana', 'Galicia'. A region runs one search per province in it, one after another, and returns companies from all of them (pricing is unchanged: as listed in Pricing). A one-province region such as 'Comunidad de Madrid' is the same as that province. For A Coruña and Araba/Álava, combine the filter with a specific company name or activity code - on a very broad search the filter cannot be applied to those two provinces."
|
|
1400
1525
|
},
|
|
1401
1526
|
"maxResults": {
|
|
1402
1527
|
"type": "integer",
|
|
@@ -1456,7 +1581,7 @@ export const ACTORS = [
|
|
|
1456
1581
|
"maxResults": {
|
|
1457
1582
|
"type": "integer",
|
|
1458
1583
|
"title": "Max results",
|
|
1459
|
-
"description": "Maximum party records to export across all queries. The register serves results in pages, and the Actor pages through until it reaches this limit or runs out of matches. Set to 0 to export every match.",
|
|
1584
|
+
"description": "Maximum party records to export across all queries. The register serves results in pages, and the Actor pages through until it reaches this limit or runs out of matches. Set to 0 to export every match. The register returns debtor entries first, so a search truncated by maxResults can contain no disqualified-person or insolvency-administrator rows even when the full result set does. Raise maxResults (or set 0) for broad name searches.",
|
|
1460
1585
|
"default": 100
|
|
1461
1586
|
}
|
|
1462
1587
|
},
|
|
@@ -1643,7 +1768,7 @@ export const ACTORS = [
|
|
|
1643
1768
|
"searchType": {
|
|
1644
1769
|
"type": "string",
|
|
1645
1770
|
"title": "Search type",
|
|
1646
|
-
"description": "How the company name is matched. '
|
|
1771
|
+
"description": "How the company name is matched. The register matches WHOLE WORDS, not the start of a name: 'INVESTMENT' finds every name containing that word, but 'INVEST' finds only names with the word 'INVEST'. 'All these words' (default) needs every word you type; 'Any of these words' needs one of them; 'Sounds like' uses the register's phonetic index. A very common word on its own (INVESTMENT, HOLDINGS, SHIPPING) is refused by the register as too many matches - add a second distinctive word.",
|
|
1647
1772
|
"enum": [
|
|
1648
1773
|
"startsWith",
|
|
1649
1774
|
"endsWith",
|
|
@@ -1683,7 +1808,7 @@ export const ACTORS = [
|
|
|
1683
1808
|
"companyNames": {
|
|
1684
1809
|
"type": "array",
|
|
1685
1810
|
"title": "Company names",
|
|
1686
|
-
"description": "One or more company names to search, each looked up separately (min 2 characters). Partial names work
|
|
1811
|
+
"description": "One or more company names to search, each looked up separately (min 2 characters). Partial names work: every word must appear in the company name, in any order (legal-form words such as 'Ltd' or 'DAC' are optional). Exact and starts-with matches come first, live companies before dissolved ones.",
|
|
1687
1812
|
"items": {
|
|
1688
1813
|
"type": "string"
|
|
1689
1814
|
}
|
|
@@ -1691,7 +1816,7 @@ export const ACTORS = [
|
|
|
1691
1816
|
"companyNumbers": {
|
|
1692
1817
|
"type": "array",
|
|
1693
1818
|
"title": "Company numbers",
|
|
1694
|
-
"description": "One or more Irish CRO registration numbers, each looked up separately.
|
|
1819
|
+
"description": "One or more Irish CRO registration numbers, each looked up separately. Each must contain digits, e.g. '104547' (a prefix such as 'IE' is ignored). Company numbers only - limited partnership (LP...), reserved name (RN...), society (...R) and trade union (...T) numbers are skipped and not charged.",
|
|
1695
1820
|
"items": {
|
|
1696
1821
|
"type": "string"
|
|
1697
1822
|
}
|
|
@@ -1699,13 +1824,13 @@ export const ACTORS = [
|
|
|
1699
1824
|
"maxResultsPerQuery": {
|
|
1700
1825
|
"type": "integer",
|
|
1701
1826
|
"title": "Max results per query",
|
|
1702
|
-
"description": "Maximum company records to export per query
|
|
1827
|
+
"description": "Maximum company records to export per query (up to 50). When a name matches more companies, the run says so - narrow the name or search by number.",
|
|
1703
1828
|
"default": 50
|
|
1704
1829
|
},
|
|
1705
1830
|
"statusFilter": {
|
|
1706
1831
|
"type": "array",
|
|
1707
1832
|
"title": "Status filter",
|
|
1708
|
-
"description": "Keep only companies whose status contains one of these words, e.g. 'Normal', 'Dissolved', 'Liquidation'. Leave empty to export every match - a Dissolved or Liquidation counterparty is usually the finding you most want to see.",
|
|
1833
|
+
"description": "Keep only companies whose status contains one of these words, e.g. 'Normal', 'Dissolved', 'Strike Off Listed', 'Liquidation'. Leave empty to export every match - a Dissolved or Liquidation counterparty is usually the finding you most want to see.",
|
|
1709
1834
|
"default": [],
|
|
1710
1835
|
"items": {
|
|
1711
1836
|
"type": "string"
|
package/index.js
CHANGED
|
@@ -36,21 +36,89 @@ function requireToken() {
|
|
|
36
36
|
return t;
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
//
|
|
39
|
+
// How long we hold a tool call open before handing back a run handle. Must stay
|
|
40
|
+
// under the MCP client's default request timeout (60s) with margin: if the CLIENT
|
|
41
|
+
// gives up first, the caller sees an error for a run that is still billing.
|
|
42
|
+
const WAIT_SECS = 45;
|
|
43
|
+
const TERMINAL = new Set(["SUCCEEDED", "FAILED", "ABORTED", "TIMED-OUT"]);
|
|
44
|
+
|
|
45
|
+
// Retrying a pending check runs - and bills - a second time. This wording is
|
|
46
|
+
// deliberately blunt: it is the only thing between a slow check and a double charge.
|
|
47
|
+
const PENDING_NOTE =
|
|
48
|
+
"This check is STILL RUNNING and is already being billed. Do NOT retry it and do NOT call this tool again - " +
|
|
49
|
+
"call regdata_run_result with the runId above to collect the result. Retrying charges the user twice for the same check.";
|
|
50
|
+
|
|
51
|
+
async function apiJson(url, init) {
|
|
52
|
+
const res = await fetch(url, init);
|
|
53
|
+
const text = await res.text();
|
|
54
|
+
if (!res.ok) throw new Error(`Apify API ${res.status}: ${text.slice(0, 300)}`);
|
|
55
|
+
return JSON.parse(text).data;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function datasetItems(datasetId, maxItems) {
|
|
59
|
+
const url = new URL(`${APIFY_BASE}/datasets/${datasetId}/items`);
|
|
60
|
+
url.searchParams.set("token", requireToken());
|
|
61
|
+
if (maxItems) url.searchParams.set("limit", String(maxItems));
|
|
62
|
+
const res = await fetch(url);
|
|
63
|
+
const text = await res.text();
|
|
64
|
+
if (!res.ok) throw new Error(`Could not read dataset ${datasetId} (${res.status})`);
|
|
65
|
+
return text; // JSON array of dataset items
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Either the items, or a redeemable handle. Never a lost run.
|
|
69
|
+
async function settle(run, label, maxItems) {
|
|
70
|
+
if (run.status === "SUCCEEDED") return await datasetItems(run.defaultDatasetId, maxItems);
|
|
71
|
+
if (TERMINAL.has(run.status)) {
|
|
72
|
+
throw new Error(
|
|
73
|
+
`regdata/${label} run ${run.id} ended as ${run.status}` +
|
|
74
|
+
(run.statusMessage ? `: ${run.statusMessage}` : "")
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
return JSON.stringify(
|
|
78
|
+
{ status: run.status, runId: run.id, datasetId: run.defaultDatasetId, note: PENDING_NOTE },
|
|
79
|
+
null,
|
|
80
|
+
2
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Start the actor and wait briefly.
|
|
85
|
+
//
|
|
86
|
+
// Started ASYNC on purpose. This previously used run-sync-get-dataset-items, which
|
|
87
|
+
// holds one connection open until the run ends. Per Apify's docs, "if the connection
|
|
88
|
+
// breaks, you will not receive any information about the run and its output" and
|
|
89
|
+
// "this won't abort the run itself" - so a client timeout destroyed the only handle
|
|
90
|
+
// to a run that then completed and BILLED. Measured durations for the Poland KYB
|
|
91
|
+
// composite were 21-148s against a 60s client default, so this was routine, not rare.
|
|
92
|
+
// Starting async means the runId exists from the first response and a disconnect is
|
|
93
|
+
// always recoverable.
|
|
40
94
|
async function runActor(slug, input, { maxItems } = {}) {
|
|
41
|
-
const url = new URL(`${APIFY_BASE}/acts/regdata~${slug}/
|
|
95
|
+
const url = new URL(`${APIFY_BASE}/acts/regdata~${slug}/runs`);
|
|
42
96
|
url.searchParams.set("token", requireToken());
|
|
97
|
+
url.searchParams.set("waitForFinish", String(WAIT_SECS)); // Apify caps this at 60
|
|
43
98
|
if (maxItems) url.searchParams.set("maxItems", String(maxItems));
|
|
44
|
-
const
|
|
99
|
+
const run = await apiJson(url, {
|
|
45
100
|
method: "POST",
|
|
46
101
|
headers: { "Content-Type": "application/json" },
|
|
47
102
|
body: JSON.stringify(input ?? {}),
|
|
48
103
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
104
|
+
return await settle(run, slug, maxItems);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Collect a run that was still going when its tool call returned.
|
|
108
|
+
//
|
|
109
|
+
// NOTE on access: we send the caller's token, but Apify does NOT scope runs or
|
|
110
|
+
// datasets to it - verified 2026-07-23, `GET /actor-runs/{id}` and
|
|
111
|
+
// `/datasets/{id}/items` both return 200 with a foreign token AND with no token
|
|
112
|
+
// at all, on a dataset whose isPublic is unset. The storage ID is itself the
|
|
113
|
+
// capability. So this tool grants nothing a runId holder could not already fetch
|
|
114
|
+
// straight from the public API; it is convenience, not an access boundary.
|
|
115
|
+
// Treat a runId as a secret and do not log or forward it.
|
|
116
|
+
async function collectRun(runId, { waitSecs, maxItems } = {}) {
|
|
117
|
+
const url = new URL(`${APIFY_BASE}/actor-runs/${runId}`);
|
|
118
|
+
url.searchParams.set("token", requireToken());
|
|
119
|
+
url.searchParams.set("waitForFinish", String(Math.max(0, Math.min(waitSecs ?? WAIT_SECS, 60))));
|
|
120
|
+
const run = await apiJson(url);
|
|
121
|
+
return await settle(run, run.actId ?? "run", maxItems);
|
|
54
122
|
}
|
|
55
123
|
|
|
56
124
|
// Fetch an actor's live input schema so the model can construct correct input.
|
|
@@ -63,14 +131,14 @@ async function describeActor(slug) {
|
|
|
63
131
|
const schema =
|
|
64
132
|
data?.defaultRunOptions?.inputSchema ||
|
|
65
133
|
data?.exampleRunInput ||
|
|
66
|
-
"See https://apify.com/regdata/" + slug + " for the input schema.";
|
|
134
|
+
"See https://apify.com/regdata/" + slug + "?fpr=getregdata for the input schema.";
|
|
67
135
|
return { slug, title: data?.title, description: data?.description, schema };
|
|
68
136
|
}
|
|
69
137
|
|
|
70
138
|
const bySlug = Object.fromEntries(ACTORS.map((a) => [a.slug, a]));
|
|
71
139
|
const byTool = Object.fromEntries(ACTORS.map((a) => [a.tool, a]));
|
|
72
140
|
|
|
73
|
-
// One tool per actor +
|
|
141
|
+
// One tool per actor + three helpers (catalog, run_result, describe).
|
|
74
142
|
const MAX_ITEMS_PROP = {
|
|
75
143
|
type: "integer",
|
|
76
144
|
description: "Optional cap on billed dataset items returned.",
|
|
@@ -110,6 +178,30 @@ function buildToolList() {
|
|
|
110
178
|
`Use this catalog to find the right single-registry tool for other jurisdictions, or when you need one specific source in depth.`,
|
|
111
179
|
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
112
180
|
},
|
|
181
|
+
{
|
|
182
|
+
name: "regdata_run_result",
|
|
183
|
+
description:
|
|
184
|
+
"Collect the result of a regdata check that was still running when its tool call returned. " +
|
|
185
|
+
"When any regdata tool returns {status, runId, note} instead of results, the check is running and already billed - " +
|
|
186
|
+
"call THIS tool with that runId rather than re-running the check, which would charge the user twice. " +
|
|
187
|
+
"Returns the dataset items once the run finishes; if it is still going, returns the same handle so you can call again.",
|
|
188
|
+
inputSchema: {
|
|
189
|
+
type: "object",
|
|
190
|
+
properties: {
|
|
191
|
+
runId: {
|
|
192
|
+
type: "string",
|
|
193
|
+
description: "The runId returned by the pending tool call, e.g. NAMNqpPch7RFSY1oQ",
|
|
194
|
+
},
|
|
195
|
+
waitSecs: {
|
|
196
|
+
type: "integer",
|
|
197
|
+
description: "Seconds to wait for the run to finish before returning (0-60, default 45).",
|
|
198
|
+
},
|
|
199
|
+
maxItems: MAX_ITEMS_PROP,
|
|
200
|
+
},
|
|
201
|
+
required: ["runId"],
|
|
202
|
+
additionalProperties: false,
|
|
203
|
+
},
|
|
204
|
+
},
|
|
113
205
|
{
|
|
114
206
|
name: "regdata_describe",
|
|
115
207
|
description:
|
|
@@ -143,6 +235,11 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
143
235
|
const list = ACTORS.map((a) => ({ tool: a.tool, slug: a.slug, title: a.title }));
|
|
144
236
|
return { content: [{ type: "text", text: JSON.stringify(list, null, 2) }] };
|
|
145
237
|
}
|
|
238
|
+
if (name === "regdata_run_result") {
|
|
239
|
+
if (!args.runId) throw new Error("runId is required - it is returned by the pending tool call.");
|
|
240
|
+
const out = await collectRun(args.runId, { waitSecs: args.waitSecs, maxItems: args.maxItems });
|
|
241
|
+
return { content: [{ type: "text", text: out }] };
|
|
242
|
+
}
|
|
146
243
|
if (name === "regdata_describe") {
|
|
147
244
|
const slug = args.slug || byTool[args.tool]?.slug;
|
|
148
245
|
if (!slug || !bySlug[slug]) throw new Error(`Unknown actor: ${args.slug || args.tool}`);
|
|
@@ -164,4 +261,4 @@ server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
164
261
|
|
|
165
262
|
const transport = new StdioServerTransport();
|
|
166
263
|
await server.connect(transport);
|
|
167
|
-
console.error(`getregdata MCP server ready - ${ACTORS.length} registry tools + catalog/describe.`);
|
|
264
|
+
console.error(`getregdata MCP server ready - ${ACTORS.length} registry tools + catalog/run_result/describe.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "getregdata-mcp",
|
|
3
|
-
"version": "1.1
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"mcpName": "io.github.Nolpak14/getregdata",
|
|
5
5
|
"description": "MCP server for official business-registry data - KYC/AML, beneficial owners, credit-risk, adverse media. One-call Poland KYB verdict, plus per-registry tools for Germany, Italy, Spain, Austria, France, Belgium, Czechia, Slovakia, Cyprus, Ireland, Portugal, Nigeria, Colombia, the US (California) and the UAE.",
|
|
6
6
|
"type": "module",
|