mcp-scraper 0.42.3 → 0.43.2

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.
Files changed (64) hide show
  1. package/README.md +2 -2
  2. package/dist/bin/api-server.cjs +3284 -2130
  3. package/dist/bin/api-server.cjs.map +1 -1
  4. package/dist/bin/api-server.js +2 -2
  5. package/dist/bin/mcp-scraper-cli.cjs +1 -1
  6. package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
  7. package/dist/bin/mcp-scraper-cli.js +3 -4
  8. package/dist/bin/mcp-scraper-cli.js.map +1 -1
  9. package/dist/bin/mcp-scraper-install.cjs +2 -2
  10. package/dist/bin/mcp-scraper-install.cjs.map +1 -1
  11. package/dist/bin/mcp-scraper-install.js +2 -2
  12. package/dist/bin/mcp-stdio-server.cjs +3361 -2817
  13. package/dist/bin/mcp-stdio-server.cjs.map +1 -1
  14. package/dist/bin/mcp-stdio-server.js +51 -24
  15. package/dist/bin/mcp-stdio-server.js.map +1 -1
  16. package/dist/bin/paa-harvest.cjs +21 -21
  17. package/dist/bin/paa-harvest.cjs.map +1 -1
  18. package/dist/bin/paa-harvest.js +2 -3
  19. package/dist/bin/paa-harvest.js.map +1 -1
  20. package/dist/{chunk-MJKVDLVR.js → chunk-2K74LVV7.js} +26 -2
  21. package/dist/{chunk-MJKVDLVR.js.map → chunk-2K74LVV7.js.map} +1 -1
  22. package/dist/{chunk-CB5C3BPB.js → chunk-3ZUBQQPQ.js} +23 -2
  23. package/dist/chunk-3ZUBQQPQ.js.map +1 -0
  24. package/dist/{chunk-6Q7V4IQV.js → chunk-6WLNXYRG.js} +19 -2
  25. package/dist/chunk-6WLNXYRG.js.map +1 -0
  26. package/dist/{chunk-G5MHJGKE.js → chunk-GUI33Q27.js} +2 -2
  27. package/dist/{chunk-DH42LIR3.js → chunk-H7LQ6PTI.js} +24 -16
  28. package/dist/chunk-H7LQ6PTI.js.map +1 -0
  29. package/dist/chunk-MD75M2L5.js +7 -0
  30. package/dist/chunk-MD75M2L5.js.map +1 -0
  31. package/dist/{chunk-ENJQ2NSX.js → chunk-TC4GDB2Q.js} +2 -2
  32. package/dist/{chunk-ENJQ2NSX.js.map → chunk-TC4GDB2Q.js.map} +1 -1
  33. package/dist/{chunk-IMUA3FJB.js → chunk-X5WDJ7D7.js} +6 -6
  34. package/dist/chunk-X5WDJ7D7.js.map +1 -0
  35. package/dist/{chunk-QKCDYMFT.js → chunk-YJNGNMDO.js} +2196 -1584
  36. package/dist/chunk-YJNGNMDO.js.map +1 -0
  37. package/dist/{chunk-FQI5PFE7.js → chunk-ZSJHRZY5.js} +3 -5
  38. package/dist/{chunk-FQI5PFE7.js.map → chunk-ZSJHRZY5.js.map} +1 -1
  39. package/dist/{extract-bundle-FH734F3R.js → extract-bundle-IOM45SFL.js} +5 -5
  40. package/dist/index.cjs +21 -21
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +21 -57
  43. package/dist/index.d.ts +21 -57
  44. package/dist/index.js +2 -3
  45. package/dist/index.js.map +1 -1
  46. package/dist/{server-B27DR4YB.js → server-BPEXEKA6.js} +800 -336
  47. package/dist/server-BPEXEKA6.js.map +1 -0
  48. package/dist/{site-extract-repository-5CVI3OWT.js → site-extract-repository-XNI4ZK2M.js} +3 -3
  49. package/dist/{worker-MQJOY4YP.js → worker-2LIOH744.js} +4 -5
  50. package/dist/{worker-MQJOY4YP.js.map → worker-2LIOH744.js.map} +1 -1
  51. package/package.json +10 -7
  52. package/dist/chunk-2YFTFT3V.js +0 -7
  53. package/dist/chunk-2YFTFT3V.js.map +0 -1
  54. package/dist/chunk-6Q7V4IQV.js.map +0 -1
  55. package/dist/chunk-CB5C3BPB.js.map +0 -1
  56. package/dist/chunk-DH42LIR3.js.map +0 -1
  57. package/dist/chunk-IMUA3FJB.js.map +0 -1
  58. package/dist/chunk-K443GQY5.js +0 -24
  59. package/dist/chunk-K443GQY5.js.map +0 -1
  60. package/dist/chunk-QKCDYMFT.js.map +0 -1
  61. package/dist/server-B27DR4YB.js.map +0 -1
  62. /package/dist/{chunk-G5MHJGKE.js.map → chunk-GUI33Q27.js.map} +0 -0
  63. /package/dist/{extract-bundle-FH734F3R.js.map → extract-bundle-IOM45SFL.js.map} +0 -0
  64. /package/dist/{site-extract-repository-5CVI3OWT.js.map → site-extract-repository-XNI4ZK2M.js.map} +0 -0
