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.
- package/README.md +118 -0
- package/dist/fastbrowser_cli/fastbrowser_cli.d.ts +3 -0
- package/dist/fastbrowser_cli/fastbrowser_cli.d.ts.map +1 -0
- package/dist/fastbrowser_cli/fastbrowser_cli.js +288 -0
- package/dist/fastbrowser_cli/fastbrowser_cli.js.map +1 -0
- package/dist/fastbrowser_cli/libs/http-client.d.ts +7 -0
- package/dist/fastbrowser_cli/libs/http-client.d.ts.map +1 -0
- package/dist/fastbrowser_cli/libs/http-client.js +51 -0
- package/dist/fastbrowser_cli/libs/http-client.js.map +1 -0
- package/dist/fastbrowser_cli/libs/server-manager.d.ts +12 -0
- package/dist/fastbrowser_cli/libs/server-manager.d.ts.map +1 -0
- package/dist/fastbrowser_cli/libs/server-manager.js +194 -0
- package/dist/fastbrowser_cli/libs/server-manager.js.map +1 -0
- package/dist/fastbrowser_httpd/fastbrowser_httpd.d.ts +3 -0
- package/dist/fastbrowser_httpd/fastbrowser_httpd.d.ts.map +1 -0
- package/dist/fastbrowser_httpd/fastbrowser_httpd.js +82 -0
- package/dist/fastbrowser_httpd/fastbrowser_httpd.js.map +1 -0
- package/dist/fastbrowser_httpd/libs/routes.d.ts +6 -0
- package/dist/fastbrowser_httpd/libs/routes.d.ts.map +1 -0
- package/dist/fastbrowser_httpd/libs/routes.js +41 -0
- package/dist/fastbrowser_httpd/libs/routes.js.map +1 -0
- package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts +72 -0
- package/dist/fastbrowser_httpd/libs/tool-schemas.d.ts.map +1 -0
- package/dist/fastbrowser_httpd/libs/tool-schemas.js +65 -0
- package/dist/fastbrowser_httpd/libs/tool-schemas.js.map +1 -0
- package/dist/fastbrowser_mcp/fastbrowser_mcp.d.ts +4 -0
- package/dist/fastbrowser_mcp/fastbrowser_mcp.d.ts.map +1 -0
- package/dist/fastbrowser_mcp/fastbrowser_mcp.js +417 -0
- package/dist/fastbrowser_mcp/fastbrowser_mcp.js.map +1 -0
- package/dist/fastbrowser_mcp/libs/mcp_client.d.ts +120 -0
- package/dist/fastbrowser_mcp/libs/mcp_client.d.ts.map +1 -0
- package/dist/fastbrowser_mcp/libs/mcp_client.js +83 -0
- package/dist/fastbrowser_mcp/libs/mcp_client.js.map +1 -0
- package/dist/fastbrowser_mcp/libs/mcp_proxy.d.ts +10 -0
- package/dist/fastbrowser_mcp/libs/mcp_proxy.d.ts.map +1 -0
- package/dist/fastbrowser_mcp/libs/mcp_proxy.js +45 -0
- package/dist/fastbrowser_mcp/libs/mcp_proxy.js.map +1 -0
- package/dist/fastbrowser_mcp/libs/schemas.d.ts +28 -0
- package/dist/fastbrowser_mcp/libs/schemas.d.ts.map +1 -0
- package/dist/fastbrowser_mcp/libs/schemas.js +38 -0
- package/dist/fastbrowser_mcp/libs/schemas.js.map +1 -0
- package/docs/brainstorm_scrap_by_ai.md +1 -1
- package/docs/feature_support_cli.md +27 -27
- package/package.json +7 -7
- package/skills/fastbrowser/SKILL.md +214 -0
- package/src/{fastweb_cli/fastweb_cli.ts → fastbrowser_cli/fastbrowser_cli.ts} +49 -15
- package/src/{fastweb_cli → fastbrowser_cli}/libs/http-client.ts +2 -2
- package/src/{fastweb_cli → fastbrowser_cli}/libs/server-manager.ts +8 -8
- package/src/{fastweb_http_server/fastweb_http_server.ts → fastbrowser_httpd/fastbrowser_httpd.ts} +10 -10
- package/src/{fastweb_http_server → fastbrowser_httpd}/libs/routes.ts +1 -1
- package/src/{fastweb_http_server → fastbrowser_httpd}/libs/tool-schemas.ts +4 -4
- package/src/{fastweb_mcp → fastbrowser_mcp}/libs/mcp_proxy.ts +1 -1
- package/src/{fastweb_mcp → fastbrowser_mcp}/libs/schemas.ts +1 -1
- package/tmp/.claude/skills/fastweb/SKILL.md +17 -17
- /package/src/{fastweb_mcp/fastweb_mcp.ts → fastbrowser_mcp/fastbrowser_mcp.ts} +0 -0
- /package/src/{fastweb_mcp → fastbrowser_mcp}/libs/mcp_client.ts +0 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
// node imports
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
3
7
|
// npm imports
|
|
4
8
|
import { Command } from 'commander';
|
|
5
9
|
|
|
6
10
|
// local imports
|
|
7
11
|
import { HttpClient } from './libs/http-client.js';
|
|
8
12
|
import { ServerManager } from './libs/server-manager.js';
|
|
9
|
-
import type { QuerySelectorInput, QuerySelectorFirstInput, QuerySelectorsAllRequest, QuerySelectorRequest } from '../
|
|
13
|
+
import type { QuerySelectorInput, QuerySelectorFirstInput, QuerySelectorsAllRequest, QuerySelectorRequest } from '../fastbrowser_httpd/libs/tool-schemas.js';
|
|
10
14
|
|
|
11
15
|
|
|
12
16
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -40,7 +44,7 @@ async function runTool(cmd: Command, routeName: string, body: unknown): Promise<
|
|
|
40
44
|
HttpClient.printResponse(response);
|
|
41
45
|
} catch (err) {
|
|
42
46
|
const message = err instanceof Error ? err.message : String(err);
|
|
43
|
-
console.error(`
|
|
47
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
44
48
|
process.exit(1);
|
|
45
49
|
}
|
|
46
50
|
}
|
|
@@ -127,54 +131,84 @@ function buildQuerySelectorFirstBody(opts: {
|
|
|
127
131
|
///////////////////////////////////////////////////////////////////////////////
|
|
128
132
|
///////////////////////////////////////////////////////////////////////////////
|
|
129
133
|
|
|
134
|
+
async function runInstall(skillFolder: string): Promise<void> {
|
|
135
|
+
const sourceSkillMd = path.resolve(__dirname, '../../skills/fastbrowser/SKILL.md');
|
|
136
|
+
const targetDir = path.resolve(skillFolder, 'skills', 'fastbrowser');
|
|
137
|
+
const targetSkillMd = path.join(targetDir, 'SKILL.md');
|
|
138
|
+
try {
|
|
139
|
+
await fs.promises.mkdir(targetDir, { recursive: true });
|
|
140
|
+
await fs.promises.copyFile(sourceSkillMd, targetSkillMd);
|
|
141
|
+
console.log(`Installed fastbrowser SKILL.md at ${targetSkillMd}`);
|
|
142
|
+
} catch (err) {
|
|
143
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
144
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
150
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
151
|
+
//
|
|
152
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
153
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
154
|
+
|
|
130
155
|
async function main(): Promise<void> {
|
|
156
|
+
const installIdx = process.argv.indexOf('--install');
|
|
157
|
+
if (installIdx !== -1) {
|
|
158
|
+
const next = process.argv[installIdx + 1];
|
|
159
|
+
const skillFolder = (next !== undefined && next.startsWith('-') === false) ? next : '.';
|
|
160
|
+
await runInstall(skillFolder);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
131
164
|
const program = new Command();
|
|
132
165
|
program
|
|
133
|
-
.name('
|
|
134
|
-
.description('CLI client for
|
|
135
|
-
.option('--server <url>', '
|
|
166
|
+
.name('fastbrowser-cli')
|
|
167
|
+
.description('CLI client for fastbrowser')
|
|
168
|
+
.option('--server <url>', 'fastbrowser-httpd URL (default: env FASTBROWSER_SERVER or http://localhost:8787)')
|
|
136
169
|
.option('--autostart', 'Auto-start the server before a command if it is not running', true)
|
|
137
|
-
.option('--no-autostart', 'Do not auto-start the server before a command')
|
|
170
|
+
.option('--no-autostart', 'Do not auto-start the server before a command')
|
|
171
|
+
.option('--install [skill-folder]', 'Install SKILL.md into <skill-folder>/skills/fastbrowser (default: .)');
|
|
138
172
|
|
|
139
173
|
const serverCmd = program
|
|
140
174
|
.command('server')
|
|
141
|
-
.description('Manage the
|
|
175
|
+
.description('Manage the fastbrowser HTTP server');
|
|
142
176
|
|
|
143
177
|
serverCmd
|
|
144
178
|
.command('start')
|
|
145
|
-
.description('Start the
|
|
179
|
+
.description('Start the fastbrowser HTTP server as a detached daemon')
|
|
146
180
|
.action(async (_opts, cmd: Command) => {
|
|
147
181
|
const server = getServerFromCmd(cmd);
|
|
148
182
|
try {
|
|
149
183
|
await ServerManager.start(server);
|
|
150
184
|
} catch (err) {
|
|
151
185
|
const message = err instanceof Error ? err.message : String(err);
|
|
152
|
-
console.error(`
|
|
186
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
153
187
|
process.exit(1);
|
|
154
188
|
}
|
|
155
189
|
});
|
|
156
190
|
|
|
157
191
|
serverCmd
|
|
158
192
|
.command('stop')
|
|
159
|
-
.description('Stop the
|
|
193
|
+
.description('Stop the fastbrowser HTTP server')
|
|
160
194
|
.action(async (_opts, cmd: Command) => {
|
|
161
195
|
const server = getServerFromCmd(cmd);
|
|
162
196
|
try {
|
|
163
197
|
await ServerManager.stop(server);
|
|
164
198
|
} catch (err) {
|
|
165
199
|
const message = err instanceof Error ? err.message : String(err);
|
|
166
|
-
console.error(`
|
|
200
|
+
console.error(`fastbrowser-cli error: ${message}`);
|
|
167
201
|
process.exit(1);
|
|
168
202
|
}
|
|
169
203
|
});
|
|
170
204
|
|
|
171
205
|
serverCmd
|
|
172
206
|
.command('status')
|
|
173
|
-
.description('Report whether the
|
|
207
|
+
.description('Report whether the fastbrowser HTTP server is running')
|
|
174
208
|
.action(async (_opts, cmd: Command) => {
|
|
175
209
|
const server = getServerFromCmd(cmd);
|
|
176
210
|
const state = await ServerManager.status(server);
|
|
177
|
-
console.log(`
|
|
211
|
+
console.log(`fastbrowser server at ${server}: ${state}`);
|
|
178
212
|
if (state === 'stopped') process.exit(1);
|
|
179
213
|
});
|
|
180
214
|
|
|
@@ -254,7 +288,7 @@ async function main(): Promise<void> {
|
|
|
254
288
|
try {
|
|
255
289
|
body = buildQuerySelectorsBody(opts);
|
|
256
290
|
} catch (err) {
|
|
257
|
-
console.error(`
|
|
291
|
+
console.error(`fastbrowser-cli error: ${(err as Error).message}`);
|
|
258
292
|
process.exit(1);
|
|
259
293
|
}
|
|
260
294
|
await runTool(cmd, 'query_selectors_all', body);
|
|
@@ -279,7 +313,7 @@ async function main(): Promise<void> {
|
|
|
279
313
|
try {
|
|
280
314
|
body = buildQuerySelectorFirstBody(opts);
|
|
281
315
|
} catch (err) {
|
|
282
|
-
console.error(`
|
|
316
|
+
console.error(`fastbrowser-cli error: ${(err as Error).message}`);
|
|
283
317
|
process.exit(1);
|
|
284
318
|
}
|
|
285
319
|
await runTool(cmd, 'query_selectors', body);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// local imports
|
|
2
|
-
import { ToolResponseSchema, type ToolResponse } from '../../
|
|
2
|
+
import { ToolResponseSchema, type ToolResponse } from '../../fastbrowser_httpd/libs/tool-schemas.js';
|
|
3
3
|
|
|
4
4
|
///////////////////////////////////////////////////////////////////////////////
|
|
5
5
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -10,7 +10,7 @@ import { ToolResponseSchema, type ToolResponse } from '../../fastweb_http_server
|
|
|
10
10
|
export class HttpClient {
|
|
11
11
|
static getServerUrl(overrideUrl: string | undefined): string {
|
|
12
12
|
if (overrideUrl !== undefined && overrideUrl !== '') return overrideUrl;
|
|
13
|
-
const envUrl = process.env.
|
|
13
|
+
const envUrl = process.env.FASTBROWSER_SERVER;
|
|
14
14
|
if (envUrl !== undefined && envUrl !== '') return envUrl;
|
|
15
15
|
return 'http://localhost:8787';
|
|
16
16
|
}
|
|
@@ -16,7 +16,7 @@ type PidFile = {
|
|
|
16
16
|
startedAt: string;
|
|
17
17
|
};
|
|
18
18
|
|
|
19
|
-
const STATE_DIR = Path.join(Os.homedir(), '.
|
|
19
|
+
const STATE_DIR = Path.join(Os.homedir(), '.fastbrowser_cli');
|
|
20
20
|
const PID_FILE = Path.join(STATE_DIR, 'server.json');
|
|
21
21
|
const LOG_FILE = Path.join(STATE_DIR, 'server.log');
|
|
22
22
|
|
|
@@ -47,7 +47,7 @@ export class ServerManager {
|
|
|
47
47
|
if (state === 'running') return;
|
|
48
48
|
|
|
49
49
|
if (ServerManager.isLocalUrl(serverUrl) === false) {
|
|
50
|
-
throw new Error(`
|
|
50
|
+
throw new Error(`fastbrowser server at ${serverUrl} is not reachable and cannot be auto-started (non-local URL)`);
|
|
51
51
|
}
|
|
52
52
|
await ServerManager.start(serverUrl);
|
|
53
53
|
}
|
|
@@ -55,7 +55,7 @@ export class ServerManager {
|
|
|
55
55
|
static async start(serverUrl: string): Promise<void> {
|
|
56
56
|
const existing = await ServerManager.status(serverUrl);
|
|
57
57
|
if (existing === 'running') {
|
|
58
|
-
console.error(`
|
|
58
|
+
console.error(`fastbrowser server already running at ${serverUrl}`);
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
61
|
|
|
@@ -64,7 +64,7 @@ export class ServerManager {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
const port = ServerManager.parsePort(serverUrl);
|
|
67
|
-
const entryPath = Path.resolve(__dirname, '..', '..', '
|
|
67
|
+
const entryPath = Path.resolve(__dirname, '..', '..', 'fastbrowser_httpd', 'fastbrowser_httpd.ts');
|
|
68
68
|
const packageRoot = Path.resolve(__dirname, '..', '..', '..');
|
|
69
69
|
|
|
70
70
|
Fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
@@ -81,7 +81,7 @@ export class ServerManager {
|
|
|
81
81
|
const pid = child.pid;
|
|
82
82
|
if (pid === undefined) {
|
|
83
83
|
Fs.closeSync(logFd);
|
|
84
|
-
throw new Error('Failed to spawn
|
|
84
|
+
throw new Error('Failed to spawn fastbrowser-httpd (no pid)');
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
const pidFile: PidFile = {
|
|
@@ -96,7 +96,7 @@ export class ServerManager {
|
|
|
96
96
|
const state = await ServerManager.status(serverUrl);
|
|
97
97
|
if (state === 'running') {
|
|
98
98
|
Fs.closeSync(logFd);
|
|
99
|
-
console.error(`
|
|
99
|
+
console.error(`fastbrowser server started (pid=${pid}, port=${port})`);
|
|
100
100
|
return;
|
|
101
101
|
}
|
|
102
102
|
await ServerManager.sleep(500);
|
|
@@ -104,7 +104,7 @@ export class ServerManager {
|
|
|
104
104
|
|
|
105
105
|
Fs.closeSync(logFd);
|
|
106
106
|
const tail = ServerManager.readLogTail(50);
|
|
107
|
-
throw new Error(`
|
|
107
|
+
throw new Error(`fastbrowser server did not become healthy within 10s. Log tail:\n${tail}`);
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
static async stop(serverUrl: string): Promise<void> {
|
|
@@ -157,7 +157,7 @@ export class ServerManager {
|
|
|
157
157
|
console.error(`warning: process ${pid} killed but ${serverUrl} still responds to /health`);
|
|
158
158
|
return;
|
|
159
159
|
}
|
|
160
|
-
console.error('
|
|
160
|
+
console.error('fastbrowser server stopped');
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
private static isLocalUrl(serverUrl: string): boolean {
|
package/src/{fastweb_http_server/fastweb_http_server.ts → fastbrowser_httpd/fastbrowser_httpd.ts}
RENAMED
|
@@ -8,7 +8,7 @@ import { Command } from 'commander';
|
|
|
8
8
|
import express from 'express';
|
|
9
9
|
|
|
10
10
|
// local imports
|
|
11
|
-
import { McpClient } from '../
|
|
11
|
+
import { McpClient } from '../fastbrowser_mcp/libs/mcp_client.js';
|
|
12
12
|
import { Routes } from './libs/routes.js';
|
|
13
13
|
|
|
14
14
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -25,25 +25,25 @@ class MainHelper {
|
|
|
25
25
|
port: number;
|
|
26
26
|
verbose?: boolean;
|
|
27
27
|
}): Promise<void> {
|
|
28
|
-
// Spawn
|
|
29
|
-
const
|
|
28
|
+
// Spawn fastbrowser-mcp as a subprocess and hold a persistent MCP client to it.
|
|
29
|
+
const fastbrowserMcpEntry = Path.resolve(__dirname, '..', 'fastbrowser_mcp', 'fastbrowser_mcp.ts');
|
|
30
30
|
const mcpClient = new McpClient({
|
|
31
|
-
name: '
|
|
31
|
+
name: 'fastbrowser-httpd',
|
|
32
32
|
version: '1.0.0',
|
|
33
33
|
transport: {
|
|
34
34
|
type: 'stdio',
|
|
35
35
|
command: 'npx',
|
|
36
|
-
args: ['tsx',
|
|
36
|
+
args: ['tsx', fastbrowserMcpEntry, 'mcp_server'],
|
|
37
37
|
},
|
|
38
38
|
});
|
|
39
39
|
|
|
40
|
-
console.error('Connecting to
|
|
40
|
+
console.error('Connecting to fastbrowser-mcp ...');
|
|
41
41
|
await mcpClient.connect();
|
|
42
42
|
console.error('MCP client connected');
|
|
43
43
|
|
|
44
44
|
if (verbose) {
|
|
45
45
|
const tools = await mcpClient.listTools();
|
|
46
|
-
console.error('Tools available in
|
|
46
|
+
console.error('Tools available in fastbrowser-mcp:');
|
|
47
47
|
for (const tool of tools) {
|
|
48
48
|
console.error(`- ${tool.name}`);
|
|
49
49
|
}
|
|
@@ -54,7 +54,7 @@ class MainHelper {
|
|
|
54
54
|
Routes.register(app, mcpClient);
|
|
55
55
|
|
|
56
56
|
const server = app.listen(port, () => {
|
|
57
|
-
console.error(`
|
|
57
|
+
console.error(`fastbrowser-httpd listening on http://localhost:${port}`);
|
|
58
58
|
});
|
|
59
59
|
|
|
60
60
|
const shutdown = async (signal: string): Promise<void> => {
|
|
@@ -78,8 +78,8 @@ async function main(): Promise<void> {
|
|
|
78
78
|
const program = new Command();
|
|
79
79
|
|
|
80
80
|
program
|
|
81
|
-
.name('
|
|
82
|
-
.description('Persistent HTTP server fronting
|
|
81
|
+
.name('fastbrowser-httpd')
|
|
82
|
+
.description('Persistent HTTP server fronting fastbrowser-mcp')
|
|
83
83
|
.option('-p, --port <number>', 'Port to listen on', '8787')
|
|
84
84
|
.option('-v, --verbose', 'Enable verbose logging')
|
|
85
85
|
.action(async (opts: { port: string; verbose?: boolean }) => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { Express, Request, Response } from 'express';
|
|
3
3
|
|
|
4
4
|
// local imports
|
|
5
|
-
import { McpClient } from '../../
|
|
5
|
+
import { McpClient } from '../../fastbrowser_mcp/libs/mcp_client.js';
|
|
6
6
|
import { TOOL_SCHEMAS, ToolResponseSchema } from './tool-schemas.js';
|
|
7
7
|
|
|
8
8
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
|
|
4
4
|
// local imports - reuse the authoritative query selector schemas
|
|
5
|
-
import { QuerySelectorsInputSchema, QuerySelectorsFirstInputSchema } from '../../
|
|
6
|
-
export type { QuerySelectorInput, QuerySelectorsInput, QuerySelectorFirstInput, QuerySelectorsFirstInput } from '../../
|
|
5
|
+
import { QuerySelectorsInputSchema, QuerySelectorsFirstInputSchema } from '../../fastbrowser_mcp/libs/schemas.js';
|
|
6
|
+
export type { QuerySelectorInput, QuerySelectorsInput, QuerySelectorFirstInput, QuerySelectorsFirstInput } from '../../fastbrowser_mcp/libs/schemas.js';
|
|
7
7
|
|
|
8
8
|
///////////////////////////////////////////////////////////////////////////////
|
|
9
9
|
///////////////////////////////////////////////////////////////////////////////
|
|
10
10
|
// Request schemas — one per tool. Shapes mirror what the underlying
|
|
11
|
-
//
|
|
11
|
+
// fastbrowser-mcp tools accept. For the proxied chrome-devtools-mcp tools,
|
|
12
12
|
// the shapes come from chrome-devtools-mcp's tool reference.
|
|
13
13
|
///////////////////////////////////////////////////////////////////////////////
|
|
14
14
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -85,7 +85,7 @@ export type ToolResponse = z.infer<typeof ToolResponseSchema>;
|
|
|
85
85
|
///////////////////////////////////////////////////////////////////////////////
|
|
86
86
|
|
|
87
87
|
// The REST route name (snake_case, matches the CLI command) is distinct from
|
|
88
|
-
// the underlying MCP tool name (which may be camelCase for
|
|
88
|
+
// the underlying MCP tool name (which may be camelCase for fastbrowser-mcp's own
|
|
89
89
|
// tools). `mcpToolName` is what we send over MCP; `routeName` is the URL path.
|
|
90
90
|
export type ToolSchemaEntry = {
|
|
91
91
|
routeName: string;
|
|
@@ -4,7 +4,7 @@ import { z } from 'zod';
|
|
|
4
4
|
///////////////////////////////////////////////////////////////////////////////
|
|
5
5
|
///////////////////////////////////////////////////////////////////////////////
|
|
6
6
|
// Authoritative query selector schemas — shared between the MCP server
|
|
7
|
-
// and the HTTP/CLI layer. Kept out of the
|
|
7
|
+
// and the HTTP/CLI layer. Kept out of the fastbrowser_mcp.ts entrypoint so
|
|
8
8
|
// importing the schemas does not execute the CLI's top-level `main()`.
|
|
9
9
|
///////////////////////////////////////////////////////////////////////////////
|
|
10
10
|
///////////////////////////////////////////////////////////////////////////////
|
|
@@ -15,7 +15,7 @@ maps 1-to-1 to a FastWeb tool and returns the tool's response on stdout.
|
|
|
15
15
|
Run the CLI directly via `tsx`:
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
npx
|
|
18
|
+
npx fastbrowser_cli <command> [flags]
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Typical Workflow
|
|
@@ -35,16 +35,16 @@ uid=1_0 RootWebArea "Example Domain" url="https://example.com/"
|
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
37
|
# List all open browser pages
|
|
38
|
-
npx
|
|
38
|
+
npx fastbrowser_cli list_pages
|
|
39
39
|
|
|
40
40
|
# Open a new page at a URL
|
|
41
|
-
npx
|
|
41
|
+
npx fastbrowser_cli new_page --url https://example.com
|
|
42
42
|
|
|
43
43
|
# Close a page by its numeric id
|
|
44
|
-
npx
|
|
44
|
+
npx fastbrowser_cli close_page --page-id 1
|
|
45
45
|
|
|
46
46
|
# Navigate the current page to a URL
|
|
47
|
-
npx
|
|
47
|
+
npx fastbrowser_cli navigate_page --url https://example.com
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
|
|
@@ -150,44 +150,44 @@ Example queries on it:
|
|
|
150
150
|
|
|
151
151
|
```bash
|
|
152
152
|
# Query the accessibility tree returning the FIRST match per selector (--selector is repeatable)
|
|
153
|
-
npx
|
|
153
|
+
npx fastbrowser_cli query_selectors --selector "button" --selector "link"
|
|
154
154
|
|
|
155
155
|
# Exclude ancestor nodes from the result
|
|
156
|
-
npx
|
|
156
|
+
npx fastbrowser_cli query_selectors --selector 'heading[level="1"]' --no-with-ancestors
|
|
157
157
|
|
|
158
158
|
# Per-selector control over withAncestors via JSON
|
|
159
|
-
npx
|
|
159
|
+
npx fastbrowser_cli query_selectors \
|
|
160
160
|
--selectors-json '[{"selector":"button","withAncestors":true},{"selector":"link","withAncestors":false}]'
|
|
161
161
|
|
|
162
162
|
# Query the accessibility tree returning ALL matches per selector (--selector is repeatable)
|
|
163
|
-
npx
|
|
163
|
+
npx fastbrowser_cli query_selectors_all --selector "button" --selector "link" --limit 5
|
|
164
164
|
|
|
165
165
|
# Exclude ancestor nodes from the result
|
|
166
|
-
npx
|
|
166
|
+
npx fastbrowser_cli query_selectors_all --selector 'heading[level="1"]' --no-with-ancestors
|
|
167
167
|
|
|
168
168
|
# Per-selector control over limit / withAncestors via JSON
|
|
169
|
-
npx
|
|
169
|
+
npx fastbrowser_cli query_selectors_all \
|
|
170
170
|
--selectors-json '[{"selector":"button","limit":3,"withAncestors":true},{"selector":"link","limit":0,"withAncestors":false}]'
|
|
171
171
|
|
|
172
172
|
# Take an accessibility-tree full page snapshot of the current page - very expensive, prefer targeted queries when possible
|
|
173
|
-
npx
|
|
173
|
+
npx fastbrowser_cli take_snapshot
|
|
174
174
|
```
|
|
175
175
|
|
|
176
176
|
## Interaction
|
|
177
177
|
|
|
178
178
|
```bash
|
|
179
179
|
# Click by a direct uid reference (fast path - no accessibility-tree lookup)
|
|
180
|
-
npx
|
|
180
|
+
npx fastbrowser_cli click --selector "#1_42"
|
|
181
181
|
|
|
182
182
|
# Click by any CSS-like selector - resolved to a uid internally
|
|
183
|
-
npx
|
|
183
|
+
npx fastbrowser_cli click -s 'button[name="Submit"]'
|
|
184
184
|
|
|
185
185
|
# Fill a single form field - selector can be a uid (#1_7) or any CSS-like selector
|
|
186
|
-
npx
|
|
186
|
+
npx fastbrowser_cli fill_form -s 'textbox[name="Email"]' --value "hello@example.com"
|
|
187
187
|
|
|
188
188
|
# Press a comma-separated sequence of keys (literals and named keys both work)
|
|
189
|
-
npx
|
|
190
|
-
npx
|
|
189
|
+
npx fastbrowser_cli press_keys --keys "Tab, Tab, Enter"
|
|
190
|
+
npx fastbrowser_cli press_keys --keys "Hello, Tab, Enter"
|
|
191
191
|
```
|
|
192
192
|
|
|
193
193
|
## Command Reference
|
|
File without changes
|
|
File without changes
|