scrapeloop-mcp 0.35.0 → 0.36.0
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/package.json +1 -1
- package/src/index.js +10 -0
- package/src/mutation-policies.js +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scrapeloop-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "Scrapeloop MCP server - set up and run Scrapeloop end-to-end (integrations, scraping, lead database, verification, cleaners, enrichment, strategies, Instantly campaigns) from any MCP client (Claude Desktop, Cursor, ChatGPT, …).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
package/src/index.js
CHANGED
|
@@ -657,6 +657,16 @@ const TOOLS = {
|
|
|
657
657
|
def: { description: 'Start or resume a complete native search after explicit approval of the exact reviewed plan, enabled checks and monthly/full-plan limits. This can spend credits. Requires the snapshot hash and updated timestamp from review_complete_scrape_plan, plus one stable operation UUID. A changed plan needs a fresh review. After uncertainty, read the plan and review; preserve the same operation and body. Never use this for sender Start or GHL writes.', inputSchema: obj({ plan_id: { ...S, format: 'uuid' }, operation_id: { ...S, format: 'uuid' }, snapshot_hash: { ...S, pattern: '^[0-9a-f]{64}$' }, expected_updated_at: { ...S, format: 'date-time' } }, ['plan_id', 'operation_id', 'snapshot_hash', 'expected_updated_at']) },
|
|
658
658
|
run: ({ plan_id, ...body }) => api('POST', `/plans/${enc(plan_id)}/launch`, body),
|
|
659
659
|
},
|
|
660
|
+
check_scrape_plan_stop: {
|
|
661
|
+
def: { description: 'Look at the stop a complete search plan is on. Use it when get_scrape_plan shows the block "A check is on hold". With dry_run true (the default) it only reads the saved records of the held Table check job. It says what it found, what would happen and how many check credits that could use, and it returns job_ids. To carry on, call it again with dry_run false and those same job_ids. It then acts only when the records prove that is safe: it ends the held job, gives unused held check credits back, runs free checks that never finished again, and runs paid checks that never started inside the plan limits. A paid check that got no answer is closed and never asked again. It sends no request to a checker itself. The answer has outcome safe, needs_person, wait or nothing, with a title, plain lines and a next line, all ready to show the person. Always show the dry run lines first and carry on only after the person says yes. If the held jobs changed since the dry run, nothing is changed and a fresh dry run comes back with changed true. A second call after it carried on finds nothing on hold. A held map search and a failed Table move are named and left to a person.', inputSchema: obj({ plan_id: { ...S, format: 'uuid' }, dry_run: B, job_ids: { ...ARR({ ...S, format: 'uuid' }), maxItems: 20 } }, ['plan_id']) },
|
|
662
|
+
run: (a) => {
|
|
663
|
+
const dryRun = a.dry_run !== false;
|
|
664
|
+
if (!dryRun && !Array.isArray(a.job_ids)) {
|
|
665
|
+
return { ok: false, status: 400, error: { detail: 'Run a dry run first, then pass its job_ids with dry_run false.' } };
|
|
666
|
+
}
|
|
667
|
+
return api('POST', `/plans/${enc(a.plan_id)}/check-stop`, dryRun ? { dry_run: true } : { dry_run: false, job_ids: a.job_ids });
|
|
668
|
+
},
|
|
669
|
+
},
|
|
660
670
|
pause_scrape_plan: {
|
|
661
671
|
def: { description: 'Pause new work from a scrape plan. A job already running may still finish. Inspect the plan and its jobs after pausing.', inputSchema: obj({ plan_id: { ...S, format: 'uuid' } }, ['plan_id']) },
|
|
662
672
|
run: (a) => api('POST', `/plans/${enc(a.plan_id)}/pause`),
|
package/src/mutation-policies.js
CHANGED
|
@@ -48,6 +48,9 @@ export const MUTATION_POLICIES = Object.freeze({
|
|
|
48
48
|
preview_pipeline: read(),
|
|
49
49
|
preview_scrape_plan: read(),
|
|
50
50
|
create_scrape_plan: keyed('POST', ['list_scrape_plans'], ['name', 'target_list_id', 'kind']),
|
|
51
|
+
// A second run finds the job already closed and changes nothing, so a
|
|
52
|
+
// repeat after a lost reply is safe (tests/test_plan_stop_check.py).
|
|
53
|
+
check_scrape_plan_stop: idempotent('POST', ['get_scrape_plan', 'get_job'], ['plan_id', 'dry_run', 'job_ids']),
|
|
51
54
|
pause_scrape_plan: never('POST', ['get_scrape_plan'], ['plan_id']),
|
|
52
55
|
launch_complete_scrape_plan: reconcile('POST', ['get_scrape_plan', 'review_complete_scrape_plan'], ['plan_id', 'operation_id', 'snapshot_hash', 'expected_updated_at']),
|
|
53
56
|
start_scrape_plan: never('POST', ['get_scrape_plan'], ['plan_id']),
|