@@ -1,26 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  HttpMcpToolExecutor,
4
- MEMORY_TOOL_SCHEMAS,
4
+ MEMORY_TOOL_REGISTRY,
5
5
  SERVER_INSTRUCTIONS,
6
6
  ScheduledResultsMcpExecutor,
7
+ permitsLocalNetworkAccess,
7
8
  registerBrowserAgentMcpTools,
8
9
  registerMemoryMcpTools,
9
10
  registerPaaExtractorMcpTools,
10
11
  registerScheduledResultsMcpTools,
11
- registerSerpIntelligenceCaptureTools
12
- } from "../chunk-QKCDYMFT.js";
13
- import "../chunk-MJKVDLVR.js";
12
+ registerSerpIntelligenceCaptureTools,
13
+ resolveDeploymentProfile
14
+ } from "../chunk-YJNGNMDO.js";
15
+ import "../chunk-2K74LVV7.js";
14
16
  import "../chunk-BBI7RGOT.js";
15
17
  import "../chunk-DAS7L4SF.js";
16
18
  import {
17
19
  renderInstallTerminal
18
- } from "../chunk-ENJQ2NSX.js";
19
- import "../chunk-CB5C3BPB.js";
20
+ } from "../chunk-TC4GDB2Q.js";
20
21
  import {
21
22
  PACKAGE_VERSION
22
- } from "../chunk-2YFTFT3V.js";
23
- import "../chunk-IMUA3FJB.js";
23
+ } from "../chunk-MD75M2L5.js";
24
+ import "../chunk-X5WDJ7D7.js";
24
25
  import "../chunk-5UN33CGU.js";
25
26
  import "../chunk-FCFQ634B.js";
26
27
 
@@ -28,12 +29,12 @@ import "../chunk-FCFQ634B.js";
28
29
  import { readFileSync } from "fs";
29
30
  import { homedir } from "os";
30
31
  import { join } from "path";
31
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
32
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
32
+ import { serveStdio } from "@modelcontextprotocol/server/stdio";
33
+ import { McpServer } from "@modelcontextprotocol/server";
33
34
 
34
35
  // src/mcp/hosted-memory-mcp-tool-executor.ts
35
36
  var publicToolNameByUpstreamName = new Map(
36
- MEMORY_TOOL_SCHEMAS.map((schema) => [schema.upstreamName, schema.id])
37
+ MEMORY_TOOL_REGISTRY.map((schema) => [schema.upstreamName, schema.id])
37
38
  );
