@weavetab/mcp 2.5.0-beta.0 → 2.5.0-beta.2

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 (98) hide show
  1. package/AGENTS.md +1 -0
  2. package/LICENSE +2 -2
  3. package/README.md +208 -43
  4. package/SECURITY.md +3 -3
  5. package/TROUBLESHOOTING.md +1 -1
  6. package/dist/cdp/bridge.d.ts +10 -0
  7. package/dist/cdp/bridge.js +288 -68
  8. package/dist/cdp/connector.d.ts +5 -3
  9. package/dist/cdp/connector.js +188 -74
  10. package/dist/cdp/extension.js +0 -1
  11. package/dist/cdp/helpers.js +0 -2
  12. package/dist/cdp/lock.d.ts +9 -6
  13. package/dist/cdp/lock.js +72 -59
  14. package/dist/cdp/omni_broker.d.ts +1 -0
  15. package/dist/cdp/omni_broker.js +12 -6
  16. package/dist/cdp/profiles.d.ts +10 -0
  17. package/dist/cdp/profiles.js +65 -0
  18. package/dist/cdp/walker.js +50 -0
  19. package/dist/cli/plugin.d.ts +0 -2
  20. package/dist/cli/plugin.js +31 -683
  21. package/dist/cli/updater.js +2 -2
  22. package/dist/config/loader.d.ts +25 -6
  23. package/dist/config/loader.js +133 -20
  24. package/dist/index.js +48 -52
  25. package/dist/lifecycle/mission_manager.d.ts +0 -1
  26. package/dist/lifecycle/mission_manager.js +0 -3
  27. package/dist/overlay/ghost.d.ts +4 -0
  28. package/dist/overlay/ghost.js +118 -94
  29. package/dist/overlay/injector.d.ts +1 -1
  30. package/dist/overlay/injector.js +1 -15
  31. package/dist/plugin/extension_bridge.d.ts +40 -0
  32. package/dist/plugin/extension_bridge.js +158 -0
  33. package/dist/plugin/interface.d.ts +78 -16
  34. package/dist/plugin/loader.d.ts +4 -0
  35. package/dist/plugin/loader.js +178 -57
  36. package/dist/plugin/registry.js +11 -1
  37. package/dist/plugin/storage.d.ts +51 -0
  38. package/dist/plugin/storage.js +164 -0
  39. package/dist/server.js +217 -151
  40. package/dist/state/session.d.ts +2 -2
  41. package/dist/state/session.js +33 -13
  42. package/dist/tools/browser_detect.d.ts +2 -1
  43. package/dist/tools/browser_detect.js +6 -5
  44. package/dist/tools/burst.d.ts +1 -0
  45. package/dist/tools/burst.js +4 -6
  46. package/dist/tools/click.js +23 -28
  47. package/dist/tools/clipboard.js +31 -24
  48. package/dist/tools/navigate.d.ts +1 -1
  49. package/dist/tools/navigate.js +28 -10
  50. package/dist/tools/read.js +1 -1
  51. package/dist/tools/tabs.d.ts +10 -10
  52. package/dist/tools/tabs.js +47 -39
  53. package/dist/tools/type.js +2 -2
  54. package/docs/DOCUMENTATION.md +63 -6
  55. package/docs/architecture/blind-injection.md +20 -0
  56. package/docs/architecture/dual-injection.md +32 -0
  57. package/docs/architecture/overview.md +49 -0
  58. package/docs/architecture/security.md +35 -0
  59. package/docs/architecture/transport.md +37 -0
  60. package/docs/captcha-stealth/captcha-solver.md +75 -0
  61. package/docs/captcha-stealth/stealth-physics.md +60 -0
  62. package/docs/cli/cli-commands.md +44 -0
  63. package/docs/cli/cli-flags.md +20 -0
  64. package/docs/cli/cli-introduction.md +20 -0
  65. package/docs/cli/cli-scripting.md +32 -0
  66. package/docs/cli/g-ide/ide-antigravity.md +24 -0
  67. package/docs/cli/g-ide/ide-claude-code.md +24 -0
  68. package/docs/cli/g-ide/ide-claude-desktop.md +32 -0
  69. package/docs/cli/g-ide/ide-cursor.md +31 -0
  70. package/docs/cli/g-ide/ide-generic.md +34 -0
  71. package/docs/cli/g-ide/ide-opencode.md +24 -0
  72. package/docs/cli/g-ide/ide-vscode-copilot.md +24 -0
  73. package/docs/cli/g-ide/ide-windsurf.md +24 -0
  74. package/docs/configuration/config-locations.md +24 -0
  75. package/docs/configuration/configuration.md +73 -0
  76. package/docs/configuration/env-variables.md +19 -0
  77. package/docs/configuration/folders.md +54 -0
  78. package/docs/desktop-automation/electron-apps.md +162 -0
  79. package/docs/get-started/installation.md +47 -0
  80. package/docs/get-started/introduction.md +60 -0
  81. package/docs/get-started/quickstart.md +54 -0
  82. package/docs/get-started/setup-wizard.md +26 -0
  83. package/docs/skills-ecosystem/skills-overview.md +35 -0
  84. package/docs/skills-ecosystem/skills-recipes.md +36 -0
  85. package/docs/tools/tools.md +293 -0
  86. package/docs/troubleshooting/trouble-browser.md +27 -0
  87. package/docs/troubleshooting/trouble-config.md +20 -0
  88. package/docs/troubleshooting/trouble-loop.md +31 -0
  89. package/ext-dist/content.js +126 -101
  90. package/mcp.json +8 -15
  91. package/package.json +11 -5
  92. package/server.json +3 -3
  93. package/dist/tools/plan.d.ts +0 -39
  94. package/dist/tools/plan.js +0 -161
  95. package/docs/DEV_MODE.md +0 -68
  96. package/docs/PLUGINS.md +0 -538
  97. package/docs/TOOLS.md +0 -104
  98. package/docs/dev_plugin.md +0 -310
