scrapeloop-mcp 0.8.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "scrapeloop-mcp",
3
- "version": "0.8.0",
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, \u2026).",
3
+ "version": "0.9.0",
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": {
7
7
  "test": "node --check src/index.js && node test/mcp_table_tools.mjs && node test/mcp_playbook_plans.mjs && node test/mcp_community_intent.mjs && node test/mcp_api_key_preflight.mjs && node test/mutation_retry_contract.mjs && node test/release_readiness.mjs",
package/src/index.js CHANGED
@@ -548,8 +548,8 @@ const TOOLS = {
548
548
  },
549
549
  create_scrape_plan: {
550
550
  def: {
551
- description: 'Create and start an approved scrape plan into an existing writable Table. This can spend credits or vendor money. Preview the exact choices first and stay within the approved limit and time period. Pass explicit territory values and matching billing limits. Reuse the same idempotency_key after a lost reply, inspect list_scrape_plans and never create a second plan to escape an uncertain result. Over-time limits reset monthly; a total one-time approval does not authorize recurring spend.',
552
- inputSchema: obj({ ...PLAN_FIELDS, target_list_id: { ...S, format: 'uuid' } }, [...PLAN_REQUIRED, 'target_list_id']),
551
+ description: 'Save a scrape plan into an existing writable Table. Set start_mode to draft to save without starting searches or spending. The default active mode starts approved work and can spend credits or vendor money. Preview the exact choices first and stay within the approved limit and time period. Pass explicit territory values and matching billing limits. Reuse the same idempotency_key after a lost reply, inspect list_scrape_plans and never create a second plan to escape an uncertain result. Over-time limits reset monthly; a total one-time approval does not authorize recurring spend.',
552
+ inputSchema: obj({ ...PLAN_FIELDS, target_list_id: { ...S, format: 'uuid' }, start_mode: { ...S, enum: ['active', 'draft'] } }, [...PLAN_REQUIRED, 'target_list_id']),
553
553
  },
554
554
  run: ({ idempotency_key: _key, ...body }) => api('POST', '/plans', body),
555
555
  },
@@ -565,6 +565,10 @@ const TOOLS = {
565
565
  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']) },
566
566
  run: (a) => api('POST', `/plans/${enc(a.plan_id)}/pause`),
567
567
  },
568
+ start_scrape_plan: {
569
+ def: { description: 'Start a saved draft after reviewing its scope, destination and cost limits with the user. This can spend credits or vendor money. Requires approval for the exact plan and budget. Pass expected_updated_at from the reviewed get_scrape_plan response. Changed drafts must be reviewed again. After a lost reply inspect get_scrape_plan; never retry blindly.', inputSchema: obj({ plan_id: { ...S, format: 'uuid' }, expected_updated_at: { ...S, format: 'date-time' } }, ['plan_id', 'expected_updated_at']) },
570
+ run: (a) => api('POST', `/plans/${enc(a.plan_id)}/start`, { expected_updated_at: a.expected_updated_at }),
571
+ },
568
572
  list_jobs: {
569
573
  def: { description: 'List recent scrape/enrich jobs in the workspace.', inputSchema: obj({}) },
570
574
  run: () => api('GET', '/jobs'),
@@ -2942,7 +2946,7 @@ async function serve() {
2942
2946
  }
2943
2947
 
2944
2948
  const server = new Server(
2945
- { name: 'scrapeloop-mcp', version: '0.8.0' },
2949
+ { name: 'scrapeloop-mcp', version: '0.9.0' },
2946
2950
  { capabilities: { tools: {} } }
2947
2951
  );
2948
2952
 
@@ -44,6 +44,7 @@ export const MUTATION_POLICIES = Object.freeze({
44
44
  preview_scrape_plan: read(),
45
45
  create_scrape_plan: keyed('POST', ['list_scrape_plans'], ['name', 'target_list_id', 'kind']),
46
46
  pause_scrape_plan: never('POST', ['get_scrape_plan'], ['plan_id']),
47
+ start_scrape_plan: never('POST', ['get_scrape_plan'], ['plan_id']),
47
48
  estimate_scrape: read(),
48
49
  submit_scrape: keyed('POST', ['list_jobs'], ['kind', 'integration_id', 'credential_id', 'table_id']),
49
50
  cancel_job: never('POST', ['get_job'], ['job_id', 'status']),