crawlio-browser 1.4.3 → 1.4.5
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/dist/mcp-server/index.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
WS_PORT,
|
|
8
8
|
WS_RECONNECT_GRACE,
|
|
9
9
|
WS_STALE_THRESHOLD
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-3UA6NXNB.js";
|
|
11
11
|
|
|
12
12
|
// src/mcp-server/index.ts
|
|
13
13
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
@@ -4027,7 +4027,7 @@ function createCodeModeTools(bridge2, crawlio2) {
|
|
|
4027
4027
|
process.title = "Crawlio Agent";
|
|
4028
4028
|
var initMode = process.argv.includes("init") || process.argv.includes("--setup") || process.argv.includes("setup");
|
|
4029
4029
|
if (initMode) {
|
|
4030
|
-
const { runInit } = await import("./init-
|
|
4030
|
+
const { runInit } = await import("./init-AJOP2HY7.js");
|
|
4031
4031
|
await runInit(process.argv.slice(2));
|
|
4032
4032
|
process.exit(0);
|
|
4033
4033
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
PKG_VERSION
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3UA6NXNB.js";
|
|
4
4
|
|
|
5
5
|
// src/mcp-server/init.ts
|
|
6
6
|
import { execFileSync, spawn } from "child_process";
|
|
@@ -58,32 +58,238 @@ function parseFlags(argv) {
|
|
|
58
58
|
}
|
|
59
59
|
return opts;
|
|
60
60
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
61
|
+
var CLIENT_REGISTRY = [
|
|
62
|
+
{
|
|
63
|
+
name: "Claude Code",
|
|
64
|
+
configPath: join(HOME, ".claude.json"),
|
|
65
|
+
serverKey: "mcpServers",
|
|
66
|
+
format: "json",
|
|
67
|
+
detect: () => existsSync(join(HOME, ".claude"))
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: "Claude Desktop",
|
|
71
|
+
configPath: join(HOME, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
|
|
72
|
+
serverKey: "mcpServers",
|
|
73
|
+
format: "json",
|
|
74
|
+
detect: () => existsSync(join(HOME, "Library", "Application Support", "Claude"))
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: "VS Code",
|
|
78
|
+
configPath: join(HOME, "Library", "Application Support", "Code", "User", "mcp.json"),
|
|
79
|
+
serverKey: "servers",
|
|
80
|
+
format: "json",
|
|
81
|
+
detect: () => existsSync(join(HOME, ".vscode"))
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: "Cursor",
|
|
85
|
+
configPath: join(HOME, ".cursor", "mcp.json"),
|
|
86
|
+
serverKey: "mcpServers",
|
|
87
|
+
format: "json",
|
|
88
|
+
detect: () => existsSync(join(HOME, ".cursor"))
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: "Windsurf",
|
|
92
|
+
configPath: join(HOME, ".codeium", "windsurf", "mcp_config.json"),
|
|
93
|
+
serverKey: "mcpServers",
|
|
94
|
+
format: "json",
|
|
95
|
+
detect: () => existsSync(join(HOME, ".codeium", "windsurf"))
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: "Cline (VS Code)",
|
|
99
|
+
configPath: join(HOME, "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings", "cline_mcp_settings.json"),
|
|
100
|
+
serverKey: "mcpServers",
|
|
101
|
+
format: "json",
|
|
102
|
+
detect: () => existsSync(join(HOME, "Library", "Application Support", "Code", "User", "globalStorage", "saoudrizwan.claude-dev", "settings")),
|
|
103
|
+
transform: (entry) => ({ ...entry, disabled: false })
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: "Cline CLI",
|
|
107
|
+
configPath: join(HOME, ".cline", "data", "settings", "cline_mcp_settings.json"),
|
|
108
|
+
serverKey: "mcpServers",
|
|
109
|
+
format: "json",
|
|
110
|
+
detect: () => existsSync(join(HOME, ".cline")),
|
|
111
|
+
transform: (entry) => ({ ...entry, disabled: false })
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
name: "Copilot CLI",
|
|
115
|
+
configPath: join(HOME, ".copilot", "mcp-config.json"),
|
|
116
|
+
serverKey: "mcpServers",
|
|
117
|
+
format: "json",
|
|
118
|
+
detect: () => existsSync(join(HOME, ".copilot"))
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
name: "Gemini CLI",
|
|
122
|
+
configPath: join(HOME, ".gemini", "settings.json"),
|
|
123
|
+
serverKey: "mcpServers",
|
|
124
|
+
format: "json",
|
|
125
|
+
detect: () => existsSync(join(HOME, ".gemini"))
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: "Codex CLI",
|
|
129
|
+
configPath: join(HOME, ".codex", "config.toml"),
|
|
130
|
+
serverKey: "mcp_servers",
|
|
131
|
+
format: "toml",
|
|
132
|
+
detect: () => existsSync(join(HOME, ".codex"))
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
name: "Goose",
|
|
136
|
+
configPath: join(HOME, ".config", "goose", "config.yaml"),
|
|
137
|
+
serverKey: "extensions",
|
|
138
|
+
format: "yaml",
|
|
139
|
+
detect: () => existsSync(join(HOME, ".config", "goose"))
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
name: "OpenCode",
|
|
143
|
+
configPath: join(HOME, ".config", "opencode", "opencode.json"),
|
|
144
|
+
serverKey: "mcp",
|
|
145
|
+
format: "json",
|
|
146
|
+
detect: () => existsSync(join(HOME, ".config", "opencode")),
|
|
147
|
+
transform: (entry) => {
|
|
148
|
+
const e = entry;
|
|
149
|
+
return { command: [e.command, ...e.args || []], env: entry.env };
|
|
150
|
+
}
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
name: "Zed",
|
|
154
|
+
configPath: join(HOME, "Library", "Application Support", "Zed", "settings.json"),
|
|
155
|
+
serverKey: "context_servers",
|
|
156
|
+
format: "json",
|
|
157
|
+
detect: () => existsSync(join(HOME, "Library", "Application Support", "Zed")),
|
|
158
|
+
transform: (entry) => ({
|
|
159
|
+
settings: { source: "custom", command: entry }
|
|
160
|
+
})
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "Antigravity",
|
|
164
|
+
configPath: join(HOME, ".gemini", "antigravity", "mcp_config.json"),
|
|
165
|
+
serverKey: "mcpServers",
|
|
166
|
+
format: "json",
|
|
167
|
+
detect: () => existsSync(join(HOME, ".gemini", "antigravity"))
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
function configureClient(client, entry, dryRun) {
|
|
171
|
+
const finalEntry = client.transform ? client.transform(entry) : entry;
|
|
172
|
+
if (client.format === "json") {
|
|
173
|
+
let config = {};
|
|
174
|
+
if (existsSync(client.configPath)) {
|
|
175
|
+
try {
|
|
176
|
+
config = JSON.parse(readFileSync(client.configPath, "utf-8"));
|
|
177
|
+
} catch {
|
|
178
|
+
config = {};
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const section = config[client.serverKey] || {};
|
|
182
|
+
if ("crawlio-browser" in section) return "skipped";
|
|
183
|
+
if (dryRun) return "configured";
|
|
184
|
+
section["crawlio-browser"] = finalEntry;
|
|
185
|
+
config[client.serverKey] = section;
|
|
186
|
+
mkdirSync(dirname(client.configPath), { recursive: true });
|
|
187
|
+
writeFileSync(client.configPath, JSON.stringify(config, null, 2) + "\n");
|
|
188
|
+
return "configured";
|
|
70
189
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
190
|
+
if (client.format === "toml") {
|
|
191
|
+
let content = "";
|
|
192
|
+
if (existsSync(client.configPath)) {
|
|
193
|
+
content = readFileSync(client.configPath, "utf-8");
|
|
194
|
+
}
|
|
195
|
+
if (content.includes("[mcp_servers.crawlio-browser]") || content.includes('[mcp_servers."crawlio-browser"]')) {
|
|
196
|
+
return "skipped";
|
|
197
|
+
}
|
|
198
|
+
if (dryRun) return "configured";
|
|
199
|
+
const e = entry;
|
|
200
|
+
const argsStr = (e.args || []).map((a) => `"${a}"`).join(", ");
|
|
201
|
+
const block = `
|
|
202
|
+
[mcp_servers.crawlio-browser]
|
|
203
|
+
command = "${e.command}"
|
|
204
|
+
args = [${argsStr}]
|
|
205
|
+
`;
|
|
206
|
+
mkdirSync(dirname(client.configPath), { recursive: true });
|
|
207
|
+
writeFileSync(client.configPath, content + block);
|
|
208
|
+
return "configured";
|
|
74
209
|
}
|
|
75
|
-
|
|
210
|
+
if (client.format === "yaml") {
|
|
211
|
+
let content = "";
|
|
212
|
+
if (existsSync(client.configPath)) {
|
|
213
|
+
content = readFileSync(client.configPath, "utf-8");
|
|
214
|
+
}
|
|
215
|
+
if (content.includes("crawlio-browser:")) {
|
|
216
|
+
return "skipped";
|
|
217
|
+
}
|
|
218
|
+
if (dryRun) return "configured";
|
|
219
|
+
const e = entry;
|
|
220
|
+
const argsYaml = (e.args || []).map((a) => ` - ${a}`).join("\n");
|
|
221
|
+
const block = `
|
|
222
|
+
crawlio-browser:
|
|
223
|
+
name: crawlio-browser
|
|
224
|
+
type: stdio
|
|
225
|
+
cmd: ${e.command}
|
|
226
|
+
args:
|
|
227
|
+
${argsYaml}
|
|
228
|
+
`;
|
|
229
|
+
if (!content.includes("extensions:")) {
|
|
230
|
+
content += "\nextensions:\n";
|
|
231
|
+
}
|
|
232
|
+
mkdirSync(dirname(client.configPath), { recursive: true });
|
|
233
|
+
writeFileSync(client.configPath, content + block);
|
|
234
|
+
return "configured";
|
|
235
|
+
}
|
|
236
|
+
return "error";
|
|
237
|
+
}
|
|
238
|
+
function configureAllClients(options) {
|
|
239
|
+
const entry = options.portal ? buildPortalEntry() : buildStdioEntry({ full: options.full });
|
|
240
|
+
const candidates = options.agents.length > 0 ? CLIENT_REGISTRY.filter((c) => options.agents.some((a) => c.name.toLowerCase().includes(a.toLowerCase()))) : CLIENT_REGISTRY.filter((c) => c.detect());
|
|
241
|
+
if (candidates.length === 0) {
|
|
242
|
+
console.log(` ${dim(" No MCP clients detected on this machine")}`);
|
|
243
|
+
printManualInstructions(entry);
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
let configured = 0;
|
|
247
|
+
let skipped = 0;
|
|
248
|
+
for (const client of candidates) {
|
|
249
|
+
const result = configureClient(client, entry, options.dryRun);
|
|
250
|
+
if (result === "configured") {
|
|
251
|
+
const prefix = options.dryRun ? dim("~") : green("+");
|
|
252
|
+
console.log(` ${prefix} ${client.name} ${dim("\u2192 " + client.configPath)}`);
|
|
253
|
+
configured++;
|
|
254
|
+
} else if (result === "skipped") {
|
|
255
|
+
console.log(` ${dim("=")} ${client.name} ${dim("(already configured)")}`);
|
|
256
|
+
skipped++;
|
|
257
|
+
} else {
|
|
258
|
+
console.log(` ${yellow("!")} ${client.name} ${dim("\u2014 failed to write config")}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
if (configured === 0 && skipped > 0) {
|
|
262
|
+
console.log(` ${dim(" All detected clients already configured")}`);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function printManualInstructions(entry) {
|
|
266
|
+
console.log("");
|
|
267
|
+
console.log(` ${dim("Add this to your MCP client config:")}`);
|
|
268
|
+
console.log("");
|
|
269
|
+
const snippet = { "crawlio-browser": entry };
|
|
270
|
+
const lines = JSON.stringify(snippet, null, 2).split("\n");
|
|
271
|
+
for (const line of lines) {
|
|
272
|
+
console.log(` ${dim(line)}`);
|
|
273
|
+
}
|
|
274
|
+
console.log("");
|
|
76
275
|
}
|
|
77
276
|
function buildStdioEntry(options) {
|
|
78
277
|
if (platform() === "darwin") {
|
|
79
|
-
const
|
|
80
|
-
const wrapperPath = createAppWrapper(
|
|
278
|
+
const serverPath2 = getServerEntryPath();
|
|
279
|
+
const wrapperPath = createAppWrapper(serverPath2);
|
|
81
280
|
if (wrapperPath) {
|
|
82
281
|
const args2 = [];
|
|
83
282
|
if (options?.full) args2.push("--full");
|
|
84
283
|
return { command: wrapperPath, args: args2 };
|
|
85
284
|
}
|
|
86
285
|
}
|
|
286
|
+
const serverPath = getServerEntryPath();
|
|
287
|
+
if (existsSync(serverPath)) {
|
|
288
|
+
const nodePath = resolveNodePath();
|
|
289
|
+
const args2 = [serverPath];
|
|
290
|
+
if (options?.full) args2.push("--full");
|
|
291
|
+
return { command: nodePath, args: args2 };
|
|
292
|
+
}
|
|
87
293
|
const args = ["-y", `crawlio-browser@${PKG_VERSION}`];
|
|
88
294
|
if (options?.full) args.push("--full");
|
|
89
295
|
return { command: "npx", args };
|
|
@@ -613,7 +819,7 @@ async function portalFlow(options) {
|
|
|
613
819
|
await ensurePortalRunning(options.dryRun);
|
|
614
820
|
console.log("");
|
|
615
821
|
console.log(` ${cyan("\u25C6")} ${bold("MCP Configuration")} ${dim("(portal mode)")}`);
|
|
616
|
-
|
|
822
|
+
configureAllClients(options);
|
|
617
823
|
}
|
|
618
824
|
async function configureMetaMcp(found, options) {
|
|
619
825
|
console.log("");
|
|
@@ -660,47 +866,7 @@ async function configureMetaMcp(found, options) {
|
|
|
660
866
|
function configureStdioClients(options) {
|
|
661
867
|
console.log("");
|
|
662
868
|
console.log(` ${cyan("\u25C6")} ${bold("MCP Configuration")} ${dim("(stdio mode)")}`);
|
|
663
|
-
|
|
664
|
-
}
|
|
665
|
-
function runAddMcp(options) {
|
|
666
|
-
const npxBin = platform() === "win32" ? "npx.cmd" : "npx";
|
|
667
|
-
const args = buildAddMcpArgs(options);
|
|
668
|
-
if (options.dryRun) {
|
|
669
|
-
console.log(` ${dim("~")} Would run: ${npxBin} ${args.join(" ")}`);
|
|
670
|
-
return;
|
|
671
|
-
}
|
|
672
|
-
try {
|
|
673
|
-
const output = execFileSync(npxBin, args, {
|
|
674
|
-
encoding: "utf-8",
|
|
675
|
-
timeout: 6e4,
|
|
676
|
-
env: { ...process.env, npm_config_yes: "true" }
|
|
677
|
-
});
|
|
678
|
-
const lines = output.split("\n").filter((l) => l.trim());
|
|
679
|
-
let configuredCount = 0;
|
|
680
|
-
for (const line of lines) {
|
|
681
|
-
const trimmed = line.trim();
|
|
682
|
-
if (trimmed) {
|
|
683
|
-
console.log(` ${green("+")} ${trimmed}`);
|
|
684
|
-
configuredCount++;
|
|
685
|
-
}
|
|
686
|
-
}
|
|
687
|
-
if (configuredCount === 0) {
|
|
688
|
-
console.log(` ${dim(" add-mcp ran but no clients detected")}`);
|
|
689
|
-
}
|
|
690
|
-
} catch (error) {
|
|
691
|
-
const errObj = error;
|
|
692
|
-
const code = errObj?.code;
|
|
693
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
694
|
-
if (code === "ENOENT") {
|
|
695
|
-
console.log(` ${yellow("!")} ${npxBin} not found in PATH \u2014 install Node.js 18+ and retry`);
|
|
696
|
-
} else if (code === "ETIMEDOUT" || msg.includes("ETIMEDOUT") || msg.includes("timed out")) {
|
|
697
|
-
console.log(` ${yellow("!")} add-mcp timed out \u2014 check network and retry`);
|
|
698
|
-
} else {
|
|
699
|
-
console.log(` ${yellow("!")} add-mcp failed: ${msg.slice(0, 200)}`);
|
|
700
|
-
}
|
|
701
|
-
const target = options.portal ? MCP_URL : "crawlio-browser";
|
|
702
|
-
console.log(` ${dim(` Manual: npx add-mcp ${target} --name crawlio-browser --global`)}`);
|
|
703
|
-
}
|
|
869
|
+
configureAllClients(options);
|
|
704
870
|
}
|
|
705
871
|
var LOGO_LINES = [
|
|
706
872
|
" \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 ",
|
|
@@ -825,10 +991,12 @@ async function runInit(argv) {
|
|
|
825
991
|
await printSummary(options);
|
|
826
992
|
}
|
|
827
993
|
export {
|
|
828
|
-
|
|
994
|
+
CLIENT_REGISTRY,
|
|
829
995
|
buildCloudflareEntry,
|
|
830
996
|
buildPortalEntry,
|
|
831
997
|
buildStdioEntry,
|
|
998
|
+
configureAllClients,
|
|
999
|
+
configureClient,
|
|
832
1000
|
createAppWrapper,
|
|
833
1001
|
extractSkillName,
|
|
834
1002
|
findConflictingConfigs,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "crawlio-browser",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.5",
|
|
4
4
|
"description": "MCP server with 96 CDP-backed tools for browser automation — screenshots, DOM, network capture, framework detection, cookies, storage, session recording, performance metrics via Chrome",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/mcp-server/index.js",
|