fastbrowser_cli 1.0.2 → 1.0.3

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 (56) hide show
  1. package/README.md +118 -0
  2. package/dist/fastbrowser_cli/fastbrowser_cli.d.ts +3 -0
  3. package/dist/fastbrowser_cli/fastbrowser_cli.d.ts.map +1 -0
  4. package/dist/fastbrowser_cli/fastbrowser_cli.js +288 -0
  5. package/dist/fastbrowser_cli/fastbrowser_cli.js.map +1 -0
  6. package/dist/fastbrowser_cli/libs/http-client.d.ts +7 -0
  7. package/dist/fastbrowser_cli/libs/http-client.d.ts.map +1 -0
  8. package/dist/fastbrowser_cli/libs/http-client.js +51 -0
  9. package/dist/fastbrowser_cli/libs/http-client.js.map +1 -0
  10. package/dist/fastbrowser_cli/libs/server-manager.d.ts +12 -0
  11. package/dist/fastbrowser_cli/libs/server-manager.d.ts.map +1 -0
  12. package/dist/fastbrowser_cli/libs/server-manager.js +194 -0
  13. package/dist/fastbrowser_cli/libs/server-manager.js.map +1 -0
  14. package/dist/fastbrowser_httpd/fastbrowser_httpd.d.ts +3 -0
  15. package/dist/fastbrowser_httpd/fastbrowser_httpd.d.ts.map +1 -0
  16. package/dist/fastbrowser_httpd/fastbrowser_httpd.js +82 -0
  17. package/dist/fastbrowser_httpd/fastbrowser_httpd.js.map +1 -0
  18. package/dist/fastbrowser_httpd/libs/routes.d.ts +6 -0
  19. package/dist/fastbrowser_httpd/libs/routes.d.ts.map +1 -0
  20. package/dist/fastbrowser_httpd/libs/routes.js +41 -0
  21. package/dist/fastbrowser_httpd/libs/routes.js.map +1 -0
  22. package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts +72 -0
  23. package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts.map +1 -0
  24. package/dist/fastbrowser_httpd/libs/tool-schemas.js +65 -0
  25. package/dist/fastbrowser_httpd/libs/tool-schemas.js.map +1 -0
  26. package/dist/fastbrowser_mcp/fastbrowser_mcp.d.ts +4 -0
  27. package/dist/fastbrowser_mcp/fastbrowser_mcp.d.ts.map +1 -0
  28. package/dist/fastbrowser_mcp/fastbrowser_mcp.js +417 -0
  29. package/dist/fastbrowser_mcp/fastbrowser_mcp.js.map +1 -0
  30. package/dist/fastbrowser_mcp/libs/mcp_client.d.ts +120 -0
  31. package/dist/fastbrowser_mcp/libs/mcp_client.d.ts.map +1 -0
  32. package/dist/fastbrowser_mcp/libs/mcp_client.js +83 -0
  33. package/dist/fastbrowser_mcp/libs/mcp_client.js.map +1 -0
  34. package/dist/fastbrowser_mcp/libs/mcp_proxy.d.ts +10 -0
  35. package/dist/fastbrowser_mcp/libs/mcp_proxy.d.ts.map +1 -0
  36. package/dist/fastbrowser_mcp/libs/mcp_proxy.js +45 -0
  37. package/dist/fastbrowser_mcp/libs/mcp_proxy.js.map +1 -0
  38. package/dist/fastbrowser_mcp/libs/schemas.d.ts +28 -0
  39. package/dist/fastbrowser_mcp/libs/schemas.d.ts.map +1 -0
  40. package/dist/fastbrowser_mcp/libs/schemas.js +38 -0
  41. package/dist/fastbrowser_mcp/libs/schemas.js.map +1 -0
  42. package/docs/brainstorm_scrap_by_ai.md +1 -1
  43. package/docs/feature_support_cli.md +27 -27
  44. package/package.json +7 -7
  45. package/skills/fastbrowser/SKILL.md +214 -0
  46. package/src/{fastweb_cli/fastweb_cli.ts → fastbrowser_cli/fastbrowser_cli.ts} +49 -15
  47. package/src/{fastweb_cli → fastbrowser_cli}/libs/http-client.ts +2 -2
  48. package/src/{fastweb_cli → fastbrowser_cli}/libs/server-manager.ts +8 -8
  49. package/src/{fastweb_http_server/fastweb_http_server.ts → fastbrowser_httpd/fastbrowser_httpd.ts} +10 -10
  50. package/src/{fastweb_http_server → fastbrowser_httpd}/libs/routes.ts +1 -1
  51. package/src/{fastweb_http_server → fastbrowser_httpd}/libs/tool-schemas.ts +4 -4
  52. package/src/{fastweb_mcp → fastbrowser_mcp}/libs/mcp_proxy.ts +1 -1
  53. package/src/{fastweb_mcp → fastbrowser_mcp}/libs/schemas.ts +1 -1
  54. package/tmp/.claude/skills/fastweb/SKILL.md +17 -17
  55. /package/src/{fastweb_mcp/fastweb_mcp.ts → fastbrowser_mcp/fastbrowser_mcp.ts} +0 -0
  56. /package/src/{fastweb_mcp → fastbrowser_mcp}/libs/mcp_client.ts +0 -0
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.McpClient = void 0;
4
+ // node import
5
+ const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
6
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/client/stdio.js");
7
+ const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/client/streamableHttp.js");
8
+ ///////////////////////////////////////////////////////////////////////////////
9
+ ///////////////////////////////////////////////////////////////////////////////
10
+ //
11
+ ///////////////////////////////////////////////////////////////////////////////
12
+ ///////////////////////////////////////////////////////////////////////////////
13
+ class McpClient {
14
+ constructor(options) {
15
+ this.options = options;
16
+ this.connected = false;
17
+ this.client = new index_js_1.Client({
18
+ name: options.name,
19
+ version: options.version,
20
+ });
21
+ }
22
+ async connect() {
23
+ if (this.connected)
24
+ return;
25
+ this.transport = this.createTransport(this.options.transport);
26
+ await this.client.connect(this.transport);
27
+ this.connected = true;
28
+ }
29
+ async close() {
30
+ if (!this.connected)
31
+ return;
32
+ await this.client.close();
33
+ this.connected = false;
34
+ }
35
+ async listTools() {
36
+ this.assertConnected();
37
+ const { tools } = await this.client.listTools();
38
+ return tools;
39
+ }
40
+ async callTool(name, args = {}) {
41
+ this.assertConnected();
42
+ return this.client.callTool({ name, arguments: args });
43
+ }
44
+ async listResources() {
45
+ this.assertConnected();
46
+ const { resources } = await this.client.listResources();
47
+ return resources;
48
+ }
49
+ async readResource(uri) {
50
+ this.assertConnected();
51
+ return this.client.readResource({ uri });
52
+ }
53
+ async listPrompts() {
54
+ this.assertConnected();
55
+ const { prompts } = await this.client.listPrompts();
56
+ return prompts;
57
+ }
58
+ async getPrompt(name, args = {}) {
59
+ this.assertConnected();
60
+ return this.client.getPrompt({ name, arguments: args });
61
+ }
62
+ createTransport(config) {
63
+ switch (config.type) {
64
+ case "stdio":
65
+ return new stdio_js_1.StdioClientTransport({
66
+ command: config.command,
67
+ args: config.args ?? [],
68
+ env: config.env,
69
+ });
70
+ case "http":
71
+ return new streamableHttp_js_1.StreamableHTTPClientTransport(new URL(config.url), {
72
+ requestInit: { headers: config.headers },
73
+ });
74
+ }
75
+ }
76
+ assertConnected() {
77
+ if (!this.connected) {
78
+ throw new Error("McpClient is not connected. Call connect() first.");
79
+ }
80
+ }
81
+ }
82
+ exports.McpClient = McpClient;
83
+ //# sourceMappingURL=mcp_client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp_client.js","sourceRoot":"","sources":["../../../src/fastbrowser_mcp/libs/mcp_client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { McpClient } from "./mcp_client.js";
3
+ export declare class McpProxy {
4
+ private _mcpServer;
5
+ constructor();
6
+ connect(): Promise<void>;
7
+ getMcpServer(): Promise<McpServer>;
8
+ proxyToolCall(mcpClient: McpClient, toolName: string): Promise<void>;
9
+ }
10
+ //# sourceMappingURL=mcp_proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp_proxy.d.ts","sourceRoot":"","sources":["../../../src/fastbrowser_mcp/libs/mcp_proxy.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAKpE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,qBAAa,QAAQ;IACpB,OAAO,CAAC,UAAU,CAAY;;IASxB,OAAO;IAKP,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC;IAOlC,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM;CAc1D"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.McpProxy = void 0;
7
+ // node imports
8
+ const node_assert_1 = __importDefault(require("node:assert"));
9
+ // npm imports
10
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
11
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
12
+ const zod_from_json_schema_1 = require("zod-from-json-schema");
13
+ class McpProxy {
14
+ constructor() {
15
+ this._mcpServer = new mcp_js_1.McpServer({
16
+ name: "fastbrowser_mcp",
17
+ version: "1.0.0",
18
+ });
19
+ }
20
+ async connect() {
21
+ const transport = new stdio_js_1.StdioServerTransport();
22
+ await this._mcpServer.connect(transport);
23
+ }
24
+ async getMcpServer() {
25
+ if (this._mcpServer === null) {
26
+ throw new Error("MCP server is not initialized");
27
+ }
28
+ return this._mcpServer;
29
+ }
30
+ async proxyToolCall(mcpClient, toolName) {
31
+ const mcpClientTools = await mcpClient.listTools();
32
+ const mcpClientTool = mcpClientTools.find((tool) => tool.name === toolName);
33
+ node_assert_1.default.ok(mcpClientTool !== undefined, `Tool ${toolName} not found in mcp client tools`);
34
+ const inputSchema = (0, zod_from_json_schema_1.convertJsonSchemaToZod)(mcpClientTool.inputSchema);
35
+ this._mcpServer.registerTool(toolName, {
36
+ description: mcpClientTool.description,
37
+ inputSchema: inputSchema,
38
+ }, async (...args) => {
39
+ const callResult = await mcpClient.callTool(toolName, args[0]);
40
+ return callResult;
41
+ });
42
+ }
43
+ }
44
+ exports.McpProxy = McpProxy;
45
+ //# sourceMappingURL=mcp_proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp_proxy.js","sourceRoot":"","sources":["../../../src/fastbrowser_mcp/libs/mcp_proxy.ts"],"names":[],"mappings":";;;;;;AAAA,eAAe;AACf,8DAAiC;AAEjC,cAAc;AACd,oEAAoE;AACpE,wEAAiF;AACjF,+DAA8D;AAK9D,MAAa,QAAQ;IAGpB;QACC,IAAI,CAAC,UAAU,GAAG,IAAI,kBAAS,CAAC;YAC/B,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,OAAO;SAChB,CAAC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO;QACZ,MAAM,SAAS,GAAG,IAAI,+BAAoB,EAAE,CAAC;QAC7C,MAAM,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,YAAY;QACjB,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAClD,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAoB,EAAE,QAAgB;QACzD,MAAM,cAAc,GAAG,MAAM,SAAS,CAAC,SAAS,EAAE,CAAA;QAClD,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;QAC5E,qBAAM,CAAC,EAAE,CAAC,aAAa,KAAK,SAAS,EAAE,QAAQ,QAAQ,gCAAgC,CAAC,CAAA;QAExF,MAAM,WAAW,GAAG,IAAA,6CAAsB,EAAC,aAAa,CAAC,WAAkB,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,QAAQ,EAAE;YACtC,WAAW,EAAE,aAAa,CAAC,WAAW;YACtC,WAAW,EAAE,WAAW;SACxB,EAAE,KAAK,EAAE,GAAG,IAAW,EAAE,EAAE;YAC3B,MAAM,UAAU,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;YAC9D,OAAO,UAAU,CAAA;QAClB,CAAC,CAAC,CAAC;IACJ,CAAC;CACD;AApCD,4BAoCC"}
@@ -0,0 +1,28 @@
1
+ import { z } from 'zod';
2
+ export declare const QuerySelectorInputSchema: z.ZodObject<{
3
+ selector: z.ZodString;
4
+ limit: z.ZodDefault<z.ZodNumber>;
5
+ withAncestors: z.ZodDefault<z.ZodBoolean>;
6
+ }, z.core.$strip>;
7
+ export declare const QuerySelectorsInputSchema: z.ZodObject<{
8
+ selectors: z.ZodArray<z.ZodObject<{
9
+ selector: z.ZodString;
10
+ limit: z.ZodDefault<z.ZodNumber>;
11
+ withAncestors: z.ZodDefault<z.ZodBoolean>;
12
+ }, z.core.$strip>>;
13
+ }, z.core.$strip>;
14
+ export declare const QuerySelectorFirstInputSchema: z.ZodObject<{
15
+ selector: z.ZodString;
16
+ withAncestors: z.ZodDefault<z.ZodBoolean>;
17
+ }, z.core.$strip>;
18
+ export declare const QuerySelectorsFirstInputSchema: z.ZodObject<{
19
+ selectors: z.ZodArray<z.ZodObject<{
20
+ selector: z.ZodString;
21
+ withAncestors: z.ZodDefault<z.ZodBoolean>;
22
+ }, z.core.$strip>>;
23
+ }, z.core.$strip>;
24
+ export type QuerySelectorInput = z.infer<typeof QuerySelectorInputSchema>;
25
+ export type QuerySelectorsInput = z.infer<typeof QuerySelectorsInputSchema>;
26
+ export type QuerySelectorFirstInput = z.infer<typeof QuerySelectorFirstInputSchema>;
27
+ export type QuerySelectorsFirstInput = z.infer<typeof QuerySelectorsFirstInputSchema>;
28
+ //# sourceMappingURL=schemas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../../src/fastbrowser_mcp/libs/schemas.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,eAAO,MAAM,wBAAwB;;;;iBASnC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;iBAGpC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;iBAMxC,CAAC;AAEH,eAAO,MAAM,8BAA8B;;;;;iBAGzC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC1E,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAC5E,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AACpF,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.QuerySelectorsFirstInputSchema = exports.QuerySelectorFirstInputSchema = exports.QuerySelectorsInputSchema = exports.QuerySelectorInputSchema = void 0;
4
+ // npm imports
5
+ const zod_1 = require("zod");
6
+ ///////////////////////////////////////////////////////////////////////////////
7
+ ///////////////////////////////////////////////////////////////////////////////
8
+ // Authoritative query selector schemas — shared between the MCP server
9
+ // and the HTTP/CLI layer. Kept out of the fastbrowser_mcp.ts entrypoint so
10
+ // importing the schemas does not execute the CLI's top-level `main()`.
11
+ ///////////////////////////////////////////////////////////////////////////////
12
+ ///////////////////////////////////////////////////////////////////////////////
13
+ exports.QuerySelectorInputSchema = zod_1.z.object({
14
+ selector: zod_1.z.string()
15
+ .describe("CSS-like selector to query the accessibility tree"),
16
+ limit: zod_1.z.number()
17
+ .describe("Maximum number of nodes to return (excluding ancestors). Set to 0 for no limit.")
18
+ .default(0),
19
+ withAncestors: zod_1.z.boolean()
20
+ .describe("Whether to include ancestor nodes in the result")
21
+ .default(true),
22
+ });
23
+ exports.QuerySelectorsInputSchema = zod_1.z.object({
24
+ selectors: zod_1.z.array(exports.QuerySelectorInputSchema)
25
+ .describe("List of selectors to query the accessibility tree"),
26
+ });
27
+ exports.QuerySelectorFirstInputSchema = zod_1.z.object({
28
+ selector: zod_1.z.string()
29
+ .describe("CSS-like selector to query the accessibility tree"),
30
+ withAncestors: zod_1.z.boolean()
31
+ .describe("Whether to include ancestor nodes in the result")
32
+ .default(true),
33
+ });
34
+ exports.QuerySelectorsFirstInputSchema = zod_1.z.object({
35
+ selectors: zod_1.z.array(exports.QuerySelectorFirstInputSchema)
36
+ .describe("List of selectors; for each, the first matching node is returned"),
37
+ });
38
+ //# sourceMappingURL=schemas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/fastbrowser_mcp/libs/schemas.ts"],"names":[],"mappings":";;;AAAA,cAAc;AACd,6BAAwB;AAExB,+EAA+E;AAC/E,+EAA+E;AAC/E,uEAAuE;AACvE,2EAA2E;AAC3E,uEAAuE;AACvE,+EAA+E;AAC/E,+EAA+E;AAElE,QAAA,wBAAwB,GAAG,OAAC,CAAC,MAAM,CAAC;IAChD,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;SAClB,QAAQ,CAAC,mDAAmD,CAAC;IAC/D,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;SACf,QAAQ,CAAC,iFAAiF,CAAC;SAC3F,OAAO,CAAC,CAAC,CAAC;IACZ,aAAa,EAAE,OAAC,CAAC,OAAO,EAAE;SACxB,QAAQ,CAAC,iDAAiD,CAAC;SAC3D,OAAO,CAAC,IAAI,CAAC;CACf,CAAC,CAAC;AAEU,QAAA,yBAAyB,GAAG,OAAC,CAAC,MAAM,CAAC;IACjD,SAAS,EAAE,OAAC,CAAC,KAAK,CAAC,gCAAwB,CAAC;SAC1C,QAAQ,CAAC,mDAAmD,CAAC;CAC/D,CAAC,CAAC;AAEU,QAAA,6BAA6B,GAAG,OAAC,CAAC,MAAM,CAAC;IACrD,QAAQ,EAAE,OAAC,CAAC,MAAM,EAAE;SAClB,QAAQ,CAAC,mDAAmD,CAAC;IAC/D,aAAa,EAAE,OAAC,CAAC,OAAO,EAAE;SACxB,QAAQ,CAAC,iDAAiD,CAAC;SAC3D,OAAO,CAAC,IAAI,CAAC;CACf,CAAC,CAAC;AAEU,QAAA,8BAA8B,GAAG,OAAC,CAAC,MAAM,CAAC;IACtD,SAAS,EAAE,OAAC,CAAC,KAAK,CAAC,qCAA6B,CAAC;SAC/C,QAAQ,CAAC,kEAAkE,CAAC;CAC9E,CAAC,CAAC"}
@@ -29,4 +29,4 @@
29
29
  - possible by selector language ? yes
