scrapeloop-mcp 0.8.0 → 0.10.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.10.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'),
@@ -1180,6 +1184,8 @@ const TOOLS = {
1180
1184
  operation_id: { ...S, format: 'uuid' }, name: S, market: S,
1181
1185
  niche_gcids: ARR(S), mode: { ...S, enum: ['auto', 'simple', 'advanced'] },
1182
1186
  channels: ARR({ ...S, enum: ['email', 'sms', 'linkedin'] }),
1187
+ phone_check_timing: { ...S, enum: ['on_arrival', 'manual'], description: 'Manual queues phone checks without running them on arrival. SMS ready still requires a passing check.' },
1188
+ linkedin_check_timing: { ...S, enum: ['on_arrival', 'manual'], description: 'Manual creates Raw LinkedIn enrichment for profile review with paid lookup off. Review and move confirmed personal profiles to LinkedIn yourself.' },
1183
1189
  checks: { ...O, description: 'Overrides for saved checks, using the Playbook checks keys.' },
1184
1190
  stage_mode: { ...S, enum: ['move', 'copy'] }, carry_values: B,
1185
1191
  raw_setup: { ...O, description: 'Optional Raw columns, packs and layout. Same shape as create_table table_setup.' },
@@ -2942,7 +2948,7 @@ async function serve() {
2942
2948
  }
2943
2949
 
2944
2950
  const server = new Server(
2945
- { name: 'scrapeloop-mcp', version: '0.8.0' },
2951
+ { name: 'scrapeloop-mcp', version: '0.10.0' },
2946
2952
  { capabilities: { tools: {} } }
2947
2953
  );
2948
2954
 
@@ -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']),