iframer-cli 1.0.1 → 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/cli.cjs +15 -0
- package/index.js +101 -0
- package/package.json +1 -1
package/cli.cjs
CHANGED
|
@@ -201,6 +201,20 @@ const [,, command, ...args] = process.argv;
|
|
|
201
201
|
|
|
202
202
|
async function main() {
|
|
203
203
|
switch (command) {
|
|
204
|
+
case "install": {
|
|
205
|
+
try {
|
|
206
|
+
execSync("claude mcp add iframer -- npx -y --package=iframer-cli iframer-mcp", { stdio: "inherit" });
|
|
207
|
+
console.log("\n iframer MCP installed in Claude Code!");
|
|
208
|
+
console.log(" Now run: iframer login");
|
|
209
|
+
} catch {
|
|
210
|
+
console.error(" Failed to install. Make sure Claude Code CLI is available.");
|
|
211
|
+
console.error(" You can manually add it with:");
|
|
212
|
+
console.error(" claude mcp add iframer -- npx -y --package=iframer-cli iframer-mcp");
|
|
213
|
+
process.exit(1);
|
|
214
|
+
}
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
|
|
204
218
|
case "login":
|
|
205
219
|
await login();
|
|
206
220
|
break;
|
|
@@ -518,6 +532,7 @@ async function main() {
|
|
|
518
532
|
iframer - CLI for the Agentic Browser API
|
|
519
533
|
|
|
520
534
|
Commands:
|
|
535
|
+
install Install iframer MCP in Claude Code
|
|
521
536
|
login Authenticate with the server
|
|
522
537
|
logout Remove saved credentials
|
|
523
538
|
status Show current auth status
|
package/index.js
CHANGED
|
@@ -514,6 +514,107 @@ ALWAYS call this tool when credentials are needed but not stored. NEVER tell the
|
|
|
514
514
|
}
|
|
515
515
|
);
|
|
516
516
|
|
|
517
|
+
// ─── Tool 11: recaptcha_solve ───────────────────────────────────────
|
|
518
|
+
|
|
519
|
+
server.tool(
|
|
520
|
+
"recaptcha_solve",
|
|
521
|
+
`Start solving a reCAPTCHA. Clicks the checkbox and if a challenge appears, returns ALL tile images inline in one response along with the prompt text. Much faster than individual recaptcha-click + screenshot + recaptcha-info calls.
|
|
522
|
+
|
|
523
|
+
If the reCAPTCHA is solved immediately (no challenge), returns solved: true.
|
|
524
|
+
If a challenge appears, returns the prompt and all tile images. Then use recaptcha_answer with the tile indices to complete it.`,
|
|
525
|
+
{},
|
|
526
|
+
async () => {
|
|
527
|
+
try {
|
|
528
|
+
const data = await apiPost("/interactive/act", {
|
|
529
|
+
action: { type: "recaptcha-solve" },
|
|
530
|
+
screenshot: false,
|
|
531
|
+
});
|
|
532
|
+
if (!data.ok) return errorResponse(`Error: ${data.error}`);
|
|
533
|
+
|
|
534
|
+
const result = data.result;
|
|
535
|
+
if (result.solved) {
|
|
536
|
+
return { content: [{ type: "text", text: "reCAPTCHA solved automatically (no challenge needed)." }] };
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
// Build content blocks: prompt text + all tile images
|
|
540
|
+
const content = [];
|
|
541
|
+
content.push({
|
|
542
|
+
type: "text",
|
|
543
|
+
text: `reCAPTCHA Challenge: "${result.prompt}"\nGrid: ${result.rows}x${result.cols} (${result.tiles.length} tiles)\nSelect the correct tiles by index (0-${result.tiles.length - 1}) using recaptcha_answer.`,
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
for (const tile of result.tiles) {
|
|
547
|
+
if (tile.image) {
|
|
548
|
+
content.push({
|
|
549
|
+
type: "text",
|
|
550
|
+
text: `Tile ${tile.index}:`,
|
|
551
|
+
});
|
|
552
|
+
content.push({
|
|
553
|
+
type: "image",
|
|
554
|
+
data: tile.image,
|
|
555
|
+
mimeType: "image/jpeg",
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
return { content };
|
|
561
|
+
} catch (err) {
|
|
562
|
+
return errorResponse(`Connection error: ${err.message}. Is the API running at ${BASE_URL}?`);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
// ─── Tool 12: recaptcha_answer ──────────────────────────────────────
|
|
568
|
+
|
|
569
|
+
server.tool(
|
|
570
|
+
"recaptcha_answer",
|
|
571
|
+
`Submit tile selections and verify the reCAPTCHA in one call. Selects the specified tiles and clicks verify.
|
|
572
|
+
|
|
573
|
+
If solved, returns success. If a new challenge appears (common with reCAPTCHA), returns the new prompt and tile images inline — just call recaptcha_answer again with new selections.`,
|
|
574
|
+
{
|
|
575
|
+
tiles: z.array(z.number()).describe("Tile indices to select (e.g. [0, 3, 6])"),
|
|
576
|
+
},
|
|
577
|
+
async ({ tiles }) => {
|
|
578
|
+
try {
|
|
579
|
+
const data = await apiPost("/interactive/act", {
|
|
580
|
+
action: { type: "recaptcha-answer", tiles },
|
|
581
|
+
screenshot: false,
|
|
582
|
+
});
|
|
583
|
+
if (!data.ok) return errorResponse(`Error: ${data.error}`);
|
|
584
|
+
|
|
585
|
+
const result = data.result;
|
|
586
|
+
if (result.solved) {
|
|
587
|
+
return { content: [{ type: "text", text: "reCAPTCHA solved!" }] };
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// New challenge — return tiles inline
|
|
591
|
+
const content = [];
|
|
592
|
+
content.push({
|
|
593
|
+
type: "text",
|
|
594
|
+
text: `Not solved yet — new challenge: "${result.prompt || "unknown"}"\nGrid: ${result.rows}x${result.cols} (${result.tiles.length} tiles)\nSelect the correct tiles by index using recaptcha_answer again.`,
|
|
595
|
+
});
|
|
596
|
+
|
|
597
|
+
for (const tile of result.tiles) {
|
|
598
|
+
if (tile.image) {
|
|
599
|
+
content.push({
|
|
600
|
+
type: "text",
|
|
601
|
+
text: `Tile ${tile.index}:`,
|
|
602
|
+
});
|
|
603
|
+
content.push({
|
|
604
|
+
type: "image",
|
|
605
|
+
data: tile.image,
|
|
606
|
+
mimeType: "image/jpeg",
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
return { content };
|
|
612
|
+
} catch (err) {
|
|
613
|
+
return errorResponse(`Connection error: ${err.message}. Is the API running at ${BASE_URL}?`);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
);
|
|
617
|
+
|
|
517
618
|
// ─── Start ───────────────────────────────────────────────────────────
|
|
518
619
|
|
|
519
620
|
const transport = new StdioServerTransport();
|