scrapeloop-mcp 0.11.1 → 0.12.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 +2 -2
- package/src/index.js +21 -1
- package/src/mutation-policies.js +1 -0
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scrapeloop-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.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": {
|
|
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",
|
|
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 && node test/mcp_server_version.mjs",
|
|
8
8
|
"release:preflight": "node scripts/release-preflight.mjs",
|
|
9
9
|
"release:verify": "node scripts/release-installed-verify.mjs"
|
|
10
10
|
},
|
package/src/index.js
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
18
18
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
19
19
|
import { randomUUID } from 'node:crypto';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
20
21
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
21
22
|
import {
|
|
22
23
|
CallToolRequestSchema,
|
|
@@ -24,6 +25,7 @@ import {
|
|
|
24
25
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
25
26
|
import { MUTATION_POLICIES, RETRY_CONTRACT_COPY } from './mutation-policies.js';
|
|
26
27
|
|
|
28
|
+
const PACKAGE_VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version;
|
|
27
29
|
const API_KEY = process.env.SCRAPELOOP_API_KEY;
|
|
28
30
|
const BASE = (process.env.SCRAPELOOP_API_URL || 'https://api.scrapeloop.com').replace(/\/$/, '');
|
|
29
31
|
const TIMEOUT_MS = Number(process.env.SCRAPELOOP_TIMEOUT_MS) || 30000;
|
|
@@ -561,6 +563,24 @@ const TOOLS = {
|
|
|
561
563
|
def: { description: 'Read one scrape plan, its saved scope, limits, progress and spending.', inputSchema: obj({ plan_id: { ...S, format: 'uuid' } }, ['plan_id']) },
|
|
562
564
|
run: (a) => api('GET', `/plans/${enc(a.plan_id)}`),
|
|
563
565
|
},
|
|
566
|
+
get_scrape_plan_ready_goal: {
|
|
567
|
+
def: { description: 'Read a scrape plan verified-email goal and its dated ready count. Newly ready, unused stock, consumption and corrections are separate. Stale or incomplete checks never imply usable stock. This read does not run paid checks or start anything.', inputSchema: obj({ plan_id: { ...S, format: 'uuid' } }, ['plan_id']) },
|
|
568
|
+
run: (a) => api('GET', `/plans/${enc(a.plan_id)}/ready`),
|
|
569
|
+
},
|
|
570
|
+
set_scrape_plan_ready_goal: {
|
|
571
|
+
def: { description: 'Save a verified-email goal on a native Maps draft without repeat searches. Choose the ready Table and its email campaign, monthly goal/minimum, unused-stock ceiling and evidence rules. Pass the reviewed expected_updated_at from get_scrape_plan. Counts require current input-bound verification, qualification, campaign fields and sender-history checks. This does not start scraping, verification or campaigns. Complete-search pacing must be available before Start.', inputSchema: obj({
|
|
572
|
+
plan_id: { ...S, format: 'uuid' }, expected_updated_at: { ...S, format: 'date-time' },
|
|
573
|
+
goal: obj({ kind: { ...S, enum: ['verified_email'] }, ready_list_id: { ...S, format: 'uuid' },
|
|
574
|
+
campaign_id: { ...S, format: 'uuid' }, monthly_goal: { type: 'integer', minimum: 1, maximum: 1000000 },
|
|
575
|
+
monthly_minimum: { type: 'integer', minimum: 0, maximum: 1000000 },
|
|
576
|
+
stock_ceiling: { type: 'integer', minimum: 1, maximum: 1000000 }, timezone: S,
|
|
577
|
+
evidence_max_age_days: { type: 'integer', minimum: 1, maximum: 90 }, allow_resolved_catchall: B,
|
|
578
|
+
required_fields: ARR({ ...S, enum: ['name', 'organization_name', 'first_name', 'last_name', 'industry', 'city', 'state', 'postal_code', 'domain', 'language'] }),
|
|
579
|
+
languages: ARR({ ...S, pattern: '^[a-z]{2}$' }),
|
|
580
|
+
}, ['ready_list_id', 'campaign_id', 'monthly_goal', 'monthly_minimum', 'stock_ceiling', 'timezone']),
|
|
581
|
+
}, ['plan_id', 'expected_updated_at', 'goal']) },
|
|
582
|
+
run: ({ plan_id, ...body }) => api('PUT', `/plans/${enc(plan_id)}/ready`, body),
|
|
583
|
+
},
|
|
564
584
|
pause_scrape_plan: {
|
|
565
585
|
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
586
|
run: (a) => api('POST', `/plans/${enc(a.plan_id)}/pause`),
|
|
@@ -2952,7 +2972,7 @@ async function serve() {
|
|
|
2952
2972
|
}
|
|
2953
2973
|
|
|
2954
2974
|
const server = new Server(
|
|
2955
|
-
{ name: 'scrapeloop-mcp', version:
|
|
2975
|
+
{ name: 'scrapeloop-mcp', version: PACKAGE_VERSION },
|
|
2956
2976
|
{ capabilities: { tools: {} } }
|
|
2957
2977
|
);
|
|
2958
2978
|
|
package/src/mutation-policies.js
CHANGED
|
@@ -45,6 +45,7 @@ export const MUTATION_POLICIES = Object.freeze({
|
|
|
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
47
|
start_scrape_plan: never('POST', ['get_scrape_plan'], ['plan_id']),
|
|
48
|
+
set_scrape_plan_ready_goal: reconcile('PUT', ['get_scrape_plan_ready_goal'], ['plan_id', 'goal']),
|
|
48
49
|
estimate_scrape: read(),
|
|
49
50
|
submit_scrape: keyed('POST', ['list_jobs'], ['kind', 'integration_id', 'credential_id', 'table_id']),
|
|
50
51
|
cancel_job: never('POST', ['get_job'], ['job_id', 'status']),
|