38
39
  function parseJsonRpcEnvelope(text) {
39
40
  const payloads = text.split("\n").filter((line) => line.startsWith("data:")).map((line) => line.slice(5).trim()).filter(Boolean);
@@ -118,22 +119,48 @@ if (!apiKey) {
118
119
  process.stderr.write("MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required\n");
119
120
  process.exit(1);
120
121
  }
122
+ var requiredApiKey = apiKey;
121
123
  var baseUrl = process.env.MCP_SCRAPER_BASE_URL?.trim() || process.env.MCP_BASE_URL?.trim() || "https://mcpscraper.dev";
124
+ var deploymentProfile = resolveDeploymentProfile();
125
+ var localNetworkAccess = permitsLocalNetworkAccess({
126
+ deploymentProfile,
127
+ transportProfile: "stdio",
128
+ baseUrl,
129
+ explicitlyEnabled: process.env.MCP_SCRAPER_ALLOW_PRIVATE_NETWORK === "1"
130
+ });
122
131
  var consoleBaseUrl = process.env.BROWSER_AGENT_CONSOLE_URL?.trim() || baseUrl;
123
- var server = new McpServer({ name: "mcp-scraper", version: PACKAGE_VERSION }, { instructions: SERVER_INSTRUCTIONS });
124
- var httpExecutor = new HttpMcpToolExecutor(baseUrl, apiKey);
125
- registerPaaExtractorMcpTools(server, httpExecutor);
126
- registerSerpIntelligenceCaptureTools(server, httpExecutor);
127
- registerBrowserAgentMcpTools(server, { baseUrl, apiKey, consoleBaseUrl });
128
- registerScheduledResultsMcpTools(server, new ScheduledResultsMcpExecutor(baseUrl, apiKey));
129
- registerMemoryMcpTools(server, new HostedMemoryMcpToolExecutor(baseUrl, apiKey));
130
- var transport = new StdioServerTransport();
131
- async function main() {
132
- await server.connect(transport);
132
+ function buildStdioServer() {
133
+ const server = new McpServer({ name: "mcp-scraper", version: PACKAGE_VERSION }, {
134
+ instructions: SERVER_INSTRUCTIONS,
135
+ cacheHints: {
136
+ "server/discover": { ttlMs: 3e5, cacheScope: "private" },
137
+ "tools/list": { ttlMs: 3e5, cacheScope: "private" },
138
+ "resources/list": { ttlMs: 3e5, cacheScope: "private" },
139
+ "resources/templates/list": { ttlMs: 3e5, cacheScope: "private" },
140
+ "resources/read": { ttlMs: 6e4, cacheScope: "private" }
141
+ }
142
+ });
143
+ const httpExecutor = new HttpMcpToolExecutor(baseUrl, requiredApiKey, { localNetworkAccess });
144
+ registerPaaExtractorMcpTools(server, httpExecutor, {
145
+ deploymentProfile,
146
+ transportProfile: "stdio",
147
+ baseUrl,
148
+ localNetworkAccess,
149
+ taskHandleSecret: requiredApiKey
150
+ });
151
+ registerSerpIntelligenceCaptureTools(server, httpExecutor, {
152
+ exposeDevelopmentDiagnostics: deploymentProfile === "development" || deploymentProfile === "test"
153
+ });
154
+ registerBrowserAgentMcpTools(server, { baseUrl, apiKey: requiredApiKey, consoleBaseUrl });
155
+ registerScheduledResultsMcpTools(server, new ScheduledResultsMcpExecutor(baseUrl, requiredApiKey));
156
+ registerMemoryMcpTools(server, new HostedMemoryMcpToolExecutor(baseUrl, requiredApiKey));
157
+ return server;
133
158
  }
134
- main().catch((err) => {
135
- process.stderr.write(`${err instanceof Error ? err.message : String(err)}
159
+ serveStdio(() => buildStdioServer(), {
160
+ legacy: "serve",
161
+ onerror(error) {
162
+ process.stderr.write(`${error.message}
136
163
  `);
137
- process.exit(1);
164
+ }
138
165
  });
139
166
  //# sourceMappingURL=mcp-stdio-server.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../bin/mcp-stdio-server.ts","../../src/mcp/hosted-memory-mcp-tool-executor.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { HttpMcpToolExecutor } from '../src/mcp/http-mcp-tool-executor.js'\nimport { registerBrowserAgentMcpTools } from '../src/mcp/browser-agent-mcp-server.js'\nimport { registerPaaExtractorMcpTools, registerSerpIntelligenceCaptureTools } from '../src/mcp/paa-mcp-server.js'\nimport { registerMemoryMcpTools } from '../src/mcp/memory-mcp-server.js'\nimport { HostedMemoryMcpToolExecutor } from '../src/mcp/hosted-memory-mcp-tool-executor.js'\nimport { SERVER_INSTRUCTIONS } from '../src/mcp/server-instructions.js'\nimport { renderInstallTerminal } from '../src/install-terminal.js'\nimport { PACKAGE_VERSION } from '../src/version.js'\nimport {\n registerScheduledResultsMcpTools,\n ScheduledResultsMcpExecutor,\n} from '../src/mcp/scheduled-results-mcp-server.js'\n\nconst forceStdio =\n process.argv.includes('--stdio') ||\n process.env.MCP_SCRAPER_FORCE_STDIO === '1'\nconst interactiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY)\nconst wantsHelp = process.argv.includes('--help') || process.argv.includes('-h')\n\nif (!forceStdio && (interactiveTerminal || wantsHelp)) {\n const noColor =\n process.argv.includes('--no-color') ||\n process.env.NO_COLOR !== undefined ||\n process.env.FORCE_COLOR === '0' ||\n !process.stdout.isTTY\n\n process.stdout.write(renderInstallTerminal({\n version: PACKAGE_VERSION,\n color: !noColor,\n apiKeyConfigured: Boolean(process.env.MCP_SCRAPER_API_KEY?.trim()),\n }))\n process.exit(0)\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.MCP_SCRAPER_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.mcp-scraper-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n void 0\n }\n }\n return undefined\n}\n\nconst apiKey = (\n process.env.MCP_SCRAPER_API_KEY ??\n process.env.MCP_SCRAPER_KEY ??\n process.env.MCP_API_KEY ??\n readApiKeyFile()\n)?.trim()\nif (!apiKey) {\n process.stderr.write('MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required\\n')\n process.exit(1)\n}\n\nconst baseUrl = process.env.MCP_SCRAPER_BASE_URL?.trim() || process.env.MCP_BASE_URL?.trim() || 'https://mcpscraper.dev'\nconst consoleBaseUrl = process.env.BROWSER_AGENT_CONSOLE_URL?.trim() || baseUrl\nconst server = new McpServer({ name: 'mcp-scraper', version: PACKAGE_VERSION }, { instructions: SERVER_INSTRUCTIONS })\n\nconst httpExecutor = new HttpMcpToolExecutor(baseUrl, apiKey)\nregisterPaaExtractorMcpTools(server, httpExecutor)\nregisterSerpIntelligenceCaptureTools(server, httpExecutor)\nregisterBrowserAgentMcpTools(server, { baseUrl, apiKey, consoleBaseUrl })\nregisterScheduledResultsMcpTools(server, new ScheduledResultsMcpExecutor(baseUrl, apiKey))\nregisterMemoryMcpTools(server, new HostedMemoryMcpToolExecutor(baseUrl, apiKey))\n\nconst transport = new StdioServerTransport()\n\nasync function main() {\n await server.connect(transport)\n}\n\nmain().catch(err => {\n process.stderr.write(`${err instanceof Error ? err.message : String(err)}\\n`)\n process.exit(1)\n})\n","import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js'\nimport { MEMORY_TOOL_SCHEMAS } from './memory-tool-schemas.js'\n\nconst publicToolNameByUpstreamName = new Map(\n MEMORY_TOOL_SCHEMAS.map(schema => [schema.upstreamName, schema.id]),\n)\n\ninterface JsonRpcEnvelope {\n result?: CallToolResult\n error?: { code?: number; message?: string }\n}\n\nfunction parseJsonRpcEnvelope(text: string): JsonRpcEnvelope {\n const payloads = text\n .split('\\n')\n .filter(line => line.startsWith('data:'))\n .map(line => line.slice(5).trim())\n .filter(Boolean)\n\n if (!payloads.length) return JSON.parse(text) as JsonRpcEnvelope\n\n for (const payload of payloads) {\n const parsed = JSON.parse(payload) as JsonRpcEnvelope\n if (parsed.result || parsed.error) return parsed\n }\n throw new Error('hosted MCP returned no JSON-RPC result')\n}\n\nfunction errorResult(message: string): CallToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify({ ok: false, error: message }) }],\n isError: true,\n }\n}\n\n/**\n * Stdio-only bridge for memory tools. It deliberately calls the hosted aggregate\n * MCP surface so local clients execute the same registered tool implementation\n * and output contract as https://mcpscraper.dev/mcp.\n */\nexport class HostedMemoryMcpToolExecutor {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(baseUrl: string, apiKey: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.apiKey = apiKey\n }\n\n async callMemoryTool(upstreamName: string, args: Record<string, unknown>): Promise<CallToolResult> {\n const publicToolName = publicToolNameByUpstreamName.get(upstreamName)\n if (!publicToolName) return errorResult(`unknown memory tool: ${upstreamName}`)\n\n try {\n const res = await fetch(`${this.baseUrl}/mcp`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'application/json, text/event-stream',\n 'x-api-key': this.apiKey,\n },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: `memory:${publicToolName}`,\n method: 'tools/call',\n params: { name: publicToolName, arguments: args },\n }),\n })\n const text = await res.text()\n if (!res.ok) return errorResult(`hosted memory ${publicToolName} failed (HTTP ${res.status})`)\n\n const envelope = parseJsonRpcEnvelope(text)\n if (envelope.error) {\n return errorResult(envelope.error.message ?? `hosted memory ${publicToolName} failed`)\n }\n return envelope.result ?? errorResult(`hosted memory ${publicToolName} returned no result`)\n } catch (err) {\n return errorResult(err instanceof Error ? err.message : `hosted memory ${publicToolName} call failed`)\n }\n }\n}\n"],"mappings":"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","names":["baseUrl","apiKey"]}
1
+ {"version":3,"sources":["../../bin/mcp-stdio-server.ts","../../src/mcp/hosted-memory-mcp-tool-executor.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { readFileSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { serveStdio } from '@modelcontextprotocol/server/stdio'\nimport { McpServer } from \"@modelcontextprotocol/server\";\nimport { HttpMcpToolExecutor } from '../src/mcp/http-mcp-tool-executor.js'\nimport { registerBrowserAgentMcpTools } from '../src/mcp/browser-agent-mcp-server.js'\nimport { registerPaaExtractorMcpTools, registerSerpIntelligenceCaptureTools } from '../src/mcp/paa-mcp-server.js'\nimport { registerMemoryMcpTools } from '../src/mcp/memory-mcp-server.js'\nimport { HostedMemoryMcpToolExecutor } from '../src/mcp/hosted-memory-mcp-tool-executor.js'\nimport { SERVER_INSTRUCTIONS } from '../src/mcp/server-instructions.js'\nimport { renderInstallTerminal } from '../src/install-terminal.js'\nimport { PACKAGE_VERSION } from '../src/version.js'\nimport { permitsLocalNetworkAccess, resolveDeploymentProfile } from '../src/runtime/deployment-profile.js'\nimport {\n registerScheduledResultsMcpTools,\n ScheduledResultsMcpExecutor,\n} from '../src/mcp/scheduled-results-mcp-server.js'\n\nconst forceStdio =\n process.argv.includes('--stdio') ||\n process.env.MCP_SCRAPER_FORCE_STDIO === '1'\nconst interactiveTerminal = Boolean(process.stdin.isTTY && process.stdout.isTTY)\nconst wantsHelp = process.argv.includes('--help') || process.argv.includes('-h')\n\nif (!forceStdio && (interactiveTerminal || wantsHelp)) {\n const noColor =\n process.argv.includes('--no-color') ||\n process.env.NO_COLOR !== undefined ||\n process.env.FORCE_COLOR === '0' ||\n !process.stdout.isTTY\n\n process.stdout.write(renderInstallTerminal({\n version: PACKAGE_VERSION,\n color: !noColor,\n apiKeyConfigured: Boolean(process.env.MCP_SCRAPER_API_KEY?.trim()),\n }))\n process.exit(0)\n}\n\nfunction readApiKeyFile(): string | undefined {\n const explicitPath = process.env.MCP_SCRAPER_KEY_PATH?.trim()\n const paths = [explicitPath, join(homedir(), '.mcp-scraper-key')].filter(Boolean) as string[]\n for (const path of paths) {\n try {\n const value = readFileSync(path, 'utf8').trim()\n if (value) return value\n } catch {\n void 0\n }\n }\n return undefined\n}\n\nconst apiKey = (\n process.env.MCP_SCRAPER_API_KEY ??\n process.env.MCP_SCRAPER_KEY ??\n process.env.MCP_API_KEY ??\n readApiKeyFile()\n)?.trim()\nif (!apiKey) {\n process.stderr.write('MCP_SCRAPER_API_KEY env var or ~/.mcp-scraper-key is required\\n')\n process.exit(1)\n}\nconst requiredApiKey = apiKey as string\n\nconst baseUrl = process.env.MCP_SCRAPER_BASE_URL?.trim() || process.env.MCP_BASE_URL?.trim() || 'https://mcpscraper.dev'\nconst deploymentProfile = resolveDeploymentProfile()\nconst localNetworkAccess = permitsLocalNetworkAccess({\n deploymentProfile,\n transportProfile: 'stdio',\n baseUrl,\n explicitlyEnabled: process.env.MCP_SCRAPER_ALLOW_PRIVATE_NETWORK === '1',\n})\nconst consoleBaseUrl = process.env.BROWSER_AGENT_CONSOLE_URL?.trim() || baseUrl\nfunction buildStdioServer(): McpServer {\n const server = new McpServer({ name: 'mcp-scraper', version: PACKAGE_VERSION }, {\n instructions: SERVER_INSTRUCTIONS,\n cacheHints: {\n 'server/discover': { ttlMs: 300_000, cacheScope: 'private' },\n 'tools/list': { ttlMs: 300_000, cacheScope: 'private' },\n 'resources/list': { ttlMs: 300_000, cacheScope: 'private' },\n 'resources/templates/list': { ttlMs: 300_000, cacheScope: 'private' },\n 'resources/read': { ttlMs: 60_000, cacheScope: 'private' },\n },\n })\n const httpExecutor = new HttpMcpToolExecutor(baseUrl, requiredApiKey, { localNetworkAccess })\n registerPaaExtractorMcpTools(server, httpExecutor, {\n deploymentProfile,\n transportProfile: 'stdio',\n baseUrl,\n localNetworkAccess,\n taskHandleSecret: requiredApiKey,\n })\n registerSerpIntelligenceCaptureTools(server, httpExecutor, {\n exposeDevelopmentDiagnostics: deploymentProfile === 'development' || deploymentProfile === 'test',\n })\n registerBrowserAgentMcpTools(server, { baseUrl, apiKey: requiredApiKey, consoleBaseUrl })\n registerScheduledResultsMcpTools(server, new ScheduledResultsMcpExecutor(baseUrl, requiredApiKey))\n registerMemoryMcpTools(server, new HostedMemoryMcpToolExecutor(baseUrl, requiredApiKey))\n return server\n}\n\nserveStdio(() => buildStdioServer(), {\n legacy: 'serve',\n onerror(error) {\n process.stderr.write(`${error.message}\\n`)\n },\n})\n","import type { CallToolResult } from \"@modelcontextprotocol/server\";\nimport { MEMORY_TOOL_REGISTRY } from './memory-tool-registry.js'\n\nconst publicToolNameByUpstreamName = new Map(\n MEMORY_TOOL_REGISTRY.map(schema => [schema.upstreamName, schema.id]),\n)\n\ninterface JsonRpcEnvelope {\n result?: CallToolResult\n error?: { code?: number; message?: string }\n}\n\nfunction parseJsonRpcEnvelope(text: string): JsonRpcEnvelope {\n const payloads = text\n .split('\\n')\n .filter(line => line.startsWith('data:'))\n .map(line => line.slice(5).trim())\n .filter(Boolean)\n\n if (!payloads.length) return JSON.parse(text) as JsonRpcEnvelope\n\n for (const payload of payloads) {\n const parsed = JSON.parse(payload) as JsonRpcEnvelope\n if (parsed.result || parsed.error) return parsed\n }\n throw new Error('hosted MCP returned no JSON-RPC result')\n}\n\nfunction errorResult(message: string): CallToolResult {\n return {\n content: [{ type: 'text', text: JSON.stringify({ ok: false, error: message }) }],\n isError: true,\n }\n}\n\n/**\n * Stdio-only bridge for memory tools. It deliberately calls the hosted aggregate\n * MCP surface so local clients execute the same registered tool implementation\n * and output contract as https://mcpscraper.dev/mcp.\n */\nexport class HostedMemoryMcpToolExecutor {\n private readonly baseUrl: string\n private readonly apiKey: string\n\n constructor(baseUrl: string, apiKey: string) {\n this.baseUrl = baseUrl.replace(/\\/$/, '')\n this.apiKey = apiKey\n }\n\n async callMemoryTool(upstreamName: string, args: Record<string, unknown>): Promise<CallToolResult> {\n const publicToolName = publicToolNameByUpstreamName.get(upstreamName)\n if (!publicToolName) return errorResult(`unknown memory tool: ${upstreamName}`)\n\n try {\n const res = await fetch(`${this.baseUrl}/mcp`, {\n method: 'POST',\n headers: {\n 'content-type': 'application/json',\n accept: 'application/json, text/event-stream',\n 'x-api-key': this.apiKey,\n },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: `memory:${publicToolName}`,\n method: 'tools/call',\n params: { name: publicToolName, arguments: args },\n }),\n })\n const text = await res.text()\n if (!res.ok) return errorResult(`hosted memory ${publicToolName} failed (HTTP ${res.status})`)\n\n const envelope = parseJsonRpcEnvelope(text)\n if (envelope.error) {\n return errorResult(envelope.error.message ?? `hosted memory ${publicToolName} failed`)\n }\n return envelope.result ?? errorResult(`hosted memory ${publicToolName} returned no result`)\n } catch (err) {\n return errorResult(err instanceof Error ? err.message : `hosted memory ${publicToolName} call failed`)\n }\n }\n}\n"],"mappings":"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","names":["baseUrl","apiKey"]}
@@ -546,11 +546,21 @@ async function ensureKernelProfile(kernelClient, name) {
546
546
  if (!isKernelProfileConflict(err)) throw err;
547
547
  }
548
548
  }
549
- function rankCheckContextOptions(config) {
549
+ async function detectRuntimeUserAgent(browser) {
550
+ try {
551
+ const page = browser.contexts()[0]?.pages()[0];
552
+ if (!page) return null;
553
+ const ua = await page.evaluate(() => navigator.userAgent);
554
+ return typeof ua === "string" && /Chrome\/\d+/.test(ua) ? ua : null;
555
+ } catch {
556
+ return null;
557
+ }
558
+ }
559
+ function rankCheckContextOptions(config, runtimeUserAgent) {
550
560
  return {
551
561
  viewport: config.viewport,
552
562
  locale: config.locale,
553
- userAgent: config.userAgent ?? (config.isMobile ? MOBILE_USER_AGENT : DESKTOP_USER_AGENT),
563
+ userAgent: config.userAgent ?? (config.isMobile ? MOBILE_USER_AGENT : runtimeUserAgent ?? DESKTOP_USER_AGENT),
554
564
  ...config.deviceScaleFactor ? { deviceScaleFactor: config.deviceScaleFactor } : {},
555
565
  ...config.isMobile !== void 0 ? { isMobile: config.isMobile } : {},
556
566
  ...config.hasTouch !== void 0 ? { hasTouch: config.hasTouch } : {}
@@ -647,7 +657,7 @@ var BrowserDriver = class {
647
657
  this.kernelHeadlessSent = useHeadless ? true : null;
648
658
  if (costCtx?.headlessSentOut) costCtx.headlessSentOut.value = this.kernelHeadlessSent;
649
659
  const kernelBrowser = await this.kernelClient.browsers.create({
650
- stealth: true,
660
+ stealth: config.kernelStealth === true,
651
661
  timeout_seconds: timeoutSeconds,
652
662
  ...useHeadless ? { headless: true } : {},
653
663
  ...config.kernelProxyId ? { proxy_id: config.kernelProxyId } : {},
@@ -712,7 +722,9 @@ var BrowserDriver = class {
712
722
  await this.populateKernelRetrieveDebug(kernelDebug, config.kernelProxyId);
713
723
  }
714
724
  this.browser = await import_playwright.chromium.connectOverCDP(kernelBrowser.cdp_ws_url);
715
- this.context = await this.browser.newContext(rankCheckContextOptions(config));
725
+ const runtimeUserAgent = await detectRuntimeUserAgent(this.browser);
726
+ this.debugSnapshot.context.userAgent = config.userAgent ?? (config.isMobile ? MOBILE_USER_AGENT : runtimeUserAgent ?? DESKTOP_USER_AGENT);
727
+ this.context = await this.browser.newContext(rankCheckContextOptions(config, runtimeUserAgent));
716
728
  await this.installEsbuildHelperShims(this.context);
717
729
  this.page = await this.context.newPage();
718
730
  await this.page.setViewportSize(config.viewport);
@@ -2845,7 +2857,6 @@ var import_sdk2 = __toESM(require("@onkernel/sdk"), 1);
2845
2857
  var BACKUP_PROXY_HOST = "pr.oxylabs.io";
2846
2858
  var BACKUP_PROXY_PORT = 7777;
2847
2859
  var BACKUP_STICKY_SESSION_MINUTES = 10;
2848
- var BACKUP_LAST_RESORT_ATTEMPTS = 2;
2849
2860
  function backupProxyUsername() {
2850
2861
  const value = process.env.OXYLABS_USERNAME?.trim();
2851
2862
  return value || void 0;
@@ -3199,15 +3210,6 @@ async function settleCreateExhaustion(options, target, createErrors) {
3199
3210
  }
3200
3211
  return resolution("configured_fallback", options.proxyMode, options.configuredKernelProxyId, target, createErrors.join(" | "));
3201
3212
  }
3202
- async function resolveBackupKernelProxyId(options) {
3203
- if (!options.kernelApiKey || !backupProxyAvailable()) return null;
3204
- try {
3205
- const backupId = await createBackupProxyId(options.kernelApiKey, { attemptIndex: options.attemptIndex });
3206
- return resolution("backup_custom", options.proxyMode, backupId, null, null, true);
3207
- } catch {
3208
- return null;
3209
- }
3210
- }
3211
3213
  async function createFreshLocationProxy(kernel, options, target) {
3212
3214
  const createErrors = [];
3213
3215
  for (const candidate of freshTargetCandidates(target, options.proxyZip, options.attemptIndex)) {
@@ -3567,7 +3569,7 @@ async function harvest(rawOptions) {
3567
3569
  const needsLocationEvidence = proxyMode === "location" && Boolean(proxyOpts.location);
3568
3570
  const requestedMaxAttempts = raw.maxAttempts;
3569
3571
  const baseMaxAttempts = typeof requestedMaxAttempts === "number" && Number.isInteger(requestedMaxAttempts) && requestedMaxAttempts >= 1 ? requestedMaxAttempts : maxAttemptsForProxyMode(proxyMode) + 1;
3570
- const maxAttempts = baseMaxAttempts + (backupProxyAvailable() ? BACKUP_LAST_RESORT_ATTEMPTS : 0);
3572
+ const maxAttempts = baseMaxAttempts;
3571
3573
  const softDeadlineMs = typeof raw.softDeadlineMs === "number" ? raw.softDeadlineMs : null;
3572
3574
  const serializer = new OutputSerializer();
3573
3575
  let lastError = null;
@@ -3578,14 +3580,11 @@ async function harvest(rawOptions) {
3578
3580
  const startedAtMs = Date.now();
3579
3581
  try {
3580
3582
  if (signal?.aborted) throw abortReason(signal);
3581
- const isBackupAttempt = i >= baseMaxAttempts;
3582
- if (isBackupAttempt && softDeadlineMs !== null && Date.now() >= softDeadlineMs) break;
3583
- const resolution2 = isBackupAttempt ? await resolveBackupKernelProxyId({ kernelApiKey, proxyMode: effectiveProxyMode, attemptIndex: i }) : await resolveKernelProxyId({
3583
+ const resolution2 = await resolveKernelProxyId({
3584
3584
  ...proxyOpts,
3585
3585
  proxyMode: effectiveProxyMode,
3586
3586
  attemptIndex: i,
3587
- fresh: effectiveProxyMode === "location",
3588
- backupOnExhaustion: true
3587
+ fresh: effectiveProxyMode === "location"
3589
3588
  });
3590
3589
  if (!resolution2) break;
3591
3590
  const mergedAttempt = {
@@ -3594,9 +3593,10 @@ async function harvest(rawOptions) {
3594
3593
  kernelProxyId: resolution2.kernelProxyId,
3595
3594
  kernelProxyResolution: resolution2.resolution,
3596
3595
  proxyMode: effectiveProxyMode,
3596
+ keepDefaultProxy: i > 0,
3597
3597
  debug: requestedDebug || needsLocationEvidence
3598
3598
  };
3599
- if (effectiveProxyMode === "none" && !isBackupAttempt) mergedAttempt.kernelProxyId = void 0;
3599
+ if (effectiveProxyMode === "none") mergedAttempt.kernelProxyId = void 0;
3600
3600
  const attemptOptions = HarvestOptionsSchema.parse(mergedAttempt);
3601
3601
  await emitAttemptEvent(onAttemptEvent, {
3602
3602
  type: "started",