30
30
  - get link with an url starting with "https://www.welcometothejungle.com/fr/companies/"
31
31
  - on a https://www.welcometothejungle.com/fr/jobs?refinementList%5Boffices.country_code%5D%5B%5D=FR&query=machine%20learning&page=7
32
- - `npx tsx ./src/fastweb_cli/fastweb_cli.ts query_selectors_all --selector 'RootWebArea > link[url^="https://www.welcometothejungle.com/fr/companies/"]'`
32
+ - `npx tsx ./src/fastbrowser_cli/fastbrowser_cli.ts query_selectors_all --selector 'RootWebArea > link[url^="https://www.welcometothejungle.com/fr/companies/"]'`
@@ -1,22 +1,22 @@
1
- # FastWeb MCP
1
+ # FastBrowser MCP
2
2
 
3
3
  ## Overview
4
4
 
5
- FastWeb is a Model Context Protocol (MCP) server accessible via STDIO. It acts as a smarter proxy in front of the official `chrome-devtools-mcp`, exposing a leaner, more efficient toolset tuned for LLM agents.
5
+ FastBrowser is a Model Context Protocol (MCP) server accessible via STDIO. It acts as a smarter proxy in front of the official `chrome-devtools-mcp`, exposing a leaner, more efficient toolset tuned for LLM agents.
6
6
 