@@ -8,7 +8,13 @@ import { readLock } from "../cdp/lock.js";
8
8
  import { resetLoopCounter } from "../intelligence/trail.js";
9
9
  import { getConfigAgentId, getConfigMaxTabs } from "../config/loader.js";
10
10
  /** Resolve the active CDP port — live > lock file */
11
- function resolvePort(_config) {
11
+ function resolvePort(_config, appName) {
12
+ if (appName) {
13
+ const lock = readLock(appName);
14
+ if (lock && lock.port)
15
+ return lock.port;
16
+ throw new Error(`[!] No active session for Electron app "${appName}". Launch it first.`);
17
+ }
12
18
  const port = getPort() || readLock()?.port;
13
19
  if (!port)
14
20
  throw new Error("[!] No active browser session. Run browser_go first.");
@@ -44,9 +50,9 @@ function calculateSemanticScore(url, title) {
44
50
  score += 30;
45
51
  return Math.min(score, 100);
46
52
  }
47
- export async function evaluateTabSemantics(targetId) {
53
+ export async function evaluateTabSemantics(targetId, appName) {
48
54
  try {
49
- const client = await connectToTab(targetId);
55
+ const client = await connectToTab(targetId, undefined, undefined, undefined, appName);
50
56
  const result = await client.session.Runtime.evaluate({
51
57
  expression: `JSON.stringify({ title: document.title, url: location.href })`,
52
58
  returnByValue: true
@@ -104,17 +110,17 @@ async function enforceMaxTabs(config) {
104
110
  logAction("browser_tabs", victim.id, `auto-closed idle tab: ${victim.title}`);
105
111
  }
106
112
  // ─── Tools ────────────────────────────────────────────────────────────────────
107
- export async function WeavetabOpen(url, config, reuse = true) {
108
- const port = resolvePort(config);
113
+ export async function WeavetabOpen(url, config, reuse = true, appName) {
114
+ const port = resolvePort(config, appName);
109
115
  // Tab reuse: if same URL is already open, focus it instead of duplicating
110
116
  if (reuse && url) {
111
117
  try {
112
- const targets = await getTabList(getConfigAgentId(config));
118
+ const targets = await getTabList(getConfigAgentId(config), appName);
113
119
  const existing = targets.find((t) => t.url === url);
114
120
  if (existing) {
115
- const client = await connectToTab(existing.id);
121
+ const client = await connectToTab(existing.id, undefined, undefined, undefined, appName);
116
122
  await client.session.Target.activateTarget({ targetId: existing.id });
117
- sessionRegistry.setActive(existing.id, getConfigAgentId(config));
123
+ sessionRegistry.setActive(existing.id, getConfigAgentId(config), appName);
118
124
  recordTabActivity(existing.id);
119
125
  logAction("browser_tabs", url, `reused existing tab ${existing.id}`);
120
126
  return { success: true, tabId: existing.id, url, reused: true };
@@ -122,22 +128,24 @@ export async function WeavetabOpen(url, config, reuse = true) {
122
128
  }
123
129
  catch { /* fall through to open new */ }
124
130
  }
125
- await enforceMaxTabs(config);
126
- const bctxId = sessionRegistry.getBrowserContextIdForAgent(getConfigAgentId(config));
131
+ if (!appName) {
132
+ await enforceMaxTabs(config);
133
+ }
134
+ const bctxId = appName ? undefined : sessionRegistry.getBrowserContextIdForAgent(getConfigAgentId(config));
127
135
  const metaSession = await CDP({ host: "127.0.0.1", port });
128
136
  const { targetId } = await metaSession.Target.createTarget({ url, browserContextId: bctxId });
129
137
  await metaSession.close();
130
138
  recordTabActivity(targetId);
131
- await connectToTab(targetId, port, getConfigAgentId(config), bctxId);
132
- await evaluateTabSemantics(targetId);
139
+ await connectToTab(targetId, port, getConfigAgentId(config), bctxId, appName);
140
+ await evaluateTabSemantics(targetId, appName);
133
141
  logAction("browser_tabs", url, `opened ${targetId}`);
134
142
  return { success: true, tabId: targetId, url };
135
143
  }
136
- export async function WeavetabSwitch(tabId, config) {
137
- const client = await connectToTab(tabId);
144
+ export async function WeavetabSwitch(tabId, config, appName) {
145
+ const client = await connectToTab(tabId, undefined, undefined, undefined, appName);
138
146
  const startSwitch = Date.now();
139
147
  await client.session.Target.activateTarget({ targetId: tabId });
140
- sessionRegistry.setActive(tabId, getConfigAgentId(config));
148
+ sessionRegistry.setActive(tabId, getConfigAgentId(config), appName);
141
149
  recordTabActivity(tabId);
142
150
  const { frameTree } = await client.session.Page.getFrameTree();
143
151
  let title = tabId;
@@ -154,9 +162,9 @@ export async function WeavetabSwitch(tabId, config) {
154
162
  resetLoopCounter("tab_switch");
155
163
  return { success: true, tab_id: tabId, title, url, contextSwitchCostMs: cost };
156
164
  }
157
- export async function WeavetabList(config) {
158
- const targets = await getTabList(getConfigAgentId(config));
159
- const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId;
165
+ export async function WeavetabList(config, appName) {
166
+ const targets = await getTabList(getConfigAgentId(config), appName);
167
+ const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config), appName)?.targetId;
160
168
  const tabs = targets
161
169
  .map((t) => ({
162
170
  id: t.id,
@@ -174,12 +182,12 @@ export async function WeavetabList(config) {
174
182
  }));
175
183
  return { tabs };
176
184
  }
177
- export async function WeavetabClose(tabId, config, force = false) {
185
+ export async function WeavetabClose(tabId, config, force = false, appName) {
178
186
  const score = semanticScores.get(tabId) ?? 10;
179
187
  if (score >= 70 && !force) {
180
188
  throw new Error(`[!] Tab Armor block: This tab is semantically protected (score: ${score}). It likely contains a login, checkout, or critical work. Do not close it! If the user explicitly requested this closure, pass force: true.`);
181
189
  }
182
- const port = resolvePort(config);
190
+ const port = resolvePort(config, appName);
183
191
  await CDP.Close({ host: "127.0.0.1", port, id: tabId });
184
192
  clearTabCache(tabId);
185
193
  sessionRegistry.unregister(tabId);
@@ -192,12 +200,12 @@ export async function WeavetabClose(tabId, config, force = false) {
192
200
  /**
193
201
  * Batch close multiple tabs at once — saves multiple round-trips.
194
202
  */
195
- export async function WeavetabCloseBatch(tabIds, config, force = false) {
203
+ export async function WeavetabCloseBatch(tabIds, config, force = false, appName) {
196
204
  const closed = [];
197
205
  const skipped = [];
198
206
  for (const tabId of tabIds) {
199
207
  try {
200
- await WeavetabClose(tabId, config, force);
208
+ await WeavetabClose(tabId, config, force, appName);
201
209
  closed.push(tabId);
202
210
  }
203
211
  catch {
@@ -209,14 +217,14 @@ export async function WeavetabCloseBatch(tabIds, config, force = false) {
209
217
  /**
210
218
  * Consolidate: deduplicate tabs by URL, close duplicates.
211
219
  */
212
- export async function WeavetabConsolidate(config) {
213
- const port = resolvePort(config);
220
+ export async function WeavetabConsolidate(config, appName) {
221
+ const port = resolvePort(config, appName);
214
222
  const targets = await CDP.List({ host: "127.0.0.1", port });
215
- const pages = targets.filter((t) => t.type === "page");
223
+ const pages = targets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app");
216
224
  const tabsBefore = pages.length;
217
225
  const seenUrls = new Set();
218
226
  let closedDuplicates = 0;
219
- const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId;
227
+ const activeTargetId = sessionRegistry.getActive(getConfigAgentId(config), appName)?.targetId;
220
228
  for (const page of pages) {
221
229
  if (page.id === activeTargetId) {
222
230
  seenUrls.add(page.url);
@@ -240,17 +248,17 @@ export async function WeavetabConsolidate(config) {
240
248
  }
241
249
  }
242
250
  const afterTargets = await CDP.List({ host: "127.0.0.1", port });
243
- const tabsAfter = afterTargets.filter((t) => t.type === "page").length;
251
+ const tabsAfter = afterTargets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app").length;
244
252
  logAction("browser_tabs", "consolidate", `${tabsBefore}→${tabsAfter} (closed ${closedDuplicates} duplicates)`);
245
253
  return { success: true, tabs_before: tabsBefore, tabs_after: tabsAfter, closed_duplicates: closedDuplicates };
246
254
  }
247
255
  /**
248
256
  * Heal: check all tabs for crashed state and reload them.
249
257
  */
250
- export async function WeavetabHeal(config) {
251
- const port = resolvePort(config);
258
+ export async function WeavetabHeal(config, appName) {
259
+ const port = resolvePort(config, appName);
252
260
  const targets = await CDP.List({ host: "127.0.0.1", port });
253
- const pages = targets.filter((t) => t.type === "page");
261
+ const pages = targets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app");
254
262
  let healed = 0;
255
263
  const healthSummary = {};
256
264
  for (const page of pages) {
@@ -269,7 +277,7 @@ export async function WeavetabHeal(config) {
269
277
  continue;
270
278
  }
271
279
  try {
272
- const client = await connectToTab(page.id);
280
+ const client = await connectToTab(page.id, undefined, undefined, undefined, appName);
273
281
  const { result } = await client.session.Runtime.evaluate({
274
282
  expression: `document.readyState`,
275
283
  returnByValue: true,
@@ -292,10 +300,10 @@ export async function WeavetabHeal(config) {
292
300
  logAction("browser_tabs", "heal", `healed ${healed}/${pages.length} tabs`);
293
301
  return { success: true, healed, tabs_checked: pages.length, health_summary: healthSummary };
294
302
  }
295
- export async function weaveWindowList(config) {
296
- const port = resolvePort(config);
303
+ export async function weaveWindowList(config, appName) {
304
+ const port = resolvePort(config, appName);
297
305
  const targets = await CDP.List({ host: "127.0.0.1", port });
298
- const pages = targets.filter((t) => t.type === "page");
306
+ const pages = targets.filter((t) => t.type === "page" || t.type === "webview" || t.type === "app");
299
307
  // Group by process — each unique window has its own set of tabs
300
308
  // We approximate via CDP Target.getTargets windowId if available
301
309
  const windows = [];
@@ -307,7 +315,7 @@ export async function weaveWindowList(config) {
307
315
  const { windowId, bounds } = await session.Browser.getWindowForTarget({ targetId: page.id });
308
316
  if (!seenWindowIds.has(windowId)) {
309
317
  seenWindowIds.add(windowId);
310
- const activeId = sessionRegistry.getActive(getConfigAgentId(config))?.targetId;
318
+ const activeId = sessionRegistry.getActive(getConfigAgentId(config), appName)?.targetId;
311
319
  windows.push({
312
320
  windowId,
313
321
  state: bounds.windowState || "normal",
@@ -324,12 +332,12 @@ export async function weaveWindowList(config) {
324
332
  }
325
333
  return { windows };
326
334
  }
327
- export async function weaveFocusWindow(windowId, config) {
328
- const port = resolvePort(config);
335
+ export async function weaveFocusWindow(windowId, config, appName) {
336
+ const port = resolvePort(config, appName);
329
337
  const targets = await CDP.List({ host: "127.0.0.1", port });
330
- const page = targets.find((t) => t.type === "page");
338
+ const page = targets.find((t) => t.type === "page" || t.type === "webview" || t.type === "app");
331
339
  if (!page)
332
- throw new Error("No page target found to focus window");
340
+ throw new Error("No page or window target found to focus window");
333
341
  const session = await CDP({ host: "127.0.0.1", port, target: page.id });
334
342
  try {
335
343
  await session.Browser.setWindowBounds({ windowId, bounds: { windowState: "normal" } });
@@ -657,10 +657,10 @@ export async function weaveType(session, args, config) {
657
657
  // Vue/React controlled inputs re-render the DOM node during focus, making
658
658
  // Ctrl+V land on the old (detached) node. If el.value is still empty,
659
659
  // fallback to Input.insertText which targets the currently-focused element.
660
- if (selector && selector !== 'document.activeElement') {
660
+ if (selector) {
661
661
  const pasteCheck = await session.Runtime.evaluate({
662
662
  expression: `(function(sel) {
663
- var el = document.querySelector(sel) || (window.__Weavetab_shadowQuery ? window.__Weavetab_shadowQuery(sel) : null);
663
+ var el = (sel === 'document.activeElement') ? document.activeElement : (document.querySelector(sel) || (window.__Weavetab_shadowQuery ? window.__Weavetab_shadowQuery(sel) : null));
664
664
  if (!el) return null;
665
665
  return el.value !== undefined ? el.value : (el.textContent || null);
666
666
  })(${JSON.stringify(selector)})`,
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## Overview
8
8
 
9
- Weavetab is a production-grade, in-process MCP (Model Context Protocol) server that grants AI agents human-like control over Chromium browsers. It communicates directly over the Chrome DevTools Protocol (CDP) at Layer 0 — no WebDriver process, no browser binary download, no Playwright/Puppeteer abstraction layer.
9
+ Weavetab is a production-grade, in-process MCP (Model Context Protocol) server providing AI agents with direct, physical Layer 0 control across Chromium browsers and Electron desktop applications. It communicates directly over the Chrome DevTools Protocol (CDP) WebSocket at Layer 0 — no WebDriver process, no browser binary download, no cloud middleware.
10
10
 
11
11
  ### Core Capabilities
12
12
 
@@ -261,10 +261,15 @@ The value is permanently masked as `[REDACTED]` in all subsequent DOM reads and
261
261
  "role": "admin",
262
262
  "telemetry": false,
263
263
  "attachPort": 0,
264
- "disableExtensions": false,
264
+ "extension": true,
265
265
  "cookies": false,
266
266
  "browserFlags": [],
267
- "policies": []
267
+ "policies": [],
268
+ "electron": {
269
+ "discord": "C:\\Users\\<user>\\AppData\\Local\\Discord\\app-1.0.9183\\Discord.exe",
270
+ "antigravity": "C:\\Users\\<user>\\AppData\\Local\\Programs\\antigravity\\Antigravity.exe",
271
+ "vscode": "C:\\Users\\<user>\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"
272
+ }
268
273
  }
269
274
  ```
270
275
 
@@ -279,10 +284,11 @@ The value is permanently masked as `[REDACTED]` in all subsequent DOM reads and
279
284
  | `role` | string | "admin" | RBAC role (admin, system, viewer, automation) |
280
285
  | `telemetry` | boolean | false | Enable anonymous usage telemetry |
281
286
  | `attachPort` | number | 0 | Chrome DevTools Protocol port |
282
- | `disableExtensions` | boolean | false | Disable Weavetab extension for HUD features |
287
+ | `extension` | boolean | true | Enable Weavetab extension integration |
283
288
  | `cookies` | boolean | false | Persist cookies/storage across sessions. When `false`, `document.cookie`, `localStorage`, and `sessionStorage` are all neutered at the browser level (returns empty/null for everything) + a fresh isolated profile is used each session. When `true`, cookies/storage work normally and persist via the profile directory. |
284
289
  | `browserFlags` | string[] | `[]` | Extra Chromium command-line flags to append on launch (e.g., `["--disable-web-security"]`). The `--disable-sync` flag is mandatory and cannot be overridden — any conflicting flag is automatically dropped. |
285
290
  | `policies` | PolicyEntry[] | `[]` | Domain-level access control policies (see [Domain Policy](#domain-policy) below). Supersedes the legacy `block`/`allow` lists. |
291
+ | `electron` | Record<string, string> | `{}` | Map of registered Electron desktop applications (e.g. Discord, VS Code, Figma, Antigravity, local dev apps) to executable paths or startup commands. |
286
292
 
287
293
  ---
288
294
 
@@ -448,10 +454,10 @@ export default plugin;
448
454
 
449
455
  ```bash
450
456
  # Official plugins
451
- wt plugin add @weavetab/plugin-sample
457
+ weavetab plugin add @weavetab/plugin-sample
452
458
 
453
459
  # Community plugins (any npm name)
454
- wt plugin add wt-my-tool
460
+ weavetab plugin add wt-my-tool
455
461
  # or via npm
456
462
  npm install wt-my-tool
457
463
  ```
@@ -489,6 +495,57 @@ Skills are automatically discovered by MCP clients and provide:
489
495
 
490
496
  ---
491
497
 
498
+ ## Electron & Desktop Application Automation
499
+
500
+ Weavetab natively supports **generic automation of any Electron or Chromium-based desktop application** (e.g. Discord, Slack, VS Code, Antigravity IDE, Figma, Obsidian, Postman, or local developer applications running from source).
501
+
502
+ ### Why It Works at Layer 0
503
+ Electron desktop applications run a bundled Chromium/Blink engine under the hood. When started with Chrome DevTools Protocol debugging enabled (either automatically via Weavetab or via `--remote-debugging-port`), Weavetab connects directly to the desktop app's internal WebSockets and exposes all 45+ MCP tools without requiring external drivers or wrappers.
504
+
505
+ ### Registering Applications
506
+ In `~/.weavetab/config.json` or project-scoped `.weavetab/config.json`:
507
+
508
+ ```json
509
+ {
510
+ "electron": {
511
+ "discord": "C:\\Users\\<user>\\AppData\\Local\\Discord\\app-1.0.9183\\Discord.exe",
512
+ "antigravity": "C:\\Users\\<user>\\AppData\\Local\\Programs\\antigravity\\Antigravity.exe",
513
+ "vscode": "C:\\Users\\<user>\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe",
514
+ "figma": "C:\\Users\\<user>\\AppData\\Local\\Figma\\Figma.exe",
515
+ "obsidian": "C:\\Users\\<user>\\AppData\\Local\\Obsidian\\Obsidian.exe",
516
+ "my-app": "C:\\path\\to\\my-project\\node_modules\\electron\\dist\\electron.exe"
517
+ }
518
+ }
519
+ ```
520
+
521
+ ### Automating Local / Source-Hosted Projects
522
+ When developing an Electron app locally (e.g. `localhost:3000` or running via Vite/Webpack/Electron forge):
523
+
524
+ 1. **Launch with remote debugging enabled:**
525
+ ```bash
526
+ npx electron . --remote-debugging-port=9222
527
+ # or with npm scripts:
528
+ npm run dev -- --remote-debugging-port=9222
529
+ ```
530
+
531
+ 2. **Automate via MCP tools:**
532
+ Set `"attachPort": 9222` or register the dev script in `"electron"` config.
533
+
534
+ ### Tool Execution Flow with Desktop Apps
535
+ Every Weavetab tool supports the optional `app` parameter:
536
+
537
+ | Tool Call | Desktop Behavior |
538
+ | :--- | :--- |
539
+ | `browser_navigate({ app: "antigravity" })` | Launches or connects to Antigravity's CDP session |
540
+ | `browser_tabs({ action: "list", app: "antigravity" })` | Lists all windows, webviews, and workbench tabs in the app |
541
+ | `browser_tabs({ action: "switch", tabId: "<id>", app: "antigravity" })` | Switches active focus to the specified workbench or window |
542
+ | `browser_map({ app: "antigravity" })` | Generates semantic Ref IDs (`w:NN`) for the desktop app's active window |
543
+ | `browser_click({ ref: "w:12", app: "antigravity" })` | Sends Ghost Cursor click to the desktop app element |
544
+ | `browser_type({ ref: "w:15", text: "...", app: "discord" })` | Types text directly into the desktop app input field |
545
+ | `browser_eval({ expression: "...", app: "vscode" })` | Evaluates JavaScript inside the desktop app frame context |
546
+
547
+ ---
548
+
492
549
  ## Troubleshooting
493
550
 
494
551
  ### Common Issues
@@ -0,0 +1,20 @@
1
+ ---
2
+ title: "Blind Injection"
3
+ description: "Enterprise-grade credential injection that never exposes secrets to the LLM."
4
+ product: mcp
5
+ section: architecture
6
+ icon: Lock
7
+ slug: blind-injection
8
+ ---
9
+
10
+ # Blind Injection
11
+
12
+ The `browser_type_secret` tool resolves passwords, tokens, and 2FA credentials directly from `secrets.json` on the server — **never exposing sensitive values to the AI model's context stream**.
13
+
14
+ ## How It Works
15
+
16
+ 1. Store a secret via `weavetab secrets set MY_KEY` or by editing `secrets.json`
17
+ 2. The agent calls `browser_type_secret({ id: "w:2", envKey: "MY_KEY" })`
18
+ 3. Weavetab resolves the secret from `secrets.json` in-process on the local machine
19
+ 4. The value is typed directly into the DOM input field over CDP
20
+ 5. All subsequent `browser_map` outputs, DOM snapshots, and audit logs permanently display `[REDACTED]` for that element
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: "Dual Injection"
3
+ description: "CDP early-script + Manifest V3 extension working in tandem."
4
+ product: mcp
5
+ section: architecture
6
+ icon: Combine
7
+ slug: dual-injection
8
+ ---
9
+
10
+ # Dual Injection Strategy
11
+
12
+ Weavetab delivers overlay UI and stealth capabilities through **two complementary channels** that cover each other's blind spots.
13
+
14
+ ## 1. CDP Early-Script Injection
15
+
16
+ ```typescript
17
+ await session.Page.addScriptToEvaluateOnNewDocument({ source: STEALTH_SCRIPT });
18
+ await session.Runtime.evaluate({ expression: STEALTH_SCRIPT }).catch(() => {});
19
+ ```
20
+
21
+ Runs **before any page JavaScript executes**. Handles:
22
+ - **Stealth patches**: `navigator.webdriver` → `undefined`, fake plugin arrays, WebGL/Canvas fingerprint noise
23
+ - **Shadow DOM bootstrap**: `#weavetab-root` host container created in every page
24
+ - **Config binding**: `window.__wt_setConfig`, `window.__wt_config` for live runtime updates
25
+
26
+ ## 2. Manifest V3 Extension
27
+
28
+ Loaded dynamically with `--load-extension=${extPath}`. Owns:
29
+ - **Ghost Cursor animation** (Bézier curve path rendering via canvas overlay)
30
+ - **Thought bubble HUD** (agent status messages during tool execution)
31
+ - **Interactive Ask Modal** (user interaction with response queue)
32
+ - **SPA navigation persistence** — survives framework router transitions without flashing
@@ -0,0 +1,49 @@
1
+ ---
2
+ title: "Overview"
3
+ description: "Five layers, deterministic pipeline, zero cloud."
4
+ product: mcp
5
+ section: architecture
6
+ icon: Layers
7
+ slug: overview
8
+ ---
9
+
10
+ # Architecture Overview
11
+
12
+ Weavetab is decomposed into **five functional layers**, all running in-process without external daemon dependencies.
13
+
14
+ ## Layer Map
15
+
16
+ | # | Layer | Responsibility |
17
+ |---|---|---|
18
+ | 1 | **Transport** | JSON-RPC 2.0 over stdio or WebSocket (`--ws --port 3000`) |
19
+ | 2 | **Security & Governance** | Domain blacklist, rate limiter (mutex), RBAC roles, policy engine, root guard |
20
+ | 3 | **Intelligence Engine** | Session memory, semantic delta diffing, DOM pruner, loop detection, intent intercept |
21
+ | 4 | **Sensor Systems** | Network telemetry, DOM mutation observer, human pacing, agent state machine |
22
+ | 5 | **CDP Bridge** | DOM walker, Ghost Cursor (Bézier trajectories), keystroke engine, shadow-DOM injector |
23
+
24
+ ## Tool Execution Pipeline
25
+
26
+ ```text
27
+ Agent → withSecurity()
28
+ ├── Rate limiter (mutex)
29
+ ├── Domain policy check (allow/deny/audit/read-only)
30
+ ├── RBAC role verification
31
+ ├── User-stop polling
32
+ ├── Chat queue draining
33
+ ├── Agent state transition (idle → weaving → reading)
34
+ └── Tool handler → CDP Bridge → Browser / Desktop App
35
+ ```
36
+
37
+ Any validation or security failure short-circuits the pipeline immediately and returns a structured `WeaveError` — no partial side-effects are left on the browser.
38
+
39
+ ## Why Direct CDP
40
+
41
+ | Feature | Weavetab | Playwright | Puppeteer | Selenium |
42
+ |---|---|---|---|---|
43
+ | **Architecture** | Direct CDP Layer 0 | Node bridge abstraction | CDP wrapper | WebDriver |
44
+ | **Mean latency** | **3–8 ms** | 15–40 ms | 10–25 ms | 50–150 ms |
45
+ | **Token efficiency** | **Semantic Deltas (97% reduction)** | Full DOM dumps | Full DOM dumps | Full DOM dumps |
46
+ | **Desktop Electron Apps** | **Native (any Electron app)** | Experimental | Limited | Third-party driver |
47
+ | **CAPTCHA Solver** | **Autonomous Zero-API** | None | None | None |
48
+ | **MCP native** | **Yes (45 tools)** | No | No | No |
49
+ | **Cloud dependency** | **Zero** | Optional | Optional | Grid required |
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: "Security Model"
3
+ description: "Layered defenses that gate every tool invocation."
4
+ product: mcp
5
+ section: architecture
6
+ icon: ShieldCheck
7
+ slug: security
8
+ ---
9
+
10
+ # Security Model
11
+
12
+ Weavetab executes direct Layer 0 CDP commands — security is layered and **deny-by-default for risky surfaces**.
13
+
14
+ ## Defense-in-Depth Mechanisms
15
+
16
+ | Mechanism | Description |
17
+ |---|---|
18
+ | **Domain Blacklist** | Hard-blocked high-risk domains (banking, IAM consoles, internal infrastructure). |
19
+ | **Domain Policy Engine** | Per-domain enforcement modes: `allow`, `read-only`, `deny`, `audit`. |
20
+ | **Localhost Binding** | WebSocket server and CDP endpoints strictly bound to `127.0.0.1`. |
21
+ | **Rate Limiting** | Mutex-enforced actions-per-minute rate limiter. |
22
+ | **RBAC Roles** | 4 strict roles gating tool access (`admin`, `operator`, `viewer`, `automation`). |
23
+ | **Root Guard** | Prevents execution as root/superuser on Unix systems. |
24
+ | **Blind Injection** | Credential injection from `secrets.json` without exposing raw text to LLM context. |
25
+ | **Shadow DOM Isolation** | All injected HUD and modal overlays run in isolated Shadow DOM trees. |
26
+ | **Path Traversal Guard** | File upload and download paths strictly validated against path traversal. |
27
+
28
+ ## RBAC Role Matrix
29
+
30
+ | Tool Category | admin | operator | viewer | automation |
31
+ |---|:---:|:---:|:---:|:---:|
32
+ | Mutation tools (`click`, `type`, `fill`, etc.) | yes | yes | no | yes |
33
+ | Read-only tools (`map`, `find`, `scrape`, `screenshot`) | yes | yes | yes | yes |
34
+ | High-level orchestration (`burst`, `plan`, `wait`) | yes | yes | no | yes |
35
+ | System management (`detect`, `reset_loop_counter`) | yes | no | no | no |
@@ -0,0 +1,37 @@
1
+ ---
2
+ title: "Transport Modes"
3
+ description: "stdio vs WebSocket — pick the right wire for your client."
4
+ product: mcp
5
+ section: architecture
6
+ icon: Cable
7
+ slug: transport
8
+ ---
9
+
10
+ # Transport Modes
11
+
12
+ | Mode | Flag | Protocol | Use Case |
13
+ |---|---|---|---|
14
+ | **stdio** | *(default)* | JSON-RPC 2.0 / stdio | Claude Desktop, Cursor, VS Code Copilot, Antigravity |
15
+ | **WebSocket** | `--ws` | JSON-RPC 2.0 / WebSocket | Custom agents, Python/Go backends, remote daemons, n8n |
16
+
17
+ ## stdio (Default)
18
+
19
+ The MCP client spawns Weavetab as a child process and pipes messages over stdin/stdout. No network port is opened:
20
+
21
+ ```json
22
+ {
23
+ "mcpServers": {
24
+ "weavetab": {
25
+ "command": "weavetab"
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## WebSocket
32
+
33
+ ```bash
34
+ weavetab --ws --port 3000
35
+ ```
36
+
37
+ WebSocket mode binds strictly to `127.0.0.1` for local security. Front it with your own TLS/auth layer if exposing across a private network.
@@ -0,0 +1,75 @@
1
+ ---
2
+ title: "CAPTCHA Solver"
3
+ description: "Autonomous zero-API solver for Turnstile, GeeTest, and reCAPTCHA."
4
+ product: mcp
5
+ section: captcha-stealth
6
+ badge: new
7
+ icon: ShieldAlert
8
+ slug: captcha-solver
9
+ ---
10
+
11
+ # Autonomous Zero-API CAPTCHA Solver
12
+
13
+ Weavetab features a built-in **Autonomous Zero-API CAPTCHA Solver** via the `browser_captcha` tool. It solves complex challenges locally using real CDP pointer physics, Bézier kinematics, and DOM heuristics — requiring **$0 external solver API costs** and zero third-party subscription keys (no 2Captcha, Anti-Captcha, or CapSolver needed).
14
+
15
+ ```typescript
16
+ // Detect and solve active challenge automatically
17
+ browser_captcha({ action: "solve", timeout: 60000 })
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Supported Challenge Matrix
23
+
24
+ | Challenge Type | Target Systems | Solving Technique | Zero API Cost |
25
+ |---|---|---|:---:|
26
+ | **Cloudflare Turnstile** | Cloudflare protected surfaces | Sustained mousedown + micro-jitter physics | Yes |
27
+ | **GeeTest Slider** | GeeTest v3 / v4 puzzle sliders | Bézier velocity drag + momentum overshoot correction | Yes |
28
+ | **Google reCAPTCHA v2** | Checkbox & iframe challenges | Nested cross-origin iframe pointer penetration | Yes |
29
+ | **Google reCAPTCHA v3** | Invisible score-based barriers | High-entropy behavioral simulation bursts | Yes |
30
+ | **Arkose Labs / FunCAPTCHA** | Interactive verification | Synthetic CDP pointer kinematics + rotation solver | Yes |
31
+ | **hCaptcha** | Checkbox challenges | Cross-domain iframe dispatch + heuristic click | Yes |
32
+ | **Math / Text Challenges** | Inline security prompts | DOM arithmetic evaluation + synthetic input | Yes |
33
+
34
+ ---
35
+
36
+ ## How It Works
37
+
38
+ ### 1. Cloudflare Turnstile & Interactive Checkboxes
39
+ Cloudflare Turnstile evaluates the physical trajectory and hold duration of the click. Weavetab:
40
+ - Calculates a randomized human Bézier path from current cursor coordinates to the checkbox center.
41
+ - Dispatches CDP `Input.dispatchMouseEvent` with `mousePressed` event.
42
+ - Applies **micro-jitter displacement** (1–3 pixel variations) for 120–280 ms simulating organic finger tremor.
43
+ - Releases `mouseReleased` event and monitors CDP DOM mutations for success tokens.
44
+
45
+ ### 2. GeeTest & Slider Puzzles
46
+ For slider challenges, Weavetab calculates the drag distance, applies variable velocity profiling (rapid acceleration, mid-flight coasting, deceleration), and introduces subtle overshoot correction:
47
+
48
+ ```text
49
+ Start (0px) ──[Fast Accel]──► Mid (70%) ──[Decel]──► Target (100%) ──[Overshoot +2px]──► Final Lock
50
+ ```
51
+
52
+ ### 3. reCAPTCHA v2 & Cross-Origin Iframes
53
+ reCAPTCHA isolates the checkbox inside cross-origin iframes (`anchor` frame). Weavetab penetrates the isolated iframe context via CDP `DOM.describeNode` and dispatches synthetic pointer events directly to the inner target.
54
+
55
+ ---
56
+
57
+ ## Tool API Reference: `browser_captcha`
58
+
59
+ **Parameters:**
60
+ | Parameter | Type | Description |
61
+ |---|---|---|
62
+ | `action` | `"detect" | "solve" | "wait_for_user" | "status"` *(required)* | Operation to perform. |
63
+ | `timeout` | `number?` | Maximum timeout in milliseconds (default `120000`). |
64
+
65
+ ### Example Usage
66
+
67
+ ```typescript
68
+ // Step 1: Detect if a CAPTCHA exists on page
69
+ const detection = await browser_captcha({ action: "detect" });
70
+ if (detection.detected) {
71
+ // Step 2: Solve autonomously
72
+ const result = await browser_captcha({ action: "solve", timeout: 45000 });
73
+ console.log("Solved:", result.success);
74
+ }
75
+ ```
@@ -0,0 +1,60 @@
1
+ ---
2
+ title: "Stealth & Physics"
3
+ description: "Ghost Cursor Bézier kinematics, typing jitter, and anti-fingerprinting."
4
+ product: mcp
5
+ section: captcha-stealth
6
+ icon: Sparkles
7
+ slug: stealth-physics
8
+ ---
9
+
10
+ # Stealth & Kinematic Physics
11
+
12
+ Weavetab is built from the ground up to make AI automation indistinguishable from human input at the browser and DOM event levels.
13
+
14
+ ## 1. Ghost Cursor Bézier Kinematics
15
+
16
+ Standard automation tools warp cursor coordinates instantaneously (`x: 0` → `x: 500` in 0ms), which triggers modern anti-bot heuristics.
17
+
18
+ Weavetab's **Ghost Cursor** engine generates dynamic **cubic Bézier curves** with randomized control points for every movement:
19
+
20
+ ```text
21
+ P0 (Current Pos) ──────► P1 (Control Pt 1) ──────► P2 (Control Pt 2) ──────► P3 (Target)
22
+ ```
23
+
24
+ - **Acceleration Profiling**: Gaussian velocity distribution with natural ramp-up and ramp-down.
25
+ - **Micro-Jitter**: Per-frame sub-pixel deviations mimicking human muscle tremor.
26
+ - **Overshoot & Correction**: Intentional minor overshoots past the target element followed by corrective micro-adjustments.
27
+ - **Visual Overlay**: Real-time canvas overlay rendering the glowing Ghost Cursor path in the browser window.
28
+
29
+ ---
30
+
31
+ ## 2. Human Keystroke Synthesis
32
+
33
+ The `browser_type` engine dispatches native CDP `Input.dispatchKeyEvent` calls with realistic human timing profiles:
34
+
35
+ - **Temporal Jitter**: Per-character delays sampled between 35 ms and 95 ms.
36
+ - **Burst Profiling**: Common character digraphs (e.g., `th`, `er`, `ing`) are typed faster in bursts.
37
+ - **Word Boundary Pauses**: Natural pauses (120–250 ms) after spaces and punctuation marks.
38
+ - **Stuck-Input Breaking**: DOM diffing detects if keystrokes are failing to register and breaks out of deadlocks.
39
+
40
+ ---
41
+
42
+ ## 3. Layer 0 Fingerprint Spoofing
43
+
44
+ Weavetab's early-script CDP injection guarantees that the following patches execute **before any page JavaScript runs**:
45
+
46
+ ```typescript
47
+ // navigator.webdriver is permanently undefined
48
+ Object.defineProperty(navigator, 'webdriver', { get: () => undefined });
49
+
50
+ // Native plugin and mime-type arrays spoofed
51
+ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5] });
52
+
53
+ // WebGL vendor and renderer noise injection
54
+ const getParameter = WebGLRenderingContext.prototype.getParameter;
55
+ WebGLRenderingContext.prototype.getParameter = function(parameter) {
56
+ if (parameter === 37445) return 'Google Inc. (Intel)';
57
+ if (parameter === 37446) return 'ANGLE (Intel, Intel(R) UHD Graphics Direct3D11)';
58
+ return getParameter.apply(this, arguments);
59
+ };
60
+ ```