mcp-scraper 0.34.1 → 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/README.md +10 -9
- package/dist/bin/api-server.cjs +24342 -17931
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +51 -7
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +48 -5
- package/dist/bin/mcp-scraper-cli.js.map +1 -1
- package/dist/bin/mcp-scraper-install.cjs +2 -2
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +2997 -2070
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +8 -8
- package/dist/bin/paa-harvest.cjs +125 -70
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +4 -4
- package/dist/chunk-345BQXZH.js +712 -0
- package/dist/chunk-345BQXZH.js.map +1 -0
- package/dist/{chunk-M2S27J6Z.js → chunk-44HZLHDV.js} +10 -1
- package/dist/chunk-44HZLHDV.js.map +1 -0
- package/dist/chunk-4HO66323.js +7 -0
- package/dist/chunk-4HO66323.js.map +1 -0
- package/dist/{chunk-BWXLTWF7.js → chunk-4ZIJ3BKZ.js} +6 -4
- package/dist/chunk-4ZIJ3BKZ.js.map +1 -0
- package/dist/{chunk-6OPHG76G.js → chunk-5RULXBJ7.js} +3166 -2322
- package/dist/chunk-5RULXBJ7.js.map +1 -0
- package/dist/chunk-AN3VQARU.js +684 -0
- package/dist/chunk-AN3VQARU.js.map +1 -0
- package/dist/{chunk-XVVNKASZ.js → chunk-ANCGXUQJ.js} +118 -73
- package/dist/chunk-ANCGXUQJ.js.map +1 -0
- package/dist/{chunk-3HBPKR5G.js → chunk-D7LM5QZN.js} +3 -3
- package/dist/{chunk-4ZB3X6BQ.js → chunk-E5UEELA7.js} +16 -2
- package/dist/{chunk-4ZB3X6BQ.js.map → chunk-E5UEELA7.js.map} +1 -1
- package/dist/{chunk-ZID3WQID.js → chunk-FQI5PFE7.js} +9 -71
- package/dist/chunk-FQI5PFE7.js.map +1 -0
- package/dist/chunk-G3P3ZDB4.js +69 -0
- package/dist/chunk-G3P3ZDB4.js.map +1 -0
- package/dist/{chunk-7AYRWAEK.js → chunk-G7KAVJ3F.js} +2 -2
- package/dist/{chunk-7AYRWAEK.js.map → chunk-G7KAVJ3F.js.map} +1 -1
- package/dist/{chunk-62DQAWPF.js → chunk-IFYER7O4.js} +367 -42
- package/dist/chunk-IFYER7O4.js.map +1 -0
- package/dist/chunk-O2MCWFXQ.js +499 -0
- package/dist/chunk-O2MCWFXQ.js.map +1 -0
- package/dist/{chunk-JWIE5NCR.js → chunk-QZXKQB7Y.js} +140 -10
- package/dist/chunk-QZXKQB7Y.js.map +1 -0
- package/dist/{db-YAI5AQOI.js → db-N6MPVMEF.js} +8 -2
- package/dist/extract-bundle-M4SDJG3V.js +568 -0
- package/dist/extract-bundle-M4SDJG3V.js.map +1 -0
- package/dist/index.cjs +129 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +4 -4
- package/dist/location-data-repository-Z4NQOU5Y.js +35 -0
- package/dist/{server-IWDHTES2.js → server-ZIGAFKOL.js} +10844 -7480
- package/dist/server-ZIGAFKOL.js.map +1 -0
- package/dist/site-extract-repository-PGQZNW6V.js +62 -0
- package/dist/site-extract-repository-PGQZNW6V.js.map +1 -0
- package/dist/{worker-645BZPEK.js → worker-EBB6CTGW.js} +7 -7
- package/docs/hosted-location-data.md +108 -0
- package/docs/mcp-tool-craft-lint.generated.md +6 -3
- package/docs/mcp-tool-manifest.generated.json +2073 -551
- package/docs/mcp-tool-quality-spec.md +1 -1
- package/docs/specs/connected-services-control-plane-decoupling-spec.md +1044 -0
- package/docs/specs/kernel-stealth-captcha-test-matrix.md +278 -0
- package/docs/specs/multimodal-image-memory-architecture-spec.md +1022 -0
- package/docs/specs/query-fanout-transport-contract-fix.md +9 -1
- package/docs/specs/unified-credit-and-scheduled-execution-billing-spec.md +36 -27
- package/package.json +6 -5
- package/dist/chunk-5PZ6N2QM.js +0 -130
- package/dist/chunk-5PZ6N2QM.js.map +0 -1
- package/dist/chunk-62DQAWPF.js.map +0 -1
- package/dist/chunk-6OPHG76G.js.map +0 -1
- package/dist/chunk-7N2KYL4U.js +0 -7
- package/dist/chunk-7N2KYL4U.js.map +0 -1
- package/dist/chunk-BWXLTWF7.js.map +0 -1
- package/dist/chunk-JWIE5NCR.js.map +0 -1
- package/dist/chunk-M2S27J6Z.js.map +0 -1
- package/dist/chunk-R7EETU7Z.js +0 -419
- package/dist/chunk-R7EETU7Z.js.map +0 -1
- package/dist/chunk-XVVNKASZ.js.map +0 -1
- package/dist/chunk-ZID3WQID.js.map +0 -1
- package/dist/extract-bundle-GPZRLBVY.js +0 -331
- package/dist/extract-bundle-GPZRLBVY.js.map +0 -1
- package/dist/server-IWDHTES2.js.map +0 -1
- package/dist/site-extract-repository-OLVWMOU2.js +0 -30
- /package/dist/{chunk-3HBPKR5G.js.map → chunk-D7LM5QZN.js.map} +0 -0
- /package/dist/{db-YAI5AQOI.js.map → db-N6MPVMEF.js.map} +0 -0
- /package/dist/{site-extract-repository-OLVWMOU2.js.map → location-data-repository-Z4NQOU5Y.js.map} +0 -0
- /package/dist/{worker-645BZPEK.js.map → worker-EBB6CTGW.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Query fan-out transport contract fix
|
|
2
2
|
|
|
3
|
-
- **Status:**
|
|
3
|
+
- **Status:** Released and verified in production
|
|
4
4
|
- **Baseline:** `origin/main` at `e2c90f8db7c22fa2aa48fc62cef10e2e0c799e15` (2026-07-25)
|
|
5
5
|
- **Decision:** [Keep hosted fan-out results inline](../decisions/2026-07-25-hosted-fanout-results-stay-inline.md)
|
|
6
6
|
- **Owner:** MCP Scraper browser-agent surface
|
|
@@ -32,6 +32,14 @@ Focused tests must prove hosted calls force upstream `export: false` and return
|
|
|
32
32
|
|
|
33
33
|
Live release acceptance requires an explicitly authorized new web-search prompt: hosted OAuth with `export: true` must return a populated inline result with `exports: null`; stdio with the same option must additionally produce readable local exports.
|
|
34
34
|
|
|
35
|
+
## Release evidence
|
|
36
|
+
|
|
37
|
+
- PR [#64](https://github.com/VilovietaSEO/mcp-scraper/pull/64) merged as `34a5eefa69b1fcaa2dec1dd645ac0dfc55cf4035`.
|
|
38
|
+
- npm, annotated tag, and GitHub/MCPB release published as `0.34.1` / `v0.34.1`.
|
|
39
|
+
- Vercel production deployment `dpl_CFCSkpAywT6PyqRe8LPDaKvicGrp` reached `READY` and serves `mcpscraper.dev`.
|
|
40
|
+
- Hosted Streamable HTTP with OAuth exposed 167 tools and returned a successful fan-out with 21 researched sources, complete inline data, `exports: null`, and no export error.
|
|
41
|
+
- The exact published npm `0.34.1` stdio package exposed 167 tools, returned a successful fan-out with 30 researched sources, and produced nine readable local export files with no export error.
|
|
42
|
+
|
|
35
43
|
## Out of scope
|
|
36
44
|
|
|
37
45
|
Public/shared download URLs, capture-parser changes, profile authentication, billing, timeout changes, and recovery of fan-out from pre-capture prompts.
|
|
@@ -1,36 +1,39 @@
|
|
|
1
1
|
# Unified Credits, Integrations, and Scheduled Execution Billing
|
|
2
2
|
|
|
3
|
-
- Status: Released
|
|
4
|
-
- Spec date: 2026-07-
|
|
3
|
+
- Status: Released scheduled-execution contract plus approved connected-account v2 contract
|
|
4
|
+
- Spec date: 2026-07-15
|
|
5
5
|
- Primary repos: mcp-scraper, mcp-scraper-scheduler, mcpscraper-web, mcpscraper-sdk
|
|
6
6
|
- Commercial decision: Scheduled Actions is a product capability, not a separate subscription
|
|
7
|
+
- Connected-account decision: each active Nango connection is a $3/month add-on; usage is metered in Credits
|
|
7
8
|
- Accounting decision: MCP Scraper's main credit ledger is the only debit authority
|
|
8
9
|
|
|
9
10
|
## Executive decision
|
|
10
11
|
|
|
11
12
|
MCP Scraper will use one visible usage currency: Credits.
|
|
12
13
|
|
|
13
|
-
Scheduled Actions uses the same Credit wallet as the rest of MCP Scraper. It is no longer sold as a separate $10-per-month product with a 1,000-run quota.
|
|
14
|
+
Scheduled Actions uses the same Credit wallet as the rest of MCP Scraper. It is no longer sold as a separate $10-per-month product with a 1,000-run quota. Connected accounts are commercial add-ons: each active Nango connection costs $3 per month, and provider usage is settled from the shared Credit wallet using authoritative receipts.
|
|
14
15
|
|
|
15
16
|
The replacement contract is:
|
|
16
17
|
|
|
17
|
-
1. Every paid MCP Scraper plan includes access to
|
|
18
|
-
2. OAuth connect and reconnect cost 0 Credits
|
|
18
|
+
1. Every paid MCP Scraper plan includes access to scheduling and the ability to add connected accounts.
|
|
19
|
+
2. OAuth connect and reconnect cost 0 Credits. Each active Nango connection is a separate $3-per-month recurring add-on, prorated by the subscription system.
|
|
19
20
|
3. Each scheduled occurrence that passes the balance check and begins execution costs 75 Credits exactly once.
|
|
20
21
|
4. A deterministic `connection_sync` occurrence has no model charge beyond that 75-Credit base.
|
|
21
22
|
5. An agent-mode occurrence additionally settles OpenRouter's actual reported model cost, multiplied by 1.5, then converted to Credits.
|
|
22
23
|
6. Token prices may be shown as current per-million-token estimates in Credits, but OpenRouter's reported cost is the settlement truth.
|
|
23
24
|
7. Separately metered scraper, browser, transcription, video-analysis, and similar tools keep their published rate-card prices when a schedule calls them.
|
|
24
|
-
8.
|
|
25
|
+
8. Connected usage costs 2 Credits per Nango function run, 2 Credits per Nango Proxy request, and 5 Credits per compute second, prorated from aggregate milliseconds and rounded once up to integer mc.
|
|
26
|
+
9. The older 5/10/15/25-Credit semantic read/write tariff, per-record/byte tariff, and 20,000-Credit active-connection minimum remain retired and are not enabled.
|
|
25
27
|
|
|
26
|
-
This design
|
|
28
|
+
This design separates the predictable credential-carrying cost from variable work. The $3 recurring line item pays for keeping a Nango connection active; function, Proxy, and compute activity draw from the shared Credit balance. There is no artificial 1,000-run cliff or separate scheduler product.
|
|
27
29
|
|
|
28
30
|
### Released v1 implementation boundary
|
|
29
31
|
|
|
30
32
|
- Authorization currently performs an idempotent wallet balance check, not a hard balance reservation.
|
|
31
33
|
- The server-side default maximum is 5,000 Credits per run and is environment-configurable; it is not yet editable in the customer UI.
|
|
32
34
|
- A missing authoritative model cost moves the schedule to `cost_pending` and pauses it. Automated recovery/reconciliation is still a hardening item.
|
|
33
|
-
-
|
|
35
|
+
- The main API accepts idempotent connected-usage receipts and is the settlement authority. The scheduler must preflight at least the fixed 2-Credit function unit, and a prior `cost_pending` connected receipt blocks new work until recovered.
|
|
36
|
+
- User-editable monthly caps, auto-refill, hard reservations, and automated Nango-to-ledger reconciliation remain hardening work.
|
|
34
37
|
|
|
35
38
|
## What was found before the v1 cutover
|
|
36
39
|
|
|
@@ -66,25 +69,25 @@ Do not assume existing scheduled-agent charges equal a clean 1.5 markup. Before
|
|
|
66
69
|
|
|
67
70
|
## Canonical Build Spec
|
|
68
71
|
|
|
69
|
-
- **Request:**
|
|
72
|
+
- **Request:** Keep Scheduled Actions on the shared Credit wallet; charge one 75-Credit occurrence base and correctly settle all-step OpenRouter cost at 1.5; add a $3 active-Nango-connection recurring line item plus receipt-based function, Proxy, and millisecond compute usage.
|
|
70
73
|
- **Lane:** Mastra Agentic Development plus MCP/API product billing.
|
|
71
74
|
- **Capability:** Unified Metered Execution.
|
|
72
75
|
- **Audience:** MCP Scraper customers, scheduled-agent users, MCP clients, SDK users, operators, finance, and support.
|
|
73
|
-
- **User-Facing Outcome:** A user
|
|
76
|
+
- **User-Facing Outcome:** A user pays $3/month for each active Nango account, sees connected usage itemized in Credits, optionally schedules work, and receives idempotent receipts without duplicate debits on retries.
|
|
74
77
|
- **Target Runtime:** Main MCP Scraper API and credit ledger; Vercel-hosted Mastra scheduler; Inngest workers; Nango connections and Proxy/functions; private Blob artifacts; public MCP; npm/SDK clients.
|
|
75
78
|
- **Inputs:** Authenticated identity, connection ID, tool or sync request, scheduled occurrence, model selection, per-run and monthly Credit limits, actual provider results, OpenRouter usage metadata, bytes and records delivered.
|
|
76
79
|
- **Agents:** Existing Scheduled Action Agent for interpretive work. Deterministic connection_sync workers remain non-agentic. Both use the same billing context.
|
|
77
80
|
- **Workflows:** Connect; direct read/write; bulk export; memory import; schedule estimate; occurrence claim; Credit authorization; execution; incremental settlement; final settlement; receipt; retry/reconciliation.
|
|
78
81
|
- **Tools:** Existing generic connected-service tools, provider-native tools, schedule tools, bulk export/import tools, credits_info, a new schedule estimator, and a shared internal billing adapter.
|
|
79
82
|
- **MCP:** Credit behavior is transport-independent. Tool descriptions state charge categories and estimates, results include receipt summaries, and exact provider tools remain protected by tenant ownership, action switches, and grants.
|
|
80
|
-
- **Signals:** Billing authorization created; low balance; budget threshold; cost pending; settlement complete; and insufficient Credits.
|
|
83
|
+
- **Signals:** Billing authorization created; connected-use preflight; low balance; budget threshold; cost pending; settlement complete; and insufficient Credits.
|
|
81
84
|
- **Background Tasks:** Usage aggregation, connection-minimum settlement, pending-cost reconciliation, low-balance notifications, automatic refill, legacy subscription migration, receipt retention, and rate-snapshot refresh.
|
|
82
85
|
- **Guardrails:** Integer microcredit arithmetic, idempotent charges, one debit authority, no model-visible billing credentials, fail closed before externally costly work, action approval independent of price, no prompt or provider credential in billing events.
|
|
83
86
|
- **Observability:** Itemized receipt per run; raw vendor cost; multiplier; model/provider; tokens; bytes; changed records; connection and schedule IDs; idempotency keys; authorization, settlement, and refund state.
|
|
84
87
|
- **Enforcement:** A call cannot bypass the billing adapter by using Mastra, the generic MCP bridge, direct REST, SDK, Nango, or a background job. Duplicate occurrence or HTTP retry cannot debit twice.
|
|
85
88
|
- **Persistence:** The main MCP Scraper/Turso credit ledger owns balances and debits. Scheduler Postgres owns schedule state, occurrence state, and a mirrored receipt reference, not the authoritative wallet.
|
|
86
89
|
- **Deployment:** Main API/ledger first, then scheduler and connection adapters, then public MCP, frontend, SDK/npm/MCPB, generated docs, Stripe migration, and Vercel production.
|
|
87
|
-
- **Done Contract:** A production scheduled run
|
|
90
|
+
- **Done Contract:** A production scheduled run charges its 75-Credit base once and aggregates every OpenRouter model step once. Every Nango call is preflighted, reports function/Proxy/compute usage under the active rate revision, and settles once in the main ledger. The UI, MCP, API, SDK, and recurring connection quantity publish the same contract.
|
|
88
91
|
- **Receipt Requirements:** Code and deployment SHAs; rate-table revision; Stripe migration result; test output; production Vercel IDs; npm/MCPB versions; sample agent and deterministic-sync billing receipts; reconciliation report; public pricing and tool-description parity.
|
|
89
92
|
|
|
90
93
|
## Product contract in plain language
|
|
@@ -106,7 +109,7 @@ A scheduled occurrence pays:
|
|
|
106
109
|
+ any separately metered scraper, browser, transcription,
|
|
107
110
|
video-analysis, or other published rate-card tools it calls
|
|
108
111
|
|
|
109
|
-
Direct connected-service reads, enabled actions, supported exports, and bounded Memory snapshots
|
|
112
|
+
Direct connected-service reads, enabled actions, supported exports, and bounded Memory snapshots report the Nango resources they actually consume: function runs, Proxy requests, and function compute milliseconds. The tool's semantic label does not change those infrastructure rates.
|
|
110
113
|
|
|
111
114
|
Internal pagination, retries, leases, and orchestration steps are not separate “runs.” A retry of the same occurrence cannot pay the fixed charge again.
|
|
112
115
|
|
|
@@ -182,21 +185,26 @@ Released v1 rates:
|
|
|
182
185
|
| Billing class | Charge |
|
|
183
186
|
|---|---:|
|
|
184
187
|
| OAuth connect, reconnect, or consent callback | Free |
|
|
185
|
-
|
|
|
186
|
-
|
|
|
187
|
-
|
|
|
188
|
-
|
|
|
189
|
-
| Active connection minimum | None |
|
|
188
|
+
| Active Nango connection | $3 per month, recurring and prorated |
|
|
189
|
+
| Nango function run | 2 Credits per run |
|
|
190
|
+
| Nango Proxy request | 2 Credits per request |
|
|
191
|
+
| Nango function compute | 5 Credits per second, prorated from aggregate milliseconds |
|
|
190
192
|
|
|
191
193
|
Action safety remains independent of price: ownership, live inventory, source-controlled policy, the account action switch, and exact scheduled grants still apply.
|
|
192
194
|
|
|
195
|
+
The active rate revision is `2026-07-15.connected-usage-v1`. Compute settlement uses:
|
|
196
|
+
|
|
197
|
+
compute mc = ceil(computeMilliseconds * 500 mc / 1000)
|
|
198
|
+
|
|
199
|
+
The scheduler aggregates raw milliseconds for one receipt before applying that ceiling. It does not round each span or function up to a whole second. Function, Proxy, and compute line items are additive; the recurring $3 connection charge is not converted into Credits.
|
|
200
|
+
|
|
193
201
|
### Deferred connected-operation pricing options (not enabled)
|
|
194
202
|
|
|
195
203
|
Earlier design work proposed 5/10/15/25-Credit read/write classes, a 25-Credit bulk base, per-record charges, and per-MiB charges. Those values are retained only as research for a later commercial decision. They are not present in the production registry and must not appear as current pricing in UI, MCP descriptions, SDKs, or support answers.
|
|
196
204
|
|
|
197
|
-
###
|
|
205
|
+
### Retired active connection minimum proposal
|
|
198
206
|
|
|
199
|
-
An earlier proposal described a 20,000-Credit minimum per active connection per 30-day billing period.
|
|
207
|
+
An earlier proposal described a 20,000-Credit wallet minimum per active connection per 30-day billing period. It is superseded by the flat $3/month recurring add-on and must not be presented as current pricing.
|
|
200
208
|
|
|
201
209
|
The remainder of this subsection records the deferred proposal for future evaluation only:
|
|
202
210
|
|
|
@@ -698,7 +706,7 @@ The deterministic worker:
|
|
|
698
706
|
- claims the same occurrence key;
|
|
699
707
|
- authorizes its budget;
|
|
700
708
|
- charges the 75-Credit occurrence base once;
|
|
701
|
-
-
|
|
709
|
+
- settles observed Nango function runs, Proxy requests, and aggregate compute milliseconds under the active connected-usage rate revision;
|
|
702
710
|
- checkpoints before settlement so retry behavior is deterministic.
|
|
703
711
|
|
|
704
712
|
The worker never invokes a model merely to paginate or transfer content.
|
|
@@ -711,9 +719,9 @@ Remove the Scheduled Actions add-on card.
|
|
|
711
719
|
|
|
712
720
|
Under every paid plan:
|
|
713
721
|
|
|
714
|
-
>
|
|
722
|
+
> Integration access and scheduled work included. Each active Nango account is $3/month; connected usage draws from your shared Credit balance.
|
|
715
723
|
|
|
716
|
-
Show the 75-Credit scheduled occurrence, the “actual OpenRouter cost plus 50%” disclosure,
|
|
724
|
+
Show the 75-Credit scheduled occurrence, the “actual OpenRouter cost plus 50%” disclosure, the $3 active-account recurring fee, and the 2/2/5 connected-usage rates. Do not show the retired semantic read/write tariff or active-connection Credit minimum as current pricing.
|
|
717
725
|
|
|
718
726
|
### Integrations page
|
|
719
727
|
|
|
@@ -940,7 +948,7 @@ Receipts must be sanitized. Do not include prompts, connection tokens, API keys,
|
|
|
940
948
|
- Separate scheduling entitlement or 1,000-run quota still enforced on any surface.
|
|
941
949
|
- Frontend, hosted MCP, SDK/npm, MCPB, or public docs showing different rates.
|
|
942
950
|
- A fixed token rate described as authoritative rather than an estimate.
|
|
943
|
-
- Any
|
|
951
|
+
- Any surface that omits or contradicts the approved $3 plus 2/2/5 connected-account contract.
|
|
944
952
|
- Commercial migration without a reconciliation and compensating-credit policy.
|
|
945
953
|
|
|
946
954
|
## Decisions locked by this spec
|
|
@@ -951,7 +959,8 @@ Receipts must be sanitized. Do not include prompts, connection tokens, API keys,
|
|
|
951
959
|
- scheduled_agent_llm uses a 1.5 multiplier.
|
|
952
960
|
- Model token tables are estimates.
|
|
953
961
|
- The fixed scheduled-occurrence charge is 75 Credits.
|
|
954
|
-
-
|
|
962
|
+
- Active Nango connections cost $3/month; usage costs 2 Credits/function execution, 2 Credits/Proxy request, and 5 Credits/compute-second measured from milliseconds.
|
|
963
|
+
- The proposed 5/10/15/25 semantic tariffs and 20,000-Credit active-connection minimum are not enabled.
|
|
955
964
|
- OAuth is free.
|
|
956
965
|
- Main MCP Scraper owns the only mutable Credit ledger.
|
|
957
966
|
- Every product and execution surface publishes the same price contract; shared itemized receipt UX remains hardening work.
|
|
@@ -959,8 +968,8 @@ Receipts must be sanitized. Do not include prompts, connection tokens, API keys,
|
|
|
959
968
|
|
|
960
969
|
## Decisions that may change only through a rate revision
|
|
961
970
|
|
|
962
|
-
- Exact per-read, per-write, per-record, and per-MiB rates.
|
|
963
|
-
-
|
|
971
|
+
- Exact semantic per-read, per-write, per-record, and per-MiB rates beyond the current Nango resource meter.
|
|
972
|
+
- Connected-account monthly price and function, Proxy, or compute rates.
|
|
964
973
|
- Pay-as-you-go Credit grant per dollar.
|
|
965
974
|
- Default per-run and monthly caps.
|
|
966
975
|
- Existing non-scheduler AI multipliers.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-scraper",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.36.0",
|
|
4
4
|
"description": "MCP server for MCP Scraper web intelligence tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"build:og-pages": "node scripts/build-og-pages.mjs",
|
|
36
36
|
"build:md": "node scripts/build-md-mirror.mjs",
|
|
37
37
|
"build:mcpb": "npm run build && node scripts/build-mcpb.mjs",
|
|
38
|
-
"build:rates": "tsx scripts/gen-rates.ts",
|
|
38
|
+
"build:rates": "node --import tsx scripts/gen-rates.ts",
|
|
39
39
|
"build:ui": "npm run build:rates && esbuild public/app.jsx --bundle --loader:.jsx=jsx --outfile=public/app.js --target=es2020",
|
|
40
40
|
"build:blog": "node scripts/run-ts-sandbox-safe.mjs scripts/build-blog.ts",
|
|
41
41
|
"mcp:manifest": "node scripts/run-ts-sandbox-safe.mjs scripts/generate-mcp-tool-manifest.ts",
|
|
@@ -52,6 +52,8 @@
|
|
|
52
52
|
"test:kernel": "vitest run tests/integration/kernel.smoke.test.ts",
|
|
53
53
|
"sync:env": "bash scripts/push-env.sh",
|
|
54
54
|
"sync:env:apply": "bash scripts/push-env.sh --apply",
|
|
55
|
+
"locations:publish-geonames": "node --import tsx scripts/publish-geonames-location-data.ts",
|
|
56
|
+
"locations:sync": "node --import tsx scripts/sync-hosted-location-data.ts",
|
|
55
57
|
"integrations:migrate-scheduler": "node --import tsx scripts/migrate-scheduler-integrations.ts",
|
|
56
58
|
"test:webhook": "node scripts/test-webhook.mjs",
|
|
57
59
|
"test:e2e": "playwright test",
|
|
@@ -76,6 +78,7 @@
|
|
|
76
78
|
"diff": "^9.0.0",
|
|
77
79
|
"hono": "^4.12.18",
|
|
78
80
|
"inngest": "^4.4.0",
|
|
81
|
+
"ipaddr.js": "^1.9.1",
|
|
79
82
|
"jose": "^6.2.3",
|
|
80
83
|
"mcpscraper-memory-tools": "^1.9.0",
|
|
81
84
|
"p-limit": "^7.3.0",
|
|
@@ -91,9 +94,6 @@
|
|
|
91
94
|
"youtube-transcript": "^1.3.1",
|
|
92
95
|
"zod": "^3.23.0"
|
|
93
96
|
},
|
|
94
|
-
"optionalDependencies": {
|
|
95
|
-
"@resvg/resvg-js-linux-arm64-gnu": "2.6.2"
|
|
96
|
-
},
|
|
97
97
|
"devDependencies": {
|
|
98
98
|
"@onkernel/cli": "^0.19.2",
|
|
99
99
|
"@playwright/test": "^1.60.0",
|
|
@@ -105,6 +105,7 @@
|
|
|
105
105
|
"better-sqlite3": "^12.9.0",
|
|
106
106
|
"bgutils-js": "^3.2.0",
|
|
107
107
|
"dotenv": "^17.4.2",
|
|
108
|
+
"fflate": "^0.7.4",
|
|
108
109
|
"jsdom": "^29.1.1",
|
|
109
110
|
"tsup": "^8.0.0",
|
|
110
111
|
"tsx": "^4.0.0",
|
package/dist/chunk-5PZ6N2QM.js
DELETED
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
LedgerOperation
|
|
3
|
-
} from "./chunk-BWXLTWF7.js";
|
|
4
|
-
import {
|
|
5
|
-
sanitizeVendorName
|
|
6
|
-
} from "./chunk-M2S27J6Z.js";
|
|
7
|
-
import {
|
|
8
|
-
getDb
|
|
9
|
-
} from "./chunk-62DQAWPF.js";
|
|
10
|
-
|
|
11
|
-
// src/api/site-extract-repository.ts
|
|
12
|
-
function rowToJob(r) {
|
|
13
|
-
return {
|
|
14
|
-
id: String(r.id),
|
|
15
|
-
userId: r.user_id != null ? Number(r.user_id) : null,
|
|
16
|
-
status: r.status != null ? String(r.status) : "pending",
|
|
17
|
-
startUrl: String(r.start_url ?? ""),
|
|
18
|
-
options: r.options ? JSON.parse(String(r.options)) : {},
|
|
19
|
-
totalUrls: Number(r.total_urls ?? 0),
|
|
20
|
-
doneUrls: Number(r.done_urls ?? 0),
|
|
21
|
-
artifacts: r.artifacts ? JSON.parse(String(r.artifacts)) : null,
|
|
22
|
-
error: r.error != null ? String(r.error) : null,
|
|
23
|
-
billedMc: r.billed_mc != null ? Number(r.billed_mc) : null,
|
|
24
|
-
createdAt: String(r.created_at ?? ""),
|
|
25
|
-
updatedAt: String(r.updated_at ?? "")
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
async function createExtractJob(jobId, userId, startUrl, options) {
|
|
29
|
-
const db = getDb();
|
|
30
|
-
await db.execute({
|
|
31
|
-
sql: `INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)
|
|
32
|
-
VALUES (?, ?, 'pending', ?, ?, datetime('now'), datetime('now'))`,
|
|
33
|
-
args: [jobId, userId, startUrl, JSON.stringify(options)]
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
async function getExtractJob(jobId) {
|
|
37
|
-
const db = getDb();
|
|
38
|
-
const res = await db.execute({ sql: `SELECT * FROM site_extract_jobs WHERE id = ?`, args: [jobId] });
|
|
39
|
-
return res.rows[0] ? rowToJob(res.rows[0]) : null;
|
|
40
|
-
}
|
|
41
|
-
async function listExtractJobs(userId) {
|
|
42
|
-
const db = getDb();
|
|
43
|
-
const res = await db.execute({ sql: `SELECT * FROM site_extract_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50`, args: [userId] });
|
|
44
|
-
return res.rows.map((r) => rowToJob(r));
|
|
45
|
-
}
|
|
46
|
-
async function setExtractJobTotal(jobId, totalUrls) {
|
|
47
|
-
const db = getDb();
|
|
48
|
-
await db.execute({
|
|
49
|
-
sql: `UPDATE site_extract_jobs SET status = 'running', total_urls = ?, updated_at = datetime('now') WHERE id = ?`,
|
|
50
|
-
args: [totalUrls, jobId]
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
async function saveExtractPages(jobId, pages) {
|
|
54
|
-
if (pages.length === 0) return;
|
|
55
|
-
const db = getDb();
|
|
56
|
-
await db.batch(
|
|
57
|
-
pages.map((p) => ({
|
|
58
|
-
sql: `INSERT OR REPLACE INTO site_extract_pages (job_id, url, page) VALUES (?, ?, ?)`,
|
|
59
|
-
args: [jobId, p.url, JSON.stringify({ ...p, bodyMarkdown: "", schema: [] })]
|
|
60
|
-
}))
|
|
61
|
-
);
|
|
62
|
-
await db.execute({
|
|
63
|
-
sql: `UPDATE site_extract_jobs
|
|
64
|
-
SET done_urls = (SELECT COUNT(*) FROM site_extract_pages WHERE job_id = ?), updated_at = datetime('now')
|
|
65
|
-
WHERE id = ?`,
|
|
66
|
-
args: [jobId, jobId]
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
async function getExtractedPages(jobId) {
|
|
70
|
-
const db = getDb();
|
|
71
|
-
const res = await db.execute({ sql: `SELECT page FROM site_extract_pages WHERE job_id = ?`, args: [jobId] });
|
|
72
|
-
return res.rows.map((r) => JSON.parse(String(r.page)));
|
|
73
|
-
}
|
|
74
|
-
async function countSuccessfulPages(jobId) {
|
|
75
|
-
const db = getDb();
|
|
76
|
-
const res = await db.execute({
|
|
77
|
-
sql: `SELECT COUNT(*) AS n FROM site_extract_pages
|
|
78
|
-
WHERE job_id = ? AND json_extract(page, '$.status') = 200 AND json_extract(page, '$.wordCount') > 0`,
|
|
79
|
-
args: [jobId]
|
|
80
|
-
});
|
|
81
|
-
return Number(res.rows[0]?.n ?? 0);
|
|
82
|
-
}
|
|
83
|
-
async function getExtractedUrls(jobId) {
|
|
84
|
-
const db = getDb();
|
|
85
|
-
const res = await db.execute({ sql: `SELECT url FROM site_extract_pages WHERE job_id = ?`, args: [jobId] });
|
|
86
|
-
return new Set(res.rows.map((r) => String(r.url)));
|
|
87
|
-
}
|
|
88
|
-
async function completeExtractJob(jobId, artifacts) {
|
|
89
|
-
const db = getDb();
|
|
90
|
-
await db.execute({
|
|
91
|
-
sql: `UPDATE site_extract_jobs SET status = 'complete', artifacts = ?, updated_at = datetime('now') WHERE id = ?`,
|
|
92
|
-
args: [JSON.stringify(artifacts ?? []), jobId]
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
async function failExtractJob(jobId, error) {
|
|
96
|
-
const db = getDb();
|
|
97
|
-
await db.execute({
|
|
98
|
-
sql: `UPDATE site_extract_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?`,
|
|
99
|
-
args: [sanitizeVendorName(error).slice(0, 2e3), jobId]
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
async function settleExtractJob(jobId, userId, refundMc, netChargeMc, reference) {
|
|
103
|
-
const db = getDb();
|
|
104
|
-
const job = await getExtractJob(jobId);
|
|
105
|
-
if (!job || job.billedMc != null) return;
|
|
106
|
-
if (refundMc <= 0) {
|
|
107
|
-
await db.execute({ sql: `UPDATE site_extract_jobs SET billed_mc = ?, updated_at = datetime('now') WHERE id = ? AND billed_mc IS NULL`, args: [Math.max(0, netChargeMc), jobId] });
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
await db.batch([
|
|
111
|
-
{ sql: "UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?", args: [refundMc, userId] },
|
|
112
|
-
{ sql: "INSERT INTO ledger (user_id, amount_mc, operation, description) VALUES (?, ?, ?, ?)", args: [userId, refundMc, LedgerOperation.EXTRACT_SITE_REFUND, reference] },
|
|
113
|
-
{ sql: `UPDATE site_extract_jobs SET billed_mc = ?, updated_at = datetime('now') WHERE id = ? AND billed_mc IS NULL`, args: [Math.max(0, netChargeMc), jobId] }
|
|
114
|
-
]);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
export {
|
|
118
|
-
createExtractJob,
|
|
119
|
-
getExtractJob,
|
|
120
|
-
listExtractJobs,
|
|
121
|
-
setExtractJobTotal,
|
|
122
|
-
saveExtractPages,
|
|
123
|
-
getExtractedPages,
|
|
124
|
-
countSuccessfulPages,
|
|
125
|
-
getExtractedUrls,
|
|
126
|
-
completeExtractJob,
|
|
127
|
-
failExtractJob,
|
|
128
|
-
settleExtractJob
|
|
129
|
-
};
|
|
130
|
-
//# sourceMappingURL=chunk-5PZ6N2QM.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/api/site-extract-repository.ts"],"sourcesContent":["import { getDb } from './db.js'\nimport { sanitizeVendorName } from '../errors.js'\nimport { LedgerOperation } from './rates.js'\nimport type { PageData } from './site-extractor.js'\n\nexport type ExtractJobStatus = 'pending' | 'running' | 'complete' | 'failed'\n\nexport interface ExtractJobRow {\n id: string\n userId: number | null\n status: ExtractJobStatus\n startUrl: string\n options: Record<string, unknown>\n totalUrls: number\n doneUrls: number\n artifacts: Array<{ key: string; url: string; bytes: number; contentType: string }> | null\n error: string | null\n billedMc: number | null\n createdAt: string\n updatedAt: string\n}\n\nfunction rowToJob(r: Record<string, unknown>): ExtractJobRow {\n return {\n id: String(r.id),\n userId: r.user_id != null ? Number(r.user_id) : null,\n status: (r.status != null ? String(r.status) : 'pending') as ExtractJobStatus,\n startUrl: String(r.start_url ?? ''),\n options: r.options ? JSON.parse(String(r.options)) : {},\n totalUrls: Number(r.total_urls ?? 0),\n doneUrls: Number(r.done_urls ?? 0),\n artifacts: r.artifacts ? JSON.parse(String(r.artifacts)) : null,\n error: r.error != null ? String(r.error) : null,\n billedMc: r.billed_mc != null ? Number(r.billed_mc) : null,\n createdAt: String(r.created_at ?? ''),\n updatedAt: String(r.updated_at ?? ''),\n }\n}\n\nexport async function createExtractJob(jobId: string, userId: number, startUrl: string, options: Record<string, unknown>): Promise<void> {\n const db = getDb()\n await db.execute({\n sql: `INSERT INTO site_extract_jobs (id, user_id, status, start_url, options, created_at, updated_at)\n VALUES (?, ?, 'pending', ?, ?, datetime('now'), datetime('now'))`,\n args: [jobId, userId, startUrl, JSON.stringify(options)],\n })\n}\n\nexport async function getExtractJob(jobId: string): Promise<ExtractJobRow | null> {\n const db = getDb()\n const res = await db.execute({ sql: `SELECT * FROM site_extract_jobs WHERE id = ?`, args: [jobId] })\n return res.rows[0] ? rowToJob(res.rows[0] as unknown as Record<string, unknown>) : null\n}\n\nexport async function listExtractJobs(userId: number): Promise<ExtractJobRow[]> {\n const db = getDb()\n const res = await db.execute({ sql: `SELECT * FROM site_extract_jobs WHERE user_id = ? ORDER BY created_at DESC LIMIT 50`, args: [userId] })\n return res.rows.map(r => rowToJob(r as unknown as Record<string, unknown>))\n}\n\nexport async function setExtractJobTotal(jobId: string, totalUrls: number): Promise<void> {\n const db = getDb()\n await db.execute({\n sql: `UPDATE site_extract_jobs SET status = 'running', total_urls = ?, updated_at = datetime('now') WHERE id = ?`,\n args: [totalUrls, jobId],\n })\n}\n\nexport async function saveExtractPages(jobId: string, pages: PageData[]): Promise<void> {\n if (pages.length === 0) return\n const db = getDb()\n await db.batch(\n pages.map(p => ({\n sql: `INSERT OR REPLACE INTO site_extract_pages (job_id, url, page) VALUES (?, ?, ?)`,\n args: [jobId, p.url, JSON.stringify({ ...p, bodyMarkdown: '', schema: [] })],\n })),\n )\n await db.execute({\n sql: `UPDATE site_extract_jobs\n SET done_urls = (SELECT COUNT(*) FROM site_extract_pages WHERE job_id = ?), updated_at = datetime('now')\n WHERE id = ?`,\n args: [jobId, jobId],\n })\n}\n\nexport async function getExtractedPages(jobId: string): Promise<PageData[]> {\n const db = getDb()\n const res = await db.execute({ sql: `SELECT page FROM site_extract_pages WHERE job_id = ?`, args: [jobId] })\n return res.rows.map(r => JSON.parse(String((r as unknown as Record<string, unknown>).page)) as PageData)\n}\n\nexport async function countSuccessfulPages(jobId: string): Promise<number> {\n const db = getDb()\n const res = await db.execute({\n sql: `SELECT COUNT(*) AS n FROM site_extract_pages\n WHERE job_id = ? AND json_extract(page, '$.status') = 200 AND json_extract(page, '$.wordCount') > 0`,\n args: [jobId],\n })\n return Number((res.rows[0] as unknown as Record<string, unknown>)?.n ?? 0)\n}\n\nexport async function getExtractedUrls(jobId: string): Promise<Set<string>> {\n const db = getDb()\n const res = await db.execute({ sql: `SELECT url FROM site_extract_pages WHERE job_id = ?`, args: [jobId] })\n return new Set(res.rows.map(r => String((r as unknown as Record<string, unknown>).url)))\n}\n\nexport async function completeExtractJob(jobId: string, artifacts: ExtractJobRow['artifacts']): Promise<void> {\n const db = getDb()\n await db.execute({\n sql: `UPDATE site_extract_jobs SET status = 'complete', artifacts = ?, updated_at = datetime('now') WHERE id = ?`,\n args: [JSON.stringify(artifacts ?? []), jobId],\n })\n}\n\nexport async function failExtractJob(jobId: string, error: string): Promise<void> {\n const db = getDb()\n await db.execute({\n sql: `UPDATE site_extract_jobs SET status = 'failed', error = ?, updated_at = datetime('now') WHERE id = ?`,\n args: [sanitizeVendorName(error).slice(0, 2000), jobId],\n })\n}\n\nexport async function settleExtractJob(jobId: string, userId: number, refundMc: number, netChargeMc: number, reference: string): Promise<void> {\n const db = getDb()\n const job = await getExtractJob(jobId)\n if (!job || job.billedMc != null) return\n if (refundMc <= 0) {\n await db.execute({ sql: `UPDATE site_extract_jobs SET billed_mc = ?, updated_at = datetime('now') WHERE id = ? AND billed_mc IS NULL`, args: [Math.max(0, netChargeMc), jobId] })\n return\n }\n await db.batch([\n { sql: 'UPDATE users SET balance_mc = balance_mc + ? WHERE id = ?', args: [refundMc, userId] },\n { sql: 'INSERT INTO ledger (user_id, amount_mc, operation, description) VALUES (?, ?, ?, ?)', args: [userId, refundMc, LedgerOperation.EXTRACT_SITE_REFUND, reference] },\n { sql: `UPDATE site_extract_jobs SET billed_mc = ?, updated_at = datetime('now') WHERE id = ? AND billed_mc IS NULL`, args: [Math.max(0, netChargeMc), jobId] },\n ])\n}\n"],"mappings":"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","names":[]}
|