mcp-scraper 0.3.42 → 0.3.45
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/dist/bin/api-server.cjs +1558 -1312
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +3 -3
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +283 -224
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +2 -2
- package/dist/{chunk-RXJHXBGG.js → chunk-BRVX6RDN.js} +21 -4
- package/dist/chunk-BRVX6RDN.js.map +1 -0
- package/dist/{chunk-KPF64WST.js → chunk-E7BZFMWB.js} +284 -225
- package/dist/chunk-E7BZFMWB.js.map +1 -0
- package/dist/{chunk-DVRPXPYH.js → chunk-FUVQR6GK.js} +14 -3
- package/dist/chunk-FUVQR6GK.js.map +1 -0
- package/dist/chunk-NVTFLLEG.js +7 -0
- package/dist/chunk-NVTFLLEG.js.map +1 -0
- package/dist/{chunk-GMTS35L6.js → chunk-RXNHY3TF.js} +2 -2
- package/dist/{db-LYQENFPW.js → db-H3S3M6KK.js} +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{server-CZT7EULY.js → server-MKUN6NQZ.js} +513 -370
- package/dist/server-MKUN6NQZ.js.map +1 -0
- package/dist/{worker-FNSBPP7Y.js → worker-4CVMSUZR.js} +4 -4
- package/package.json +4 -2
- package/dist/chunk-DVRPXPYH.js.map +0 -1
- package/dist/chunk-KPF64WST.js.map +0 -1
- package/dist/chunk-OUZZNW3I.js +0 -7
- package/dist/chunk-OUZZNW3I.js.map +0 -1
- package/dist/chunk-RXJHXBGG.js.map +0 -1
- package/dist/server-CZT7EULY.js.map +0 -1
- /package/dist/{chunk-GMTS35L6.js.map → chunk-RXNHY3TF.js.map} +0 -0
- /package/dist/{db-LYQENFPW.js.map → db-H3S3M6KK.js.map} +0 -0
- /package/dist/{worker-FNSBPP7Y.js.map → worker-4CVMSUZR.js.map} +0 -0
|
@@ -264,6 +264,12 @@ var HttpMcpToolExecutor = class {
|
|
|
264
264
|
redditThread(input) {
|
|
265
265
|
return this.call("/reddit/thread", input, this.httpTimeoutOverrideMs ?? 24e4);
|
|
266
266
|
}
|
|
267
|
+
videoFrameAnalysis(input) {
|
|
268
|
+
return this.call("/video/analyze", input);
|
|
269
|
+
}
|
|
270
|
+
videoFrameAnalysisStatus(input) {
|
|
271
|
+
return this.call("/video/status", input);
|
|
272
|
+
}
|
|
267
273
|
facebookAdTranscribe(input) {
|
|
268
274
|
return this.call("/facebook/transcribe", input);
|
|
269
275
|
}
|
|
@@ -468,7 +474,7 @@ render();
|
|
|
468
474
|
}
|
|
469
475
|
|
|
470
476
|
// src/version.ts
|
|
471
|
-
var PACKAGE_VERSION = "0.3.
|
|
477
|
+
var PACKAGE_VERSION = "0.3.45";
|
|
472
478
|
|
|
473
479
|
// src/mcp/browser-agent-tool-schemas.ts
|
|
474
480
|
var import_zod = require("zod");
|
|
@@ -488,18 +494,18 @@ var BrowserOpenInputSchema = {
|
|
|
488
494
|
label: import_zod.z.string().optional().describe("Optional human label for this session, shown in the watch console."),
|
|
489
495
|
url: import_zod.z.string().url().optional().describe("Optional URL to navigate to immediately after opening."),
|
|
490
496
|
profile: import_zod.z.string().optional().describe("Optional saved hosted profile name to load a logged-in session for a site."),
|
|
491
|
-
save_profile_changes: import_zod.z.boolean().optional().describe("Persist cookies
|
|
492
|
-
timeout_seconds: import_zod.z.number().int().min(60).max(259200).optional().describe("
|
|
497
|
+
save_profile_changes: import_zod.z.boolean().optional().describe("Persist cookies/storage back to the named profile on close. Avoid parallel sessions writing to the same profile."),
|
|
498
|
+
timeout_seconds: import_zod.z.number().int().min(60).max(259200).optional().describe("Session lifetime before auto-termination. Defaults to 600.")
|
|
493
499
|
};
|
|
494
500
|
var BrowserProfileConnectInputSchema = {
|
|
495
|
-
email: import_zod.z.string().optional().describe("Account email for the login
|
|
496
|
-
profile: import_zod.z.string().optional().describe("Profile to add this login to. Omit to derive
|
|
497
|
-
domain: import_zod.z.string().optional().describe("Site to log into, e.g. chatgpt.com, claude.ai, reddit.com. Defaults to chatgpt.com.
|
|
498
|
-
login_url: import_zod.z.string().url().optional().describe("Login page for the domain. Defaults to https://<domain
|
|
499
|
-
url: import_zod.z.string().url().optional().describe("Deprecated alias for login_url.
|
|
500
|
-
note: import_zod.z.string().optional().describe(
|
|
501
|
+
email: import_zod.z.string().optional().describe("Account email for the login. Derives a stable profile name and is recorded as a note. Does NOT import existing cookies \u2014 the user signs in fresh."),
|
|
502
|
+
profile: import_zod.z.string().optional().describe("Profile to add this login to. Omit to derive from email. A single profile holds MANY logins \u2014 pass the same name with a different domain to stack accounts."),
|
|
503
|
+
domain: import_zod.z.string().optional().describe("Site to log into, e.g. chatgpt.com, claude.ai, reddit.com. Defaults to chatgpt.com."),
|
|
504
|
+
login_url: import_zod.z.string().url().optional().describe("Login page for the domain. Defaults to https://<domain>/."),
|
|
505
|
+
url: import_zod.z.string().url().optional().describe("Deprecated alias for login_url."),
|
|
506
|
+
note: import_zod.z.string().optional().describe("Free-text note describing this login. Surfaced by browser_profile_list."),
|
|
501
507
|
label: import_zod.z.string().optional().describe("Optional human label for this sign-in setup session."),
|
|
502
|
-
timeout_seconds: import_zod.z.number().int().min(60).max(259200).optional().describe("
|
|
508
|
+
timeout_seconds: import_zod.z.number().int().min(60).max(259200).optional().describe("Sign-in session lifetime before auto-termination. Defaults to 600.")
|
|
503
509
|
};
|
|
504
510
|
var BrowserProfileListInputSchema = {
|
|
505
511
|
profile: import_zod.z.string().optional().describe("Profile whose saved logins to list. Omit to derive from email."),
|
|
@@ -508,7 +514,7 @@ var BrowserProfileListInputSchema = {
|
|
|
508
514
|
connection_id: import_zod.z.string().optional().describe("A specific login connection id returned by browser_profile_connect, to poll just that one.")
|
|
509
515
|
};
|
|
510
516
|
var BrowserSessionInputSchema = {
|
|
511
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
517
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.")
|
|
512
518
|
};
|
|
513
519
|
var BrowserLocateTargetSchema = import_zod.z.object({
|
|
514
520
|
name: import_zod.z.string().optional().describe("Optional label for this target, echoed in the result."),
|
|
@@ -520,94 +526,94 @@ var BrowserLocateTargetSchema = import_zod.z.object({
|
|
|
520
526
|
message: "target requires selector or text"
|
|
521
527
|
});
|
|
522
528
|
var BrowserLocateInputSchema = {
|
|
523
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
529
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
524
530
|
targets: import_zod.z.array(BrowserLocateTargetSchema).min(1).max(20).describe("DOM targets to locate in the current viewport. Use selectors for exact elements, or text for visible text ranges.")
|
|
525
531
|
};
|
|
526
532
|
var BrowserGotoInputSchema = {
|
|
527
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
533
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
528
534
|
url: import_zod.z.string().url().describe("URL to navigate the browser to.")
|
|
529
535
|
};
|
|
530
536
|
var BrowserClickInputSchema = {
|
|
531
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
537
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
532
538
|
x: import_zod.z.number().describe("X coordinate to click, in screenshot pixels. Use only coordinates from the latest browser_screenshot, browser_read, or browser_locate result; do not guess."),
|
|
533
539
|
y: import_zod.z.number().describe("Y coordinate to click, in screenshot pixels. Use only coordinates from the latest browser_screenshot, browser_read, or browser_locate result; do not guess."),
|
|
534
540
|
button: import_zod.z.enum(["left", "right", "middle"]).default("left").describe("Mouse button."),
|
|
535
541
|
num_clicks: import_zod.z.number().int().min(1).max(3).optional().describe("Number of clicks, e.g. 2 for double-click.")
|
|
536
542
|
};
|
|
537
543
|
var BrowserTypeInputSchema = {
|
|
538
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
544
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
539
545
|
text: import_zod.z.string().describe("Text to type at the current focus. Click a field first to focus it."),
|
|
540
546
|
delay: import_zod.z.number().int().min(0).max(500).optional().describe("Optional per-keystroke delay in ms for human-like typing.")
|
|
541
547
|
};
|
|
542
548
|
var BrowserScrollInputSchema = {
|
|
543
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
549
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
544
550
|
delta_y: import_zod.z.number().default(5).describe("Vertical scroll in wheel units. Positive scrolls down, negative up."),
|
|
545
551
|
delta_x: import_zod.z.number().default(0).describe("Horizontal scroll in wheel units."),
|
|
546
552
|
x: import_zod.z.number().optional().describe("X position to scroll at. Defaults to screen center."),
|
|
547
553
|
y: import_zod.z.number().optional().describe("Y position to scroll at. Defaults to screen center.")
|
|
548
554
|
};
|
|
549
555
|
var BrowserPressInputSchema = {
|
|
550
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
556
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
551
557
|
keys: import_zod.z.array(import_zod.z.string()).min(1).describe('Keys or combinations to press, e.g. ["Return"], ["Ctrl+a"], ["Ctrl+Shift+Tab"].')
|
|
552
558
|
};
|
|
553
559
|
var BrowserReplayStopInputSchema = {
|
|
554
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
555
|
-
replay_id: import_zod.z.string().describe("The replay id returned by browser_replay_start or browser_list_replays.
|
|
560
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
561
|
+
replay_id: import_zod.z.string().describe("The replay id returned by browser_replay_start or browser_list_replays.")
|
|
556
562
|
};
|
|
557
563
|
var BrowserReplayDownloadInputSchema = {
|
|
558
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
559
|
-
replay_id: import_zod.z.string().describe("The replay id returned by browser_replay_start or browser_list_replays.
|
|
564
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
565
|
+
replay_id: import_zod.z.string().describe("The replay id returned by browser_replay_start or browser_list_replays."),
|
|
560
566
|
filename: import_zod.z.string().optional().describe("Optional local MP4 filename. Defaults to a timestamped replay filename.")
|
|
561
567
|
};
|
|
562
568
|
var BrowserReplayAnnotationSchema = import_zod.z.object({
|
|
563
|
-
type: import_zod.z.enum(["box", "circle", "underline", "arrow", "label"]).default("box").describe("Annotation style
|
|
564
|
-
start_seconds: import_zod.z.number().min(0).default(0).describe("When the annotation should appear
|
|
565
|
-
end_seconds: import_zod.z.number().min(0).optional().describe("When
|
|
566
|
-
left: import_zod.z.number().optional().describe("Target left edge in
|
|
567
|
-
top: import_zod.z.number().optional().describe("Target top edge in
|
|
568
|
-
width: import_zod.z.number().positive().optional().describe("Target width in
|
|
569
|
-
height: import_zod.z.number().positive().optional().describe("Target height in
|
|
570
|
-
x: import_zod.z.number().optional().describe("Point target x coordinate
|
|
571
|
-
y: import_zod.z.number().optional().describe("Point target y coordinate
|
|
572
|
-
from_x: import_zod.z.number().optional().describe("Arrow start x coordinate
|
|
573
|
-
from_y: import_zod.z.number().optional().describe("Arrow start y coordinate
|
|
574
|
-
to_x: import_zod.z.number().optional().describe("Arrow
|
|
575
|
-
to_y: import_zod.z.number().optional().describe("Arrow
|
|
576
|
-
label: import_zod.z.string().max(120).optional().describe("Optional text callout
|
|
577
|
-
color: import_zod.z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe("Annotation color as hex,
|
|
569
|
+
type: import_zod.z.enum(["box", "circle", "underline", "arrow", "label"]).default("box").describe("Annotation style."),
|
|
570
|
+
start_seconds: import_zod.z.number().min(0).default(0).describe("When the annotation should appear."),
|
|
571
|
+
end_seconds: import_zod.z.number().min(0).optional().describe("When it disappears. Defaults to 2s after start_seconds."),
|
|
572
|
+
left: import_zod.z.number().optional().describe("Target left edge in screenshot pixels (element.left)."),
|
|
573
|
+
top: import_zod.z.number().optional().describe("Target top edge in screenshot pixels (element.top)."),
|
|
574
|
+
width: import_zod.z.number().positive().optional().describe("Target width in screenshot pixels (element.width)."),
|
|
575
|
+
height: import_zod.z.number().positive().optional().describe("Target height in screenshot pixels (element.height)."),
|
|
576
|
+
x: import_zod.z.number().optional().describe("Point target x coordinate when no box is available."),
|
|
577
|
+
y: import_zod.z.number().optional().describe("Point target y coordinate when no box is available."),
|
|
578
|
+
from_x: import_zod.z.number().optional().describe("Arrow start x coordinate. Defaults near the target."),
|
|
579
|
+
from_y: import_zod.z.number().optional().describe("Arrow start y coordinate. Defaults near the target."),
|
|
580
|
+
to_x: import_zod.z.number().optional().describe("Arrow end x coordinate. Defaults to the target box center."),
|
|
581
|
+
to_y: import_zod.z.number().optional().describe("Arrow end y coordinate. Defaults to the target box center."),
|
|
582
|
+
label: import_zod.z.string().max(120).optional().describe("Optional text callout."),
|
|
583
|
+
color: import_zod.z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe("Annotation color as hex, e.g. #ff3b30."),
|
|
578
584
|
thickness: import_zod.z.number().min(1).max(24).optional().describe("Stroke thickness in pixels. Defaults to 5.")
|
|
579
585
|
});
|
|
580
586
|
var BrowserReplayMarkInputSchema = {
|
|
581
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
587
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions. A replay must already be recording."),
|
|
582
588
|
target: BrowserLocateTargetSchema.describe("The exact DOM element or text range to mark in the current viewport."),
|
|
583
|
-
type: import_zod.z.enum(["box", "circle", "underline", "arrow"]).default("box").describe("Annotation style to generate.
|
|
589
|
+
type: import_zod.z.enum(["box", "circle", "underline", "arrow"]).default("box").describe("Annotation style to generate."),
|
|
584
590
|
label: import_zod.z.string().max(120).optional().describe("Optional callout text to render near the target."),
|
|
585
|
-
color: import_zod.z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe("Annotation color as hex,
|
|
591
|
+
color: import_zod.z.string().regex(/^#?[0-9a-fA-F]{6}$/).optional().describe("Annotation color as hex, e.g. #ff3b30."),
|
|
586
592
|
thickness: import_zod.z.number().min(1).max(24).optional().describe("Stroke thickness in pixels. Defaults to 5."),
|
|
587
593
|
padding: import_zod.z.number().min(0).max(80).default(8).describe("Pixels to expand the DOM bounds so the highlight does not touch the text edge."),
|
|
588
|
-
start_offset_seconds: import_zod.z.number().min(-5).max(10).default(-0.25).describe("Offset from the current replay time
|
|
589
|
-
duration_seconds: import_zod.z.number().min(0.5).max(30).default(4).describe("How long the
|
|
594
|
+
start_offset_seconds: import_zod.z.number().min(-5).max(10).default(-0.25).describe("Offset from the current replay time; negative appears just before the mark action."),
|
|
595
|
+
duration_seconds: import_zod.z.number().min(0.5).max(30).default(4).describe("How long the annotation should remain visible.")
|
|
590
596
|
};
|
|
591
597
|
var BrowserReplayAnnotateInputSchema = {
|
|
592
|
-
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions.
|
|
593
|
-
replay_id: import_zod.z.string().describe("The replay id returned by browser_replay_start or browser_list_replays.
|
|
594
|
-
annotations: import_zod.z.array(BrowserReplayAnnotationSchema).min(1).max(50).describe("Timed overlay annotations
|
|
595
|
-
filename: import_zod.z.string().optional().describe("Optional output MP4 filename. Defaults to a timestamped
|
|
598
|
+
session_id: import_zod.z.string().describe("The session id returned by browser_open or browser_list_sessions."),
|
|
599
|
+
replay_id: import_zod.z.string().describe("The replay id returned by browser_replay_start or browser_list_replays."),
|
|
600
|
+
annotations: import_zod.z.array(BrowserReplayAnnotationSchema).min(1).max(50).describe("Timed overlay annotations. Prefer ones from browser_replay_mark; otherwise use exact DOM bounds from browser_locate."),
|
|
601
|
+
filename: import_zod.z.string().optional().describe("Optional output MP4 filename. Defaults to a timestamped filename."),
|
|
596
602
|
source_width: import_zod.z.number().positive().optional().describe("Width of the screenshot coordinate space used for annotations. Defaults to the replay video width."),
|
|
597
|
-
source_height: import_zod.z.number().positive().optional().describe("Height of the coordinate space
|
|
598
|
-
source_left_offset: import_zod.z.number().min(0).optional().describe("
|
|
599
|
-
source_top_offset: import_zod.z.number().min(0).optional().describe("
|
|
603
|
+
source_height: import_zod.z.number().positive().optional().describe("Height of the annotation coordinate space; if smaller than the replay video height, the browser chrome offset is inferred."),
|
|
604
|
+
source_left_offset: import_zod.z.number().min(0).optional().describe("Explicit X offset from annotation to replay video coordinates. Usually omitted."),
|
|
605
|
+
source_top_offset: import_zod.z.number().min(0).optional().describe("Explicit Y offset from annotation to replay video coordinates. Usually omitted.")
|
|
600
606
|
};
|
|
601
607
|
var BrowserListInputSchema = {
|
|
602
608
|
include_closed: import_zod.z.boolean().default(false).describe("Include closed sessions in the list.")
|
|
603
609
|
};
|
|
604
610
|
var BrowserCaptureFanoutInputSchema = {
|
|
605
|
-
session_id: import_zod.z.string().describe("
|
|
606
|
-
prompt: import_zod.z.string().optional().describe("Optional prompt to type
|
|
607
|
-
wait_ms: import_zod.z.number().int().min(0).max(18e4).optional().describe("How long to wait for the answer stream to finish
|
|
608
|
-
first_party_domain: import_zod.z.string().optional().describe("The brand/site being researched,
|
|
609
|
-
reset: import_zod.z.boolean().default(false).describe("Clear any previously buffered stream for this page before capturing.
|
|
610
|
-
export: import_zod.z.boolean().default(false).describe("
|
|
611
|
+
session_id: import_zod.z.string().describe("Session id from browser_open. Must be on chatgpt.com or claude.ai, logged in via a saved hosted profile."),
|
|
612
|
+
prompt: import_zod.z.string().optional().describe("Optional prompt to type and submit before capturing. Omit to passively capture a prompt the user just ran. Must trigger web search to produce a fan-out."),
|
|
613
|
+
wait_ms: import_zod.z.number().int().min(0).max(18e4).optional().describe("How long to wait for the answer stream to finish. Defaults to 90000 when a prompt is sent, 8000 for passive capture."),
|
|
614
|
+
first_party_domain: import_zod.z.string().optional().describe("The brand/site being researched, e.g. example.com \u2014 sources on this domain are tagged First-party/vendor."),
|
|
615
|
+
reset: import_zod.z.boolean().default(false).describe("Clear any previously buffered stream for this page before capturing."),
|
|
616
|
+
export: import_zod.z.boolean().default(false).describe("Write JSON/CSV/TSV/HTML exports to MCP_SCRAPER_OUTPUT_DIR/fanout, returning relative paths.")
|
|
611
617
|
};
|
|
612
618
|
var FanoutSourceOutput = import_zod.z.object({
|
|
613
619
|
url: import_zod.z.string(),
|
|
@@ -631,10 +637,10 @@ var BrowserCaptureFanoutOutputSchema = {
|
|
|
631
637
|
title: import_zod.z.string(),
|
|
632
638
|
rounds: import_zod.z.number().int().min(0)
|
|
633
639
|
}),
|
|
634
|
-
queries: import_zod.z.array(import_zod.z.string()).describe("Every web-search sub-query
|
|
635
|
-
browsed_urls: import_zod.z.array(FanoutSourceOutput).describe("Every researched URL
|
|
636
|
-
cited_urls: import_zod.z.array(FanoutSourceOutput).describe("
|
|
637
|
-
browsed_only: import_zod.z.array(FanoutSourceOutput).describe("Researched URLs
|
|
640
|
+
queries: import_zod.z.array(import_zod.z.string()).describe("Every web-search sub-query issued, in capture order."),
|
|
641
|
+
browsed_urls: import_zod.z.array(FanoutSourceOutput).describe("Every researched URL, cited first."),
|
|
642
|
+
cited_urls: import_zod.z.array(FanoutSourceOutput).describe("Researched URLs cited in the final answer."),
|
|
643
|
+
browsed_only: import_zod.z.array(FanoutSourceOutput).describe("Researched URLs pulled but not cited."),
|
|
638
644
|
snippets: import_zod.z.array(import_zod.z.object({ url: import_zod.z.string(), domain: import_zod.z.string(), title: import_zod.z.string(), text: import_zod.z.string() })),
|
|
639
645
|
counts: import_zod.z.object({
|
|
640
646
|
subQueries: import_zod.z.number().int().min(0),
|
|
@@ -1293,7 +1299,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1293
1299
|
"browser_profile_connect",
|
|
1294
1300
|
{
|
|
1295
1301
|
title: "Save a Site Login to a Profile",
|
|
1296
|
-
description:
|
|
1302
|
+
description: "Save a logged-in browser session so this server can reuse a site the user is signed into (ChatGPT, Claude, Reddit, any account-gated site). Returns a watch_url; the user signs in fresh (existing browser cookies are NOT imported) and cookies save to a named profile. ONE profile holds MANY logins \u2014 call again with the same profile and a different domain to stack another account. NOT for one-off scraping (use extract_url) or driving the browser (use browser_open). After sign-in, poll browser_profile_list until AUTHENTICATED, then browser_open with the profile.",
|
|
1297
1303
|
inputSchema: BrowserProfileConnectInputSchema,
|
|
1298
1304
|
outputSchema: BrowserProfileConnectOutputSchema,
|
|
1299
1305
|
annotations: annotations("Save a Site Login to a Profile")
|
|
@@ -1351,7 +1357,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1351
1357
|
"browser_profile_list",
|
|
1352
1358
|
{
|
|
1353
1359
|
title: "List Saved Logins in a Profile",
|
|
1354
|
-
description:
|
|
1360
|
+
description: "List every site login saved in a profile with its auth status (NEEDS_AUTH/AUTHENTICATED), email, and note. Use to check what's connected, or to poll a just-saved login until AUTHENTICATED. Read-only, no cost. Pass profile (or email to derive it); narrow with domain or connection_id.",
|
|
1355
1361
|
inputSchema: BrowserProfileListInputSchema,
|
|
1356
1362
|
outputSchema: BrowserProfileListOutputSchema,
|
|
1357
1363
|
annotations: annotations("List Saved Logins in a Profile", true)
|
|
@@ -1385,7 +1391,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1385
1391
|
"browser_open",
|
|
1386
1392
|
{
|
|
1387
1393
|
title: "Open Browser Session",
|
|
1388
|
-
description: "Open a direct no-proxy hosted browser session you can drive. Pass a saved profile name to load a session
|
|
1394
|
+
description: "Open a direct no-proxy hosted browser session you can drive. Pass a saved profile name to load a session already logged into that profile's sites (set one up first with browser_profile_connect). Returns a session_id used by all other browser_* tools.",
|
|
1389
1395
|
inputSchema: BrowserOpenInputSchema,
|
|
1390
1396
|
outputSchema: BrowserOpenOutputSchema,
|
|
1391
1397
|
annotations: annotations("Open Browser Session")
|
|
@@ -1419,7 +1425,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1419
1425
|
"browser_screenshot",
|
|
1420
1426
|
{
|
|
1421
1427
|
title: "See Page (Screenshot + Elements)",
|
|
1422
|
-
description: "Capture what the browser currently shows
|
|
1428
|
+
description: "Capture what the browser currently shows: a screenshot plus a text snapshot of interactive elements with x,y coordinates, page url/title, and visible text. Primary way to perceive the page; click elements by their listed x,y. If a Cloudflare/CAPTCHA challenge is visible, wait and screenshot again rather than clicking it.",
|
|
1423
1429
|
inputSchema: BrowserSessionInputSchema,
|
|
1424
1430
|
outputSchema: BrowserScreenshotOutputSchema,
|
|
1425
1431
|
annotations: annotations("See Page", true)
|
|
@@ -1451,7 +1457,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1451
1457
|
"browser_read",
|
|
1452
1458
|
{
|
|
1453
1459
|
title: "Read Page Text + Elements",
|
|
1454
|
-
description: "Return the page url, title, visible text, and
|
|
1460
|
+
description: "Return the page url, title, visible text, and interactive elements (with x,y) without an image. Cheaper than browser_screenshot when you only need to read content or find a click target.",
|
|
1455
1461
|
inputSchema: BrowserSessionInputSchema,
|
|
1456
1462
|
outputSchema: BrowserReadOutputSchema,
|
|
1457
1463
|
annotations: annotations("Read Page", true)
|
|
@@ -1475,7 +1481,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1475
1481
|
"browser_locate",
|
|
1476
1482
|
{
|
|
1477
1483
|
title: "Locate DOM Targets",
|
|
1478
|
-
description: "Locate exact visible DOM elements or text ranges
|
|
1484
|
+
description: "Locate exact visible DOM elements or text ranges and return left/top/width/height bounds in screenshot pixels. Use before drawing annotations that must circle, box, underline, or point to a real element. Prefer CSS selectors; use text when selector is unknown.",
|
|
1479
1485
|
inputSchema: BrowserLocateInputSchema,
|
|
1480
1486
|
outputSchema: BrowserLocateOutputSchema,
|
|
1481
1487
|
annotations: annotations("Locate DOM Targets", true)
|
|
@@ -1500,7 +1506,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1500
1506
|
"browser_goto",
|
|
1501
1507
|
{
|
|
1502
1508
|
title: "Navigate To URL",
|
|
1503
|
-
description: "Navigate an existing browser session to a URL
|
|
1509
|
+
description: "Navigate an existing browser session to a URL. Use browser_open first if no session exists; follow with browser_screenshot to see the loaded page.",
|
|
1504
1510
|
inputSchema: BrowserGotoInputSchema,
|
|
1505
1511
|
outputSchema: BrowserActionOutputSchema,
|
|
1506
1512
|
annotations: annotations("Navigate To URL")
|
|
@@ -1514,7 +1520,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1514
1520
|
"browser_click",
|
|
1515
1521
|
{
|
|
1516
1522
|
title: "Click",
|
|
1517
|
-
description: "Click a visible page target using screenshot pixel coordinates. Use
|
|
1523
|
+
description: "Click a visible page target using screenshot pixel coordinates. Use x/y only from the latest browser_screenshot, browser_read, or browser_locate result; do not guess coordinates.",
|
|
1518
1524
|
inputSchema: BrowserClickInputSchema,
|
|
1519
1525
|
outputSchema: BrowserActionOutputSchema,
|
|
1520
1526
|
annotations: annotations("Click")
|
|
@@ -1533,7 +1539,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1533
1539
|
"browser_type",
|
|
1534
1540
|
{
|
|
1535
1541
|
title: "Type Text",
|
|
1536
|
-
description: 'Type text into the currently focused browser field.
|
|
1542
|
+
description: 'Type text into the currently focused browser field. Click or Tab to the field first if focus is uncertain. Use browser_press with ["Return"] to submit.',
|
|
1537
1543
|
inputSchema: BrowserTypeInputSchema,
|
|
1538
1544
|
outputSchema: BrowserActionOutputSchema,
|
|
1539
1545
|
annotations: annotations("Type Text")
|
|
@@ -1547,7 +1553,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1547
1553
|
"browser_scroll",
|
|
1548
1554
|
{
|
|
1549
1555
|
title: "Scroll",
|
|
1550
|
-
description: "Scroll the page to reveal more content
|
|
1556
|
+
description: "Scroll the page to reveal more content. Positive delta_y scrolls down; negative scrolls up.",
|
|
1551
1557
|
inputSchema: BrowserScrollInputSchema,
|
|
1552
1558
|
outputSchema: BrowserActionOutputSchema,
|
|
1553
1559
|
annotations: annotations("Scroll")
|
|
@@ -1566,7 +1572,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1566
1572
|
"browser_press",
|
|
1567
1573
|
{
|
|
1568
1574
|
title: "Press Keys",
|
|
1569
|
-
description:
|
|
1575
|
+
description: "Press keyboard keys or combinations in the active browser session \u2014 submit, Escape, Tab navigation, select-all, or shortcuts. Use browser_type for text entry.",
|
|
1570
1576
|
inputSchema: BrowserPressInputSchema,
|
|
1571
1577
|
outputSchema: BrowserActionOutputSchema,
|
|
1572
1578
|
annotations: annotations("Press Keys")
|
|
@@ -1580,7 +1586,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1580
1586
|
"browser_replay_start",
|
|
1581
1587
|
{
|
|
1582
1588
|
title: "Start Recording",
|
|
1583
|
-
description: "Start recording an MP4 replay of the session. Returns replay_id
|
|
1589
|
+
description: "Start recording an MP4 replay of the session. Returns replay_id and a download_url. Stop with browser_replay_stop.",
|
|
1584
1590
|
inputSchema: BrowserSessionInputSchema,
|
|
1585
1591
|
outputSchema: BrowserReplayStartOutputSchema,
|
|
1586
1592
|
annotations: annotations("Start Recording")
|
|
@@ -1603,7 +1609,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1603
1609
|
"browser_replay_stop",
|
|
1604
1610
|
{
|
|
1605
1611
|
title: "Stop Recording",
|
|
1606
|
-
description: "Stop a replay recording and expose
|
|
1612
|
+
description: "Stop a replay recording and expose its final view_url/download_url. Use browser_replay_download to save the MP4.",
|
|
1607
1613
|
inputSchema: BrowserReplayStopInputSchema,
|
|
1608
1614
|
outputSchema: BrowserReplayStopOutputSchema,
|
|
1609
1615
|
annotations: annotations("Stop Recording")
|
|
@@ -1626,7 +1632,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1626
1632
|
"browser_list_replays",
|
|
1627
1633
|
{
|
|
1628
1634
|
title: "List Replay Videos",
|
|
1629
|
-
description: "List replay recordings for a browser session, including
|
|
1635
|
+
description: "List replay recordings for a browser session, including view_url and download_url when available.",
|
|
1630
1636
|
inputSchema: BrowserSessionInputSchema,
|
|
1631
1637
|
outputSchema: BrowserListReplaysOutputSchema,
|
|
1632
1638
|
annotations: annotations("List Replay Videos", true)
|
|
@@ -1648,7 +1654,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1648
1654
|
"browser_replay_download",
|
|
1649
1655
|
{
|
|
1650
1656
|
title: "Download Replay MP4",
|
|
1651
|
-
description: "Download a replay recording
|
|
1657
|
+
description: "Download a replay recording and save the MP4 under MCP_SCRAPER_OUTPUT_DIR/browser-replays. Use after browser_replay_stop or browser_list_replays.",
|
|
1652
1658
|
inputSchema: BrowserReplayDownloadInputSchema,
|
|
1653
1659
|
outputSchema: BrowserReplayDownloadOutputSchema,
|
|
1654
1660
|
annotations: annotations("Download Replay MP4")
|
|
@@ -1672,7 +1678,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1672
1678
|
"browser_replay_mark",
|
|
1673
1679
|
{
|
|
1674
1680
|
title: "Mark Replay Annotation",
|
|
1675
|
-
description: "While a replay is actively recording, locate one exact DOM target and return a ready-to-use annotation
|
|
1681
|
+
description: "While a replay is actively recording, locate one exact DOM target and return a ready-to-use annotation with DOM bounds and replay-relative timing, instead of guessing start_seconds or rectangles. Pass the returned annotations to browser_replay_annotate after stopping the replay.",
|
|
1676
1682
|
inputSchema: BrowserReplayMarkInputSchema,
|
|
1677
1683
|
outputSchema: BrowserReplayMarkOutputSchema,
|
|
1678
1684
|
annotations: annotations("Mark Replay Annotation", true)
|
|
@@ -1722,7 +1728,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1722
1728
|
"browser_replay_annotate",
|
|
1723
1729
|
{
|
|
1724
1730
|
title: "Annotate Replay MP4",
|
|
1725
|
-
description: "Download a browser replay MP4, render visual annotations over it, and save a new annotated MP4
|
|
1731
|
+
description: "Download a browser replay MP4, render visual annotations (circles/boxes/arrows/labels) over it, and save a new annotated MP4. Prefer annotations from browser_replay_mark for accurate timing; otherwise use exact bounds from browser_locate. Pass source_width/source_height if the replay video size differs from the screenshot coordinate space.",
|
|
1726
1732
|
inputSchema: BrowserReplayAnnotateInputSchema,
|
|
1727
1733
|
outputSchema: BrowserReplayAnnotateOutputSchema,
|
|
1728
1734
|
annotations: annotations("Annotate Replay MP4")
|
|
@@ -1764,7 +1770,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1764
1770
|
"browser_close",
|
|
1765
1771
|
{
|
|
1766
1772
|
title: "Close Browser Session",
|
|
1767
|
-
description: "Close and release a browser session when the task is done,
|
|
1773
|
+
description: "Close and release a browser session when the task is done, to end active browser billing. Use browser_list_sessions first to recover a session_id.",
|
|
1768
1774
|
inputSchema: BrowserSessionInputSchema,
|
|
1769
1775
|
outputSchema: BrowserCloseOutputSchema,
|
|
1770
1776
|
annotations: { title: "Close Browser Session", readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }
|
|
@@ -1785,7 +1791,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1785
1791
|
"browser_list_sessions",
|
|
1786
1792
|
{
|
|
1787
1793
|
title: "List Browser Sessions",
|
|
1788
|
-
description: "List browser sessions and their status, with a watch_url for each. Use
|
|
1794
|
+
description: "List browser sessions and their status, with a watch_url for each. Use to recover a session_id or decide which session to close.",
|
|
1789
1795
|
inputSchema: BrowserListInputSchema,
|
|
1790
1796
|
outputSchema: BrowserListSessionsOutputSchema,
|
|
1791
1797
|
annotations: annotations("List Browser Sessions", true)
|
|
@@ -1807,7 +1813,7 @@ function registerBrowserAgentMcpTools(server2, opts) {
|
|
|
1807
1813
|
"query_fanout_workflow",
|
|
1808
1814
|
{
|
|
1809
1815
|
title: "Capture AI Search Fan-Out",
|
|
1810
|
-
description:
|
|
1816
|
+
description: "Capture the query fan-out behind a ChatGPT or Claude web-search answer for AEO: sub-queries issued, every researched URL split into cited vs browsed-only, and top sourced sites. Returns raw structured data for you to classify and analyze. Set export=true for JSON/CSV/TSV/HTML artifacts. WRITE NOTE: passing prompt submits a real message in the user's logged-in account \u2014 only send when the user wants that; omit it to capture a prompt the user just ran. The session must already be open on chatgpt.com or claude.ai (see browser_profile_connect) while the prompt streams. NOT for Google AI Overview \u2014 use harvest_paa for that.",
|
|
1811
1817
|
inputSchema: BrowserCaptureFanoutInputSchema,
|
|
1812
1818
|
outputSchema: BrowserCaptureFanoutOutputSchema,
|
|
1813
1819
|
annotations: annotations("Capture AI Search Fan-Out")
|
|
@@ -4544,6 +4550,19 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
|
|
|
4544
4550
|
- Stand up a rank-tracking blueprint (database + cron + ingestion plan) -> **rank_tracker_workflow**.
|
|
4545
4551
|
- Find which sources an AI answer cites for a query (AEO) -> **query_fanout_workflow** (open a browser
|
|
4546
4552
|
session on chatgpt.com or claude.ai FIRST, then run it against that session).
|
|
4553
|
+
- Not sure which workflow fits a goal -> **workflow_suggest**; to just see what's available -> **workflow_list**.
|
|
4554
|
+
- Hosted/stepwise chain: **workflow_run** starts and returns \`runId\` (+ \`nextStep\` when multi-leg) ->
|
|
4555
|
+
**workflow_step** with that \`runId\` advances one leg at a time until \`done\` -> **workflow_status**
|
|
4556
|
+
re-opens a run to check state or recover artifact ids -> **workflow_artifact_read** pulls one artifact's
|
|
4557
|
+
full content by \`runId\` + \`artifactId\`.
|
|
4558
|
+
- Browser replay recording: **browser_replay_start** begins it -> **browser_replay_mark** (while
|
|
4559
|
+
recording) locates a DOM target and returns a ready-to-use timed annotation -> **browser_replay_stop**
|
|
4560
|
+
ends it -> feed collected annotations to **browser_replay_annotate**, or just
|
|
4561
|
+
**browser_replay_download** the plain MP4. **browser_list_replays** recovers replay ids.
|
|
4562
|
+
- Video breakdown is async: **video_frame_analysis** takes a DIRECT media file URL (resolve
|
|
4563
|
+
YouTube/Facebook/Instagram page URLs to one first, e.g. via \`facebook_page_intel\`'s \`videoUrl\`) and
|
|
4564
|
+
returns a \`runId\` immediately -> poll **video_frame_analysis_status** with that \`runId\` until \`status\`
|
|
4565
|
+
is \`done\`.
|
|
4547
4566
|
|
|
4548
4567
|
## Notes
|
|
4549
4568
|
- Bulk / full-site crawls: call \`extract_site\` with \`rotateProxies:true\` for blocked or rate-limited
|
|
@@ -4658,25 +4677,25 @@ var RawMapsAboutAttributeSchema = import_zod2.z.object({
|
|
|
4658
4677
|
|
|
4659
4678
|
// src/mcp/mcp-tool-schemas.ts
|
|
4660
4679
|
var HarvestPaaInputSchema = {
|
|
4661
|
-
query: import_zod3.z.string().min(1).describe('
|
|
4662
|
-
location: import_zod3.z.string().optional().describe('City, region, or country for geo
|
|
4663
|
-
maxQuestions: import_zod3.z.number().int().min(1).max(200).default(30).describe("
|
|
4664
|
-
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location or user language.
|
|
4665
|
-
hl: import_zod3.z.string().default("en").describe("Google interface/content language inferred from the user request.
|
|
4666
|
-
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use
|
|
4667
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset
|
|
4668
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe(
|
|
4669
|
-
debug: import_zod3.z.boolean().default(false).describe("Include sanitized
|
|
4680
|
+
query: import_zod3.z.string().min(1).describe('The search query. KEEP the place in the query text for localized results (e.g. "best hvac company Denver CO") and also set location \u2014 city-in-query is what localizes reliably.'),
|
|
4681
|
+
location: import_zod3.z.string().optional().describe('City, region, or country for geo signals, e.g. "Denver, CO". Set alongside city-in-query wording; alone it does NOT reliably localize.'),
|
|
4682
|
+
maxQuestions: import_zod3.z.number().int().min(1).max(200).default(30).describe("PAA questions to extract. Default 30, maximum 200. Use 10 for quick probes, 100-200 for deep research. Billed per extracted question; unused hold refunded."),
|
|
4683
|
+
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location or user language."),
|
|
4684
|
+
hl: import_zod3.z.string().default("en").describe("Google interface/content language inferred from the user request."),
|
|
4685
|
+
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only for mobile rankings."),
|
|
4686
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress). Do NOT set "location" just because a city was named \u2014 that comes from city-in-query wording. "location" forces residential geo-IP for rank-tracking fidelity, is frequently CAPTCHA-blocked, and accepts failures.'),
|
|
4687
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location".'),
|
|
4688
|
+
debug: import_zod3.z.boolean().default(false).describe("Include sanitized diagnostics for debugging localization, CAPTCHA, or proxy behavior.")
|
|
4670
4689
|
};
|
|
4671
4690
|
var ExtractUrlInputSchema = {
|
|
4672
|
-
url: import_zod3.z.string().url().describe("Public http/https URL to extract.
|
|
4673
|
-
screenshot: import_zod3.z.boolean().default(false).describe("
|
|
4674
|
-
screenshotDevice: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("Viewport for screenshot. desktop = 1440\xD7900
|
|
4675
|
-
extractBranding: import_zod3.z.boolean().default(false).describe("Extract brand colors, fonts, logo, and favicon
|
|
4676
|
-
downloadMedia: import_zod3.z.boolean().default(false).describe("Extract and download
|
|
4691
|
+
url: import_zod3.z.string().url().describe("Public http/https URL to extract."),
|
|
4692
|
+
screenshot: import_zod3.z.boolean().default(false).describe("Capture a full-page screenshot, saved to ~/Downloads/mcp-scraper/screenshots/ and returned inline."),
|
|
4693
|
+
screenshotDevice: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("Viewport for screenshot. desktop = 1440\xD7900, mobile = 390\xD7844."),
|
|
4694
|
+
extractBranding: import_zod3.z.boolean().default(false).describe("Extract brand colors, fonts, logo, and favicon via a rendered browser session."),
|
|
4695
|
+
downloadMedia: import_zod3.z.boolean().default(false).describe("Extract and download page media (images/video/audio) to ~/Downloads/mcp-scraper/media/. Ad/tracking noise is filtered automatically."),
|
|
4677
4696
|
mediaTypes: import_zod3.z.array(import_zod3.z.enum(["image", "video", "audio"])).default(["image", "video", "audio"]).describe("Which media types to download. Default all three."),
|
|
4678
|
-
allowLocal: import_zod3.z.boolean().default(false).describe("Allow localhost and private-network URLs.
|
|
4679
|
-
depositToVault: import_zod3.z.boolean().default(false).describe("
|
|
4697
|
+
allowLocal: import_zod3.z.boolean().default(false).describe("Allow localhost and private-network URLs. Local development only."),
|
|
4698
|
+
depositToVault: import_zod3.z.boolean().default(false).describe("Save the full page content into the user's MCP Memory vault server-side, embedded for semantic recall \u2014 the full body is NOT returned to chat."),
|
|
4680
4699
|
vaultName: import_zod3.z.string().trim().min(1).max(120).optional().describe("Optional vault to deposit into. Defaults to the user's personal vault.")
|
|
4681
4700
|
};
|
|
4682
4701
|
var MapSiteUrlsInputSchema = {
|
|
@@ -4684,34 +4703,34 @@ var MapSiteUrlsInputSchema = {
|
|
|
4684
4703
|
maxUrls: import_zod3.z.number().int().min(1).max(1e4).optional().describe("Maximum URLs to discover. Use 100 for normal maps, up to 10000 for a full inventory. Large maps (over 500 URLs) write the complete inventory to a local file and return only a summary plus the file path instead of the full list inline.")
|
|
4685
4704
|
};
|
|
4686
4705
|
var ExtractSiteInputSchema = {
|
|
4687
|
-
url: import_zod3.z.string().url().describe("Public website URL or domain to crawl for page CONTENT
|
|
4688
|
-
maxPages: import_zod3.z.number().int().min(1).max(1e4).optional().describe("Maximum pages to extract.
|
|
4689
|
-
rotateProxies: import_zod3.z.boolean().optional().describe("Route page fetches through rotating residential proxies
|
|
4690
|
-
rotateProxyEvery: import_zod3.z.number().int().min(1).max(100).optional().describe("When rotateProxies is on,
|
|
4691
|
-
formats: import_zod3.z.array(import_zod3.z.enum(["markdown", "links", "json", "images", "branding"])).optional().describe("
|
|
4706
|
+
url: import_zod3.z.string().url().describe("Public website URL or domain to crawl for page CONTENT (map + scrape). For a technical SEO audit use audit_site instead \u2014 this returns content only, not analysis."),
|
|
4707
|
+
maxPages: import_zod3.z.number().int().min(1).max(1e4).optional().describe("Maximum pages to extract. Bulk crawls (over 25 pages) switch to folder mode: each page saved as its own Markdown file, with a summary plus folder path returned instead of inlining content."),
|
|
4708
|
+
rotateProxies: import_zod3.z.boolean().optional().describe("Route page fetches through rotating residential proxies to defeat rate-limiting and bot blocks (403/429). Slower and pricier \u2014 use only when a site blocks normal crawling."),
|
|
4709
|
+
rotateProxyEvery: import_zod3.z.number().int().min(1).max(100).optional().describe("When rotateProxies is on, pages fetched per proxy before rotating. Default 30."),
|
|
4710
|
+
formats: import_zod3.z.array(import_zod3.z.enum(["markdown", "links", "json", "images", "branding"])).optional().describe("Per-page output formats: markdown, links, json, images are captured cheaply from HTML; branding (site-level logo/colors/fonts) requires a browser and adds time. Defaults to markdown+links.")
|
|
4692
4711
|
};
|
|
4693
4712
|
var AuditSiteInputSchema = {
|
|
4694
|
-
url: import_zod3.z.string().url().describe("Public website URL or domain
|
|
4695
|
-
maxPages: import_zod3.z.number().int().min(1).max(1e4).optional().describe("Maximum pages to crawl and audit.
|
|
4696
|
-
rotateProxies: import_zod3.z.boolean().optional().describe("Route page fetches through rotating residential proxies to defeat rate-limiting and bot blocks
|
|
4697
|
-
rotateProxyEvery: import_zod3.z.number().int().min(1).max(100).optional().describe("When rotateProxies is on,
|
|
4713
|
+
url: import_zod3.z.string().url().describe("Public website URL or domain for a full technical SEO audit (issues, link graph, indexability, headings, images). For plain content use extract_site instead."),
|
|
4714
|
+
maxPages: import_zod3.z.number().int().min(1).max(1e4).optional().describe("Maximum pages to crawl and audit. Always writes a folder of analysis files plus per-page content, returning a summary plus the folder path."),
|
|
4715
|
+
rotateProxies: import_zod3.z.boolean().optional().describe("Route page fetches through rotating residential proxies to defeat rate-limiting and bot blocks. Slower/pricier \u2014 use only when a site blocks normal crawling."),
|
|
4716
|
+
rotateProxyEvery: import_zod3.z.number().int().min(1).max(100).optional().describe("When rotateProxies is on, pages fetched per proxy before rotating. Default 30.")
|
|
4698
4717
|
};
|
|
4699
4718
|
var YoutubeHarvestInputSchema = {
|
|
4700
4719
|
mode: import_zod3.z.enum(["search", "channel"]).describe("Use search for topic/keyword requests. Use channel when the user provides @handle, channel ID, or channel URL."),
|
|
4701
4720
|
query: import_zod3.z.string().optional().describe("Required when mode is search. The YouTube search topic in the user\u2019s words."),
|
|
4702
4721
|
channelHandle: import_zod3.z.string().optional().describe("YouTube channel handle, channel ID, or URL. Examples: @mkbhd, UC..., https://youtube.com/@mkbhd."),
|
|
4703
|
-
maxVideos: import_zod3.z.number().int().min(1).max(500).default(50).describe("Number of videos to return. Default 50, maximum 500.
|
|
4722
|
+
maxVideos: import_zod3.z.number().int().min(1).max(500).default(50).describe("Number of videos to return. Default 50, maximum 500.")
|
|
4704
4723
|
};
|
|
4705
4724
|
var YoutubeTranscribeInputSchema = {
|
|
4706
4725
|
videoId: import_zod3.z.string().min(1).optional().describe("YouTube video ID, e.g. dQw4w9WgXcQ. Use only an ID returned by youtube_harvest or visible in a YouTube URL; do not invent one."),
|
|
4707
|
-
url: import_zod3.z.string().url().optional().describe("Full YouTube URL
|
|
4726
|
+
url: import_zod3.z.string().url().optional().describe("Full YouTube URL. Use when the user pasted a URL instead of an ID. Provide videoId or url.")
|
|
4708
4727
|
};
|
|
4709
4728
|
var FacebookPageIntelInputSchema = {
|
|
4710
|
-
pageId: import_zod3.z.string().optional().describe("Facebook advertiser/page ID. Use only a
|
|
4711
|
-
libraryId: import_zod3.z.string().optional().describe("Facebook Ad Library archive ID
|
|
4729
|
+
pageId: import_zod3.z.string().optional().describe("Facebook advertiser/page ID. Use only a value returned by facebook_ad_search or copied from Ad Library."),
|
|
4730
|
+
libraryId: import_zod3.z.string().optional().describe("Facebook Ad Library archive ID. Use a value returned by facebook_ad_search, or a libraryId/adArchiveId visible in Ad Library."),
|
|
4712
4731
|
query: import_zod3.z.string().optional().describe("Advertiser or brand name when pageId/libraryId is not known. One of pageId, libraryId, or query is required."),
|
|
4713
|
-
maxAds: import_zod3.z.number().int().min(1).max(200).default(50).describe("Maximum ads to inspect. Default 50, maximum 200.
|
|
4714
|
-
country: import_zod3.z.string().length(2).default("US").describe("Two-letter Ad Library country code. Default US.
|
|
4732
|
+
maxAds: import_zod3.z.number().int().min(1).max(200).default(50).describe("Maximum ads to inspect. Default 50, maximum 200."),
|
|
4733
|
+
country: import_zod3.z.string().length(2).default("US").describe("Two-letter Ad Library country code. Default US.")
|
|
4715
4734
|
};
|
|
4716
4735
|
var FacebookAdSearchInputSchema = {
|
|
4717
4736
|
query: import_zod3.z.string().min(1).describe("Advertiser, brand, competitor, niche, or keyword to search in Facebook Ad Library."),
|
|
@@ -4719,18 +4738,28 @@ var FacebookAdSearchInputSchema = {
|
|
|
4719
4738
|
maxResults: import_zod3.z.number().int().min(1).max(20).default(10).describe("Maximum advertisers to return. Default 10, maximum 20. Prefer tighter search terms over maxing this out.")
|
|
4720
4739
|
};
|
|
4721
4740
|
var RedditThreadInputSchema = {
|
|
4722
|
-
url: import_zod3.z.string().min(1).describe("A reddit.com thread/post URL (www, old,
|
|
4741
|
+
url: import_zod3.z.string().min(1).describe("A reddit.com thread/post URL (www, old, new Reddit, or redd.it)."),
|
|
4723
4742
|
maxComments: import_zod3.z.number().int().min(1).max(2e3).optional().describe("Optional cap on comments returned. Omit to return all captured comments.")
|
|
4724
4743
|
};
|
|
4744
|
+
var VideoFrameAnalysisInputSchema = {
|
|
4745
|
+
sourceUrl: import_zod3.z.string().min(1).describe("A DIRECT video file URL (.mp4/.webm/.mov). Not a YouTube/Facebook/Instagram page URL \u2014 resolve those to a direct media URL first. Videos up to 30 minutes are supported."),
|
|
4746
|
+
intervalS: import_zod3.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."),
|
|
4747
|
+
maxFrames: import_zod3.z.number().int().min(1).max(120).optional().describe("Max frames analyzed (<=120, default 120). Frames are spread evenly across the whole video."),
|
|
4748
|
+
detail: import_zod3.z.enum(["fast", "standard", "deep"]).optional().describe("Analysis depth. Default standard."),
|
|
4749
|
+
vault: import_zod3.z.string().min(1).optional().describe('Memory vault to save the finished breakdown into. Default "Library".')
|
|
4750
|
+
};
|
|
4751
|
+
var VideoFrameAnalysisStatusInputSchema = {
|
|
4752
|
+
runId: import_zod3.z.string().min(1).describe("The runId returned by video_frame_analysis.")
|
|
4753
|
+
};
|
|
4725
4754
|
var FacebookAdTranscribeInputSchema = {
|
|
4726
|
-
videoUrl: import_zod3.z.string().url().describe("Direct Facebook CDN video URL from
|
|
4755
|
+
videoUrl: import_zod3.z.string().url().describe("Direct Facebook CDN video URL from facebook_page_intel. Do not pass a public post/reel/share URL \u2014 use facebook_video_transcribe for those.")
|
|
4727
4756
|
};
|
|
4728
4757
|
var FacebookVideoTranscribeInputSchema = {
|
|
4729
|
-
url: import_zod3.z.string().url().describe("Organic Facebook reel
|
|
4758
|
+
url: import_zod3.z.string().url().describe("Organic Facebook reel/video/watch/post/share URL from facebook.com, m.facebook.com, or fb.watch."),
|
|
4730
4759
|
quality: import_zod3.z.enum(["best", "hd", "sd"]).default("best").describe("Preferred progressive MP4 quality. Use best by default; hd prefers the highest HD progressive URL; sd forces the SD URL.")
|
|
4731
4760
|
};
|
|
4732
4761
|
var GoogleAdsSearchInputSchema = {
|
|
4733
|
-
query: import_zod3.z.string().min(1).describe("A domain (e.g. getviktor.com) or advertiser/brand name to look up in
|
|
4762
|
+
query: import_zod3.z.string().min(1).describe("A domain (e.g. getviktor.com) or advertiser/brand name to look up in Google Ads Transparency Center."),
|
|
4734
4763
|
region: import_zod3.z.string().length(2).default("US").describe("Two-letter region code for where the ads are shown. Default US. Examples: US, CA, GB, AU."),
|
|
4735
4764
|
maxResults: import_zod3.z.number().int().min(1).max(20).default(10).describe("Maximum advertisers to return. Default 10, maximum 20.")
|
|
4736
4765
|
};
|
|
@@ -4741,78 +4770,78 @@ var GoogleAdsPageIntelInputSchema = {
|
|
|
4741
4770
|
maxAds: import_zod3.z.number().int().min(1).max(200).default(50).describe("Maximum creatives to inspect and hydrate. Default 50, maximum 200. Prefer 25-50 for focused scans.")
|
|
4742
4771
|
};
|
|
4743
4772
|
var GoogleAdsTranscribeInputSchema = {
|
|
4744
|
-
videoUrl: import_zod3.z.string().url().describe("Direct googlevideo.com playback URL from
|
|
4773
|
+
videoUrl: import_zod3.z.string().url().describe("Direct googlevideo.com playback URL from google_ads_page_intel. For YouTube-hosted ads use youtube_transcribe instead.")
|
|
4745
4774
|
};
|
|
4746
4775
|
var InstagramProfileContentInputSchema = {
|
|
4747
4776
|
handle: import_zod3.z.string().min(1).optional().describe("Instagram handle, with or without @. Provide handle or url."),
|
|
4748
|
-
url: import_zod3.z.string().url().optional().describe("Instagram profile URL
|
|
4749
|
-
profile: import_zod3.z.string().min(1).optional().describe("Optional saved hosted browser profile name
|
|
4750
|
-
saveProfileChanges: import_zod3.z.boolean().optional().describe("
|
|
4751
|
-
maxItems: import_zod3.z.number().int().min(1).max(2e3).default(50).describe("Maximum
|
|
4752
|
-
maxScrolls: import_zod3.z.number().int().min(0).max(250).default(10).describe("Maximum pagination scroll attempts. Default 10, maximum 250.
|
|
4753
|
-
scrollDelayMs: import_zod3.z.number().int().min(250).max(5e3).default(1200).describe("Delay after each
|
|
4754
|
-
stableScrollLimit: import_zod3.z.number().int().min(1).max(10).default(4).describe("Stop after this many consecutive scrolls with no new links
|
|
4777
|
+
url: import_zod3.z.string().url().optional().describe("Instagram profile URL. Provide handle or url."),
|
|
4778
|
+
profile: import_zod3.z.string().min(1).optional().describe("Optional saved hosted browser profile name for authenticated Instagram access."),
|
|
4779
|
+
saveProfileChanges: import_zod3.z.boolean().optional().describe("Save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login."),
|
|
4780
|
+
maxItems: import_zod3.z.number().int().min(1).max(2e3).default(50).describe("Maximum grid URLs to collect. Default 50, maximum 2000."),
|
|
4781
|
+
maxScrolls: import_zod3.z.number().int().min(0).max(250).default(10).describe("Maximum pagination scroll attempts. Default 10, maximum 250."),
|
|
4782
|
+
scrollDelayMs: import_zod3.z.number().int().min(250).max(5e3).default(1200).describe("Delay after each scroll before collecting new links. Default 1200ms."),
|
|
4783
|
+
stableScrollLimit: import_zod3.z.number().int().min(1).max(10).default(4).describe("Stop after this many consecutive scrolls with no new links.")
|
|
4755
4784
|
};
|
|
4756
4785
|
var InstagramMediaDownloadInputSchema = {
|
|
4757
|
-
url: import_zod3.z.string().url().describe("Instagram post, reel, or tv URL, e.g. https://www.instagram.com/reel/SHORTCODE/.
|
|
4758
|
-
profile: import_zod3.z.string().min(1).optional().describe("Optional saved hosted browser profile name
|
|
4759
|
-
saveProfileChanges: import_zod3.z.boolean().optional().describe("
|
|
4760
|
-
mediaTypes: import_zod3.z.array(import_zod3.z.enum(["image", "video", "audio"])).default(["image", "video", "audio"]).describe("Which media types to download when downloadMedia is true.
|
|
4761
|
-
downloadMedia: import_zod3.z.boolean().default(true).describe("Download extracted text/media files to the
|
|
4762
|
-
downloadAllTracks: import_zod3.z.boolean().default(false).describe("Download every captured
|
|
4763
|
-
includeTranscript: import_zod3.z.boolean().default(false).describe("Transcribe the selected audio track
|
|
4764
|
-
mux: import_zod3.z.boolean().default(true).describe("
|
|
4786
|
+
url: import_zod3.z.string().url().describe("Instagram post, reel, or tv URL, e.g. https://www.instagram.com/reel/SHORTCODE/."),
|
|
4787
|
+
profile: import_zod3.z.string().min(1).optional().describe("Optional saved hosted browser profile name for authenticated Instagram access."),
|
|
4788
|
+
saveProfileChanges: import_zod3.z.boolean().optional().describe("Save browser changes back to the hosted profile. Leave unset unless intentionally updating the saved login."),
|
|
4789
|
+
mediaTypes: import_zod3.z.array(import_zod3.z.enum(["image", "video", "audio"])).default(["image", "video", "audio"]).describe("Which media types to download when downloadMedia is true."),
|
|
4790
|
+
downloadMedia: import_zod3.z.boolean().default(true).describe("Download extracted text/media files to the output directory. Media URLs are always returned even when false."),
|
|
4791
|
+
downloadAllTracks: import_zod3.z.boolean().default(false).describe("Download every captured MP4 track instead of only the best video/audio pair."),
|
|
4792
|
+
includeTranscript: import_zod3.z.boolean().default(false).describe("Transcribe the selected audio track. Adds transcription cost and time."),
|
|
4793
|
+
mux: import_zod3.z.boolean().default(true).describe("Mux separately downloaded video/audio tracks into one MP4 if ffmpeg is available.")
|
|
4765
4794
|
};
|
|
4766
4795
|
var MapsPlaceIntelInputSchema = {
|
|
4767
|
-
businessName: import_zod3.z.string().min(1).describe('Business name only.
|
|
4768
|
-
location: import_zod3.z.string().min(1).describe('City/region/country where the business should be searched, e.g. "Denver, CO".
|
|
4796
|
+
businessName: import_zod3.z.string().min(1).describe('Business name only, e.g. "Elite Roofing" (not "Elite Roofing Denver CO" \u2014 put the city in location).'),
|
|
4797
|
+
location: import_zod3.z.string().min(1).describe('City/region/country where the business should be searched, e.g. "Denver, CO".'),
|
|
4769
4798
|
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location."),
|
|
4770
4799
|
hl: import_zod3.z.string().length(2).default("en").describe("Language inferred from user request."),
|
|
4771
|
-
includeReviews: import_zod3.z.boolean().default(false).describe("
|
|
4772
|
-
maxReviews: import_zod3.z.number().int().min(1).max(500).default(50).describe("Max review cards
|
|
4800
|
+
includeReviews: import_zod3.z.boolean().default(false).describe("Fetch individual review cards \u2014 for reviews, customer pain, complaints, or praise themes."),
|
|
4801
|
+
maxReviews: import_zod3.z.number().int().min(1).max(500).default(50).describe("Max review cards when includeReviews is true. Default 50, maximum 500.")
|
|
4773
4802
|
};
|
|
4774
4803
|
var MapsSearchInputSchema = {
|
|
4775
|
-
query: import_zod3.z.string().min(1).describe('Business category, niche,
|
|
4776
|
-
location: import_zod3.z.string().optional().describe('City, region, country, or service area
|
|
4804
|
+
query: import_zod3.z.string().min(1).describe('Business category, niche, or search term, e.g. "roofers". Do not include location here \u2014 use location instead.'),
|
|
4805
|
+
location: import_zod3.z.string().optional().describe('City, region, country, or service area, e.g. "Denver, CO".'),
|
|
4777
4806
|
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location."),
|
|
4778
4807
|
hl: import_zod3.z.string().length(2).default("en").describe("Language inferred from user request."),
|
|
4779
|
-
maxResults: import_zod3.z.number().int().min(1).max(50).default(10).describe("Number of
|
|
4780
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("
|
|
4781
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe("Optional US ZIP override for residential
|
|
4782
|
-
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics
|
|
4808
|
+
maxResults: import_zod3.z.number().int().min(1).max(50).default(10).describe("Number of candidates to return. Default 10, maximum 50."),
|
|
4809
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Defaults to location (city/state residential proxy targeting). configured forces the service proxy without city/ZIP targeting; none is local debugging only."),
|
|
4810
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe("Optional US ZIP override for residential proxy targeting."),
|
|
4811
|
+
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics.")
|
|
4783
4812
|
};
|
|
4784
4813
|
var DirectoryWorkflowInputSchema = {
|
|
4785
|
-
query: import_zod3.z.string().min(1).describe("Business category, niche, or keyword to search on Google Maps for every
|
|
4786
|
-
state: import_zod3.z.string().min(2).default("TN").describe("US state abbreviation or
|
|
4787
|
-
minPopulation: import_zod3.z.number().int().min(0).default(1e5).describe(
|
|
4788
|
-
populationYear: import_zod3.z.number().int().min(2020).max(2025).default(2025).describe("Census population estimate year
|
|
4789
|
-
maxCities: import_zod3.z.number().int().min(1).max(100).default(25).describe("Maximum
|
|
4790
|
-
maxResultsPerCity: import_zod3.z.number().int().min(1).max(50).default(50).describe("Google Maps
|
|
4791
|
-
concurrency: import_zod3.z.number().int().min(1).max(5).default(5).describe("
|
|
4792
|
-
includeZipGroups: import_zod3.z.boolean().default(true).describe("Attach ZIP groups from a configured US ZIPS CSV when available
|
|
4793
|
-
usZipsCsvPath: import_zod3.z.string().optional().describe("Local/test-only path to a US ZIPS CSV
|
|
4794
|
-
saveCsv: import_zod3.z.boolean().default(true).describe("Save a directory-ready CSV to the MCP Scraper output directory and return its path.
|
|
4795
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy targeting
|
|
4796
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe("Optional ZIP override for proxy targeting
|
|
4797
|
-
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics
|
|
4814
|
+
query: import_zod3.z.string().min(1).describe("Business category, niche, or keyword to search on Google Maps for every market. Do not include the city."),
|
|
4815
|
+
state: import_zod3.z.string().min(2).default("TN").describe("US state abbreviation or name used to select Census places, e.g. TN."),
|
|
4816
|
+
minPopulation: import_zod3.z.number().int().min(0).default(1e5).describe("Minimum Census place population for market selection."),
|
|
4817
|
+
populationYear: import_zod3.z.number().int().min(2020).max(2025).default(2025).describe("Census population estimate year (2020-2025 Population Estimates Program)."),
|
|
4818
|
+
maxCities: import_zod3.z.number().int().min(1).max(100).default(25).describe("Maximum markets to process after sorting by population descending."),
|
|
4819
|
+
maxResultsPerCity: import_zod3.z.number().int().min(1).max(50).default(50).describe("Google Maps candidates to collect per city."),
|
|
4820
|
+
concurrency: import_zod3.z.number().int().min(1).max(5).default(5).describe("City Maps searches to run in parallel."),
|
|
4821
|
+
includeZipGroups: import_zod3.z.boolean().default(true).describe("Attach ZIP groups from a configured US ZIPS CSV when available (MCP_SCRAPER_USZIPS_CSV_PATH or usZipsCsvPath)."),
|
|
4822
|
+
usZipsCsvPath: import_zod3.z.string().optional().describe("Local/test-only path to a US ZIPS CSV (state_abbr, zipcode, county, city columns). Deployed APIs should use MCP_SCRAPER_USZIPS_CSV_PATH instead."),
|
|
4823
|
+
saveCsv: import_zod3.z.boolean().default(true).describe("Save a directory-ready CSV of results to the MCP Scraper output directory and return its path."),
|
|
4824
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy targeting per city search. Defaults to location (city/ZIP-group residential targeting); configured forces the service proxy; none is local debugging only."),
|
|
4825
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe("Optional ZIP override for proxy targeting; normally omitted."),
|
|
4826
|
+
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics.")
|
|
4798
4827
|
};
|
|
4799
4828
|
var RankTrackerModeSchema = import_zod3.z.enum(["maps", "organic", "ai_overview", "paa"]);
|
|
4800
4829
|
var RankTrackerBlueprintInputSchema = {
|
|
4801
4830
|
projectName: import_zod3.z.string().min(1).optional().describe("Optional name for the rank tracker project, client, or campaign."),
|
|
4802
|
-
targetDomain: import_zod3.z.string().min(1).optional().describe("Primary domain to track in organic results, AI Overview citations, and PAA sources
|
|
4803
|
-
targetBusinessName: import_zod3.z.string().min(1).optional().describe("Primary Google Business Profile
|
|
4804
|
-
trackingModes: import_zod3.z.array(RankTrackerModeSchema).min(1).max(4).default(["maps", "organic", "ai_overview", "paa"]).describe("Rank tracker surfaces to build
|
|
4805
|
-
keywords: import_zod3.z.array(import_zod3.z.string().min(1)).max(200).default([]).describe("Seed keywords or service queries to track. Leave empty
|
|
4806
|
-
locations: import_zod3.z.array(import_zod3.z.string().min(1)).max(100).default([]).describe(
|
|
4831
|
+
targetDomain: import_zod3.z.string().min(1).optional().describe("Primary domain to track in organic results, AI Overview citations, and PAA sources."),
|
|
4832
|
+
targetBusinessName: import_zod3.z.string().min(1).optional().describe("Primary Google Business Profile/brand name to match in Maps results. Required for Maps tracking."),
|
|
4833
|
+
trackingModes: import_zod3.z.array(RankTrackerModeSchema).min(1).max(4).default(["maps", "organic", "ai_overview", "paa"]).describe("Rank tracker surfaces to build: maps, organic, ai_overview, paa."),
|
|
4834
|
+
keywords: import_zod3.z.array(import_zod3.z.string().min(1)).max(200).default([]).describe("Seed keywords or service queries to track. Leave empty to derive from user input downstream."),
|
|
4835
|
+
locations: import_zod3.z.array(import_zod3.z.string().min(1)).max(100).default([]).describe('Markets, cities, ZIPs, or service areas to track, e.g. "Denver, CO".'),
|
|
4807
4836
|
competitors: import_zod3.z.array(import_zod3.z.string().min(1)).max(100).default([]).describe("Optional competitor domains or business names to persist as comparison targets."),
|
|
4808
|
-
database: import_zod3.z.enum(["postgres", "neon", "supabase", "sqlite", "mysql"]).default("postgres").describe("Database family
|
|
4809
|
-
scheduleCadence: import_zod3.z.enum(["daily", "weekly", "monthly", "custom"]).default("weekly").describe("Default recurring rank check cadence
|
|
4837
|
+
database: import_zod3.z.enum(["postgres", "neon", "supabase", "sqlite", "mysql"]).default("postgres").describe("Database family to target when generating migrations."),
|
|
4838
|
+
scheduleCadence: import_zod3.z.enum(["daily", "weekly", "monthly", "custom"]).default("weekly").describe("Default recurring rank check cadence."),
|
|
4810
4839
|
customCron: import_zod3.z.string().min(1).optional().describe("Cron expression to use when scheduleCadence is custom."),
|
|
4811
|
-
timezone: import_zod3.z.string().min(1).default("UTC").describe("IANA timezone for scheduled rank checks
|
|
4812
|
-
includeCron: import_zod3.z.boolean().default(true).describe("Include a cron
|
|
4813
|
-
includeDashboard: import_zod3.z.boolean().default(true).describe("Include dashboard/reporting requirements
|
|
4814
|
-
includeAlerts: import_zod3.z.boolean().default(true).describe("Include alert rules for rank movement and SERP feature
|
|
4815
|
-
notes: import_zod3.z.string().max(4e3).optional().describe("Extra product, client, stack, or hosting requirements
|
|
4840
|
+
timezone: import_zod3.z.string().min(1).default("UTC").describe("IANA timezone for scheduled rank checks."),
|
|
4841
|
+
includeCron: import_zod3.z.boolean().default(true).describe("Include a cron/heartbeat worker plan."),
|
|
4842
|
+
includeDashboard: import_zod3.z.boolean().default(true).describe("Include dashboard/reporting requirements."),
|
|
4843
|
+
includeAlerts: import_zod3.z.boolean().default(true).describe("Include alert rules for rank movement and SERP feature changes."),
|
|
4844
|
+
notes: import_zod3.z.string().max(4e3).optional().describe("Extra product, client, stack, or hosting requirements.")
|
|
4816
4845
|
};
|
|
4817
4846
|
var NullableString2 = import_zod3.z.string().nullable();
|
|
4818
4847
|
var MapsSearchAttemptOutput = import_zod3.z.object({
|
|
@@ -4962,7 +4991,7 @@ var EntityIdsOutput = import_zod3.z.object({
|
|
|
4962
4991
|
kgId: import_zod3.z.string().nullable(),
|
|
4963
4992
|
cid: import_zod3.z.string().nullable(),
|
|
4964
4993
|
gcid: import_zod3.z.string().nullable()
|
|
4965
|
-
})).describe("
|
|
4994
|
+
})).describe("Entities named on the page with their kgId/cid/gcid. Flat lists below are the same IDs deduplicated, kept for backward compatibility."),
|
|
4966
4995
|
kgIds: import_zod3.z.array(import_zod3.z.string()),
|
|
4967
4996
|
cids: import_zod3.z.array(import_zod3.z.string()),
|
|
4968
4997
|
gcids: import_zod3.z.array(import_zod3.z.string())
|
|
@@ -5151,6 +5180,22 @@ var FacebookAdSearchOutputSchema = {
|
|
|
5151
5180
|
sampleLibraryId: NullableString2
|
|
5152
5181
|
}))
|
|
5153
5182
|
};
|
|
5183
|
+
var VideoFrameAnalysisOutputSchema = {
|
|
5184
|
+
ok: import_zod3.z.boolean(),
|
|
5185
|
+
runId: NullableString2,
|
|
5186
|
+
status: NullableString2,
|
|
5187
|
+
message: NullableString2
|
|
5188
|
+
};
|
|
5189
|
+
var VideoFrameAnalysisStatusOutputSchema = {
|
|
5190
|
+
ok: import_zod3.z.boolean(),
|
|
5191
|
+
runId: NullableString2,
|
|
5192
|
+
status: NullableString2,
|
|
5193
|
+
progress: import_zod3.z.object({ analyzed: import_zod3.z.number().int(), total: import_zod3.z.number().int() }).nullable().optional(),
|
|
5194
|
+
frameCount: import_zod3.z.number().int().nullable().optional(),
|
|
5195
|
+
artifactPath: NullableString2,
|
|
5196
|
+
report: NullableString2,
|
|
5197
|
+
error: NullableString2
|
|
5198
|
+
};
|
|
5154
5199
|
var RedditThreadOutputSchema = {
|
|
5155
5200
|
sourceUrl: NullableString2,
|
|
5156
5201
|
oldRedditUrl: NullableString2,
|
|
@@ -5413,7 +5458,7 @@ var WorkflowIdSchema = import_zod3.z.enum([
|
|
|
5413
5458
|
"ai-overview-language"
|
|
5414
5459
|
]);
|
|
5415
5460
|
var WorkflowListInputSchema = {
|
|
5416
|
-
includeRecipes: import_zod3.z.boolean().default(true).describe("Include high-level AI-facing recipes
|
|
5461
|
+
includeRecipes: import_zod3.z.boolean().default(true).describe("Include high-level AI-facing recipes (market analysis, ICP research, CRO audits, content gaps, etc).")
|
|
5417
5462
|
};
|
|
5418
5463
|
var WorkflowSuggestInputSchema = {
|
|
5419
5464
|
goal: import_zod3.z.string().min(1).describe('The user goal or job to route, e.g. "market analysis for roofers in Tennessee", "ICP research for med spas", "CRO audit for this URL", or "brand design briefing".'),
|
|
@@ -5426,12 +5471,12 @@ var WorkflowSuggestInputSchema = {
|
|
|
5426
5471
|
maxSuggestions: import_zod3.z.number().int().min(1).max(8).default(3).describe("Number of matching workflow recipes to return.")
|
|
5427
5472
|
};
|
|
5428
5473
|
var WorkflowRunInputSchema = {
|
|
5429
|
-
workflowId: WorkflowIdSchema.describe("Workflow to run
|
|
5430
|
-
input: import_zod3.z.record(import_zod3.z.unknown()).default({}).describe("Workflow-specific input object
|
|
5474
|
+
workflowId: WorkflowIdSchema.describe("Workflow to run. Call workflow_list or workflow_suggest first when unsure."),
|
|
5475
|
+
input: import_zod3.z.record(import_zod3.z.unknown()).default({}).describe("Workflow-specific input object; shape depends on workflowId. Call workflow_list or workflow_suggest to see required fields."),
|
|
5431
5476
|
webhookUrl: import_zod3.z.string().url().optional().describe("Optional HTTPS webhook to receive the completed hosted workflow run event.")
|
|
5432
5477
|
};
|
|
5433
5478
|
var WorkflowStepInputSchema = {
|
|
5434
|
-
runId: import_zod3.z.string().min(1).describe("Workflow run id returned by workflow_run
|
|
5479
|
+
runId: import_zod3.z.string().min(1).describe("Workflow run id returned by workflow_run/workflow_step/workflow_status. Advances the run by exactly one step.")
|
|
5435
5480
|
};
|
|
5436
5481
|
var WorkflowStatusInputSchema = {
|
|
5437
5482
|
runId: import_zod3.z.string().min(1).describe("Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself.")
|
|
@@ -5439,7 +5484,7 @@ var WorkflowStatusInputSchema = {
|
|
|
5439
5484
|
var WorkflowArtifactReadInputSchema = {
|
|
5440
5485
|
runId: import_zod3.z.string().min(1).describe("Workflow run id returned by workflow_run, workflow_step, or workflow_status. Use only a returned runId; do not construct one yourself."),
|
|
5441
5486
|
artifactId: import_zod3.z.string().min(1).describe("Artifact id from the run artifact list returned by workflow_run, workflow_step, or workflow_status. Use only a returned artifactId; do not construct one yourself."),
|
|
5442
|
-
maxBytes: import_zod3.z.number().int().min(1e3).max(1e6).default(2e5).describe("Maximum bytes of artifact text to return inline.
|
|
5487
|
+
maxBytes: import_zod3.z.number().int().min(1e3).max(1e6).default(2e5).describe("Maximum bytes of artifact text to return inline.")
|
|
5443
5488
|
};
|
|
5444
5489
|
var WorkflowRecipeOutput = import_zod3.z.object({
|
|
5445
5490
|
id: import_zod3.z.string(),
|
|
@@ -5498,28 +5543,28 @@ var WorkflowArtifactReadOutputSchema = {
|
|
|
5498
5543
|
text: import_zod3.z.string()
|
|
5499
5544
|
};
|
|
5500
5545
|
var SearchSerpInputSchema = {
|
|
5501
|
-
query: import_zod3.z.string().min(1).describe('
|
|
5502
|
-
location: import_zod3.z.string().optional().describe("City, region, or country for geo-
|
|
5546
|
+
query: import_zod3.z.string().min(1).describe('The search query. KEEP the place in the query text for localized results (e.g. "best dentist Brooklyn NY") and also set location \u2014 city-in-query is what localizes reliably.'),
|
|
5547
|
+
location: import_zod3.z.string().optional().describe("City, region, or country for geo signals. Set alongside city-in-query wording; alone it does NOT reliably localize."),
|
|
5503
5548
|
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from location or user language."),
|
|
5504
5549
|
hl: import_zod3.z.string().default("en").describe("Google interface/content language inferred from user request."),
|
|
5505
|
-
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use
|
|
5506
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset \u2014
|
|
5507
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe(
|
|
5508
|
-
debug: import_zod3.z.boolean().default(false).describe("Include sanitized
|
|
5509
|
-
pages: import_zod3.z.number().int().min(1).max(2).default(1).describe("Number of result pages to fetch (1\u20132)")
|
|
5550
|
+
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only for mobile rankings."),
|
|
5551
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress). Do NOT set "location" just because a city was named \u2014 that comes from city-in-query wording. "location" forces residential geo-IP for rank-tracking fidelity, is frequently CAPTCHA-blocked, and accepts failures.'),
|
|
5552
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location".'),
|
|
5553
|
+
debug: import_zod3.z.boolean().default(false).describe("Include sanitized diagnostics for debugging localization, CAPTCHA, or proxy behavior."),
|
|
5554
|
+
pages: import_zod3.z.number().int().min(1).max(2).default(1).describe("Number of result pages to fetch (1\u20132).")
|
|
5510
5555
|
};
|
|
5511
5556
|
var CaptureSerpSnapshotInputSchema = {
|
|
5512
|
-
query: import_zod3.z.string().min(1).describe(
|
|
5513
|
-
location: import_zod3.z.string().optional().describe("City, region, country, or service area
|
|
5514
|
-
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from the requested market
|
|
5557
|
+
query: import_zod3.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.'),
|
|
5558
|
+
location: import_zod3.z.string().optional().describe("City, region, country, or service area for localized Google results."),
|
|
5559
|
+
gl: import_zod3.z.string().length(2).default("us").describe("Google country code inferred from the requested market."),
|
|
5515
5560
|
hl: import_zod3.z.string().default("en").describe("Google interface/content language inferred from the user request."),
|
|
5516
|
-
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only
|
|
5517
|
-
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset \u2014
|
|
5518
|
-
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe(
|
|
5519
|
-
pages: import_zod3.z.number().int().min(1).max(2).default(1).describe("
|
|
5520
|
-
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser
|
|
5521
|
-
includePageSnapshots: import_zod3.z.boolean().default(false).describe("Also capture ranking-page snapshots for selected SERP URLs
|
|
5522
|
-
pageSnapshotLimit: import_zod3.z.number().int().min(0).max(10).default(0).describe("Maximum ranking-page snapshots
|
|
5561
|
+
device: import_zod3.z.enum(["desktop", "mobile"]).default("desktop").describe("SERP device context. Use mobile only for mobile rankings/evidence."),
|
|
5562
|
+
proxyMode: import_zod3.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE).describe('Leave unset (clean egress). Do NOT set "location" just because a city was named \u2014 that comes from city-in-query wording. "location" forces residential geo-IP, is frequently CAPTCHA-blocked, and accepts failures.'),
|
|
5563
|
+
proxyZip: import_zod3.z.string().regex(/^\d{5}$/).optional().describe('US ZIP for residential geo-IP targeting. Only meaningful with proxyMode "location".'),
|
|
5564
|
+
pages: import_zod3.z.number().int().min(1).max(2).default(1).describe("Google result pages to capture. Use 2 only for deeper ranking evidence."),
|
|
5565
|
+
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/proxy/location diagnostics."),
|
|
5566
|
+
includePageSnapshots: import_zod3.z.boolean().default(false).describe("Also capture ranking-page snapshots for selected SERP URLs."),
|
|
5567
|
+
pageSnapshotLimit: import_zod3.z.number().int().min(0).max(10).default(0).describe("Maximum ranking-page snapshots when includePageSnapshots is true.")
|
|
5523
5568
|
};
|
|
5524
5569
|
var ScreenshotInputSchema = {
|
|
5525
5570
|
url: import_zod3.z.string().url().describe("URL to capture as a full-page screenshot. Use http or https. Pass allowLocal: true to capture localhost or private-network URLs during development."),
|
|
@@ -5527,15 +5572,15 @@ var ScreenshotInputSchema = {
|
|
|
5527
5572
|
allowLocal: import_zod3.z.boolean().default(false).describe("Allow localhost and private-network URLs (127.x, 192.168.x, 10.x, etc.). For local development only \u2014 not for production use.")
|
|
5528
5573
|
};
|
|
5529
5574
|
var CaptureSerpPageSnapshotsInputSchema = {
|
|
5530
|
-
urls: import_zod3.z.array(import_zod3.z.string().url()).min(1).max(25).describe("Public HTTP/HTTPS URLs to capture
|
|
5575
|
+
urls: import_zod3.z.array(import_zod3.z.string().url()).min(1).max(25).describe("Public HTTP/HTTPS URLs to capture. Do not pass localhost, private IPs, file URLs, or internal admin URLs."),
|
|
5531
5576
|
targets: import_zod3.z.array(import_zod3.z.object({
|
|
5532
5577
|
url: import_zod3.z.string().url().describe("Public HTTP/HTTPS URL to capture."),
|
|
5533
|
-
sourceKind: import_zod3.z.enum(["organic", "ai_citation", "local_pack_website", "configured_target", "site_subject"]).default("configured_target").describe("Why this page is being captured
|
|
5578
|
+
sourceKind: import_zod3.z.enum(["organic", "ai_citation", "local_pack_website", "configured_target", "site_subject"]).default("configured_target").describe("Why this page is being captured."),
|
|
5534
5579
|
sourcePosition: import_zod3.z.number().int().min(1).optional().describe("Ranking or citation position when the page came from SERP evidence.")
|
|
5535
|
-
}).strict()).min(1).max(25).optional().describe("Structured
|
|
5536
|
-
maxConcurrency: import_zod3.z.number().int().min(1).max(5).default(2).describe("Parallel page captures.
|
|
5537
|
-
timeoutMs: import_zod3.z.number().int().min(1e3).max(6e4).default(15e3).describe("Per-page capture timeout in milliseconds
|
|
5538
|
-
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics
|
|
5580
|
+
}).strict()).min(1).max(25).optional().describe("Structured targets. Use instead of urls when source kind or position should be preserved."),
|
|
5581
|
+
maxConcurrency: import_zod3.z.number().int().min(1).max(5).default(2).describe("Parallel page captures."),
|
|
5582
|
+
timeoutMs: import_zod3.z.number().int().min(1e3).max(6e4).default(15e3).describe("Per-page capture timeout in milliseconds; timeouts return as structured capture failures."),
|
|
5583
|
+
debug: import_zod3.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics.")
|
|
5539
5584
|
};
|
|
5540
5585
|
|
|
5541
5586
|
// src/mcp/rank-tracker-blueprint.ts
|
|
@@ -5874,14 +5919,14 @@ function liveWebToolAnnotations(title) {
|
|
|
5874
5919
|
function registerSerpIntelligenceCaptureTools(server2, executor) {
|
|
5875
5920
|
server2.registerTool("capture_serp_snapshot", {
|
|
5876
5921
|
title: "SERP Intelligence Snapshot",
|
|
5877
|
-
description: "Capture a structured SERP Intelligence Google snapshot
|
|
5922
|
+
description: "Capture a structured SERP Intelligence Google snapshot (the product capture path used by Phoenix). Split query from location; leave proxyMode unset.",
|
|
5878
5923
|
inputSchema: CaptureSerpSnapshotInputSchema,
|
|
5879
5924
|
outputSchema: CaptureSerpSnapshotOutputSchema,
|
|
5880
5925
|
annotations: liveWebToolAnnotations("SERP Intelligence Snapshot")
|
|
5881
5926
|
}, async (input) => formatCaptureSerpSnapshot(await executor.captureSerpSnapshot(input), input));
|
|
5882
5927
|
server2.registerTool("capture_serp_page_snapshots", {
|
|
5883
5928
|
title: "SERP Intelligence Page Snapshots",
|
|
5884
|
-
description: "Capture public ranking-page evidence
|
|
5929
|
+
description: "Capture public ranking-page evidence as SERP Intelligence page snapshots (the product path used by Phoenix). Provide urls, or targets to preserve source metadata. Private IPs, localhost, file, and internal URLs are rejected.",
|
|
5885
5930
|
inputSchema: CaptureSerpPageSnapshotsInputSchema,
|
|
5886
5931
|
outputSchema: CaptureSerpPageSnapshotsOutputSchema,
|
|
5887
5932
|
annotations: liveWebToolAnnotations("SERP Intelligence Page Snapshots")
|
|
@@ -5937,203 +5982,217 @@ function registerPaaExtractorMcpTools(server2, executor, options = {}) {
|
|
|
5937
5982
|
if (savesReports) registerSavedReportResources(server2);
|
|
5938
5983
|
server2.registerTool("harvest_paa", {
|
|
5939
5984
|
title: "Google PAA + SERP Harvest",
|
|
5940
|
-
description: withReportNote(
|
|
5985
|
+
description: withReportNote("Best default tool for Google search research: People Also Ask questions with answers/sources, organic SERP, local pack, entity IDs, and AI Overview. Split topic from location; leave proxyMode unset. Warn the user before maxQuestions above 100 \u2014 deep harvests can run several minutes with no interim progress, billed per extracted question."),
|
|
5941
5986
|
inputSchema: HarvestPaaInputSchema,
|
|
5942
5987
|
outputSchema: HarvestPaaOutputSchema,
|
|
5943
5988
|
annotations: liveWebToolAnnotations("Google PAA + SERP Harvest")
|
|
5944
5989
|
}, async (input) => formatHarvestPaa(await executor.harvestPaa(input), input));
|
|
5945
5990
|
server2.registerTool("search_serp", {
|
|
5946
5991
|
title: "Google SERP Lookup",
|
|
5947
|
-
description: withReportNote("Fast Google SERP lookup without PAA expansion
|
|
5992
|
+
description: withReportNote("Fast Google SERP lookup without PAA expansion \u2014 rankings, organic results, local pack, positions. Split topic from location; leave proxyMode unset."),
|
|
5948
5993
|
inputSchema: SearchSerpInputSchema,
|
|
5949
5994
|
outputSchema: SearchSerpOutputSchema,
|
|
5950
5995
|
annotations: liveWebToolAnnotations("Google SERP Lookup")
|
|
5951
5996
|
}, async (input) => formatSearchSerp(await executor.searchSerp(input), input));
|
|
5952
5997
|
server2.registerTool("extract_url", {
|
|
5953
5998
|
title: "Single URL Extract",
|
|
5954
|
-
description: withReportNote("Extract structured data from one public URL
|
|
5999
|
+
description: withReportNote("Extract structured data from one public URL: content, schema, headings, metadata, screenshots, branding, or media assets. Set depositToVault:true to save the full page into the user's MCP Memory vault server-side (not returned to chat)."),
|
|
5955
6000
|
inputSchema: ExtractUrlInputSchema,
|
|
5956
6001
|
outputSchema: ExtractUrlOutputSchema,
|
|
5957
6002
|
annotations: liveWebToolAnnotations("Single URL Extract")
|
|
5958
6003
|
}, async (input) => formatExtractUrl(await executor.extractUrl(input), input));
|
|
5959
6004
|
server2.registerTool("map_site_urls", {
|
|
5960
6005
|
title: "Site URL Map",
|
|
5961
|
-
description: withReportNote("Map/crawl a public website
|
|
6006
|
+
description: withReportNote("Map/crawl a public website for a sitemap, URL inventory, or broken-link scan. Returns internal URLs with HTTP status; maps over 500 URLs are written to a local CSV file instead of inlined."),
|
|
5962
6007
|
inputSchema: MapSiteUrlsInputSchema,
|
|
5963
6008
|
outputSchema: MapSiteUrlsOutputSchema,
|
|
5964
6009
|
annotations: liveWebToolAnnotations("Site URL Map")
|
|
5965
6010
|
}, async (input) => formatMapSiteUrls(await executor.mapSiteUrls(input), input));
|
|
5966
6011
|
server2.registerTool("extract_site", {
|
|
5967
6012
|
title: "Multi-Page Site Content Crawl",
|
|
5968
|
-
description: withReportNote("Crawl a public website and return
|
|
6013
|
+
description: withReportNote("Crawl a public website and return page CONTENT (Markdown) across multiple pages. Bulk crawls over 25 pages are saved as per-page Markdown files in a local folder instead of inlined. Content only \u2014 for a technical SEO audit use audit_site instead."),
|
|
5969
6014
|
inputSchema: ExtractSiteInputSchema,
|
|
5970
6015
|
outputSchema: ExtractSiteOutputSchema,
|
|
5971
6016
|
annotations: liveWebToolAnnotations("Multi-Page Site Content Crawl")
|
|
5972
6017
|
}, async (input) => formatExtractSite(await executor.extractSite(input), input));
|
|
5973
6018
|
server2.registerTool("audit_site", {
|
|
5974
6019
|
title: "Technical SEO Audit",
|
|
5975
|
-
description: withReportNote("Run a full technical SEO audit (Screaming-Frog-style) on a public website
|
|
6020
|
+
description: withReportNote("Run a full technical SEO audit (Screaming-Frog-style) on a public website: on-page issues, internal link graph, indexability, heading/image analysis. Writes a folder of analysis files plus per-page content, and returns a summary plus the folder path. Use extract_site instead for plain page content."),
|
|
5976
6021
|
inputSchema: AuditSiteInputSchema,
|
|
5977
6022
|
outputSchema: AuditSiteOutputSchema,
|
|
5978
6023
|
annotations: liveWebToolAnnotations("Technical SEO Audit")
|
|
5979
6024
|
}, async (input) => formatAuditSite(await executor.auditSite(input), input));
|
|
5980
6025
|
server2.registerTool("youtube_harvest", {
|
|
5981
6026
|
title: "YouTube Video Harvest",
|
|
5982
|
-
description: withReportNote('Harvest YouTube video metadata
|
|
6027
|
+
description: withReportNote('Harvest YouTube video metadata by topic search or channel library. Use mode "search" for keyword/topic requests, mode "channel" for @handles/channel IDs/URLs. Returns titles, views, durations, and videoIds.'),
|
|
5983
6028
|
inputSchema: YoutubeHarvestInputSchema,
|
|
5984
6029
|
outputSchema: YoutubeHarvestOutputSchema,
|
|
5985
6030
|
annotations: liveWebToolAnnotations("YouTube Video Harvest")
|
|
5986
6031
|
}, async (input) => formatYoutubeHarvest(await executor.youtubeHarvest(input), input));
|
|
5987
6032
|
server2.registerTool("youtube_transcribe", {
|
|
5988
6033
|
title: "YouTube Transcription",
|
|
5989
|
-
description: withReportNote("Fetch and transcribe captions from a YouTube video.
|
|
6034
|
+
description: withReportNote("Fetch and transcribe captions from a YouTube video. Pass videoId from youtube_harvest, or a url the user pasted. Returns full transcript, timestamped chunks, and word count."),
|
|
5990
6035
|
inputSchema: YoutubeTranscribeInputSchema,
|
|
5991
6036
|
outputSchema: YoutubeTranscribeOutputSchema,
|
|
5992
6037
|
annotations: liveWebToolAnnotations("YouTube Transcription")
|
|
5993
6038
|
}, async (input) => formatYoutubeTranscribe(await executor.youtubeTranscribe(input), input));
|
|
5994
6039
|
server2.registerTool("facebook_page_intel", {
|
|
5995
6040
|
title: "Facebook Advertiser Ad Intel",
|
|
5996
|
-
description: withReportNote("Harvest ads from a Facebook advertiser
|
|
6041
|
+
description: withReportNote("Harvest ads from a Facebook advertiser: copy, creative angles, CTAs, and direct video URLs ready for facebook_ad_transcribe. Accepts pageId, libraryId, or a brand/advertiser name."),
|
|
5997
6042
|
inputSchema: FacebookPageIntelInputSchema,
|
|
5998
6043
|
outputSchema: FacebookPageIntelOutputSchema,
|
|
5999
6044
|
annotations: liveWebToolAnnotations("Facebook Advertiser Ad Intel")
|
|
6000
6045
|
}, async (input) => formatFacebookPageIntel(await executor.facebookPageIntel(input), input));
|
|
6001
6046
|
server2.registerTool("facebook_ad_search", {
|
|
6002
6047
|
title: "Facebook Ad Library Search",
|
|
6003
|
-
description: withReportNote("Search Facebook Ad Library
|
|
6048
|
+
description: withReportNote("Search Facebook Ad Library to find advertisers by brand, competitor, niche, or keyword. Returns advertisers with ad counts and library IDs."),
|
|
6004
6049
|
inputSchema: FacebookAdSearchInputSchema,
|
|
6005
6050
|
outputSchema: FacebookAdSearchOutputSchema,
|
|
6006
6051
|
annotations: liveWebToolAnnotations("Facebook Ad Library Search")
|
|
6007
6052
|
}, async (input) => formatFacebookAdSearch(await executor.facebookAdSearch(input), input));
|
|
6008
6053
|
server2.registerTool("reddit_thread", {
|
|
6009
6054
|
title: "Reddit Thread + Comments",
|
|
6010
|
-
description: withReportNote("Capture a Reddit post and its comment tree from
|
|
6055
|
+
description: withReportNote("Capture a Reddit post and its comment tree from a reddit.com thread URL \u2014 comments, opinions, audience voice. Handles Reddit's bot protection automatically; pass maxComments to cap the list."),
|
|
6011
6056
|
inputSchema: RedditThreadInputSchema,
|
|
6012
6057
|
outputSchema: RedditThreadOutputSchema,
|
|
6013
6058
|
annotations: liveWebToolAnnotations("Reddit Thread + Comments")
|
|
6014
6059
|
}, async (input) => formatRedditThread(await executor.redditThread(input), input));
|
|
6060
|
+
server2.registerTool("video_frame_analysis", {
|
|
6061
|
+
title: "Video Breakdown (frame-by-frame + transcript)",
|
|
6062
|
+
description: "Produce a deep frame-by-frame + transcript breakdown of a video \u2014 pacing, hook, visual style, and how to replicate it. Pass a DIRECT video file URL (.mp4/.webm/.mov), not a page URL. Runs asynchronously and costs a flat $1 (refunded on failure): returns a runId immediately; poll video_frame_analysis_status until done.",
|
|
6063
|
+
inputSchema: VideoFrameAnalysisInputSchema,
|
|
6064
|
+
outputSchema: VideoFrameAnalysisOutputSchema,
|
|
6065
|
+
annotations: { title: "Video Breakdown", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }
|
|
6066
|
+
}, async (input) => executor.videoFrameAnalysis(input));
|
|
6067
|
+
server2.registerTool("video_frame_analysis_status", {
|
|
6068
|
+
title: "Video Breakdown Status",
|
|
6069
|
+
description: 'Check progress of a video breakdown started with video_frame_analysis, using its runId. Free to call. When status is "done" it returns the full report and vault path; stop polling on "done" or "failed".',
|
|
6070
|
+
inputSchema: VideoFrameAnalysisStatusInputSchema,
|
|
6071
|
+
outputSchema: VideoFrameAnalysisStatusOutputSchema,
|
|
6072
|
+
annotations: { title: "Video Breakdown Status", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
6073
|
+
}, async (input) => executor.videoFrameAnalysisStatus(input));
|
|
6015
6074
|
server2.registerTool("facebook_ad_transcribe", {
|
|
6016
6075
|
title: "Facebook Ad Transcription",
|
|
6017
|
-
description: "Transcribe audio from a Facebook ad video CDN URL
|
|
6076
|
+
description: "Transcribe audio from a Facebook ad video CDN URL returned by facebook_page_intel. Use only that direct videoUrl value \u2014 do not pass public Facebook post/reel/share URLs (use facebook_video_transcribe for those).",
|
|
6018
6077
|
inputSchema: FacebookAdTranscribeInputSchema,
|
|
6019
6078
|
outputSchema: FacebookAdTranscribeOutputSchema,
|
|
6020
6079
|
annotations: liveWebToolAnnotations("Facebook Ad Transcription")
|
|
6021
6080
|
}, async (input) => formatFacebookAdTranscribe(await executor.facebookAdTranscribe(input), input));
|
|
6022
6081
|
server2.registerTool("google_ads_search", {
|
|
6023
6082
|
title: "Google Ads Transparency Search",
|
|
6024
|
-
description: withReportNote("Search the Google Ads Transparency Center to find advertisers
|
|
6083
|
+
description: withReportNote("Search the Google Ads Transparency Center to find advertisers by domain or brand name. Returns advertisers with advertiser ID and approximate ad count, to pass to google_ads_page_intel."),
|
|
6025
6084
|
inputSchema: GoogleAdsSearchInputSchema,
|
|
6026
6085
|
outputSchema: GoogleAdsSearchOutputSchema,
|
|
6027
6086
|
annotations: liveWebToolAnnotations("Google Ads Transparency Search")
|
|
6028
6087
|
}, async (input) => formatGoogleAdsSearch(await executor.googleAdsSearch(input), input));
|
|
6029
6088
|
server2.registerTool("google_ads_page_intel", {
|
|
6030
6089
|
title: "Google Ads Advertiser Intel",
|
|
6031
|
-
description: withReportNote("Harvest an advertiser's
|
|
6090
|
+
description: withReportNote("Harvest an advertiser's ad creatives from the Google Ads Transparency Center: format, image URLs, and \u2014 for video ads \u2014 a YouTube video ID or direct video URL. Accepts advertiserId (from google_ads_search) or a domain."),
|
|
6032
6091
|
inputSchema: GoogleAdsPageIntelInputSchema,
|
|
6033
6092
|
outputSchema: GoogleAdsPageIntelOutputSchema,
|
|
6034
6093
|
annotations: liveWebToolAnnotations("Google Ads Advertiser Intel")
|
|
6035
6094
|
}, async (input) => formatGoogleAdsPageIntel(await executor.googleAdsPageIntel(input), input));
|
|
6036
6095
|
server2.registerTool("google_ads_transcribe", {
|
|
6037
6096
|
title: "Google Ad Video Transcription",
|
|
6038
|
-
description: "Transcribe audio from a Google video ad
|
|
6097
|
+
description: "Transcribe audio from a Google video ad's direct videoUrl (a googlevideo.com playback URL) returned by google_ads_page_intel. For YouTube-hosted ads, use youtube_transcribe with the returned youtubeVideoId instead.",
|
|
6039
6098
|
inputSchema: GoogleAdsTranscribeInputSchema,
|
|
6040
6099
|
outputSchema: GoogleAdsTranscribeOutputSchema,
|
|
6041
6100
|
annotations: liveWebToolAnnotations("Google Ad Video Transcription")
|
|
6042
6101
|
}, async (input) => formatGoogleAdsTranscribe(await executor.googleAdsTranscribe(input), input));
|
|
6043
6102
|
server2.registerTool("facebook_video_transcribe", {
|
|
6044
6103
|
title: "Facebook Organic Video Transcription",
|
|
6045
|
-
description: withReportNote("Transcribe audio from an organic Facebook reel
|
|
6104
|
+
description: withReportNote("Transcribe audio from an organic Facebook reel/video/post/share URL (including fb.watch). Renders the page, selects the best public CDN MP4, and returns the transcript plus resolved video metadata."),
|
|
6046
6105
|
inputSchema: FacebookVideoTranscribeInputSchema,
|
|
6047
6106
|
outputSchema: FacebookVideoTranscribeOutputSchema,
|
|
6048
6107
|
annotations: liveWebToolAnnotations("Facebook Organic Video Transcription")
|
|
6049
6108
|
}, async (input) => formatFacebookVideoTranscribe(await executor.facebookVideoTranscribe(input), input));
|
|
6050
6109
|
server2.registerTool("instagram_profile_content", {
|
|
6051
6110
|
title: "Instagram Profile Content Discovery",
|
|
6052
|
-
description: withReportNote("Discover Instagram profile grid content links for a handle or profile URL
|
|
6111
|
+
description: withReportNote("Discover Instagram profile grid content links (posts/reels/tv) for a handle or profile URL, for later selection with instagram_media_download. Returns profile stats and collected URLs."),
|
|
6053
6112
|
inputSchema: InstagramProfileContentInputSchema,
|
|
6054
6113
|
outputSchema: InstagramProfileContentOutputSchema,
|
|
6055
6114
|
annotations: liveWebToolAnnotations("Instagram Profile Content Discovery")
|
|
6056
6115
|
}, async (input) => formatInstagramProfileContent(await executor.instagramProfileContent(input), input));
|
|
6057
6116
|
server2.registerTool("instagram_media_download", {
|
|
6058
6117
|
title: "Instagram Post/Reel Media Download",
|
|
6059
|
-
description: withReportNote("Extract and download media from one Instagram post, reel, or tv URL
|
|
6118
|
+
description: withReportNote("Extract and download media from one Instagram post, reel, or tv URL \u2014 image, caption, video/audio tracks, optional muxed MP4, or transcript. Selects the best video/audio track pair and muxes when ffmpeg is available."),
|
|
6060
6119
|
inputSchema: InstagramMediaDownloadInputSchema,
|
|
6061
6120
|
outputSchema: InstagramMediaDownloadOutputSchema,
|
|
6062
6121
|
annotations: liveWebToolAnnotations("Instagram Post/Reel Media Download")
|
|
6063
6122
|
}, async (input) => formatInstagramMediaDownload(await executor.instagramMediaDownload(input), input));
|
|
6064
6123
|
server2.registerTool("maps_place_intel", {
|
|
6065
6124
|
title: "Google Maps Business Profile Details",
|
|
6066
|
-
description: withReportNote(
|
|
6125
|
+
description: withReportNote("Extract Google Maps business intelligence for one known/named business: rating, reviews, category, address, phone, hours, entity IDs. Not for category searches or multi-business prospect lists \u2014 use maps_search for those. Split business name from location."),
|
|
6067
6126
|
inputSchema: MapsPlaceIntelInputSchema,
|
|
6068
6127
|
outputSchema: MapsPlaceIntelOutputSchema,
|
|
6069
6128
|
annotations: liveWebToolAnnotations("Google Maps Business Profile Details")
|
|
6070
6129
|
}, async (input) => formatMapsPlaceIntel(await executor.mapsPlaceIntel(input), input));
|
|
6071
6130
|
server2.registerTool("maps_search", {
|
|
6072
6131
|
title: "Google Maps Business Search",
|
|
6073
|
-
description: withReportNote(
|
|
6132
|
+
description: withReportNote("Search Google Maps for multiple businesses by category, niche, or local market \u2014 leads, prospects, competitors, or beyond the 3-pack. Leave proxyMode unset. Returns up to 50 candidates (default 10) with names, place URLs, CIDs, ratings."),
|
|
6074
6133
|
inputSchema: MapsSearchInputSchema,
|
|
6075
6134
|
outputSchema: MapsSearchOutputSchema,
|
|
6076
6135
|
annotations: liveWebToolAnnotations("Google Maps Business Search")
|
|
6077
6136
|
}, async (input) => formatMapsSearch(await executor.mapsSearch(input), input));
|
|
6078
6137
|
server2.registerTool("directory_workflow", {
|
|
6079
6138
|
title: "Directory Workflow: Markets + Maps",
|
|
6080
|
-
description: withReportNote('Build directory/prospecting datasets
|
|
6139
|
+
description: withReportNote('Build directory/prospecting datasets: selects US city markets from Census population data, optionally joins configured ZIP groups, then runs Google Maps business searches per city in parallel. Use for "all cities over 100k population in a state" or market+Maps workflows. Saves a CSV of results per city. For ZIP enrichment, set MCP_SCRAPER_USZIPS_CSV_PATH on the server, or pass usZipsCsvPath in local/test mode.'),
|
|
6081
6140
|
inputSchema: DirectoryWorkflowInputSchema,
|
|
6082
6141
|
outputSchema: DirectoryWorkflowOutputSchema,
|
|
6083
6142
|
annotations: liveWebToolAnnotations("Directory Workflow: Markets + Maps")
|
|
6084
6143
|
}, async (input) => formatDirectoryWorkflow(await executor.directoryWorkflow(input), input));
|
|
6085
6144
|
server2.registerTool("workflow_list", {
|
|
6086
6145
|
title: "Workflow Catalog",
|
|
6087
|
-
description: "List MCP Scraper higher-level workflows and
|
|
6146
|
+
description: "List MCP Scraper higher-level workflows and recipes \u2014 market analysis, ICP research, CRO audits, competitive positioning, content gap briefs, AI search visibility, and more. Returns runnable workflow ids plus tool-chain guidance.",
|
|
6088
6147
|
inputSchema: WorkflowListInputSchema,
|
|
6089
6148
|
outputSchema: WorkflowListOutputSchema,
|
|
6090
6149
|
annotations: localPlanningToolAnnotations("Workflow Catalog")
|
|
6091
6150
|
}, async (input) => formatWorkflowList(await executor.workflowList(input), input));
|
|
6092
6151
|
server2.registerTool("workflow_suggest", {
|
|
6093
6152
|
title: "Workflow Intent Router",
|
|
6094
|
-
description:
|
|
6153
|
+
description: "Route a high-level business/research goal (market analysis, ICP research, CRO audit, competitor comparison, content gap brief, AI search visibility, etc) to the right MCP Scraper workflow/tool chain. Free; tells you what to run next.",
|
|
6095
6154
|
inputSchema: WorkflowSuggestInputSchema,
|
|
6096
6155
|
outputSchema: WorkflowSuggestOutputSchema,
|
|
6097
6156
|
annotations: localPlanningToolAnnotations("Workflow Intent Router")
|
|
6098
6157
|
}, async (input) => formatWorkflowSuggest(input));
|
|
6099
6158
|
server2.registerTool("workflow_run", {
|
|
6100
6159
|
title: "Run Workflow",
|
|
6101
|
-
description: withReportNote("Start a higher-level MCP Scraper workflow
|
|
6160
|
+
description: withReportNote("Start a higher-level MCP Scraper workflow (directory, agent-packet, local-competitive-audit, map-comparison, serp-comparison, paa-expansion-brief, ai-overview-language). Use after workflow_suggest or workflow_list. Stepwise workflows return runId + nextStep \u2014 call workflow_step with the runId until done is true."),
|
|
6102
6161
|
inputSchema: WorkflowRunInputSchema,
|
|
6103
6162
|
outputSchema: WorkflowRunOutputSchema,
|
|
6104
6163
|
annotations: liveWebToolAnnotations("Run Workflow")
|
|
6105
6164
|
}, async (input) => formatWorkflowRun(await executor.workflowRun(input), input));
|
|
6106
6165
|
server2.registerTool("workflow_step", {
|
|
6107
6166
|
title: "Advance Workflow Step",
|
|
6108
|
-
description: withReportNote("Run the next leg of a stepwise
|
|
6167
|
+
description: withReportNote("Run the next leg of a stepwise workflow started with workflow_run. Pass the runId; each call executes one step and returns its output plus nextStep. Keep calling with the same runId until done is true."),
|
|
6109
6168
|
inputSchema: WorkflowStepInputSchema,
|
|
6110
6169
|
outputSchema: WorkflowStepOutputSchema,
|
|
6111
6170
|
annotations: liveWebToolAnnotations("Advance Workflow Step")
|
|
6112
6171
|
}, async (input) => formatWorkflowStep(await executor.workflowStep(input), input));
|
|
6113
6172
|
server2.registerTool("workflow_status", {
|
|
6114
6173
|
title: "Workflow Status",
|
|
6115
|
-
description: "Fetch a hosted workflow run by id and list its current status and artifacts
|
|
6174
|
+
description: "Fetch a hosted workflow run by id and list its current status and artifacts, to re-open a run or recover artifact ids. Use only a runId returned by workflow_run/workflow_step/workflow_status.",
|
|
6116
6175
|
inputSchema: WorkflowStatusInputSchema,
|
|
6117
6176
|
outputSchema: WorkflowStatusOutputSchema,
|
|
6118
6177
|
annotations: liveWebToolAnnotations("Workflow Status")
|
|
6119
6178
|
}, async (input) => formatWorkflowStatus(await executor.workflowStatus(input), input));
|
|
6120
6179
|
server2.registerTool("workflow_artifact_read", {
|
|
6121
6180
|
title: "Read Workflow Artifact",
|
|
6122
|
-
description: "Read a workflow artifact back into
|
|
6181
|
+
description: "Read a workflow artifact back into context by run id and artifact id, so final deliverables are grounded in generated evidence rather than memory. Use workflow_status first when artifact ids are unknown. Use maxBytes to limit large artifacts.",
|
|
6123
6182
|
inputSchema: WorkflowArtifactReadInputSchema,
|
|
6124
6183
|
outputSchema: WorkflowArtifactReadOutputSchema,
|
|
6125
6184
|
annotations: liveWebToolAnnotations("Read Workflow Artifact")
|
|
6126
6185
|
}, async (input) => formatWorkflowArtifactRead(await executor.workflowArtifactRead(input), input));
|
|
6127
6186
|
server2.registerTool("rank_tracker_workflow", {
|
|
6128
6187
|
title: "Rank Tracker Blueprint Builder",
|
|
6129
|
-
description: "Generate a build-ready database, cron
|
|
6188
|
+
description: "Generate a build-ready database schema, cron plan, and implementation prompt for a rank tracker powered by MCP Scraper (Maps, organic, AI Overview, or PAA tracking). Local planning only \u2014 does not call the web or spend credits.",
|
|
6130
6189
|
inputSchema: RankTrackerBlueprintInputSchema,
|
|
6131
6190
|
outputSchema: RankTrackerBlueprintOutputSchema,
|
|
6132
6191
|
annotations: localPlanningToolAnnotations("Rank Tracker Blueprint Builder")
|
|
6133
6192
|
}, async (input) => buildRankTrackerBlueprint(input));
|
|
6134
6193
|
server2.registerTool("credits_info", {
|
|
6135
6194
|
title: "MCP Scraper Credits & Costs",
|
|
6136
|
-
description: "Answer questions about MCP Scraper credits, usage limits, and concurrency upgrades
|
|
6195
|
+
description: "Answer questions about MCP Scraper credits, usage limits, and concurrency upgrades \u2014 balance, tool costs, concurrency limits, billing URL. Does not expose payment methods or card information.",
|
|
6137
6196
|
inputSchema: CreditsInfoInputSchema,
|
|
6138
6197
|
outputSchema: CreditsInfoOutputSchema,
|
|
6139
6198
|
annotations: {
|