7
- Where the standard Chrome DevTools MCP exposes a broad, low-level API, FastWeb adds a structured accessibility-tree query layer (`querySelectorsAll`) that lets an agent extract exactly the page nodes it needs in a single call — rather than consuming the entire raw snapshot. This reduces token usage and round-trips, making FastWeb noticeably more efficient for web automation tasks.
7
+ Where the standard Chrome DevTools MCP exposes a broad, low-level API, FastBrowser adds a structured accessibility-tree query layer (`querySelectorsAll`) that lets an agent extract exactly the page nodes it needs in a single call — rather than consuming the entire raw snapshot. This reduces token usage and round-trips, making FastBrowser noticeably more efficient for web automation tasks.
8
8
 
9
9
  ## HTTP Server Architecture
10
10
 
11
- Connecting to `fastweb-mcp` on every invocation is slow: the MCP process starts cold, handshakes with `chrome-devtools-mcp`, and tears down after each session. To eliminate that overhead, `fastweb-http-server` acts as a persistent MCP client that connects to `fastweb-mcp` once and keeps that connection alive. It then re-exposes the same capabilities over a REST API, so `fastweb-cli` can issue commands with minimal latency. This splits the stack into two roles — a long-lived server that owns the MCP connection, and a thin client that issues commands and reads results — making interactions dramatically faster and easier to script.
11
+ Connecting to `fastbrowser-mcp` on every invocation is slow: the MCP process starts cold, handshakes with `chrome-devtools-mcp`, and tears down after each session. To eliminate that overhead, `fastbrowser-httpd` acts as a persistent MCP client that connects to `fastbrowser-mcp` once and keeps that connection alive. It then re-exposes the same capabilities over a REST API, so `fastbrowser-cli` can issue commands with minimal latency. This splits the stack into two roles — a long-lived server that owns the MCP connection, and a thin client that issues commands and reads results — making interactions dramatically faster and easier to script.
12
12
 
