mcp-scraper 0.33.6 → 0.34.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 +2 -2
- package/dist/bin/api-server.cjs +13558 -12516
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +13 -2
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +14 -4
- 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 +117 -7
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +7 -7
- package/dist/bin/paa-harvest.cjs +128 -13
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +4 -4
- package/dist/{chunk-DUS4ENOY.js → chunk-2EDFOQD7.js} +2 -2
- package/dist/{chunk-DUS4ENOY.js.map → chunk-2EDFOQD7.js.map} +1 -1
- package/dist/{chunk-C2OD4ELT.js → chunk-3HBPKR5G.js} +2 -2
- package/dist/{chunk-A54ELKJK.js → chunk-4KQVIYIH.js} +139 -17
- package/dist/chunk-4KQVIYIH.js.map +1 -0
- package/dist/{chunk-AIK7WQD5.js → chunk-62DQAWPF.js} +141 -3
- package/dist/chunk-62DQAWPF.js.map +1 -0
- package/dist/{chunk-V73MPRU6.js → chunk-CB5C3BPB.js} +17 -1
- package/dist/chunk-CB5C3BPB.js.map +1 -0
- package/dist/{chunk-6ZUK4H66.js → chunk-J32XSMJI.js} +117 -8
- package/dist/chunk-J32XSMJI.js.map +1 -0
- package/dist/{chunk-LKIP7VDN.js → chunk-JBSGBSGT.js} +46 -3
- package/dist/chunk-JBSGBSGT.js.map +1 -0
- package/dist/chunk-NFMIHEYE.js +7 -0
- package/dist/chunk-NFMIHEYE.js.map +1 -0
- package/dist/{chunk-XL6YIWJ3.js → chunk-SUOHUXQS.js} +3 -3
- package/dist/{chunk-WJJTGRK4.js → chunk-V36LS5YV.js} +2 -2
- package/dist/{chunk-AT2PFWHW.js → chunk-ZID3WQID.js} +2 -2
- package/dist/{db-5SZQUI7A.js → db-YAI5AQOI.js} +16 -2
- package/dist/{extract-bundle-YNXTFCC3.js → extract-bundle-GPZRLBVY.js} +2 -2
- package/dist/index.cjs +128 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +4 -4
- package/dist/{server-SHOYO52X.js → server-LKVPEQFE.js} +1386 -778
- package/dist/server-LKVPEQFE.js.map +1 -0
- package/dist/{site-extract-repository-ZDTO7ODZ.js → site-extract-repository-JHMVHENZ.js} +4 -4
- package/dist/{worker-BJ64GCDE.js → worker-ZZHSYI3Y.js} +7 -7
- package/docs/mcp-tool-manifest.generated.json +213 -3
- package/package.json +1 -1
- package/dist/chunk-6ZUK4H66.js.map +0 -1
- package/dist/chunk-A54ELKJK.js.map +0 -1
- package/dist/chunk-AIK7WQD5.js.map +0 -1
- package/dist/chunk-F65IIUHI.js +0 -7
- package/dist/chunk-F65IIUHI.js.map +0 -1
- package/dist/chunk-LKIP7VDN.js.map +0 -1
- package/dist/chunk-V73MPRU6.js.map +0 -1
- package/dist/server-SHOYO52X.js.map +0 -1
- /package/dist/{chunk-C2OD4ELT.js.map → chunk-3HBPKR5G.js.map} +0 -0
- /package/dist/{chunk-XL6YIWJ3.js.map → chunk-SUOHUXQS.js.map} +0 -0
- /package/dist/{chunk-WJJTGRK4.js.map → chunk-V36LS5YV.js.map} +0 -0
- /package/dist/{chunk-AT2PFWHW.js.map → chunk-ZID3WQID.js.map} +0 -0
- /package/dist/{db-5SZQUI7A.js.map → db-YAI5AQOI.js.map} +0 -0
- /package/dist/{extract-bundle-YNXTFCC3.js.map → extract-bundle-GPZRLBVY.js.map} +0 -0
- /package/dist/{site-extract-repository-ZDTO7ODZ.js.map → site-extract-repository-JHMVHENZ.js.map} +0 -0
- /package/dist/{worker-BJ64GCDE.js.map → worker-ZZHSYI3Y.js.map} +0 -0
|
@@ -12,17 +12,17 @@ import {
|
|
|
12
12
|
browserServiceProfileSaveChanges,
|
|
13
13
|
recordVendorUsage,
|
|
14
14
|
vendorCostUsd
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-V36LS5YV.js";
|
|
16
16
|
import {
|
|
17
17
|
DEFAULT_MAPS_PROXY_MODE,
|
|
18
18
|
DEFAULT_PROXY_MODE
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-CB5C3BPB.js";
|
|
20
20
|
import {
|
|
21
21
|
PACKAGE_VERSION
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-NFMIHEYE.js";
|
|
23
23
|
import {
|
|
24
24
|
MC_PER_CREDIT
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-JBSGBSGT.js";
|
|
26
26
|
import {
|
|
27
27
|
sanitizeVendorName
|
|
28
28
|
} from "./chunk-M2S27J6Z.js";
|
|
@@ -343,8 +343,11 @@ seam is noted so you can chain them.
|
|
|
343
343
|
url the user gives).
|
|
344
344
|
|
|
345
345
|
## Reddit
|
|
346
|
-
-
|
|
347
|
-
Reddit's bot wall itself (no login needed). Find threads first with \`search_serp\`.
|
|
346
|
+
- Read ONE known reddit.com thread/post URL -> **reddit_thread**. Returns the post plus its comment tree and
|
|
347
|
+
handles Reddit's bot wall itself (no login needed). Find threads first with \`search_serp\` or \`reddit_trending\`.
|
|
348
|
+
- DISCOVER what a niche is talking about (topic, no known thread) -> **reddit_trending** (takes a topic, optional
|
|
349
|
+
subreddit; returns the last 30 days' top threads ranked by engagement plus the questions people asked \u2014
|
|
350
|
+
feed winning \`rankedThreads[].url\` values into \`reddit_thread\` for the full comment tree).
|
|
348
351
|
|
|
349
352
|
## Other sites & logins (browser agent)
|
|
350
353
|
For an arbitrary site or a logged-in dashboard with no dedicated tool, use the browser_* agent. **First
|
|
@@ -1956,6 +1959,65 @@ ${commentMd || "_No comments captured._"}`
|
|
|
1956
1959
|
}
|
|
1957
1960
|
};
|
|
1958
1961
|
}
|
|
1962
|
+
function formatRedditTrending(raw, input) {
|
|
1963
|
+
const parsed = parseData(raw);
|
|
1964
|
+
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
1965
|
+
const d = parsed.data;
|
|
1966
|
+
const threads = d.rankedThreads ?? [];
|
|
1967
|
+
const questions = (d.questions ?? []).filter((q) => q.question);
|
|
1968
|
+
const totals = {
|
|
1969
|
+
threads: d.totals?.threads ?? threads.length,
|
|
1970
|
+
upvotes: d.totals?.upvotes ?? 0,
|
|
1971
|
+
comments: d.totals?.comments ?? 0
|
|
1972
|
+
};
|
|
1973
|
+
const subreddit = d.subreddit ?? input.subreddit ?? null;
|
|
1974
|
+
const threadBlocks = threads.map((t, i) => [
|
|
1975
|
+
`### ${i + 1}. ${t.title || "Untitled"}`,
|
|
1976
|
+
`**${t.subreddit || "r/?"}** \xB7 ${t.score ?? 0} upvotes \xB7 ${t.commentCount ?? 0} comments \xB7 engagement ${t.engagementScore ?? 0}${t.ageText ? ` \xB7 ${t.ageText}` : ""}`,
|
|
1977
|
+
t.url ? `${t.url}` : "",
|
|
1978
|
+
t.topQuestions?.length ? `**Top questions:**
|
|
1979
|
+
${t.topQuestions.map((q) => `- ${q}`).join("\n")}` : ""
|
|
1980
|
+
].filter(Boolean).join("\n")).join("\n\n");
|
|
1981
|
+
const questionList = questions.map((q) => `- ${q.question}${q.threadUrl ? `
|
|
1982
|
+
${q.threadUrl}` : ""}`).join("\n");
|
|
1983
|
+
const full = [
|
|
1984
|
+
`# Reddit Trending: "${d.topic || input.topic}"${subreddit ? ` in r/${subreddit}` : ""}`,
|
|
1985
|
+
`**${totals.threads} threads \xB7 ${totals.upvotes} upvotes \xB7 ${totals.comments} comments** \xB7 last ${d.window === "7d" ? "week" : "month"} \xB7 ${d.threadsScraped ?? 0} of ${d.candidatesFound ?? threads.length} discovered scraped${d.partial ? " (partial \u2014 hit the time limit)" : ""}`,
|
|
1986
|
+
`
|
|
1987
|
+
## Ranked threads
|
|
1988
|
+
${threadBlocks || "_No threads found._"}`,
|
|
1989
|
+
`
|
|
1990
|
+
## Questions people asked
|
|
1991
|
+
${questionList || "_No questions extracted._"}`,
|
|
1992
|
+
`
|
|
1993
|
+
---
|
|
1994
|
+
\u{1F4A1} Deep-dive a winner's full comment tree: pass its url to \`reddit_thread\``
|
|
1995
|
+
].join("\n");
|
|
1996
|
+
return {
|
|
1997
|
+
...oneBlock(full),
|
|
1998
|
+
structuredContent: {
|
|
1999
|
+
topic: d.topic ?? input.topic,
|
|
2000
|
+
subreddit,
|
|
2001
|
+
window: d.window ?? "30d",
|
|
2002
|
+
totals,
|
|
2003
|
+
rankedThreads: threads.map((t) => ({
|
|
2004
|
+
title: t.title ?? "",
|
|
2005
|
+
url: t.url ?? "",
|
|
2006
|
+
subreddit: t.subreddit ?? "",
|
|
2007
|
+
score: Number(t.score ?? 0),
|
|
2008
|
+
commentCount: Number(t.commentCount ?? 0),
|
|
2009
|
+
engagementScore: Number(t.engagementScore ?? 0),
|
|
2010
|
+
ageText: t.ageText ?? "",
|
|
2011
|
+
topQuestions: t.topQuestions ?? []
|
|
2012
|
+
})),
|
|
2013
|
+
questions: questions.map((q) => ({ question: q.question ?? "", threadUrl: q.threadUrl ?? "" })),
|
|
2014
|
+
threadsScraped: Number(d.threadsScraped ?? 0),
|
|
2015
|
+
candidatesFound: Number(d.candidatesFound ?? threads.length),
|
|
2016
|
+
partial: Boolean(d.partial),
|
|
2017
|
+
searchQuery: d.searchQuery ?? ""
|
|
2018
|
+
}
|
|
2019
|
+
};
|
|
2020
|
+
}
|
|
1959
2021
|
function formatFacebookAdSearch(raw, input) {
|
|
1960
2022
|
const parsed = parseData(raw);
|
|
1961
2023
|
if ("error" in parsed) return { content: [{ type: "text", text: parsed.error }], isError: true };
|
|
@@ -3553,6 +3615,14 @@ var RedditThreadInputSchema = {
|
|
|
3553
3615
|
url: z.string().min(1).describe("A reddit.com thread/post URL (www, old, new Reddit, or redd.it)."),
|
|
3554
3616
|
maxComments: z.number().int().min(1).max(2e3).optional().describe("Optional cap on comments returned. Omit to return all captured comments.")
|
|
3555
3617
|
};
|
|
3618
|
+
var RedditTrendingInputSchema = {
|
|
3619
|
+
topic: z.string().min(1).describe('Topic to scan, in plain words (e.g. "crm for small business"). Not a URL \u2014 pass a known thread URL to reddit_thread instead.'),
|
|
3620
|
+
subreddit: z.string().min(1).optional().describe('Bare subreddit name to scope the scan to one community, e.g. "SEO" (no r/ prefix, no URL). Omit to scan all of Reddit.'),
|
|
3621
|
+
window: z.enum(["week", "month"]).default("month").describe('How recent the threads must be: "week" or "month" (default). Applied via a Google time filter over reddit.com, so it reflects genuine recency.'),
|
|
3622
|
+
maxThreads: z.number().int().min(1).max(40).default(20).describe("How many discovered threads to scrape and rank. Default 20 (scrape-all). Each scraped thread is billed like reddit_thread + its comments, so lower this to cap cost; raise toward 40 for a wider sweep. Scraping runs in parallel and stops early if it nears the request time limit (partial:true in the response)."),
|
|
3623
|
+
includeComments: z.boolean().default(true).describe("Scrape each discovered thread for real upvotes, comments, and the questions people asked, then rank by engagement. Set false for a fast, cheap discovery-only sweep \u2014 returns the discovered threads (title + url) in relevance order with NO engagement stats and NO per-thread billing, so you can then call reddit_thread on the ones you want."),
|
|
3624
|
+
maxCommentsPerThread: z.number().int().min(1).max(200).default(50).describe("Comments captured per scraped thread when includeComments is true. Default 50. Billed per captured comment.")
|
|
3625
|
+
};
|
|
3556
3626
|
var VideoFrameAnalysisInputSchema = {
|
|
3557
3627
|
sourceUrl: z.string().min(1).describe("A YouTube, Facebook, Instagram, TikTok, or Vimeo URL (downloaded automatically), or a direct video file URL (.mp4/.webm/.mov). Videos up to 30 minutes are supported."),
|
|
3558
3628
|
intervalS: z.number().min(1).max(30).optional().describe("Preferred seconds between sampled frames (1-30, default 2). Automatically widened for long videos so the whole duration is covered within the frame budget."),
|
|
@@ -4140,6 +4210,34 @@ var RedditThreadOutputSchema = {
|
|
|
4140
4210
|
body: z.string()
|
|
4141
4211
|
}))
|
|
4142
4212
|
};
|
|
4213
|
+
var RedditTrendingOutputSchema = {
|
|
4214
|
+
topic: z.string(),
|
|
4215
|
+
subreddit: NullableString,
|
|
4216
|
+
window: z.string(),
|
|
4217
|
+
totals: z.object({
|
|
4218
|
+
threads: z.number().int().min(0),
|
|
4219
|
+
upvotes: z.number().int().min(0),
|
|
4220
|
+
comments: z.number().int().min(0)
|
|
4221
|
+
}),
|
|
4222
|
+
rankedThreads: z.array(z.object({
|
|
4223
|
+
title: z.string(),
|
|
4224
|
+
url: z.string(),
|
|
4225
|
+
subreddit: z.string(),
|
|
4226
|
+
score: z.number().int().min(0),
|
|
4227
|
+
commentCount: z.number().int().min(0),
|
|
4228
|
+
engagementScore: z.number().int().min(0),
|
|
4229
|
+
ageText: z.string(),
|
|
4230
|
+
topQuestions: z.array(z.string())
|
|
4231
|
+
})),
|
|
4232
|
+
questions: z.array(z.object({
|
|
4233
|
+
question: z.string(),
|
|
4234
|
+
threadUrl: z.string()
|
|
4235
|
+
})),
|
|
4236
|
+
threadsScraped: z.number().int().min(0),
|
|
4237
|
+
candidatesFound: z.number().int().min(0),
|
|
4238
|
+
partial: z.boolean(),
|
|
4239
|
+
searchQuery: z.string()
|
|
4240
|
+
};
|
|
4143
4241
|
var FacebookPageIntelOutputSchema = {
|
|
4144
4242
|
advertiserName: NullableString,
|
|
4145
4243
|
inputMode: z.enum(["pageId", "libraryId", "query"]),
|
|
@@ -4510,7 +4608,8 @@ var SearchSerpInputSchema = {
|
|
|
4510
4608
|
proxyMode: z.enum(["configured", "none"]).default(DEFAULT_PROXY_MODE).describe("Leave unset for the default route. Country/region localization comes from gl/hl plus the city or region in the query."),
|
|
4511
4609
|
proxyZip: z.string().regex(/^\d{5}$/).optional().describe("Optional US ZIP override."),
|
|
4512
4610
|
debug: z.boolean().default(false).describe("Include sanitized diagnostics for debugging."),
|
|
4513
|
-
pages: z.number().int().min(1).max(2).default(1).describe("Number of result pages to fetch (1\u20132).")
|
|
4611
|
+
pages: z.number().int().min(1).max(2).default(1).describe("Number of result pages to fetch (1\u20132)."),
|
|
4612
|
+
recency: z.enum(["day", "week", "month", "year"]).optional().describe('Restrict results to a recent time window (Google "past day/week/month/year" filter). Omit for all-time. Useful for "what is being said this week" style queries; pairs well with a site: operator in the query.')
|
|
4514
4613
|
};
|
|
4515
4614
|
var CaptureSerpSnapshotInputSchema = {
|
|
4516
4615
|
query: z.string().min(1).describe('Search query to capture. KEEP the place in the query text for localized captures (e.g. "botox clinic austin tx") and also set location.'),
|
|
@@ -5438,6 +5537,13 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
5438
5537
|
outputSchema: recordOutputSchema("reddit_thread", RedditThreadOutputSchema),
|
|
5439
5538
|
annotations: liveWebToolAnnotations("Reddit Thread + Comments")
|
|
5440
5539
|
}, async (input) => formatRedditThread(await executor.redditThread(input), input));
|
|
5540
|
+
server.registerTool("reddit_trending", {
|
|
5541
|
+
title: "Reddit Trending",
|
|
5542
|
+
description: "Discover the top Reddit conversations about a topic from the last week or month: finds relevant recent threads via a Google site:reddit.com search (optionally scoped to one subreddit), scrapes them for real upvotes, comments, and the questions people asked, and ranks by engagement (upvotes + 2x comments). Scraping runs in parallel across the discovered threads; set includeComments:false for a fast, cheap discovery-only sweep (relevant thread list, no engagement stats, no per-thread billing) and then read the ones you want with reddit_thread. Not for reading one known thread URL \u2014 use reddit_thread for that.",
|
|
5543
|
+
inputSchema: RedditTrendingInputSchema,
|
|
5544
|
+
outputSchema: recordOutputSchema("reddit_trending", RedditTrendingOutputSchema),
|
|
5545
|
+
annotations: liveWebToolAnnotations("Reddit Trending")
|
|
5546
|
+
}, async (input) => formatRedditTrending(await executor.redditTrending(input), input));
|
|
5441
5547
|
server.registerTool("video_frame_analysis", {
|
|
5442
5548
|
title: "Video Breakdown (frame-by-frame + transcript)",
|
|
5443
5549
|
description: "Produce a deep frame-by-frame + transcript breakdown of a video \u2014 pacing, hook, visual style, and how to replicate it. Accepts a YouTube, Facebook, Instagram, TikTok, or Vimeo URL directly (downloaded for you), or a direct video file URL (.mp4/.webm/.mov). Costs $1 per 120 frames requested (max 480 = $4; refunded down if the video can't use them; refunded fully on failure): returns a runId immediately; poll video_frame_analysis_status until done. Videos up to 30 minutes.",
|
|
@@ -5951,6 +6057,9 @@ var HttpMcpToolExecutor = class {
|
|
|
5951
6057
|
redditThread(input) {
|
|
5952
6058
|
return this.call("/reddit/thread", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
5953
6059
|
}
|
|
6060
|
+
redditTrending(input) {
|
|
6061
|
+
return this.call("/reddit/trending", input, this.httpTimeoutOverrideMs ?? 3e5);
|
|
6062
|
+
}
|
|
5954
6063
|
videoFrameAnalysis(input) {
|
|
5955
6064
|
return this.call("/video/analyze", input);
|
|
5956
6065
|
}
|
|
@@ -10153,4 +10262,4 @@ export {
|
|
|
10153
10262
|
MEMORY_TOOL_SCHEMAS,
|
|
10154
10263
|
registerMemoryMcpTools
|
|
10155
10264
|
};
|
|
10156
|
-
//# sourceMappingURL=chunk-
|
|
10265
|
+
//# sourceMappingURL=chunk-J32XSMJI.js.map
|