cbrowser 5.0.2 → 5.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.
@@ -0,0 +1,286 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * CBrowser MCP Server
5
+ *
6
+ * Exposes CBrowser browser automation tools via Model Context Protocol.
7
+ * Run with: cbrowser mcp-server
8
+ * Or: npx cbrowser mcp-server
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.startMcpServer = startMcpServer;
12
+ const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
13
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
14
+ const zod_1 = require("zod");
15
+ const browser_js_1 = require("./browser.js");
16
+ // Shared browser instance
17
+ let browser = null;
18
+ async function getBrowser() {
19
+ if (!browser) {
20
+ browser = new browser_js_1.CBrowser({
21
+ headless: true,
22
+ persistent: true,
23
+ });
24
+ }
25
+ return browser;
26
+ }
27
+ async function startMcpServer() {
28
+ const server = new mcp_js_1.McpServer({
29
+ name: "cbrowser",
30
+ version: "5.0.0",
31
+ });
32
+ // =========================================================================
33
+ // Navigation Tools
34
+ // =========================================================================
35
+ server.tool("navigate", "Navigate to a URL and take a screenshot", {
36
+ url: zod_1.z.string().url().describe("The URL to navigate to"),
37
+ }, async ({ url }) => {
38
+ const b = await getBrowser();
39
+ const result = await b.navigate(url);
40
+ return {
41
+ content: [
42
+ {
43
+ type: "text",
44
+ text: JSON.stringify({
45
+ success: true,
46
+ url: result.url,
47
+ title: result.title,
48
+ loadTime: result.loadTime,
49
+ screenshot: result.screenshot,
50
+ }, null, 2),
51
+ },
52
+ ],
53
+ };
54
+ });
55
+ // =========================================================================
56
+ // Interaction Tools
57
+ // =========================================================================
58
+ server.tool("click", "Click an element on the page using text, selector, or description", {
59
+ selector: zod_1.z.string().describe("Element to click (text content, CSS selector, or description)"),
60
+ force: zod_1.z.boolean().optional().describe("Bypass safety checks for destructive actions"),
61
+ }, async ({ selector, force }) => {
62
+ const b = await getBrowser();
63
+ const result = await b.click(selector, { force });
64
+ return {
65
+ content: [
66
+ {
67
+ type: "text",
68
+ text: JSON.stringify({
69
+ success: result.success,
70
+ message: result.message,
71
+ screenshot: result.screenshot,
72
+ }, null, 2),
73
+ },
74
+ ],
75
+ };
76
+ });
77
+ server.tool("smart_click", "Click with auto-retry and self-healing selectors", {
78
+ selector: zod_1.z.string().describe("Element to click"),
79
+ maxRetries: zod_1.z.number().optional().default(3).describe("Maximum retry attempts"),
80
+ }, async ({ selector, maxRetries }) => {
81
+ const b = await getBrowser();
82
+ const result = await b.smartClick(selector, { maxRetries });
83
+ return {
84
+ content: [
85
+ {
86
+ type: "text",
87
+ text: JSON.stringify({
88
+ success: result.success,
89
+ attempts: result.attempts.length,
90
+ finalSelector: result.finalSelector,
91
+ message: result.message,
92
+ aiSuggestion: result.aiSuggestion,
93
+ }, null, 2),
94
+ },
95
+ ],
96
+ };
97
+ });
98
+ server.tool("fill", "Fill a form field with text", {
99
+ selector: zod_1.z.string().describe("Input field to fill (name, placeholder, label, or selector)"),
100
+ value: zod_1.z.string().describe("Value to enter"),
101
+ }, async ({ selector, value }) => {
102
+ const b = await getBrowser();
103
+ const result = await b.fill(selector, value);
104
+ return {
105
+ content: [
106
+ {
107
+ type: "text",
108
+ text: JSON.stringify({
109
+ success: result.success,
110
+ message: result.message,
111
+ }, null, 2),
112
+ },
113
+ ],
114
+ };
115
+ });
116
+ // =========================================================================
117
+ // Extraction Tools
118
+ // =========================================================================
119
+ server.tool("screenshot", "Take a screenshot of the current page", {
120
+ path: zod_1.z.string().optional().describe("Optional path to save the screenshot"),
121
+ }, async ({ path }) => {
122
+ const b = await getBrowser();
123
+ const file = await b.screenshot(path);
124
+ return {
125
+ content: [
126
+ {
127
+ type: "text",
128
+ text: JSON.stringify({ screenshot: file }, null, 2),
129
+ },
130
+ ],
131
+ };
132
+ });
133
+ server.tool("extract", "Extract data from the page", {
134
+ what: zod_1.z.enum(["links", "headings", "forms", "images", "text"]).describe("What to extract"),
135
+ }, async ({ what }) => {
136
+ const b = await getBrowser();
137
+ const result = await b.extract(what);
138
+ return {
139
+ content: [
140
+ {
141
+ type: "text",
142
+ text: JSON.stringify(result.data, null, 2),
143
+ },
144
+ ],
145
+ };
146
+ });
147
+ // =========================================================================
148
+ // Assertion Tools
149
+ // =========================================================================
150
+ server.tool("assert", "Assert a condition using natural language", {
151
+ assertion: zod_1.z.string().describe("Natural language assertion like \"page contains 'Welcome'\" or \"title is 'Home'\""),
152
+ }, async ({ assertion }) => {
153
+ const b = await getBrowser();
154
+ const result = await b.assert(assertion);
155
+ return {
156
+ content: [
157
+ {
158
+ type: "text",
159
+ text: JSON.stringify({
160
+ passed: result.passed,
161
+ message: result.message,
162
+ actual: result.actual,
163
+ expected: result.expected,
164
+ }, null, 2),
165
+ },
166
+ ],
167
+ };
168
+ });
169
+ // =========================================================================
170
+ // Analysis Tools
171
+ // =========================================================================
172
+ server.tool("analyze_page", "Analyze page structure for forms, buttons, links", {}, async () => {
173
+ const b = await getBrowser();
174
+ const analysis = await b.analyzePage();
175
+ return {
176
+ content: [
177
+ {
178
+ type: "text",
179
+ text: JSON.stringify({
180
+ title: analysis.title,
181
+ forms: analysis.forms.length,
182
+ buttons: analysis.buttons.length,
183
+ links: analysis.links.length,
184
+ hasLogin: analysis.hasLogin,
185
+ hasSearch: analysis.hasSearch,
186
+ hasNavigation: analysis.hasNavigation,
187
+ }, null, 2),
188
+ },
189
+ ],
190
+ };
191
+ });
192
+ server.tool("generate_tests", "Generate test scenarios for a page", {
193
+ url: zod_1.z.string().url().optional().describe("URL to analyze (uses current page if not provided)"),
194
+ }, async ({ url }) => {
195
+ const b = await getBrowser();
196
+ const result = await b.generateTests(url);
197
+ return {
198
+ content: [
199
+ {
200
+ type: "text",
201
+ text: JSON.stringify({
202
+ testsGenerated: result.tests.length,
203
+ tests: result.tests.map(t => ({
204
+ name: t.name,
205
+ description: t.description,
206
+ steps: t.steps.length,
207
+ })),
208
+ }, null, 2),
209
+ },
210
+ ],
211
+ };
212
+ });
213
+ // =========================================================================
214
+ // Session Tools
215
+ // =========================================================================
216
+ server.tool("save_session", "Save browser session (cookies, storage) for later use", {
217
+ name: zod_1.z.string().describe("Name for the saved session"),
218
+ }, async ({ name }) => {
219
+ const b = await getBrowser();
220
+ await b.saveSession(name);
221
+ return {
222
+ content: [
223
+ {
224
+ type: "text",
225
+ text: JSON.stringify({ success: true, sessionName: name }, null, 2),
226
+ },
227
+ ],
228
+ };
229
+ });
230
+ server.tool("load_session", "Load a previously saved session", {
231
+ name: zod_1.z.string().describe("Name of the session to load"),
232
+ }, async ({ name }) => {
233
+ const b = await getBrowser();
234
+ const loaded = await b.loadSession(name);
235
+ return {
236
+ content: [
237
+ {
238
+ type: "text",
239
+ text: JSON.stringify({ success: loaded, sessionName: name }, null, 2),
240
+ },
241
+ ],
242
+ };
243
+ });
244
+ server.tool("list_sessions", "List all saved sessions", {}, async () => {
245
+ const b = await getBrowser();
246
+ const sessions = await b.listSessions();
247
+ return {
248
+ content: [
249
+ {
250
+ type: "text",
251
+ text: JSON.stringify(sessions, null, 2),
252
+ },
253
+ ],
254
+ };
255
+ });
256
+ // =========================================================================
257
+ // Self-Healing Tools
258
+ // =========================================================================
259
+ server.tool("heal_stats", "Get self-healing selector cache statistics", {}, async () => {
260
+ const b = await getBrowser();
261
+ const stats = b.getSelectorCacheStats();
262
+ return {
263
+ content: [
264
+ {
265
+ type: "text",
266
+ text: JSON.stringify(stats, null, 2),
267
+ },
268
+ ],
269
+ };
270
+ });
271
+ // Connect via stdio transport
272
+ const transport = new stdio_js_1.StdioServerTransport();
273
+ await server.connect(transport);
274
+ // Handle shutdown
275
+ process.on("SIGINT", async () => {
276
+ if (browser) {
277
+ await browser.close();
278
+ }
279
+ process.exit(0);
280
+ });
281
+ }
282
+ // Run if called directly
283
+ if (process.argv[1]?.endsWith("mcp-server.js") || process.argv[1]?.endsWith("mcp-server.ts")) {
284
+ startMcpServer().catch(console.error);
285
+ }
286
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
package/docs/INSTALL.md CHANGED
@@ -57,7 +57,7 @@ CBROWSER_DATA_DIR="./data" npx cbrowser navigate "https://example.com"
57
57
  | Variable | Default | Description |