13
13
  ## Components
14
14
 
15
- FastWeb is made up of three tools that work together:
15
+ FastBrowser is made up of three tools that work together:
16
16
 
17
- - **fastweb-mcp** — The MCP server, accessible via STDIO. It connects directly to Chrome via `chrome-devtools-mcp` and exposes a curated, efficient toolset to any MCP-compatible LLM agent.
18
- - **fastweb-http-server** — A persistent HTTP server that acts as an MCP client connecting to `fastweb-mcp`. By keeping that MCP connection alive, it eliminates the cold-start penalty and exposes the same capabilities over a REST API for other clients to consume.
19
- - **fastweb-cli** — A lightweight command-line client that talks to `fastweb-http-server` over a REST API. It provides a fast, scriptable interface to browser automation without the overhead of spawning a new MCP process each time.
17
+ - **fastbrowser-mcp** — The MCP server, accessible via STDIO. It connects directly to Chrome via `chrome-devtools-mcp` and exposes a curated, efficient toolset to any MCP-compatible LLM agent.
18
+ - **fastbrowser-httpd** — A persistent HTTP server that acts as an MCP client connecting to `fastbrowser-mcp`. By keeping that MCP connection alive, it eliminates the cold-start penalty and exposes the same capabilities over a REST API for other clients to consume.
19
+ - **fastbrowser-cli** — A lightweight command-line client that talks to `fastbrowser-httpd` over a REST API. It provides a fast, scriptable interface to browser automation without the overhead of spawning a new MCP process each time.
20
20
 
