scrapeloop-mcp 0.3.0 → 0.4.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/index.js +51 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scrapeloop-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.4.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
  "bin": {
package/src/index.js CHANGED
@@ -183,7 +183,10 @@ const TOOLS = {
183
183
  description: "List an integration's stored credentials (masked — keys are never returned).",
184
184
  inputSchema: obj({ integration_id: S }, ['integration_id']),
185
185
  },
186
- run: (a) => api('GET', `/integrations/${enc(a.integration_id)}/credentials`),
186
+ run: (a) =>
187
+ a.integration_id
188
+ ? api('GET', `/integrations/${enc(a.integration_id)}/credentials`)
189
+ : { ok: false, status: 400, error: { detail: 'integration_id is required. Use list_integrations to find it.' } },
187
190
  },
188
191
  add_credential: {
189
192
  def: {
@@ -546,6 +549,52 @@ const TOOLS = {
546
549
  def: { description: 'Add lead-database people to a list by global_person_id (acquires them, dedup-aware).', inputSchema: obj({ list_id: S, global_person_ids: ARR(S) }, ['list_id', 'global_person_ids']) },
547
550
  run: (a) => api('POST', `/lists/${enc(a.list_id)}/members`, { global_person_ids: a.global_person_ids }),
548
551
  },
552
+ import_leads: {
553
+ def: {
554
+ description:
555
+ 'Bring your own leads: import externally-sourced lead records into a campaign-bindable Scrapeloop list. For leads you already have (a CSV/export with emails — optionally pre-verified, with a generated first line) — no scraping, no lead credits, and NO re-verification (your verification_status is preserved). Idempotent: dedupe within the workspace by email (default) or external_id — re-running the same batch UPDATES existing leads (merges custom_fields, unions strategy tags), never duplicates. custom_fields flow through to Instantly as custom variables (usable as {{first_line}} etc.). Target an existing list_id OR a list_name (create-or-get). Batch up to 1000 records. Each record: {email (required), first_name, last_name, business_name, phone, website, address, city, state_region, country, niche, rating, reviews_count, verification_status ("verified"|"catchall_verified"|"unverified"|"risky"|"invalid"), strategy_tags:[], custom_fields:{}, external_id}. Returns {list_id, inserted, updated, deduped, invalid, invalid_reasons}. Then bind list_id with create_campaign(source_list_id=...).',
556
+ inputSchema: obj(
557
+ {
558
+ list_id: S,
559
+ list_name: S,
560
+ records: ARR(O),
561
+ dedupe_by: { ...S, description: '"email" (default) or "external_id"' },
562
+ default_verification_status: S,
563
+ },
564
+ ['records'],
565
+ ),
566
+ },
567
+ run: (a) =>
568
+ api('POST', '/leads/import', {
569
+ ...(a.list_id ? { list_id: a.list_id } : {}),
570
+ ...(a.list_name ? { list_name: a.list_name } : {}),
571
+ records: a.records || [],
572
+ ...(a.dedupe_by ? { dedupe_by: a.dedupe_by } : {}),
573
+ ...(a.default_verification_status ? { default_verification_status: a.default_verification_status } : {}),
574
+ }),
575
+ },
576
+ delete_list: {
577
+ def: {
578
+ description:
579
+ 'Delete a list (the list + its membership; the underlying leads stay in the workspace). Works for any Scrapeloop list. Irreversible — confirm with the user first.',
580
+ inputSchema: obj({ list_id: S }, ['list_id']),
581
+ },
582
+ run: (a) =>
583
+ a.list_id
584
+ ? api('DELETE', `/lists/${enc(a.list_id)}`)
585
+ : { ok: false, status: 400, error: { detail: 'list_id is required.' } },
586
+ },
587
+ delete_campaign: {
588
+ def: {
589
+ description:
590
+ 'Delete a campaign (the Scrapeloop campaign + its ledger; the Instantly campaign itself is not deleted). Irreversible — if you only want to stop sending, pause_campaign instead. Confirm with the user first.',
591
+ inputSchema: obj({ campaign_id: S }, ['campaign_id']),
592
+ },
593
+ run: (a) =>
594
+ a.campaign_id
595
+ ? api('DELETE', `/campaigns/${enc(a.campaign_id)}`)
596
+ : { ok: false, status: 400, error: { detail: 'campaign_id is required.' } },
597
+ },
549
598
  };
550
599
 
551
600
  async function serve() {
@@ -560,7 +609,7 @@ async function serve() {
560
609
  }
561
610
 
562
611
  const server = new Server(
563
- { name: 'scrapeloop-mcp', version: '0.3.0' },
612
+ { name: 'scrapeloop-mcp', version: '0.4.0' },
564
613
  { capabilities: { tools: {} } }
565
614
  );
566
615