@fusengine/browser-mcp 0.1.13 → 0.1.14

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 CHANGED
@@ -128,11 +128,12 @@ Supported: `FUSE_ENGINE`, `FUSE_CHANNEL`, `FUSE_CDP_ENDPOINT`, `FUSE_EXECUTABLE_
128
128
  `FUSE_HEADLESS`, `FUSE_COUNTRY`, `FUSE_CURRENCY`, `FUSE_USER_DATA_DIR`,
129
129
  `FUSE_STORAGE_STATE`, `FUSE_OUTPUT_DIR`.
130
130
 
131
- ### Tools (24)
131
+ ### Tools (25)
132
132
 
133
133
  | Group | Tools |
134
134
  | --- | --- |
135
135
  | **One-shot** | `browser_probe`, `browser_probe_html` |
136
+ | **Fast-path** | `browser_fetch` — HTTP fetch with browser TLS/HTTP2 impersonation, **no browser launch** (~10× faster) for server-rendered HTML |
136
137
  | **Session** | `browser_open`, `browser_connect`, `browser_status`, `browser_close` |
137
138
  | **Navigate** | `browser_navigate`, `browser_back`, `browser_forward`, `browser_wait`, `browser_wait_for` |
138
139
  | **Act** | `browser_click`, `browser_fill`, `browser_login`, `browser_scroll`, `browser_press`, `browser_select` |
@@ -151,6 +152,12 @@ Key agentic patterns:
151
152
  - **`browser_run`** — execute an ordered plan (navigate/act/wait/extract) in one call,
152
153
  stopping at the first failure. Guardrails apply to the whole plan.
153
154
 
155
+ - **`browser_fetch`** — when a page is server-rendered (price lists, indexes, docs),
156
+ skip the browser entirely: `impit` impersonates a real Chrome TLS/JA3 + HTTP2
157
+ fingerprint, `linkedom` extracts the text, and the same price extractor runs on it.
158
+ ~10× faster and far lighter. Passes static HTML and low/medium Cloudflare; for JS
159
+ challenges, Turnstile, DataDome or SPA content, fall back to `browser_probe`.
160
+
154
161
  A `runs` resource exposes the JSON reports and screenshots written under the output dir
155
162
  (see *Output & data location*).
156
163
 
package/dist/bin/cli.js CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * fuse-browser CLI entry point. Subcommands: `probe`, `serp-batch`.
3
+ * fuse-browser CLI entry point. Subcommands: `probe`, `fetch`, `serp-batch`, `shots`.
4
4
  * @module bin/cli
5
5
  */
6
6
  import { parseArgs } from "node:util";
7
+ import { runFetchCli } from "./fetch-cli.js";
7
8
  import { runProbeCli } from "./probe-cli.js";
8
9
  import { runSerpBatch } from "./serp-batch-cli.js";
9
10
  import { runShots } from "./shots-cli.js";
@@ -48,11 +49,14 @@ if (command === "serp-batch") {
48
49
  else if (command === "shots" && rest[0]) {
49
50
  await runShots(rest[0], opts);
50
51
  }
52
+ else if (command === "fetch" && rest[0]) {
53
+ await runFetchCli(rest[0], opts);
54
+ }
51
55
  else if (command === "probe" && rest[0]) {
52
56
  await runProbeCli(rest[0], opts);
53
57
  }
54
58
  else {
55
- process.stderr.write("usage: fuse-browser probe <url> [...] | serp-batch <query...> --rank-domain <d> | shots <url> --viewports mobile,desktop\n");
59
+ process.stderr.write("usage: fuse-browser probe <url> [...] | fetch <url> [--extract-prices --proxy <url>] | serp-batch <query...> --rank-domain <d> | shots <url> --viewports mobile,desktop\n");
56
60
  process.exit(1);
57
61
  }
58
62
  //# sourceMappingURL=cli.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bin/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/bin/cli.ts"],"names":[],"mappings":";AACA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE1C,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACxC,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE;QACP,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC1B,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC3B,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC5B,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3B,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACnC,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACrC,mBAAmB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACxC,gBAAgB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACrC,cAAc,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACnC,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAChC,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACjC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC7B,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC/B,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtB,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtB,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC9B,YAAY,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QACjC,QAAQ,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC7B,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;QAC3B,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC7B,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAChC,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACnC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC/B,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACnC,iBAAiB,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACrC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QACzC,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;KACzC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,WAAW,CAAC;AACvC,MAAM,IAAI,GAAG,MAAiC,CAAC;AAE/C,IAAI,OAAO,KAAK,YAAY,EAAE,CAAC;IAC7B,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACjC,CAAC;KAAM,IAAI,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AAChC,CAAC;KAAM,IAAI,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;KAAM,IAAI,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1C,MAAM,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AACnC,CAAC;KAAM,CAAC;IACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,2KAA2K,CAC5K,CAAC;IACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,5 @@
1
+ type Values = Record<string, unknown>;
2
+ /** Run the `fetch` subcommand against `url`. */
3
+ export declare function runFetchCli(url: string, values: Values): Promise<void>;
4
+ export {};
5
+ //# sourceMappingURL=fetch-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-cli.d.ts","sourceRoot":"","sources":["../../src/bin/fetch-cli.ts"],"names":[],"mappings":"AAOA,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAGtC,gDAAgD;AAChD,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS5E"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * `fetch` subcommand handler: HTTP fast-path (TLS impersonation), prints JSON.
3
+ * @module bin/fetch-cli
4
+ */
5
+ import { extractPrices } from "../extraction/prices.js";
6
+ import { fetchFast } from "../net/fetch-fast.js";
7
+ const str = (v) => (typeof v === "string" ? v : undefined);
8
+ /** Run the `fetch` subcommand against `url`. */
9
+ export async function runFetchCli(url, values) {
10
+ const r = await fetchFast(url, str(values.proxy));
11
+ const out = {
12
+ status: r.status,
13
+ url: r.url,
14
+ text: r.text.slice(0, 20_000),
15
+ prices: values["extract-prices"] ? extractPrices(r.text) : undefined,
16
+ };
17
+ process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
18
+ }
19
+ //# sourceMappingURL=fetch-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-cli.js","sourceRoot":"","sources":["../../src/bin/fetch-cli.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAGjD,MAAM,GAAG,GAAG,CAAC,CAAU,EAAsB,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAExF,gDAAgD;AAChD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW,EAAE,MAAc;IAC3D,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG;QACV,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,CAAC;QAC7B,MAAM,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KACrE,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,12 @@
1
+ /** Extract readable body text from an HTML string (no browser, no layout). */
2
+ export declare function htmlToText(html: string): string;
3
+ /** Result of a fast HTTP fetch. */
4
+ export interface FastResponse {
5
+ status: number;
6
+ url: string;
7
+ html: string;
8
+ text: string;
9
+ }
10
+ /** Fetch `url` with Chrome impersonation; returns status, raw html and body text. */
11
+ export declare function fetchFast(url: string, proxyUrl?: string): Promise<FastResponse>;
12
+ //# sourceMappingURL=fetch-fast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-fast.d.ts","sourceRoot":"","sources":["../../src/net/fetch-fast.ts"],"names":[],"mappings":"AAgBA,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG/C;AAED,mCAAmC;AACnC,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qFAAqF;AACrF,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAIrF"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * HTTP fast-path: fetch a URL with browser TLS/HTTP2 impersonation (impit) and
3
+ * parse it server-side with linkedom — no browser launch. For server-rendered
4
+ * HTML (price/index/SERP pages); JS/SPA pages still need `browser_probe`.
5
+ * @module net/fetch-fast
6
+ */
7
+ import { Impit } from "impit";
8
+ import { parseHTML } from "linkedom";
9
+ let shared = null;
10
+ function client(proxyUrl) {
11
+ if (proxyUrl)
12
+ return new Impit({ browser: "chrome", proxyUrl });
13
+ shared ??= new Impit({ browser: "chrome" });
14
+ return shared;
15
+ }
16
+ /** Extract readable body text from an HTML string (no browser, no layout). */
17
+ export function htmlToText(html) {
18
+ const { document } = parseHTML(html);
19
+ return (document.body?.textContent ?? document.documentElement?.textContent ?? "").trim();
20
+ }
21
+ /** Fetch `url` with Chrome impersonation; returns status, raw html and body text. */
22
+ export async function fetchFast(url, proxyUrl) {
23
+ const res = await client(proxyUrl).fetch(url);
24
+ const html = await res.text();
25
+ return { status: res.status, url: res.url ?? url, html, text: htmlToText(html) };
26
+ }
27
+ //# sourceMappingURL=fetch-fast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-fast.js","sourceRoot":"","sources":["../../src/net/fetch-fast.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,IAAI,MAAM,GAAiB,IAAI,CAAC;AAChC,SAAS,MAAM,CAAC,QAAiB;IAC/B,IAAI,QAAQ;QAAE,OAAO,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;IAChE,MAAM,KAAK,IAAI,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IACrC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,WAAW,IAAI,QAAQ,CAAC,eAAe,EAAE,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AAC5F,CAAC;AAUD,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,QAAiB;IAC5D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,EAAG,GAAwB,CAAC,GAAG,IAAI,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;AACzG,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAevD,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,IAAI,WAAW,CAiB1C"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAgBvD,+DAA+D;AAC/D,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,SAAS,CAAC;IAClB,QAAQ,EAAE,cAAc,CAAC;CAC1B;AAED,6EAA6E;AAC7E,wBAAgB,YAAY,IAAI,WAAW,CAkB1C"}
@@ -11,6 +11,7 @@ import { registerConnectTool } from "./tools/connect.js";
11
11
  import { registerExtractTool } from "./tools/extract.js";
12
12
  import { registerExtractSchemaTool } from "./tools/extract-schema.js";
13
13
  import { registerNavigateTool } from "./tools/navigate.js";
14
+ import { registerFetchTool } from "./tools/fetch.js";
14
15
  import { registerProbeTools } from "./tools/probe.js";
15
16
  import { registerSerpBatchTool } from "./tools/serp-batch.js";
16
17
  import { registerRunTool } from "./tools/run.js";
@@ -23,6 +24,7 @@ export function createServer() {
23
24
  const server = new McpServer({ name: "fuse-browser", version: VERSION });
24
25
  const sessions = new SessionManager();
25
26
  registerProbeTools(server);
27
+ registerFetchTool(server);
26
28
  registerSerpBatchTool(server);
27
29
  registerSessionTools(server, sessions);
28
30
  registerConnectTool(server, sessions);
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQnD,6EAA6E;AAC7E,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IACtC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACxC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,yBAAyB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAQnD,6EAA6E;AAC7E,MAAM,UAAU,YAAY;IAC1B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACzE,MAAM,QAAQ,GAAG,IAAI,cAAc,EAAE,CAAC;IACtC,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC3B,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9B,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,oBAAoB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACvC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,qBAAqB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACxC,gBAAgB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,eAAe,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAClC,mBAAmB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACtC,yBAAyB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC5C,sBAAsB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACzC,iBAAiB,CAAC,MAAM,CAAC,CAAC;IAC1B,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAC9B,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * `browser_fetch` tool: HTTP fast-path (browser TLS impersonation, no browser
3
+ * launch) for server-rendered HTML. Returns status, body text, optional prices.
4
+ * @module server/tools/fetch
5
+ */
6
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ /** Register `browser_fetch`. */
8
+ export declare function registerFetchTool(server: McpServer): void;
9
+ //# sourceMappingURL=fetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.d.ts","sourceRoot":"","sources":["../../../src/server/tools/fetch.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAMzE,gCAAgC;AAChC,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA0BzD"}
@@ -0,0 +1,28 @@
1
+ import { z } from "zod";
2
+ import { extractPrices } from "../../extraction/prices.js";
3
+ import { fetchFast } from "../../net/fetch-fast.js";
4
+ import { jsonResult } from "../result.js";
5
+ /** Register `browser_fetch`. */
6
+ export function registerFetchTool(server) {
7
+ server.registerTool("browser_fetch", {
8
+ title: "HTTP fast fetch",
9
+ description: "Fetch a URL with browser TLS/HTTP2 impersonation — NO browser launch, ~10x faster. For server-rendered HTML (price/index pages). Returns status, body text, optional prices. Not for JS/SPA pages — use browser_probe there.",
10
+ inputSchema: {
11
+ url: z.string(),
12
+ extractPrices: z.boolean().optional(),
13
+ proxyUrl: z.string().optional(),
14
+ maxChars: z.number().int().optional(),
15
+ },
16
+ }, async (args) => {
17
+ const a = args;
18
+ const r = await fetchFast(String(a.url), typeof a.proxyUrl === "string" ? a.proxyUrl : undefined);
19
+ const max = typeof a.maxChars === "number" ? a.maxChars : 20_000;
20
+ return jsonResult({
21
+ status: r.status,
22
+ url: r.url,
23
+ text: r.text.slice(0, max),
24
+ prices: a.extractPrices ? extractPrices(r.text) : undefined,
25
+ });
26
+ });
27
+ }
28
+ //# sourceMappingURL=fetch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch.js","sourceRoot":"","sources":["../../../src/server/tools/fetch.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,gCAAgC;AAChC,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,YAAY,CACjB,eAAe,EACf;QACE,KAAK,EAAE,iBAAiB;QACxB,WAAW,EACT,8NAA8N;QAChO,WAAW,EAAE;YACX,GAAG,EAAE,CAAC,CAAC,MAAM,EAAE;YACf,aAAa,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE;YACrC,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YAC/B,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;SACtC;KACF,EACD,KAAK,EAAE,IAAI,EAAE,EAAE;QACb,MAAM,CAAC,GAAG,IAA+B,CAAC;QAC1C,MAAM,CAAC,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAClG,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC;QACjE,OAAO,UAAU,CAAC;YAChB,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC;YAC1B,MAAM,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;SAC5D,CAAC,CAAC;IACL,CAAC,CACF,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/browser-mcp",
3
- "version": "0.1.13",
3
+ "version": "0.1.14",
4
4
  "description": "MCP server + CLI giving AI agents a real, stealth browser (Patchright/Playwright) — per-country identity, self-healing actions, snapshots, multi-step plans, structured extraction, CDP attach.",
5
5
  "license": "MIT",
6
6
  "author": "Fusengine",
@@ -65,6 +65,8 @@
65
65
  ],
66
66
  "dependencies": {
67
67
  "@modelcontextprotocol/sdk": "^1.29.0",
68
+ "impit": "^0.14.1",
69
+ "linkedom": "^0.18.12",
68
70
  "patchright": "^1.60.1",
69
71
  "playwright": "^1.60.0",
70
72
  "zod": "^4.4.3"