58
58
  |----------|---------|-------------|
59
59
  | `CBROWSER_DATA_DIR` | `~/.cbrowser` | Data storage directory |
60
- | `CBROWSER_HEADLESS` | `false` | Run headless by default |
60
+ | `CBROWSER_HEADLESS` | `true` | Run headless by default (set to `false` for GUI) |
61
61
  | `CBROWSER_TIMEOUT` | `30000` | Default timeout (ms) |
62
62
  | `CBROWSER_VIEWPORT_WIDTH` | `1280` | Default viewport width |
63
63
  | `CBROWSER_VIEWPORT_HEIGHT` | `800` | Default viewport height |
@@ -2,9 +2,11 @@
2
2
  * CBrowser Basic Usage Examples
3
3
  *
4
4
  * Run with: npx ts-node examples/basic-usage.ts
5
+ * Or: bun run examples/basic-usage.ts
5
6
  */
6
7
 
7
- import { CBrowser } from "../src/index.js";
8
+ import { CBrowser } from "cbrowser";
9
+ // For local development: import { CBrowser } from "../src/index.js";
8
10
 
9
11
  async function basicNavigation() {
10
12
  console.log("=== Basic Navigation ===\n");
@@ -0,0 +1,184 @@
1
+ /**
2
+ * CBrowser v5.0.0 Smart Automation Examples
3
+ *
4
+ * Demonstrates:
5
+ * - Smart click with auto-retry
6
+ * - Natural language assertions
7
+ * - Self-healing selector cache
8
+ * - AI test generation
9
+ *
10
+ * Run with: npx ts-node examples/smart-automation.ts
11
+ */
12
+
13
+ import { CBrowser } from "../src/index.js";
14
+
15
+ async function smartClickExample() {
16
+ console.log("=== Smart Click with Auto-Retry ===\n");
17
+
18
+ const browser = new CBrowser({ headless: true });
19
+
20
+ try {
21
+ await browser.navigate("https://example.com");
22
+
23
+ // Smart click automatically:
24
+ // 1. Checks self-healing cache for known working selectors
25
+ // 2. Tries the original selector
26
+ // 3. Generates alternatives (text variants, ARIA roles, attributes)
27
+ // 4. Retries with each alternative
28
+ // 5. Caches the working selector for future use
29
+ const result = await browser.smartClick("More information...", {
30
+ maxRetries: 3,
31
+ });
32
+
33
+ console.log(`Success: ${result.success}`);
34
+ console.log(`Attempts: ${result.attempts.length}`);
35
+ console.log(`Final selector: ${result.finalSelector}`);
36
+
37
+ if (result.aiSuggestion) {
38
+ console.log(`AI suggestion: ${result.aiSuggestion}`);
39
+ }
40
+ } finally {
41
+ await browser.close();
42
+ }
43
+ }
44
+
45
+ async function assertionsExample() {
46
+ console.log("\n=== Natural Language Assertions ===\n");
47
+
48
+ const browser = new CBrowser({ headless: true });
49
+
50
+ try {
51
+ await browser.navigate("https://example.com");
52
+
53
+ // Title assertions
54
+ const titleResult = await browser.assert("title contains 'Example'");
55
+ console.log(`Title assertion: ${titleResult.passed ? "PASS" : "FAIL"}`);
56
+ console.log(` Message: ${titleResult.message}`);
57
+
58
+ // URL assertions
59
+ const urlResult = await browser.assert("url contains 'example.com'");
60
+ console.log(`URL assertion: ${urlResult.passed ? "PASS" : "FAIL"}`);
61
+ console.log(` Message: ${urlResult.message}`);
62
+
63
+ // Content assertions
64
+ const contentResult = await browser.assert(
65
+ "page contains 'illustrative examples'"
66
+ );
67
+ console.log(`Content assertion: ${contentResult.passed ? "PASS" : "FAIL"}`);
68
+ console.log(` Message: ${contentResult.message}`);
69
+
70
+ // Element count assertions
71
+ const linkResult = await browser.assert("1 links");
72
+ console.log(`Link count assertion: ${linkResult.passed ? "PASS" : "FAIL"}`);
73
+ console.log(` Actual: ${linkResult.actual}, Expected: ${linkResult.expected}`);
74
+ } finally {
75
+ await browser.close();
76
+ }
77
+ }
78
+
79
+ async function selfHealingExample() {
80
+ console.log("\n=== Self-Healing Selector Cache ===\n");
81
+
82
+ const browser = new CBrowser({ headless: true });
83
+
84
+ try {
85
+ // Get cache statistics
86
+ const stats = browser.getSelectorCacheStats();
87
+ console.log(`Cache entries: ${stats.totalEntries}`);
88
+ console.log(`Total successes: ${stats.totalSuccesses}`);
89
+ console.log(`Total failures: ${stats.totalFailures}`);
90
+
91
+ if (stats.topDomains.length > 0) {
92
+ console.log("\nTop domains:");
93
+ for (const { domain, count } of stats.topDomains) {
94
+ console.log(` ${domain}: ${count} cached selectors`);
95
+ }
96
+ }
97
+
98
+ // The cache is stored in ~/.cbrowser/selector-cache.json
99
+ // Each entry maps: domain + originalSelector -> workingSelector
100
+ // When a selector fails, CBrowser checks the cache first
101
+ // If found, it uses the cached working selector
102
+ // If not found, it tries alternatives and caches the one that works
103
+ } finally {
104
+ await browser.close();
105
+ }
106
+ }
107
+
108
+ async function testGenerationExample() {
109
+ console.log("\n=== AI Test Generation ===\n");
110
+
111
+ const browser = new CBrowser({ headless: true });
112
+
113
+ try {
114
+ // Generate tests for a page
115
+ const result = await browser.generateTests("https://example.com");
116
+
117
+ console.log(`Page analyzed: ${result.url}`);
118
+ console.log(`Tests generated: ${result.tests.length}\n`);
119
+
120
+ // Show generated test scenarios
121
+ for (const test of result.tests) {
122
+ console.log(`Test: ${test.name}`);
123
+ console.log(` Description: ${test.description}`);
124
+ console.log(` Steps: ${test.steps.length}`);
125
+ console.log(` Assertions: ${test.assertions.join(", ")}`);
126
+ console.log();
127
+ }
128
+
129
+ // Generated Playwright code
130
+ console.log("=== Generated Playwright Code ===");
131
+ console.log(result.playwrightCode.slice(0, 500) + "...\n");
132
+
133
+ // Generated CBrowser script
134
+ console.log("=== Generated CBrowser Script ===");
135
+ console.log(result.cbrowserScript.slice(0, 500) + "...\n");
136
+ } finally {
137
+ await browser.close();
138
+ }
139
+ }
140
+
141
+ async function pageAnalysisExample() {
142
+ console.log("\n=== Page Analysis ===\n");
143
+
144
+ const browser = new CBrowser({ headless: true });
145
+
146
+ try {
147
+ await browser.navigate("https://example.com");
148
+
149
+ const analysis = await browser.analyzePage();
150
+
151
+ console.log(`Title: ${analysis.title}`);
152
+ console.log(`URL: ${analysis.url}`);
153
+ console.log(`Forms: ${analysis.forms.length}`);
154
+ console.log(`Buttons: ${analysis.buttons.length}`);
155
+ console.log(`Links: ${analysis.links.length}`);
156
+ console.log(`Inputs: ${analysis.inputs.length}`);
157
+ console.log(`Has login form: ${analysis.hasLogin}`);
158
+ console.log(`Has search: ${analysis.hasSearch}`);
159
+ console.log(`Has navigation: ${analysis.hasNavigation}`);
160
+
161
+ // Detailed form analysis
162
+ if (analysis.forms.length > 0) {
163
+ console.log("\nForm details:");
164
+ for (const form of analysis.forms) {
165
+ console.log(` Selector: ${form.selector}`);
166
+ console.log(` Fields: ${form.fields.length}`);
167
+ console.log(` Is login: ${form.isLoginForm}`);
168
+ console.log(` Is search: ${form.isSearchForm}`);
169
+ }
170
+ }
171
+ } finally {
172
+ await browser.close();
173
+ }
174
+ }
175
+
176
+ async function main() {
177
+ await smartClickExample();
178
+ await assertionsExample();
179
+ await selfHealingExample();
180
+ await testGenerationExample();
181
+ await pageAnalysisExample();
182
+ }
183
+
184
+ main().catch(console.error);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cbrowser",
3
- "version": "5.0.2",
4
- "description": "AI-powered browser automation with constitutional safety, personas, session persistence, and autonomous journeys",
3
+ "version": "5.2.0",
4
+ "description": "AI-powered browser automation with self-healing selectors, natural language assertions, test generation, MCP server, constitutional safety, and autonomous journeys",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "bin": {
@@ -32,30 +32,38 @@
32
32
  "core-web-vitals",
33
33
  "har-export",
34
34
  "network-mocking",
35
- "video-recording"
35
+ "video-recording",
36
+ "self-healing-selectors",
37
+ "smart-retry",
38
+ "natural-language-assertions",
39
+ "test-generation",
40
+ "mcp-server",
41
+ "claude-integration"
36
42
  ],
37
- "author": "Your Name",
43
+ "author": "Wyld Digital",
38
44
  "license": "MIT",
39
45
  "repository": {
40
46
  "type": "git",
41
- "url": "git+https://github.com/yourusername/cbrowser.git"
47
+ "url": "git+https://github.com/wyld-digital/cbrowser.git"
42
48
  },
43
49
  "bugs": {
44
- "url": "https://github.com/yourusername/cbrowser/issues"
50
+ "url": "https://github.com/wyld-digital/cbrowser/issues"
45
51
  },
46
- "homepage": "https://github.com/yourusername/cbrowser#readme",
52
+ "homepage": "https://github.com/wyld-digital/cbrowser#readme",
47
53
  "engines": {
48
54
  "node": ">=18.0.0"
49
55
  },
50
56
  "dependencies": {
51
- "playwright": "^1.40.0"
57
+ "@modelcontextprotocol/sdk": "^1.25.3",
58
+ "playwright": "^1.40.0",
59
+ "zod": "^3.25.76"
52
60
  },
53
61
  "devDependencies": {
54
62
  "@types/node": "^20.10.0",
55
- "typescript": "^5.3.0",
56
- "eslint": "^8.55.0",
57
63
  "@typescript-eslint/eslint-plugin": "^6.13.0",
58
- "@typescript-eslint/parser": "^6.13.0"
64
+ "@typescript-eslint/parser": "^6.13.0",
65
+ "eslint": "^8.55.0",
66
+ "typescript": "^5.3.0"
59
67
  },
60
68
  "files": [
61
69
  "dist/",