mcp-scraper 0.3.8 → 0.3.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/bin/api-server.cjs +116 -3
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/browser-agent-stdio-server.cjs +99 -30
- package/dist/bin/browser-agent-stdio-server.cjs.map +1 -1
- package/dist/bin/browser-agent-stdio-server.js +2 -2
- 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-combined-stdio-server.cjs +105 -36
- package/dist/bin/mcp-scraper-combined-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-scraper-combined-stdio-server.js +4 -4
- package/dist/bin/mcp-scraper-install.cjs +7 -7
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +1 -1
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/{chunk-FU3WERZ7.js → chunk-CED7X4WB.js} +2 -2
- package/dist/{chunk-ELI6NDEG.js → chunk-KPXMPAJ3.js} +7 -7
- package/dist/chunk-KPXMPAJ3.js.map +1 -0
- package/dist/chunk-NEGW2ZEJ.js +7 -0
- package/dist/chunk-NEGW2ZEJ.js.map +1 -0
- package/dist/{chunk-VQFVA6RH.js → chunk-QPFF3V2R.js} +100 -31
- package/dist/chunk-QPFF3V2R.js.map +1 -0
- package/dist/{server-7CGBJWJY.js → server-QTV2EUKA.js} +118 -5
- package/dist/{server-7CGBJWJY.js.map → server-QTV2EUKA.js.map} +1 -1
- package/docs/mcp-tool-craft-lint.generated.md +3 -2
- package/docs/mcp-tool-manifest.generated.json +43 -13
- package/package.json +1 -1
- package/dist/chunk-7I6PA2UQ.js +0 -7
- package/dist/chunk-7I6PA2UQ.js.map +0 -1
- package/dist/chunk-ELI6NDEG.js.map +0 -1
- package/dist/chunk-VQFVA6RH.js.map +0 -1
- /package/dist/{chunk-FU3WERZ7.js.map → chunk-CED7X4WB.js.map} +0 -0
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
HttpMcpToolExecutor,
|
|
4
4
|
buildPaaExtractorMcpServer
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-CED7X4WB.js";
|
|
6
6
|
import "../chunk-M2S27J6Z.js";
|
|
7
7
|
import "../chunk-LFATOGDF.js";
|
|
8
|
-
import "../chunk-
|
|
8
|
+
import "../chunk-NEGW2ZEJ.js";
|
|
9
9
|
|
|
10
10
|
// bin/mcp-stdio-server.ts
|
|
11
11
|
import { readFileSync } from "fs";
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-LFATOGDF.js";
|
|
8
8
|
import {
|
|
9
9
|
PACKAGE_VERSION
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-NEGW2ZEJ.js";
|
|
11
11
|
|
|
12
12
|
// src/harvest-timeout.ts
|
|
13
13
|
var VERCEL_FUNCTION_MAX_MS = 3e5;
|
|
@@ -3335,4 +3335,4 @@ export {
|
|
|
3335
3335
|
registerPaaExtractorMcpTools,
|
|
3336
3336
|
HttpMcpToolExecutor
|
|
3337
3337
|
};
|
|
3338
|
-
//# sourceMappingURL=chunk-
|
|
3338
|
+
//# sourceMappingURL=chunk-CED7X4WB.js.map
|
|
@@ -48,14 +48,14 @@ function renderInstallTerminal(options) {
|
|
|
48
48
|
colorize(ascii, "amber", color),
|
|
49
49
|
`${colorize("MCP Scraper Agent", "cyan", color)} . v${options.version} . mcpscraper.dev`,
|
|
50
50
|
"1/1 install surfaces ready",
|
|
51
|
-
colorize("Newest: saved hosted browser profiles for AI visibility.
|
|
51
|
+
colorize("Newest: saved hosted browser profiles for AI visibility. Share the watch_url, user signs in, then verify with browser_profile_status. Browser sessions are direct/no-proxy by default.", "lime", color),
|
|
52
52
|
"",
|
|
53
|
-
`${colorize("Tools", "cyan", color)} ${colorize("(
|
|
53
|
+
`${colorize("Tools", "cyan", color)} ${colorize("(44 MCP tools)", "muted", color)}`,
|
|
54
54
|
toolRow("search", ["harvest_paa", "search_serp", "maps_search", "maps_place_intel"], color),
|
|
55
55
|
toolRow("extract", ["extract_url", "map_site_urls", "extract_site", "directory_workflow"], color),
|
|
56
56
|
toolRow("build", ["rank_tracker_blueprint", "cron plan", "database prompt"], color),
|
|
57
57
|
toolRow("media", ["youtube_harvest", "youtube_transcribe", "facebook_ad_search", "facebook_page_intel", "facebook_ad_transcribe", "facebook_video_transcribe", "instagram_profile_content", "instagram_media_download"], color),
|
|
58
|
-
toolRow("browser", ["browser_open", "browser_profile_onboard", "browser_close", "browser_screenshot", "browser_read", "browser_locate", "browser_replay_mark", "browser_replay_annotate"], color),
|
|
58
|
+
toolRow("browser", ["browser_open", "browser_profile_onboard", "browser_profile_status", "browser_close", "browser_screenshot", "browser_read", "browser_locate", "browser_replay_mark", "browser_replay_annotate"], color),
|
|
59
59
|
toolRow("account", ["credits_info", "reports", "MCP resources"], color),
|
|
60
60
|
`${colorize("Workflows", "cyan", color)} ${colorize("(MCP + CLI + API)", "muted", color)}`,
|
|
61
61
|
toolRow("route", ["workflow_list", "workflow_suggest", "workflow_run", "workflow_step", "workflow_status", "workflow_artifact_read"], color),
|
|
@@ -65,7 +65,7 @@ function renderInstallTerminal(options) {
|
|
|
65
65
|
"Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.",
|
|
66
66
|
"Run mcp-scraper-combined in a human terminal to print this card; MCP clients get the same command as a silent stdio server.",
|
|
67
67
|
"Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install",
|
|
68
|
-
"Customer auth setup: run browser_profile_onboard
|
|
68
|
+
"Customer auth setup: run browser_profile_onboard, send the watch_url, let the user sign in, then call browser_profile_status until AUTHENTICATED.",
|
|
69
69
|
"Reconnect setup: if a saved profile shows login controls later, run browser_profile_onboard again with the same profile name.",
|
|
70
70
|
"Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.",
|
|
71
71
|
"For MCP clients, use mcp-scraper-combined so one install can mix SERP, Maps, browser, reports, and saved MCP resources.",
|
|
@@ -77,8 +77,8 @@ function renderInstallTerminal(options) {
|
|
|
77
77
|
"npx -y -p mcp-scraper@latest mcp-scraper-cli doctor",
|
|
78
78
|
"",
|
|
79
79
|
colorize("Hosted profile setup", "amber", color),
|
|
80
|
-
'In your MCP client, call browser_profile_onboard with
|
|
81
|
-
"Give the returned watch_url to the user. After they sign in, call
|
|
80
|
+
'In your MCP client, call browser_profile_onboard with email="seo@example.com" and domain="chatgpt.com".',
|
|
81
|
+
"Give the returned watch_url to the user. After they sign in, call browser_profile_status, then browser_open with the returned profile.",
|
|
82
82
|
"",
|
|
83
83
|
colorize("Claude Code one-command setup", "amber", color),
|
|
84
84
|
claudeCommand,
|
|
@@ -100,4 +100,4 @@ function renderInstallTerminal(options) {
|
|
|
100
100
|
export {
|
|
101
101
|
renderInstallTerminal
|
|
102
102
|
};
|
|
103
|
-
//# sourceMappingURL=chunk-
|
|
103
|
+
//# sourceMappingURL=chunk-KPXMPAJ3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/install-terminal.ts"],"sourcesContent":["export interface InstallTerminalOptions {\n color?: boolean\n version: string\n apiKeyConfigured?: boolean\n}\n\ntype Tone = 'cyan' | 'lime' | 'amber' | 'red' | 'muted' | 'bold'\n\nconst CODES: Record<Tone | 'reset', string> = {\n reset: '\\x1b[0m',\n cyan: '\\x1b[36m',\n lime: '\\x1b[32m',\n amber: '\\x1b[33m',\n red: '\\x1b[31m',\n muted: '\\x1b[90m',\n bold: '\\x1b[1m',\n}\n\nfunction colorize(value: string, tone: Tone, enabled: boolean): string {\n if (!enabled) return value\n return `${CODES[tone]}${value}${CODES.reset}`\n}\n\nfunction toolRow(label: string, tools: string[], enabled: boolean): string {\n const padded = label.padEnd(9, ' ')\n return ` ${colorize(padded, 'muted', enabled)} ${tools.join(colorize(' . ', 'muted', enabled))}`\n}\n\nexport function renderInstallTerminal(options: InstallTerminalOptions): string {\n const color = options.color ?? true\n const apiKeyValue = options.apiKeyConfigured ? '$MCP_SCRAPER_API_KEY' : 'sk_live_your_key'\n const ascii = String.raw`\n __ __ ____ ____ \n| \\/ |/ ___| _ \\\n| |\\/| | | | |_) |\n| | | | |___| __/\n|_| |_|\\____|_|\n\n ____ ____ ____ _ ____ _____ ____\n/ ___| / ___| _ \\ / \\ | _ \\| ____| _ \\\n\\___ \\| | | |_) | / _ \\ | |_) | _| | |_) |\n ___) | |___| _ < / ___ \\| __/| |___| _ <\n|____/ \\____|_| \\_\\/_/ \\_\\_| |_____|_| \\_\\\n`\n\n const claudeCommand = [\n `MCP_SCRAPER_API_KEY=${apiKeyValue} npx -y -p mcp-scraper@latest \\\\`,\n ' mcp-scraper-cli agent install claude --apply',\n ].join('\\n')\n\n const codexConfig = [\n '[mcp_servers.mcp-scraper]',\n 'command = \"npx\"',\n 'args = [\"-y\", \"-p\", \"mcp-scraper@latest\", \"mcp-scraper-combined\"]',\n `env = { MCP_SCRAPER_API_KEY = \"${apiKeyValue}\" }`,\n ].join('\\n')\n\n return [\n colorize(`mcp-scraper v${options.version}`, 'bold', color),\n colorize('> mcp-scraper-install', 'muted', color),\n colorize(ascii, 'amber', color),\n `${colorize('MCP Scraper Agent', 'cyan', color)} . v${options.version} . mcpscraper.dev`,\n '1/1 install surfaces ready',\n colorize('Newest: saved hosted browser profiles for AI visibility. Share the watch_url, user signs in, then verify with browser_profile_status. Browser sessions are direct/no-proxy by default.', 'lime', color),\n '',\n `${colorize('Tools', 'cyan', color)} ${colorize('(44 MCP tools)', 'muted', color)}`,\n toolRow('search', ['harvest_paa', 'search_serp', 'maps_search', 'maps_place_intel'], color),\n toolRow('extract', ['extract_url', 'map_site_urls', 'extract_site', 'directory_workflow'], color),\n toolRow('build', ['rank_tracker_blueprint', 'cron plan', 'database prompt'], color),\n toolRow('media', ['youtube_harvest', 'youtube_transcribe', 'facebook_ad_search', 'facebook_page_intel', 'facebook_ad_transcribe', 'facebook_video_transcribe', 'instagram_profile_content', 'instagram_media_download'], color),\n toolRow('browser', ['browser_open', 'browser_profile_onboard', 'browser_profile_status', 'browser_close', 'browser_screenshot', 'browser_read', 'browser_locate', 'browser_replay_mark', 'browser_replay_annotate'], color),\n toolRow('account', ['credits_info', 'reports', 'MCP resources'], color),\n `${colorize('Workflows', 'cyan', color)} ${colorize('(MCP + CLI + API)', 'muted', color)}`,\n toolRow('route', ['workflow_list', 'workflow_suggest', 'workflow_run', 'workflow_step', 'workflow_status', 'workflow_artifact_read'], color),\n toolRow('seo', ['directory', 'agent-packet', 'competitive audit', 'map/serp comparison', 'PAA/AIO briefs', 'scheduled runs'], color),\n '',\n colorize('Usage tips:', 'amber', color),\n 'Run mcp-scraper-install for this visible card. Run mcp-scraper-cli for setup utilities and subcommands.',\n 'Run mcp-scraper-combined in a human terminal to print this card; MCP clients get the same command as a silent stdio server.',\n 'Explicit card command: npx -y -p mcp-scraper@latest mcp-scraper-install',\n 'Customer auth setup: run browser_profile_onboard, send the watch_url, let the user sign in, then call browser_profile_status until AUTHENTICATED.',\n 'Reconnect setup: if a saved profile shows login controls later, run browser_profile_onboard again with the same profile name.',\n 'Start with workflow_suggest for broad jobs like market analysis, ICP research, CRO audits, brand briefs, content gaps, and AI visibility.',\n 'For MCP clients, use mcp-scraper-combined so one install can mix SERP, Maps, browser, reports, and saved MCP resources.',\n 'If you hit the concurrency limit, add an extra slot for $5/month with mcp-scraper-cli billing concurrency checkout.',\n '',\n `${colorize('Ready.', 'lime', color)} Install the combined MCP server with one command:`,\n '',\n colorize('Setup doctor', 'amber', color),\n 'npx -y -p mcp-scraper@latest mcp-scraper-cli doctor',\n '',\n colorize('Hosted profile setup', 'amber', color),\n 'In your MCP client, call browser_profile_onboard with email=\"seo@example.com\" and domain=\"chatgpt.com\".',\n 'Give the returned watch_url to the user. After they sign in, call browser_profile_status, then browser_open with the returned profile.',\n '',\n colorize('Claude Code one-command setup', 'amber', color),\n claudeCommand,\n 'Then fully exit Claude Code and open a new Claude terminal. Check with: claude mcp list',\n '',\n colorize('Codex config', 'amber', color),\n codexConfig,\n '',\n colorize('Claude Desktop Extension', 'amber', color),\n 'Download: https://mcpscraper.dev/downloads/mcp-scraper.mcpb',\n '',\n colorize('Safety note:', 'muted', color),\n 'mcp-scraper-combined prints this card only when stdin/stdout are an interactive TTY. In MCP clients it writes only JSON-RPC to stdout.',\n 'Use --stdio or MCP_SCRAPER_FORCE_STDIO=1 to force server mode from a terminal.',\n '',\n ].join('\\n')\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = '0.3.10'\n"],"mappings":";AAAO,IAAM,kBAAkB;","names":[]}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-WN7PBKMV.js";
|
|
5
5
|
import {
|
|
6
6
|
PACKAGE_VERSION
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NEGW2ZEJ.js";
|
|
8
8
|
|
|
9
9
|
// src/mcp/browser-agent-mcp-server.ts
|
|
10
10
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -36,10 +36,17 @@ var BrowserOpenInputSchema = {
|
|
|
36
36
|
var BrowserProfileOnboardInputSchema = {
|
|
37
37
|
email: z.string().optional().describe("Optional account email used to derive a stable MCP Scraper profile name. This does not import cookies or browser state."),
|
|
38
38
|
profile: z.string().optional().describe("Optional saved MCP Scraper hosted browser profile name to create or load. If omitted, email is used to derive one."),
|
|
39
|
-
|
|
39
|
+
domain: z.string().optional().describe("Authenticated site domain to connect to the profile. Defaults to chatgpt.com for AI visibility fan-out tracking."),
|
|
40
|
+
login_url: z.string().url().optional().describe("Optional login URL for the target domain. Defaults to https://chatgpt.com/ when domain is omitted."),
|
|
41
|
+
url: z.string().url().optional().describe("Deprecated alias for login_url. Use login_url for the target site login page."),
|
|
40
42
|
label: z.string().optional().describe("Optional human label for this setup session."),
|
|
41
43
|
timeout_seconds: z.number().int().min(60).max(259200).optional().describe("How long the direct no-proxy setup session may live before auto-termination. Defaults to 600.")
|
|
42
44
|
};
|
|
45
|
+
var BrowserProfileStatusInputSchema = {
|
|
46
|
+
connection_id: z.string().optional().describe("Auth connection id returned by browser_profile_onboard. Prefer this when available."),
|
|
47
|
+
profile: z.string().optional().describe("Saved hosted profile name to check when connection_id is unavailable."),
|
|
48
|
+
domain: z.string().optional().describe("Authenticated site domain to check with profile. Defaults to chatgpt.com when omitted.")
|
|
49
|
+
};
|
|
43
50
|
var BrowserSessionInputSchema = {
|
|
44
51
|
session_id: z.string().describe("The session id returned by browser_open or browser_list_sessions. Use only a returned session_id; do not construct one yourself.")
|
|
45
52
|
};
|
|
@@ -211,15 +218,36 @@ var BrowserOpenOutputSchema = {
|
|
|
211
218
|
var BrowserProfileOnboardOutputSchema = {
|
|
212
219
|
ok: z.boolean(),
|
|
213
220
|
tool: z.literal("browser_profile_onboard"),
|
|
214
|
-
session_id:
|
|
221
|
+
session_id: NullableString,
|
|
222
|
+
auth_connection_id: z.string(),
|
|
215
223
|
watch_url: z.string(),
|
|
216
224
|
live_view_url: NullableString,
|
|
217
225
|
profile: z.string(),
|
|
226
|
+
domain: z.string(),
|
|
218
227
|
setup_url: z.string(),
|
|
219
228
|
account_email: NullableString,
|
|
229
|
+
status: z.string(),
|
|
230
|
+
flow_status: NullableString,
|
|
231
|
+
flow_step: NullableString,
|
|
232
|
+
flow_expires_at: NullableString,
|
|
233
|
+
post_login_url: NullableString,
|
|
220
234
|
next_steps: z.array(z.string()),
|
|
221
235
|
raw: BrowserRawObject.optional()
|
|
222
236
|
};
|
|
237
|
+
var BrowserProfileStatusOutputSchema = {
|
|
238
|
+
ok: z.boolean(),
|
|
239
|
+
tool: z.literal("browser_profile_status"),
|
|
240
|
+
session_id: NullableString,
|
|
241
|
+
auth_connection_id: z.string(),
|
|
242
|
+
profile: z.string(),
|
|
243
|
+
domain: z.string(),
|
|
244
|
+
status: z.string(),
|
|
245
|
+
flow_status: NullableString,
|
|
246
|
+
flow_step: NullableString,
|
|
247
|
+
flow_expires_at: NullableString,
|
|
248
|
+
post_login_url: NullableString,
|
|
249
|
+
raw: BrowserRawObject.optional()
|
|
250
|
+
};
|
|
223
251
|
var BrowserScreenshotOutputSchema = {
|
|
224
252
|
...BrowserBaseOutput,
|
|
225
253
|
tool: z.literal("browser_screenshot"),
|
|
@@ -626,10 +654,16 @@ function replayFilePath(sessionId, replayId, filename) {
|
|
|
626
654
|
const name = requested ? safeFilePart(requested).replace(/\.mp4$/i, "") : `${stamp}-${safeFilePart(sessionId)}-${safeFilePart(replayId)}`;
|
|
627
655
|
return join2(outputBaseDir(), "browser-replays", `${name}.mp4`);
|
|
628
656
|
}
|
|
629
|
-
function
|
|
630
|
-
const
|
|
657
|
+
function slugPart(value) {
|
|
658
|
+
const trimmed = value?.trim().toLowerCase();
|
|
659
|
+
if (!trimmed) return null;
|
|
660
|
+
return trimmed.replace(/^https?:\/\//, "").replace(/^www\./, "").replace(/\/.*$/, "").replace(/[^a-z0-9._-]+/g, "-").replace(/[._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
661
|
+
}
|
|
662
|
+
function savedProfileNameFromEmail(email, domain) {
|
|
663
|
+
const value = slugPart(email);
|
|
631
664
|
if (!value) return null;
|
|
632
|
-
|
|
665
|
+
const domainPart = slugPart(domain);
|
|
666
|
+
return `${value}${domainPart ? `-${domainPart}` : ""}`.slice(0, 80) || null;
|
|
633
667
|
}
|
|
634
668
|
function annotatedReplayFilePath(sessionId, replayId, filename) {
|
|
635
669
|
const requested = filename?.trim();
|
|
@@ -720,46 +754,83 @@ function registerBrowserAgentMcpTools(server, opts) {
|
|
|
720
754
|
"browser_profile_onboard",
|
|
721
755
|
{
|
|
722
756
|
title: "Connect Hosted Browser Profile",
|
|
723
|
-
description: "Create or load a saved MCP Scraper hosted browser profile and
|
|
757
|
+
description: "Create or load a saved MCP Scraper hosted browser profile auth connection and return a user takeover login URL. This is the customer auth setup and reconnect flow for AI visibility tracking: give the user the watch_url, let them complete login for the target domain, then call browser_profile_status until status is AUTHENTICATED. If a saved profile later shows login controls, run this same setup flow again.",
|
|
724
758
|
inputSchema: BrowserProfileOnboardInputSchema,
|
|
725
759
|
outputSchema: BrowserProfileOnboardOutputSchema,
|
|
726
760
|
annotations: annotations("Connect Hosted Browser Profile")
|
|
727
761
|
},
|
|
728
762
|
async (input) => {
|
|
729
|
-
const
|
|
763
|
+
const domain = slugPart(input.domain) || "chatgpt.com";
|
|
764
|
+
const setupUrl = input.login_url ?? input.url ?? (domain === "chatgpt.com" ? "https://chatgpt.com/" : `https://${domain}/`);
|
|
765
|
+
const profile = input.profile?.trim() || savedProfileNameFromEmail(input.email, domain) || browserServiceProfileName();
|
|
730
766
|
if (!profile) {
|
|
731
767
|
return errorResult("browser_profile_onboard", {
|
|
732
768
|
error: "profile or email is required when BROWSER_AGENT_PROFILE_NAME is not available"
|
|
733
769
|
});
|
|
734
770
|
}
|
|
735
|
-
const
|
|
736
|
-
const open = await req("POST", "/agent/sessions", {
|
|
771
|
+
const open = await req("POST", "/agent/profiles/onboard", {
|
|
737
772
|
label: input.label ?? `Profile setup: ${profile}`,
|
|
738
773
|
profile,
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
timeout_seconds: input.timeout_seconds
|
|
774
|
+
domain,
|
|
775
|
+
login_url: setupUrl
|
|
742
776
|
});
|
|
743
777
|
if (!open.ok) return errorResult("browser_profile_onboard", open.data);
|
|
744
|
-
const session = open.data;
|
|
745
|
-
const goto = await req("POST", `/agent/sessions/${session.session_id}/goto`, { url: setupUrl });
|
|
746
|
-
if (!goto.ok) return errorResult("browser_profile_onboard", goto.data, session.session_id);
|
|
747
778
|
return structuredResult({
|
|
748
779
|
ok: true,
|
|
749
780
|
tool: "browser_profile_onboard",
|
|
750
|
-
session_id:
|
|
751
|
-
|
|
752
|
-
|
|
781
|
+
session_id: null,
|
|
782
|
+
auth_connection_id: open.data.connection_id,
|
|
783
|
+
watch_url: open.data.hosted_url,
|
|
784
|
+
live_view_url: open.data.live_view_url ?? null,
|
|
753
785
|
profile,
|
|
786
|
+
domain,
|
|
754
787
|
setup_url: setupUrl,
|
|
755
788
|
account_email: input.email?.trim() || null,
|
|
789
|
+
status: open.data.status ?? null,
|
|
790
|
+
flow_status: open.data.flow_status ?? null,
|
|
791
|
+
flow_step: open.data.flow_step ?? null,
|
|
792
|
+
flow_expires_at: open.data.flow_expires_at ?? null,
|
|
793
|
+
post_login_url: open.data.post_login_url ?? null,
|
|
756
794
|
next_steps: [
|
|
757
|
-
"Open the watch_url and let the user
|
|
758
|
-
"
|
|
759
|
-
"
|
|
760
|
-
"
|
|
795
|
+
"Open the watch_url and let the user complete login for the target domain.",
|
|
796
|
+
"Call browser_profile_status with auth_connection_id until status is AUTHENTICATED.",
|
|
797
|
+
"After authentication, call browser_open with this profile name and the target site URL.",
|
|
798
|
+
"If the saved profile later shows login controls or disconnects, repeat browser_profile_onboard."
|
|
761
799
|
],
|
|
762
|
-
raw:
|
|
800
|
+
raw: open.data
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
);
|
|
804
|
+
server.registerTool(
|
|
805
|
+
"browser_profile_status",
|
|
806
|
+
{
|
|
807
|
+
title: "Check Browser Profile Auth Status",
|
|
808
|
+
description: "Check whether a hosted browser profile auth connection is authenticated after browser_profile_onboard. Use auth_connection_id when available. Once status is AUTHENTICATED, use browser_open with the returned profile.",
|
|
809
|
+
inputSchema: BrowserProfileStatusInputSchema,
|
|
810
|
+
outputSchema: BrowserProfileStatusOutputSchema,
|
|
811
|
+
annotations: annotations("Check Browser Profile Auth Status", true)
|
|
812
|
+
},
|
|
813
|
+
async (input) => {
|
|
814
|
+
const domain = slugPart(input.domain) || "chatgpt.com";
|
|
815
|
+
const res = await req("POST", "/agent/profiles/status", {
|
|
816
|
+
...input.connection_id ? { connection_id: input.connection_id } : {},
|
|
817
|
+
...input.profile ? { profile: input.profile } : {},
|
|
818
|
+
domain
|
|
819
|
+
});
|
|
820
|
+
if (!res.ok) return errorResult("browser_profile_status", res.data);
|
|
821
|
+
return structuredResult({
|
|
822
|
+
ok: true,
|
|
823
|
+
tool: "browser_profile_status",
|
|
824
|
+
session_id: null,
|
|
825
|
+
auth_connection_id: res.data.connection_id,
|
|
826
|
+
profile: res.data.profile,
|
|
827
|
+
domain: res.data.domain,
|
|
828
|
+
status: res.data.status,
|
|
829
|
+
flow_status: res.data.flow_status ?? null,
|
|
830
|
+
flow_step: res.data.flow_step ?? null,
|
|
831
|
+
flow_expires_at: res.data.flow_expires_at ?? null,
|
|
832
|
+
post_login_url: res.data.post_login_url ?? null,
|
|
833
|
+
raw: res.data
|
|
763
834
|
});
|
|
764
835
|
}
|
|
765
836
|
);
|
|
@@ -767,7 +838,7 @@ function registerBrowserAgentMcpTools(server, opts) {
|
|
|
767
838
|
"browser_open",
|
|
768
839
|
{
|
|
769
840
|
title: "Open Browser Session",
|
|
770
|
-
description: "Open a direct no-proxy hosted browser session you can drive. Pass a saved profile name to load an authenticated session for a site. For customer login setup or reconnects, use browser_profile_onboard first
|
|
841
|
+
description: "Open a direct no-proxy hosted browser session you can drive. Pass a saved profile name to load an authenticated session for a site. For customer login setup or reconnects, use browser_profile_onboard first, then call browser_profile_status until status is AUTHENTICATED. Returns a session_id used by all other browser_* tools.",
|
|
771
842
|
inputSchema: BrowserOpenInputSchema,
|
|
772
843
|
outputSchema: BrowserOpenOutputSchema,
|
|
773
844
|
annotations: annotations("Open Browser Session")
|
|
@@ -780,13 +851,11 @@ function registerBrowserAgentMcpTools(server, opts) {
|
|
|
780
851
|
...profile ? { profile } : {},
|
|
781
852
|
...profile && typeof saveProfileChanges === "boolean" ? { save_profile_changes: saveProfileChanges } : {},
|
|
782
853
|
disable_default_proxy: true,
|
|
783
|
-
timeout_seconds: input.timeout_seconds
|
|
854
|
+
timeout_seconds: input.timeout_seconds,
|
|
855
|
+
...input.url ? { url: input.url } : {}
|
|
784
856
|
});
|
|
785
857
|
if (!open.ok) return errorResult("browser_open", open.data);
|
|
786
858
|
const session = open.data;
|
|
787
|
-
if (input.url) {
|
|
788
|
-
await req("POST", `/agent/sessions/${session.session_id}/goto`, { url: input.url });
|
|
789
|
-
}
|
|
790
859
|
return structuredResult({
|
|
791
860
|
ok: true,
|
|
792
861
|
tool: "browser_open",
|
|
@@ -1191,7 +1260,7 @@ function registerBrowserAgentMcpTools(server, opts) {
|
|
|
1191
1260
|
"browser_capture_fanout",
|
|
1192
1261
|
{
|
|
1193
1262
|
title: "Capture AI Search Fan-Out",
|
|
1194
|
-
description: `Capture the query fan-out behind a ChatGPT or Claude web-search answer for Answer Engine Optimization (AEO): the exact sub-queries the model issued, every researched URL split into cited vs browsed-only (with citation frequency and snippet), each source tagged by category (First-party/vendor, News/media, Reddit, Social/video, Encyclopedia, Review site, Docs, Blog), plus top sourced sites and citation order. This returns the raw structured data; YOU analyze it \u2014 classify each sub-query by funnel stage (Problem-aware, Solution-aware, Decision-aware, Retention) and type (BoFu, Branded, Comparison, How-to, Search operator), name the brands the model researched, and give AEO insights. Sample asks: "capture the fan-out for this ChatGPT answer", "what did Claude search and cite for best CRM", "show the sub-queries and sources behind this AI answer". WRITE NOTE: passing prompt submits a real message in the user's logged-in account (a new conversation turn) \u2014 only send when the user wants that; omit prompt to capture a prompt the user just ran. Setup, if not already connected or if the profile disconnected: call browser_profile_onboard, give the user the watch_url, let them
|
|
1263
|
+
description: `Capture the query fan-out behind a ChatGPT or Claude web-search answer for Answer Engine Optimization (AEO): the exact sub-queries the model issued, every researched URL split into cited vs browsed-only (with citation frequency and snippet), each source tagged by category (First-party/vendor, News/media, Reddit, Social/video, Encyclopedia, Review site, Docs, Blog), plus top sourced sites and citation order. This returns the raw structured data; YOU analyze it \u2014 classify each sub-query by funnel stage (Problem-aware, Solution-aware, Decision-aware, Retention) and type (BoFu, Branded, Comparison, How-to, Search operator), name the brands the model researched, and give AEO insights. Sample asks: "capture the fan-out for this ChatGPT answer", "what did Claude search and cite for best CRM", "show the sub-queries and sources behind this AI answer". WRITE NOTE: passing prompt submits a real message in the user's logged-in account (a new conversation turn) \u2014 only send when the user wants that; omit prompt to capture a prompt the user just ran. Setup, if not already connected or if the profile disconnected: call browser_profile_onboard, give the user the watch_url, let them complete login, then call browser_profile_status until status is AUTHENTICATED. After that, browser_open the saved direct no-proxy profile and go to chatgpt.com or claude.ai. Fan-out is captured only as it streams, so the session must be open when the prompt runs. NOT for Google AI Overview citations \u2014 use harvest_paa for those; this tool is ChatGPT and Claude only.`,
|
|
1195
1264
|
inputSchema: BrowserCaptureFanoutInputSchema,
|
|
1196
1265
|
outputSchema: BrowserCaptureFanoutOutputSchema,
|
|
1197
1266
|
annotations: annotations("Capture AI Search Fan-Out")
|
|
@@ -1233,4 +1302,4 @@ export {
|
|
|
1233
1302
|
buildBrowserAgentMcpServer,
|
|
1234
1303
|
registerBrowserAgentMcpTools
|
|
1235
1304
|
};
|
|
1236
|
-
//# sourceMappingURL=chunk-
|
|
1305
|
+
//# sourceMappingURL=chunk-QPFF3V2R.js.map
|