21
21
  ### Tools exposed
22
22
 
@@ -32,49 +32,49 @@ FastWeb is made up of three tools that work together:
32
32
  | `querySelectors` | Query the accessibility tree and return the first matching node per selector |
33
33
  | `pressKeys` | Send a sequence of keyboard events |
34
34
 
35
- ## FastWeb CLI Command Lines
35
+ ## FastBrowser CLI Command Lines
36
36
 
37
- Each command maps 1-to-1 to a FastWeb MCP tool and sends the request to `fastweb-http-server` via REST.
37
+ Each command maps 1-to-1 to a FastBrowser MCP tool and sends the request to `fastbrowser-httpd` via REST.
38
38
 
39
39
  ```bash
40
40
  # List all open browser pages
41
- fastweb-cli list_pages
41
+ fastbrowser-cli list_pages
42
42
 
43
43
  # Open a new browser page
44
- fastweb-cli new_page
44
+ fastbrowser-cli new_page
45
45
 
46
46
  # Close a page by its ID
47
- fastweb-cli close_page --page-id <pageId>
47
+ fastbrowser-cli close_page --page-id <pageId>
48
48
 
49
49
  # Navigate the current page to a URL
50
- fastweb-cli navigate_page --url https://example.com
50
+ fastbrowser-cli navigate_page --url https://example.com
51
51
 
52
52
  # Click an element by accessibility selector (fast path: "#1_42" is a direct uid reference)
53
- fastweb-cli click --selector "#1_42"
54
- fastweb-cli click -s 'button[name="Submit"]'
53
+ fastbrowser-cli click --selector "#1_42"
54
+ fastbrowser-cli click -s 'button[name="Submit"]'
55
55
 
56
56
  # Fill a form field by accessibility selector
57
- fastweb-cli fill_form -s 'textbox[name="Email"]' --value "hello@example.com"
57
+ fastbrowser-cli fill_form -s 'textbox[name="Email"]' --value "hello@example.com"
58
58
 
59
59
  # Query the accessibility tree — --selector can be repeated for multiple selectors.
60
60
  # --limit and --with-ancestors apply to all selectors equally.
61
- fastweb-cli query_selectors_all --selector "button" --selector "link" --limit 5 --with-ancestors
62
- fastweb-cli query_selectors_all --selector 'heading[level="1"]' --no-with-ancestors
61
+ fastbrowser-cli query_selectors_all --selector "button" --selector "link" --limit 5 --with-ancestors
62
+ fastbrowser-cli query_selectors_all --selector 'heading[level="1"]' --no-with-ancestors
63
63
 
64
64
  # For per-selector control over limit/withAncestors, pass a JSON array directly:
65
- fastweb-cli query_selectors_all --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
65
+ fastbrowser-cli query_selectors_all --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
66
66
 
67
67
  # Query the accessibility tree for the first matching element per selector (mirrors DOM querySelector).
68
68
  # --selector can be repeated for multiple selectors; --with-ancestors applies to all.
69
- fastweb-cli query_selectors --selector "button"
70
- fastweb-cli query_selectors --selector "button" --selector "link" --no-with-ancestors
69
+ fastbrowser-cli query_selectors --selector "button"
70
+ fastbrowser-cli query_selectors --selector "button" --selector "link" --no-with-ancestors
71
71
 
72
72
  # For per-selector control over withAncestors, pass a JSON array directly:
73
- fastweb-cli query_selectors --selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withAncestors":false}]'
73
+ fastbrowser-cli query_selectors --selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withAncestors":false}]'
74
74
 
75
75
  # Press a sequence of keys
76
- fastweb-cli press_keys --keys "Tab, Tab, Enter"
77
- fastweb-cli press_keys --keys "Hello, Tab, Enter"
76
+ fastbrowser-cli press_keys --keys "Tab, Tab, Enter"
77
+ fastbrowser-cli press_keys --keys "Hello, Tab, Enter"
78
78
  ```
