pagebolt-mcp 1.1.0 → 1.2.0
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 +34 -2
- package/package.json +3 -2
- package/src/index.mjs +149 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://modelcontextprotocol.io)
|
|
6
6
|
|
|
7
|
-
Take screenshots, generate PDFs,
|
|
7
|
+
Take screenshots, generate PDFs, create OG images, inspect pages, and record demo videos directly from your AI coding assistant.
|
|
8
8
|
|
|
9
9
|
**Works with Claude Desktop, Cursor, Windsurf, Cline, and any MCP-compatible client.**
|
|
10
10
|
|
|
@@ -22,6 +22,8 @@ PageBolt MCP Server connects your AI assistant to [PageBolt's web capture API](h
|
|
|
22
22
|
- **Generate PDFs** from URLs or HTML (invoices, reports, docs)
|
|
23
23
|
- **Create OG images** for social cards using templates or custom HTML
|
|
24
24
|
- **Run browser sequences** — multi-step automation (navigate, click, fill, screenshot)
|
|
25
|
+
- **Record demo videos** — browser automation as MP4/WebM/GIF with cursor effects, click animations, and auto-zoom
|
|
26
|
+
- **Inspect pages** — get a structured map of interactive elements with CSS selectors (use before sequences)
|
|
25
27
|
- **List device presets** — 25+ devices (iPhone, iPad, MacBook, Galaxy, etc.)
|
|
26
28
|
- **Check usage** — monitor your API quota in real time
|
|
27
29
|
|
|
@@ -164,6 +166,36 @@ Execute multi-step browser automation.
|
|
|
164
166
|
- "Go to https://example.com, click the pricing link, then screenshot both pages"
|
|
165
167
|
- "Navigate to the login page, fill in test credentials, submit, and screenshot the dashboard"
|
|
166
168
|
|
|
169
|
+
### `inspect_page`
|
|
170
|
+
|
|
171
|
+
Inspect a web page and get a structured map of all interactive elements, headings, forms, links, and images — each with a unique CSS selector.
|
|
172
|
+
|
|
173
|
+
**Key parameters:** `url`/`html`, `width`, `height`, `viewportDevice`, `darkMode`, `cookies`, `headers`, `authorization`, `blockBanners`, `blockAds`, `waitUntil`, `waitForSelector`
|
|
174
|
+
|
|
175
|
+
**Example prompts:**
|
|
176
|
+
- "Inspect https://example.com and tell me what buttons and forms are on the page"
|
|
177
|
+
- "What interactive elements are on the login page? I need selectors for a sequence"
|
|
178
|
+
|
|
179
|
+
**Tip:** Use `inspect_page` before `run_sequence` to discover reliable CSS selectors instead of guessing.
|
|
180
|
+
|
|
181
|
+
### `record_video`
|
|
182
|
+
|
|
183
|
+
Record a professional demo video of a multi-step browser automation sequence with cursor effects, click animations, and smooth movement.
|
|
184
|
+
|
|
185
|
+
**Key parameters:**
|
|
186
|
+
- `steps` — same actions as `run_sequence` (except no screenshot/pdf — the whole sequence is the video)
|
|
187
|
+
- `format` — `mp4`, `webm`, or `gif` (default: mp4; webm/gif require Starter+)
|
|
188
|
+
- `framerate` — 24, 30, or 60 fps (default: 30)
|
|
189
|
+
- `pace` — speed preset: `"fast"`, `"normal"`, `"slow"`, `"dramatic"`, `"cinematic"`, or a number 0.25–6.0
|
|
190
|
+
- `cursor` — style (`highlight`/`circle`/`spotlight`/`dot`), color, size, smoothing
|
|
191
|
+
- `clickEffect` — style (`ripple`/`pulse`/`ring`), color
|
|
192
|
+
- `zoom` — auto-zoom on clicks with configurable level and duration
|
|
193
|
+
- `saveTo` — output file path
|
|
194
|
+
|
|
195
|
+
**Example prompts:**
|
|
196
|
+
- "Record a video of logging into https://example.com with a spotlight cursor"
|
|
197
|
+
- "Make a demo video of the signup flow at slow pace, save as demo.mp4"
|
|
198
|
+
|
|
167
199
|
### `list_devices`
|
|
168
200
|
|
|
169
201
|
List all 25+ available device presets with viewport dimensions.
|
|
@@ -204,7 +236,7 @@ Free plan requires no credit card. Starter and Growth include a 14-day free tria
|
|
|
204
236
|
|
|
205
237
|
## Why PageBolt?
|
|
206
238
|
|
|
207
|
-
- **
|
|
239
|
+
- **6 APIs, one key** — screenshot, PDF, OG image, browser automation, video recording, page inspection. Stop paying for separate tools.
|
|
208
240
|
- **Clean captures** — automatic ad blocking, cookie banner removal, chat widget suppression, tracker blocking.
|
|
209
241
|
- **25+ device presets** — iPhone SE to Galaxy S24 Ultra, iPad Pro, MacBook, Desktop 4K.
|
|
210
242
|
- **Ship in 5 minutes** — plain HTTP, no SDKs required, works in any language.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pagebolt-mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "MCP server for PageBolt — take screenshots, generate PDFs, create OG images, and record demo videos from AI coding assistants like Claude, Cursor, and Windsurf.",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "MCP server for PageBolt — take screenshots, generate PDFs, create OG images, inspect pages, and record demo videos from AI coding assistants like Claude, Cursor, and Windsurf.",
|
|
5
5
|
"main": "src/index.mjs",
|
|
6
6
|
"module": "src/index.mjs",
|
|
7
7
|
"bin": {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"browser-automation",
|
|
26
26
|
"video-recording",
|
|
27
27
|
"demo-video",
|
|
28
|
+
"page-inspection",
|
|
28
29
|
"puppeteer",
|
|
29
30
|
"web-capture",
|
|
30
31
|
"pagebolt",
|
package/src/index.mjs
CHANGED
|
@@ -146,7 +146,7 @@ server.tool(
|
|
|
146
146
|
}),
|
|
147
147
|
])
|
|
148
148
|
).optional().describe('Cookies to set — array of "name=value" strings or { name, value, domain? } objects'),
|
|
149
|
-
headers: z.record(z.string()).optional().describe('Extra HTTP headers to send with the request'),
|
|
149
|
+
headers: z.record(z.string(), z.string()).optional().describe('Extra HTTP headers to send with the request'),
|
|
150
150
|
authorization: z.string().optional().describe('Authorization header value (e.g. "Bearer <token>")'),
|
|
151
151
|
bypassCSP: z.boolean().optional().describe('Bypass Content-Security-Policy on the page'),
|
|
152
152
|
// ── Content manipulation ──
|
|
@@ -410,6 +410,10 @@ server.tool(
|
|
|
410
410
|
style: z.enum(['ripple', 'pulse', 'ring']).optional().describe('Click effect style (default: ripple)'),
|
|
411
411
|
color: z.string().optional().describe('Click effect color as hex'),
|
|
412
412
|
}).optional().describe('Visual click effect settings'),
|
|
413
|
+
pace: z.union([
|
|
414
|
+
z.number().min(0.25).max(6),
|
|
415
|
+
z.enum(['fast', 'normal', 'slow', 'dramatic', 'cinematic']),
|
|
416
|
+
]).optional().describe('Controls how deliberate the video feels. Number (0.25–6.0, higher = slower) or preset: "fast" (0.5×), "normal" (1×), "slow" (2×), "dramatic" (3×), "cinematic" (4.5×). Default: "normal".'),
|
|
413
417
|
darkMode: z.boolean().optional().describe('Emulate dark color scheme (default: false)'),
|
|
414
418
|
blockBanners: z.boolean().optional().describe('Hide cookie consent banners (default: true)'),
|
|
415
419
|
deviceScaleFactor: z.number().min(1).max(3).optional().describe('Device pixel ratio (default: 1)'),
|
|
@@ -461,6 +465,150 @@ server.tool(
|
|
|
461
465
|
}
|
|
462
466
|
);
|
|
463
467
|
|
|
468
|
+
// ─── Tool: inspect_page ─────────────────────────────────────────
|
|
469
|
+
server.tool(
|
|
470
|
+
'inspect_page',
|
|
471
|
+
'Inspect a web page and get a structured map of all interactive elements, headings, forms, links, and images — each with a unique CSS selector. Use this BEFORE run_sequence to discover what elements exist on the page and get reliable selectors. Returns text (not an image), so it is fast and cheap. Costs 1 API request.',
|
|
472
|
+
{
|
|
473
|
+
// ── Source ──
|
|
474
|
+
url: z.string().url().optional().describe('URL to inspect (required if no html)'),
|
|
475
|
+
html: z.string().optional().describe('Raw HTML to inspect (required if no url)'),
|
|
476
|
+
// ── Viewport ──
|
|
477
|
+
width: z.number().int().min(1).max(3840).optional().describe('Viewport width in pixels (default: 1280)'),
|
|
478
|
+
height: z.number().int().min(1).max(2160).optional().describe('Viewport height in pixels (default: 720)'),
|
|
479
|
+
viewportDevice: z.string().optional().describe('Device preset for viewport emulation (e.g. "iphone_14_pro"). Use list_devices to see all presets.'),
|
|
480
|
+
viewportMobile: z.boolean().optional().describe('Enable mobile meta viewport emulation'),
|
|
481
|
+
viewportHasTouch: z.boolean().optional().describe('Enable touch event emulation'),
|
|
482
|
+
deviceScaleFactor: z.number().min(1).max(3).optional().describe('Device pixel ratio (default: 1)'),
|
|
483
|
+
// ── Timing ──
|
|
484
|
+
waitUntil: z.enum(['load', 'domcontentloaded', 'networkidle0', 'networkidle2']).optional().describe('When to consider navigation finished (default: networkidle2)'),
|
|
485
|
+
waitForSelector: z.string().optional().describe('Wait for this CSS selector to appear before inspecting'),
|
|
486
|
+
// ── Emulation ──
|
|
487
|
+
darkMode: z.boolean().optional().describe('Emulate dark color scheme (default: false)'),
|
|
488
|
+
reducedMotion: z.boolean().optional().describe('Emulate prefers-reduced-motion'),
|
|
489
|
+
userAgent: z.string().optional().describe('Override the browser User-Agent string'),
|
|
490
|
+
// ── Auth & headers ──
|
|
491
|
+
cookies: z.array(
|
|
492
|
+
z.union([
|
|
493
|
+
z.string(),
|
|
494
|
+
z.object({
|
|
495
|
+
name: z.string(),
|
|
496
|
+
value: z.string(),
|
|
497
|
+
domain: z.string().optional(),
|
|
498
|
+
}),
|
|
499
|
+
])
|
|
500
|
+
).optional().describe('Cookies to set — array of "name=value" strings or { name, value, domain? } objects'),
|
|
501
|
+
headers: z.record(z.string(), z.string()).optional().describe('Extra HTTP headers to send with the request'),
|
|
502
|
+
authorization: z.string().optional().describe('Authorization header value (e.g. "Bearer <token>")'),
|
|
503
|
+
bypassCSP: z.boolean().optional().describe('Bypass Content-Security-Policy on the page'),
|
|
504
|
+
// ── Content manipulation ──
|
|
505
|
+
hideSelectors: z.array(z.string()).optional().describe('Array of CSS selectors to hide before inspecting'),
|
|
506
|
+
blockBanners: z.boolean().optional().describe('Hide cookie consent banners (default: false)'),
|
|
507
|
+
blockAds: z.boolean().optional().describe('Block advertisements on the page'),
|
|
508
|
+
blockChats: z.boolean().optional().describe('Block live chat widgets'),
|
|
509
|
+
blockTrackers: z.boolean().optional().describe('Block tracking scripts'),
|
|
510
|
+
injectCss: z.string().optional().describe('Custom CSS to inject before inspecting'),
|
|
511
|
+
injectJs: z.string().optional().describe('Custom JavaScript to execute before inspecting'),
|
|
512
|
+
},
|
|
513
|
+
async (params) => {
|
|
514
|
+
if (!params.url && !params.html) {
|
|
515
|
+
return { content: [{ type: 'text', text: 'Error: Either "url" or "html" is required.' }], isError: true };
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
try {
|
|
519
|
+
const res = await callApi('/api/v1/inspect', {
|
|
520
|
+
method: 'POST',
|
|
521
|
+
body: params,
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
const data = await res.json();
|
|
525
|
+
|
|
526
|
+
// Format as structured text for efficient LLM consumption
|
|
527
|
+
const lines = [];
|
|
528
|
+
|
|
529
|
+
// Header
|
|
530
|
+
lines.push(`Page: ${data.title || '(untitled)'} (${data.url || params.url || 'html content'})`);
|
|
531
|
+
if (data.metadata) {
|
|
532
|
+
if (data.metadata.description) lines.push(`Description: ${data.metadata.description}`);
|
|
533
|
+
if (data.metadata.lang) lines.push(`Language: ${data.metadata.lang}`);
|
|
534
|
+
if (data.metadata.httpStatusCode) lines.push(`HTTP Status: ${data.metadata.httpStatusCode}`);
|
|
535
|
+
}
|
|
536
|
+
lines.push('');
|
|
537
|
+
|
|
538
|
+
// Headings
|
|
539
|
+
if (data.headings && data.headings.length > 0) {
|
|
540
|
+
lines.push(`Headings (${data.headings.length}):`);
|
|
541
|
+
for (const h of data.headings) {
|
|
542
|
+
lines.push(` H${h.level}: ${h.text} — selector: ${h.selector}`);
|
|
543
|
+
}
|
|
544
|
+
lines.push('');
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Interactive elements
|
|
548
|
+
if (data.elements && data.elements.length > 0) {
|
|
549
|
+
lines.push(`Interactive Elements (${data.elements.length}):`);
|
|
550
|
+
for (const el of data.elements) {
|
|
551
|
+
let desc = `[${el.tag}`;
|
|
552
|
+
if (el.attributes && el.attributes.type) desc += ` type=${el.attributes.type}`;
|
|
553
|
+
desc += `]`;
|
|
554
|
+
if (el.text) desc += ` "${el.text}"`;
|
|
555
|
+
if (el.attributes && el.attributes.placeholder) desc += ` placeholder="${el.attributes.placeholder}"`;
|
|
556
|
+
if (el.attributes && el.attributes.href) desc += ` → ${el.attributes.href}`;
|
|
557
|
+
desc += ` — selector: ${el.selector}`;
|
|
558
|
+
lines.push(` ${desc}`);
|
|
559
|
+
}
|
|
560
|
+
lines.push('');
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
// Forms
|
|
564
|
+
if (data.forms && data.forms.length > 0) {
|
|
565
|
+
lines.push(`Forms (${data.forms.length}):`);
|
|
566
|
+
for (const f of data.forms) {
|
|
567
|
+
const method = f.method || 'GET';
|
|
568
|
+
const action = f.action || '(none)';
|
|
569
|
+
lines.push(` ${f.selector} (${method} ${action}): ${f.fields.length} field(s)`);
|
|
570
|
+
for (const field of f.fields) {
|
|
571
|
+
lines.push(` - ${field}`);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
lines.push('');
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
// Links
|
|
578
|
+
if (data.links && data.links.length > 0) {
|
|
579
|
+
lines.push(`Links (${data.links.length}):`);
|
|
580
|
+
for (const l of data.links) {
|
|
581
|
+
lines.push(` "${l.text || '(no text)'}" → ${l.href} — selector: ${l.selector}`);
|
|
582
|
+
}
|
|
583
|
+
lines.push('');
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// Images
|
|
587
|
+
if (data.images && data.images.length > 0) {
|
|
588
|
+
lines.push(`Images (${data.images.length}):`);
|
|
589
|
+
for (const img of data.images) {
|
|
590
|
+
const alt = img.alt ? `"${img.alt}"` : '(no alt)';
|
|
591
|
+
lines.push(` ${alt} src=${img.src} — selector: ${img.selector}`);
|
|
592
|
+
}
|
|
593
|
+
lines.push('');
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
lines.push(`Duration: ${data.duration_ms}ms`);
|
|
597
|
+
|
|
598
|
+
return {
|
|
599
|
+
content: [
|
|
600
|
+
{
|
|
601
|
+
type: 'text',
|
|
602
|
+
text: lines.join('\n'),
|
|
603
|
+
},
|
|
604
|
+
],
|
|
605
|
+
};
|
|
606
|
+
} catch (err) {
|
|
607
|
+
return { content: [{ type: 'text', text: `Inspect error: ${err.message}` }], isError: true };
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
);
|
|
611
|
+
|
|
464
612
|
// ─── Tool: list_devices ─────────────────────────────────────────
|
|
465
613
|
server.tool(
|
|
466
614
|
'list_devices',
|