iframer-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 (2) hide show
  1. package/index.js +101 -0
  2. package/package.json +1 -1
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();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iframer-cli",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "CLI and MCP server for iframer — a headful/headless browser for AI agents",
5
5
  "type": "module",
6
6
  "main": "index.js",