79
79
 
80
80
  ## Implementation Notes
@@ -82,5 +82,5 @@ fastweb-cli press_keys --keys "Hello, Tab, Enter"
82
82
  - The HTTP server is built with **Express**.
83
83
  - All REST request and response payloads are validated with **Zod**.
84
84
  - Every data structure has both a TypeScript `type` alias and a corresponding Zod schema — the type is derived from the schema via `z.infer<>` to keep them in sync.
85
- - `fastweb-http-server` lives in `contrib/fastweb-http-server/`.
86
- - `fastweb-cli` lives in `contrib/fastweb-cli/`.
85
+ - `fastbrowser-httpd` lives in `contrib/fastbrowser-httpd/`.
86
+ - `fastbrowser-cli` lives in `contrib/fastbrowser-cli/`.
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "fastbrowser_cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "",
5
- "main": "dist/fastweb_cli/fastweb_cli.js",
5
+ "main": "dist/fastbrowser_cli/fastbrowser_cli.js",
6
6
  "bin": {
7
- "fastbrowser_cli": "./dist/fastweb_cli/fastweb_cli.js"
7
+ "fastbrowser_cli": "./dist/fastbrowser_cli/fastbrowser_cli.js"
8
8
  },
9
9
  "scripts": {
10
- "start:fastweb_mcp": "npx tsx ./src/fastweb_mcp/fastweb_mcp.ts",
11
- "start:http-server": "npx tsx ./src/fastweb_http_server/fastweb_http_server.ts",
12
- "start:cli": "npx tsx ./src/fastweb_cli/fastweb_cli.ts",
13
- "inspect:fastweb_mcp": "npx @modelcontextprotocol/inspector npx tsx ./src/fastweb_mcp/fastweb_mcp.ts mcp_server",
10
+ "start:fastbrowser_mcp": "npx tsx ./src/fastbrowser_mcp/fastbrowser_mcp.ts",
11
+ "start:http-server": "npx tsx ./src/fastbrowser_httpd/fastbrowser_httpd.ts",
12
+ "start:cli": "npx tsx ./src/fastbrowser_cli/fastbrowser_cli.ts",
13
+ "inspect:fastbrowser_mcp": "npx @modelcontextprotocol/inspector npx tsx ./src/fastbrowser_mcp/fastbrowser_mcp.ts mcp_server",
14
14
  "inspect:chrome-devtools": "npx @modelcontextprotocol/inspector npx chrome-devtools-mcp@latest --autoconnect",
15
15
  "build": "tsc -p tsconfig.json",
16
16
  "publish:all": "npm run build && npm version patch && npm publish --access public",
@@ -0,0 +1,214 @@
1
+ ---
2
+ name: fastbrowser
3
+ description: >
4
+ Control a live browser from the command line: navigate, click, fill forms, and query the accessibility tree with CSS-like selectors. Lighter alternative to Chrome DevTools MCP or Puppeteer. Triggers on: navigate/click/fill actions, page snapshots, or mentions of fastbrowser.
5
+ ---
6
+
7
+ # fastbrowser Skill
8
+
9
+ `fastbrowser-cli` is a command-line client for the FastWeb HTTP server, which keeps a persistent
10
+ MCP connection to a Chrome browser alive so commands incur minimal latency. Each command
11
+ maps 1-to-1 to a FastWeb tool and returns the tool's response on stdout.
12
+
13
+ ## Invocation
14
+
15
+ Run the CLI directly via `tsx`:
16
+
17
+ ```bash
18
+ npx fastbrowser_cli <command> [flags]
19
+ ```
20
+
21
+ ## Typical Workflow
22
+
23
+ 1. **Query** the accessibility tree for specific nodes: `query_selectors` (first match per selector) or `query_selectors_all` (every match per selector).
24
+ 2. **Act** on an element by its accessibility selector: `click`, `fill_form`, `press_keys`. The selector can be a direct uid reference (e.g. `#1_42`, fastest path) or any CSS-like selector (e.g. `button[name="Submit"]`), which is resolved to a uid internally.
25
+
26
+ Snapshot output looks like:
27
+
28
+ ```
29
+ uid=1_0 RootWebArea "Example Domain" url="https://example.com/"
30
+ uid=1_1 heading "Example Domain" level="1"
31
+ uid=1_2 link "More information..." url="https://www.iana.org/..."
32
+ ```
33
+
34
+ ## Page Management
35
+
36
+ ```bash
37
+ # List all open browser pages
38
+ npx fastbrowser_cli list_pages
39
+
40
+ # Open a new page at a URL
41
+ npx fastbrowser_cli new_page --url https://example.com
42
+
43
+ # Close a page by its numeric id
44
+ npx fastbrowser_cli close_page --page-id 1
45
+
46
+ # Navigate the current page to a URL
47
+ npx fastbrowser_cli navigate_page --url https://example.com
48
+ ```
49
+
50
+
51
+ ## Selector Language
52
+
53
+ The selector syntax is modelled on CSS selectors, adapted for accessibility tree structures.
54
+
55
+ ### Role selector
56
+
57
+ Matches nodes by their accessibility role.
58
+
59
+ ```
60
+ button
61
+ link
62
+ comboxbox
63
+ searchbox
64
+ heading
65
+ WebArea
66
+ ```
67
+
68
+ ### Universal selector
69
+
70
+ Matches any node.
71
+
72
+ ```
73
+ *
74
+ ```
75
+
76
+ ### UID selector
77
+
78
+ Matches a node by its exact unique identifier.
79
+
80
+ ```
81
+ #4
82
+ #1_3
83
+ ```
84
+
85
+ ### Attribute selectors
86
+
87
+ Attribute selectors match values inside `node.attributes`. The special virtual attribute `name` maps to `node.name`.
88
+
89
+ | Syntax | Semantics |
90
+ |--------|-----------|
91
+ | `[attr]` | attribute is present |
92
+ | `[attr="value"]` | exact match |
93
+ | `[attr^="prefix"]` | starts with |
94
+ | `[attr$="suffix"]` | ends with |
95
+ | `[attr*="sub"]` | contains substring |
96
+
97
+ ```
98
+ link[href]
99
+ button[disabled="true"]
100
+ link[href^="https"]
101
+ link[href$=".com"]
102
+ link[href*="example"]
103
+ heading[name="Welcome"]
104
+ link[name="Click \"here\""]
105
+ ```
106
+
107
+ ### Combinators
108
+
109
+ | Syntax | Semantics |
110
+ |--------|-----------|
111
+ | `A B` | B is a descendant of A (any depth) |
112
+ | `A > B` | B is a direct child of A |
113
+ | `A, B` | union — matches A or B |
114
+
115
+ ```
116
+ WebArea link
117
+ main > button
118
+ heading, button
119
+ RootWebArea > link[href^="https"]
120
+ ```
121
+
122
+ ### Examples
123
+
124
+ Sample accessibility tree:
125
+
126
+ ```
127
+ uid=1 WebArea "Main Page"
128
+ uid=2 main
129
+ uid=3 heading "Welcome"
130
+ uid=4 link "Click here" href="https://example.com"
131
+ uid=5 button "Submit" disabled="true"
132
+ uid=6 navigation
133
+ uid=7 link "Home" href="/"
134
+ uid=8 link "About" href="/about"
135
+ ```
136
+
137
+ Example queries on it:
138
+ - `link` matches all the links (uid=4, uid=7, uid=8)
139
+ - 'navigation > link' matches only the links that are direct children of navigation (uid=7, uid=8)
140
+ - `link[href^="https"]` matches links with an external href (uid=4)
141
+ - `button[name="Submit"]` matches the submit button by name (uid=5)
142
+ - `*[disabled="true"]` matches any disabled element (uid=5)
143
+ - `heading, button` matches both headings and buttons in one query (uid=3, uid=5)
144
+ - `#7` matches a node by its UID (uid=7)
145
+
146
+ ## Inspection
147
+
148
+ - `query_selectors` and `query_selectors_all` are the most efficient way to get specific elements or data from the page. Use them instead of `take_snapshot` whenever possible.
149
+ - Prefer `query_selectors` when you only need the first match per selector (cheaper, less output); use `query_selectors_all` when you need every match or want to cap with `--limit`.
150
+
151
+ ```bash
152
+ # Query the accessibility tree returning the FIRST match per selector (--selector is repeatable)
153
+ npx fastbrowser_cli query_selectors --selector "button" --selector "link"
154
+
155
+ # Exclude ancestor nodes from the result
156
+ npx fastbrowser_cli query_selectors --selector 'heading[level="1"]' --no-with-ancestors
157
+
158
+ # Per-selector control over withAncestors via JSON
159
+ npx fastbrowser_cli query_selectors \
160
+ --selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withAncestors":false}]'
161
+
162
+ # Query the accessibility tree returning ALL matches per selector (--selector is repeatable)
163
+ npx fastbrowser_cli query_selectors_all --selector "button" --selector "link" --limit 5
164
+
165
+ # Exclude ancestor nodes from the result
166
+ npx fastbrowser_cli query_selectors_all --selector 'heading[level="1"]' --no-with-ancestors
167
+
168
+ # Per-selector control over limit / withAncestors via JSON
169
+ npx fastbrowser_cli query_selectors_all \
170
+ --selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
171
+
172
+ # Take an accessibility-tree full page snapshot of the current page - very expensive, prefer targeted queries when possible
173
+ npx fastbrowser_cli take_snapshot
174
+ ```
175
+
176
+ ## Interaction
177
+
178
+ ```bash
179
+ # Click by a direct uid reference (fast path - no accessibility-tree lookup)
180
+ npx fastbrowser_cli click --selector "#1_42"
181
+
182
+ # Click by any CSS-like selector - resolved to a uid internally
183
+ npx fastbrowser_cli click -s 'button[name="Submit"]'
184
+
185
+ # Fill a single form field - selector can be a uid (#1_7) or any CSS-like selector
186
+ npx fastbrowser_cli fill_form -s 'textbox[name="Email"]' --value "hello@example.com"
187
+
188
+ # Press a comma-separated sequence of keys (literals and named keys both work)
189
+ npx fastbrowser_cli press_keys --keys "Tab, Tab, Enter"
190
+ npx fastbrowser_cli press_keys --keys "Hello, Tab, Enter"
191
+ ```
192
+
193
+ ## Command Reference
194
+
195
+ | Command | Purpose | Required flags |
196
+ |---------|---------|----------------|
197
+ | `list_pages` | List open browser pages | — |
198
+ | `new_page` | Open a new page at a URL | `--url` |
199
+ | `close_page` | Close a page by id | `--page-id` |
200
+ | `navigate_page` | Navigate current page to a URL | `--url` |
201
+ | `take_snapshot` | Dump the accessibility tree of the whole page - very expensive, prefer targeted queries (`query_selectors` / `query_selectors_all`) when possible | — |
202
+ | `query_selectors` | Query a11y tree by CSS-like selector, returning the first match per selector | `--selector` or `--selectors-json` |
203
+ | `query_selectors_all` | Query a11y tree by CSS-like selector, returning every match per selector | `--selector` or `--selectors-json` |
204
+ | `click` | Click an element by accessibility selector | `--selector` / `-s` |
205
+ | `fill_form` | Fill a form field by accessibility selector | `--selector` / `-s`, `--value` |
206
+ | `press_keys` | Press a comma-separated key sequence | `--keys` |
207
+ | `server start` | Start the HTTP server daemon | — |
208
+ | `server status` | Report server running/stopped | — |
209
+ | `server stop` | Stop the HTTP server | — |
210
+
211
+ ## Output & Errors
212
+
213
+ Tool output is written to **stdout** — one line per response content part. On failure the
214
+ CLI writes `fastbrowser-cli error: <message>` to **stderr** and exits with code 1.