@opentabs-dev/mcp-server 0.0.63 → 0.0.65

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 (100) hide show
  1. package/dist/browser-tools/click-element.js +3 -3
  2. package/dist/browser-tools/click-element.js.map +1 -1
  3. package/dist/browser-tools/press-key.js +5 -5
  4. package/dist/browser-tools/press-key.js.map +1 -1
  5. package/dist/dev-proxy.js +19 -7
  6. package/dist/dev-proxy.js.map +1 -1
  7. package/dist/extension-handlers.d.ts +11 -2
  8. package/dist/extension-handlers.d.ts.map +1 -1
  9. package/dist/extension-handlers.js +73 -7
  10. package/dist/extension-handlers.js.map +1 -1
  11. package/dist/extension-protocol.d.ts.map +1 -1
  12. package/dist/extension-protocol.js +10 -1
  13. package/dist/extension-protocol.js.map +1 -1
  14. package/dist/http-routes.d.ts.map +1 -1
  15. package/dist/http-routes.js +56 -0
  16. package/dist/http-routes.js.map +1 -1
  17. package/dist/loader.d.ts +2 -0
  18. package/dist/loader.d.ts.map +1 -1
  19. package/dist/loader.js +9 -0
  20. package/dist/loader.js.map +1 -1
  21. package/dist/mcp-prompts.d.ts +71 -0
  22. package/dist/mcp-prompts.d.ts.map +1 -0
  23. package/dist/mcp-prompts.js +248 -0
  24. package/dist/mcp-prompts.js.map +1 -0
  25. package/dist/mcp-resources.d.ts +53 -0
  26. package/dist/mcp-resources.d.ts.map +1 -0
  27. package/dist/mcp-resources.js +139 -0
  28. package/dist/mcp-resources.js.map +1 -0
  29. package/dist/mcp-setup.d.ts +13 -1
  30. package/dist/mcp-setup.d.ts.map +1 -1
  31. package/dist/mcp-setup.js +166 -2
  32. package/dist/mcp-setup.js.map +1 -1
  33. package/dist/plugin-management.d.ts +14 -1
  34. package/dist/plugin-management.d.ts.map +1 -1
  35. package/dist/plugin-management.js +55 -1
  36. package/dist/plugin-management.js.map +1 -1
  37. package/dist/prompts/audit-ai-docs.d.ts +6 -0
  38. package/dist/prompts/audit-ai-docs.d.ts.map +1 -0
  39. package/dist/prompts/audit-ai-docs.js +155 -0
  40. package/dist/prompts/audit-ai-docs.js.map +1 -0
  41. package/dist/prompts/build-plugin.d.ts +3 -0
  42. package/dist/prompts/build-plugin.d.ts.map +1 -0
  43. package/dist/prompts/build-plugin.js +455 -0
  44. package/dist/prompts/build-plugin.js.map +1 -0
  45. package/dist/prompts/contribute-learnings.d.ts +12 -0
  46. package/dist/prompts/contribute-learnings.d.ts.map +1 -0
  47. package/dist/prompts/contribute-learnings.js +107 -0
  48. package/dist/prompts/contribute-learnings.js.map +1 -0
  49. package/dist/prompts/plugin-icon.d.ts +5 -0
  50. package/dist/prompts/plugin-icon.d.ts.map +1 -0
  51. package/dist/prompts/plugin-icon.js +147 -0
  52. package/dist/prompts/plugin-icon.js.map +1 -0
  53. package/dist/prompts/setup-plugin.d.ts +3 -0
  54. package/dist/prompts/setup-plugin.d.ts.map +1 -0
  55. package/dist/prompts/setup-plugin.js +197 -0
  56. package/dist/prompts/setup-plugin.js.map +1 -0
  57. package/dist/prompts/troubleshoot.d.ts +3 -0
  58. package/dist/prompts/troubleshoot.d.ts.map +1 -0
  59. package/dist/prompts/troubleshoot.js +191 -0
  60. package/dist/prompts/troubleshoot.js.map +1 -0
  61. package/dist/reload.d.ts.map +1 -1
  62. package/dist/reload.js +9 -6
  63. package/dist/reload.js.map +1 -1
  64. package/dist/resources/browser-tools.d.ts +3 -0
  65. package/dist/resources/browser-tools.d.ts.map +1 -0
  66. package/dist/resources/browser-tools.js +100 -0
  67. package/dist/resources/browser-tools.js.map +1 -0
  68. package/dist/resources/cli.d.ts +3 -0
  69. package/dist/resources/cli.d.ts.map +1 -0
  70. package/dist/resources/cli.js +217 -0
  71. package/dist/resources/cli.js.map +1 -0
  72. package/dist/resources/plugin-development.d.ts +3 -0
  73. package/dist/resources/plugin-development.d.ts.map +1 -0
  74. package/dist/resources/plugin-development.js +596 -0
  75. package/dist/resources/plugin-development.js.map +1 -0
  76. package/dist/resources/quick-start.d.ts +3 -0
  77. package/dist/resources/quick-start.d.ts.map +1 -0
  78. package/dist/resources/quick-start.js +210 -0
  79. package/dist/resources/quick-start.js.map +1 -0
  80. package/dist/resources/sdk-api.d.ts +3 -0
  81. package/dist/resources/sdk-api.d.ts.map +1 -0
  82. package/dist/resources/sdk-api.js +199 -0
  83. package/dist/resources/sdk-api.js.map +1 -0
  84. package/dist/resources/self-improvement.d.ts +10 -0
  85. package/dist/resources/self-improvement.d.ts.map +1 -0
  86. package/dist/resources/self-improvement.js +91 -0
  87. package/dist/resources/self-improvement.js.map +1 -0
  88. package/dist/resources/status.d.ts +5 -0
  89. package/dist/resources/status.d.ts.map +1 -0
  90. package/dist/resources/status.js +27 -0
  91. package/dist/resources/status.js.map +1 -0
  92. package/dist/resources/troubleshooting.d.ts +3 -0
  93. package/dist/resources/troubleshooting.d.ts.map +1 -0
  94. package/dist/resources/troubleshooting.js +167 -0
  95. package/dist/resources/troubleshooting.js.map +1 -0
  96. package/dist/state.d.ts +6 -0
  97. package/dist/state.d.ts.map +1 -1
  98. package/dist/state.js +9 -3
  99. package/dist/state.js.map +1 -1
  100. package/package.json +1 -1
@@ -0,0 +1,147 @@
1
+ /**
2
+ * plugin_icon prompt — workflow for adding or updating an SVG icon for an OpenTabs plugin.
3
+ */
4
+ export const pluginIconPromptText = (plugin) => `Add or update the SVG icon for the **${plugin}** OpenTabs plugin. Follow the full workflow below.
5
+
6
+ ---
7
+
8
+ ## How Plugin Icons Work
9
+
10
+ Plugin icons are **discovered by convention** during \`opentabs-plugin build\`. The build tool looks for \`icon.svg\` at the **plugin root directory** (next to \`package.json\`).
11
+
12
+ ### Icon File Layout
13
+
14
+ | File | Purpose | If absent |
15
+ |---|---|---|
16
+ | \`icon.svg\` | Light mode active icon | Letter avatar fallback |
17
+ | \`icon-inactive.svg\` | Light mode inactive icon | Auto-generated (grayscale via BT.709) |
18
+ | \`icon-dark.svg\` | Dark mode active icon | Auto-generated (lightness inversion for low-contrast colors) |
19
+ | \`icon-dark-inactive.svg\` | Dark mode inactive icon | Auto-generated (grayscale of dark variant) |
20
+
21
+ ### Icon Pipeline
22
+
23
+ \`\`\`
24
+ icon.svg + icon-dark.svg (plugin root)
25
+ → opentabs-plugin build (validates, minifies, auto-generates missing variants)
26
+ → dist/tools.json (iconSvg / iconInactiveSvg / iconDarkSvg / iconDarkInactiveSvg)
27
+ → MCP server loads from tools.json → Chrome extension → side panel
28
+ \`\`\`
29
+
30
+ ### Dark Mode Auto-Generation
31
+
32
+ When \`icon-dark.svg\` is not provided, the build tool adapts colors with insufficient WCAG contrast (< 3:1) against the dark card background (\`#242424\`). Colors with sufficient contrast pass through unchanged — colorful brand icons (Slack, Discord) stay untouched, while monochrome dark icons have their lightness inverted in HSL space.
33
+
34
+ **Provide explicit \`icon-dark.svg\` when:** the brand provides official light/dark variants, or auto-generation doesn't produce a satisfactory result.
35
+
36
+ ---
37
+
38
+ ## SVG Requirements
39
+
40
+ The build tool (\`platform/plugin-tools/src/validate-icon.ts\`) enforces:
41
+
42
+ | Constraint | Rule |
43
+ |---|---|
44
+ | File size | <= 8 KB |
45
+ | viewBox | Must be present |
46
+ | viewBox shape | Must be **square** (width === height) |
47
+ | Forbidden elements | No \`<image>\`, no \`<script>\` |
48
+ | Forbidden attributes | No event handlers (\`onclick\`, \`onload\`, etc.) |
49
+
50
+ Custom inactive icons must additionally use only achromatic colors (grays, black, white).
51
+
52
+ ---
53
+
54
+ ## Step 1: Obtain the Source SVG
55
+
56
+ Get the brand SVG from the service's official brand assets page. Prefer:
57
+ - The **icon-only** variant (no wordmark/lockup)
58
+ - A **single-color** version (works best at small sizes)
59
+ - The **dark/black** variant for \`icon.svg\` (light mode has a light background)
60
+ - If the brand provides separate light and dark variants, use dark-colored for \`icon.svg\` and light-colored for \`icon-dark.svg\`
61
+
62
+ **Watch out for fake SVGs**: Some downloads are rasterized PNGs embedded inside SVG wrappers (\`<image>\` with base64 \`data:image/png\`). These fail validation. A real vector SVG contains \`<path>\`, \`<circle>\`, \`<rect>\`, etc.
63
+
64
+ ### Fallback: Simple Icons
65
+
66
+ If official brand assets don't provide a usable vector SVG, use **Simple Icons**:
67
+
68
+ \`\`\`
69
+ https://raw.githubusercontent.com/simple-icons/simple-icons/develop/icons/<name>.svg
70
+ \`\`\`
71
+
72
+ Use WebFetch to download, then clean up:
73
+ - Remove \`role="img"\` from \`<svg>\`
74
+ - Remove \`<title>\` element
75
+ - Add \`fill="black"\` to the \`<path>\`
76
+ - The viewBox is already square (\`0 0 24 24\`)
77
+
78
+ Simple Icons are CC0 (public domain).
79
+
80
+ ---
81
+
82
+ ## Step 2: Prepare the SVG
83
+
84
+ ### Non-Square viewBox (most common issue)
85
+
86
+ Expand the viewBox to a square and center content using the min-x/min-y offset:
87
+
88
+ For \`0 0 W H\` where \`W > H\`: \`viewBox="0 -(W-H)/2 W W"\`
89
+ For \`0 0 W H\` where \`H > W\`: \`viewBox="-(H-W)/2 0 H H"\`
90
+
91
+ Example: \`0 0 98 96\` → \`viewBox="0 -1 98 98"\`
92
+
93
+ ### Cleanup
94
+
95
+ Remove from \`<svg>\`: \`width\`, \`height\`, Figma/Illustrator metadata.
96
+ Keep: \`xmlns="http://www.w3.org/2000/svg"\`, \`viewBox\`.
97
+
98
+ ### Clip Paths
99
+
100
+ If a \`<clipPath>\` clips to the original non-square dimensions and you expanded the viewBox, evaluate whether the clip path is still needed — often it can be removed.
101
+
102
+ ### File Size
103
+
104
+ If > 8 KB: remove comments/metadata, simplify paths, reduce decimal precision, remove redundant \`<g>\` wrappers.
105
+
106
+ ---
107
+
108
+ ## Step 3: Place the Icons
109
+
110
+ \`\`\`
111
+ plugins/${plugin}/icon.svg # Required
112
+ plugins/${plugin}/icon-dark.svg # Optional — dark mode active
113
+ plugins/${plugin}/icon-inactive.svg # Optional — light mode inactive override
114
+ plugins/${plugin}/icon-dark-inactive.svg # Optional — dark mode inactive override
115
+ \`\`\`
116
+
117
+ Only \`icon.svg\` is required. All other variants are auto-generated if absent.
118
+
119
+ ---
120
+
121
+ ## Step 4: Build
122
+
123
+ \`\`\`bash
124
+ cd plugins/${plugin}
125
+ npm run build
126
+ \`\`\`
127
+
128
+ The build output confirms icon discovery. If validation fails, it reports specific errors.
129
+
130
+ ---
131
+
132
+ ## Step 5: Verify
133
+
134
+ 1. Check all icon variants are in \`dist/tools.json\`:
135
+
136
+ \`\`\`bash
137
+ node -e "const m = require('./dist/tools.json'); console.log('iconSvg:', !!m.iconSvg, 'iconInactiveSvg:', !!m.iconInactiveSvg, 'iconDarkSvg:', !!m.iconDarkSvg, 'iconDarkInactiveSvg:', !!m.iconDarkInactiveSvg)"
138
+ \`\`\`
139
+
140
+ 2. Open the Chrome extension side panel and verify the icon renders correctly in both light and dark mode, in both active and inactive states.
141
+
142
+ ---
143
+
144
+ ## Write Learnings Back
145
+
146
+ If you discover new SVG preparation techniques or icon gotchas, add them directly to this prompt file: \`platform/mcp-server/src/prompts/plugin-icon.ts\`.`;
147
+ //# sourceMappingURL=plugin-icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-icon.js","sourceRoot":"","sources":["../../src/prompts/plugin-icon.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,MAAc,EACN,EAAE,CAAC,wCAAwC,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA2GjD,MAAM;UACN,MAAM;UACN,MAAM;UACN,MAAM;;;;;;;;;;aAUH,MAAM;;;;;;;;;;;;;;;;;;;;;;2JAsBwI,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Prompt text for the `setup_plugin` prompt — plugin installation and configuration workflow. */
2
+ export declare const setupPluginPromptText: (name: string) => string;
3
+ //# sourceMappingURL=setup-plugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-plugin.d.ts","sourceRoot":"","sources":["../../src/prompts/setup-plugin.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAElG,eAAO,MAAM,qBAAqB,GAAI,MAAM,MAAM,KAAG,MAmMpD,CAAC"}
@@ -0,0 +1,197 @@
1
+ /** Prompt text for the `setup_plugin` prompt — plugin installation and configuration workflow. */
2
+ export const setupPluginPromptText = (name) => {
3
+ const isFullPackageName = name.includes('/') || name.startsWith('opentabs-plugin-');
4
+ const packageName = isFullPackageName ? name : `opentabs-plugin-${name}`;
5
+ const pluginName = isFullPackageName ? name.replace(/^@[^/]+\//, '').replace(/^opentabs-plugin-/, '') : name;
6
+ return `Set up the **${pluginName}** OpenTabs plugin. Follow each step below.
7
+
8
+ ---
9
+
10
+ ## Step 1: Search for the Plugin
11
+
12
+ Search npm to find the plugin package:
13
+
14
+ \`\`\`bash
15
+ opentabs plugin search ${pluginName}
16
+ \`\`\`
17
+
18
+ This lists matching packages with their descriptions and versions. Look for the official package (usually \`@opentabs-dev/${packageName}\` or \`${packageName}\`).
19
+
20
+ If the search returns no results, the plugin may not be published to npm. Check if the user has a local plugin directory to add instead.
21
+
22
+ ---
23
+
24
+ ## Step 2: Install the Plugin
25
+
26
+ Install the plugin via the CLI:
27
+
28
+ \`\`\`bash
29
+ opentabs plugin install ${packageName}
30
+ \`\`\`
31
+
32
+ This installs the package globally and triggers plugin rediscovery. The MCP server picks it up automatically (no restart needed).
33
+
34
+ **If the install fails:**
35
+ - Check the package name is correct
36
+ - Check npm registry access: \`npm ping\`
37
+ - For scoped packages, ensure the user is authenticated: \`npm whoami\`
38
+
39
+ For local plugins (under active development), add the path instead:
40
+
41
+ \`\`\`bash
42
+ opentabs config set localPlugins.add /path/to/plugin
43
+ \`\`\`
44
+
45
+ ---
46
+
47
+ ## Step 3: Open the Target Web App
48
+
49
+ The user needs to open the web app that the plugin targets in a Chrome browser tab. The plugin's URL patterns determine which tabs it matches.
50
+
51
+ Ask the user to navigate to the appropriate URL in their browser.
52
+
53
+ ---
54
+
55
+ ## Step 4: Verify Plugin Loaded
56
+
57
+ Check that the plugin was discovered and a matching tab is ready:
58
+
59
+ \`\`\`
60
+ plugin_list_tabs(plugin: "${pluginName}")
61
+ \`\`\`
62
+
63
+ Expected result:
64
+ - The plugin appears in the list
65
+ - \`state\` is \`ready\` (the tab matches and the plugin's \`isReady()\` returned true)
66
+ - At least one tab is shown with \`ready: true\`
67
+
68
+ **If the plugin is not listed:**
69
+ - Check the server logs: \`opentabs logs\`
70
+ - The plugin may have failed to load (missing \`dist/adapter.iife.js\`, invalid \`package.json\`, etc.)
71
+
72
+ **If state is \`unavailable\`:**
73
+ - The user may need to log in to the web app first
74
+ - Wait a few seconds for the page to finish loading, then re-check
75
+
76
+ **If state is \`closed\`:**
77
+ - No open tab matches the plugin's URL patterns
78
+ - Ask the user to open the correct URL
79
+
80
+ ---
81
+
82
+ ## Step 5: Review the Plugin
83
+
84
+ New plugins start with permission \`off\` (disabled) and must be reviewed before use. This is a security measure — the plugin adapter runs code in the user's authenticated browser session.
85
+
86
+ ### 5a. Inspect the plugin's adapter code:
87
+
88
+ \`\`\`
89
+ plugin_inspect(plugin: "${pluginName}")
90
+ \`\`\`
91
+
92
+ This returns the full adapter IIFE source code, metadata (name, version, author, line count), and a review token.
93
+
94
+ ### 5b. Review the code for security concerns:
95
+
96
+ Check for:
97
+ - **Network requests**: Are they only to the expected API domains? No exfiltration to third-party servers?
98
+ - **Data access**: Does it only read data relevant to its tools? No excessive localStorage/cookie reading?
99
+ - **DOM manipulation**: Does it only interact with the target web app's UI? No injecting external scripts?
100
+ - **Permissions**: Does it request only the capabilities it needs?
101
+
102
+ ### 5c. Mark the plugin as reviewed:
103
+
104
+ After reviewing and confirming with the user:
105
+
106
+ \`\`\`
107
+ plugin_mark_reviewed(
108
+ plugin: "${pluginName}",
109
+ version: "<version from inspect>",
110
+ reviewToken: "<token from inspect>",
111
+ permission: "ask"
112
+ )
113
+ \`\`\`
114
+
115
+ Use \`ask\` permission initially — this requires user approval for each tool call. The user can upgrade to \`auto\` later if they trust the plugin.
116
+
117
+ ---
118
+
119
+ ## Step 6: Test the Plugin
120
+
121
+ Call a read-only tool first to verify everything works end-to-end:
122
+
123
+ 1. Check which tools are available — they are prefixed with \`${pluginName}_\` (e.g., \`${pluginName}_list_channels\`, \`${pluginName}_get_profile\`)
124
+ 2. Call a simple read-only tool (list, get, search) to verify:
125
+ - The tool dispatches to the browser tab
126
+ - The adapter extracts auth correctly
127
+ - The API call succeeds
128
+ - The response is well-formatted
129
+
130
+ If the tool call fails, use the \`troubleshoot\` prompt for guided debugging.
131
+
132
+ ---
133
+
134
+ ## Step 7: Configure Permissions
135
+
136
+ Once the plugin is working, help the user set permissions based on their trust level:
137
+
138
+ ### Plugin-level permission (applies to all tools):
139
+
140
+ \`\`\`bash
141
+ # Require approval for every tool call (default after review)
142
+ opentabs config set plugin-permission.${pluginName} ask
143
+
144
+ # Auto-approve all tool calls (skip approval dialogs)
145
+ opentabs config set plugin-permission.${pluginName} auto
146
+
147
+ # Disable the plugin
148
+ opentabs config set plugin-permission.${pluginName} off
149
+ \`\`\`
150
+
151
+ ### Per-tool permissions (override the plugin-level default):
152
+
153
+ \`\`\`bash
154
+ # Auto-approve read-only tools, require approval for write tools
155
+ opentabs config set tool-permission.${pluginName}.list_channels auto
156
+ opentabs config set tool-permission.${pluginName}.send_message ask
157
+ \`\`\`
158
+
159
+ ### Permission resolution order:
160
+ 1. \`skipPermissions\` env var (bypasses everything — development only)
161
+ 2. Per-tool override (\`tool-permission.<plugin>.<tool>\`)
162
+ 3. Plugin default (\`plugin-permission.<plugin>\`)
163
+ 4. Global default: \`off\`
164
+
165
+ ---
166
+
167
+ ## Summary
168
+
169
+ After completing all steps, the plugin is:
170
+ - Installed and discovered by the MCP server
171
+ - Loaded with a matching browser tab in \`ready\` state
172
+ - Reviewed and approved with the appropriate permission level
173
+ - Tested with at least one successful tool call
174
+ - Configured with the user's preferred permission settings
175
+
176
+ The plugin's tools are now available for use in your AI workflow.
177
+
178
+ ---
179
+
180
+ ## Step 8: Write Learnings Back
181
+
182
+ If the setup process surfaced new patterns, gotchas, or common issues, write them back into the source files so future AI agents benefit automatically.
183
+
184
+ **Where to write:**
185
+
186
+ | What you learned | Write to |
187
+ |---|---|
188
+ | Installation or discovery issues | \`platform/mcp-server/src/resources/quick-start.ts\` |
189
+ | Permission or review flow issues | \`platform/mcp-server/src/prompts/setup-plugin.ts\` (this prompt) |
190
+ | New troubleshooting patterns | \`platform/mcp-server/src/resources/troubleshooting.ts\` |
191
+
192
+ **Rules:**
193
+ - Check for duplicates before adding — scan existing content
194
+ - Keep learnings generic, not specific to a single plugin
195
+ - Verify the server builds after editing: \`cd platform/mcp-server && npm run build\``;
196
+ };
197
+ //# sourceMappingURL=setup-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-plugin.js","sourceRoot":"","sources":["../../src/prompts/setup-plugin.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAElG,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAU,EAAE;IAC5D,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC;IACpF,MAAM,WAAW,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,mBAAmB,IAAI,EAAE,CAAC;IACzE,MAAM,UAAU,GAAG,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE7G,OAAO,gBAAgB,UAAU;;;;;;;;;yBASV,UAAU;;;4HAGyF,WAAW,WAAW,WAAW;;;;;;;;;;;0BAWnI,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4BA+BT,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0BA6BZ,UAAU;;;;;;;;;;;;;;;;;;;aAmBvB,UAAU;;;;;;;;;;;;;;;gEAeyC,UAAU,gBAAgB,UAAU,uBAAuB,UAAU;;;;;;;;;;;;;;;;;;;wCAmB7F,UAAU;;;wCAGV,UAAU;;;wCAGV,UAAU;;;;;;;sCAOZ,UAAU;sCACV,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sFAuCsC,CAAC;AACvF,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Prompt text for the `troubleshoot` prompt — guided debugging workflow. */
2
+ export declare const troubleshootPromptText: (error: string) => string;
3
+ //# sourceMappingURL=troubleshoot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"troubleshoot.d.ts","sourceRoot":"","sources":["../../src/prompts/troubleshoot.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,eAAO,MAAM,sBAAsB,GAAI,OAAO,MAAM,KAAG,MA6LtD,CAAC"}
@@ -0,0 +1,191 @@
1
+ /** Prompt text for the `troubleshoot` prompt — guided debugging workflow. */
2
+ export const troubleshootPromptText = (error) => {
3
+ const errorClause = error
4
+ ? `The user is experiencing this issue: "${error}"\n\nDiagnose this specific problem using the workflow below.`
5
+ : 'Run a general health check of the OpenTabs platform using the workflow below.';
6
+ return `${errorClause}
7
+
8
+ ---
9
+
10
+ ## Step 1: Check Extension Connectivity
11
+
12
+ \`\`\`
13
+ extension_get_state
14
+ \`\`\`
15
+
16
+ Verify the response shows the WebSocket is connected. Key fields to check:
17
+ - \`connected\`: must be \`true\`
18
+ - \`tabCount\`: number of tracked tabs
19
+ - \`injectedAdapters\`: plugins with adapters injected into tabs
20
+
21
+ **If the extension is not connected:**
22
+ 1. Verify the Chrome extension is loaded: the user should check \`chrome://extensions/\` and confirm OpenTabs is enabled
23
+ 2. Verify the MCP server is running: \`opentabs status\`
24
+ 3. Check if the extension needs to be reloaded: the user should click the refresh icon on the OpenTabs extension card at \`chrome://extensions/\`
25
+ 4. Check if the side panel is open — opening the OpenTabs side panel triggers the WebSocket connection
26
+ 5. If the extension was recently updated, the user needs to reload it and reopen the side panel
27
+
28
+ ---
29
+
30
+ ## Step 2: Check Plugin State and Tab Readiness
31
+
32
+ \`\`\`
33
+ plugin_list_tabs
34
+ \`\`\`
35
+
36
+ This returns all loaded plugins with their tab states. For each plugin, verify:
37
+ - **state**: \`ready\` means a matching tab is open and the plugin's \`isReady()\` returned true
38
+ - **state**: \`unavailable\` means a matching tab exists but \`isReady()\` returned false (auth issue, page still loading)
39
+ - **state**: \`closed\` means no tab matches the plugin's URL patterns
40
+
41
+ **If the target plugin is not listed:**
42
+ - The plugin may not be installed: \`opentabs plugin list\`
43
+ - The plugin may have failed to load: check \`opentabs logs\` for discovery errors
44
+
45
+ **If state is \`closed\`:**
46
+ - The user needs to open the web app in a browser tab
47
+ - The URL must match the plugin's URL patterns
48
+
49
+ **If state is \`unavailable\`:**
50
+ - The user may not be logged in to the web app
51
+ - The page may still be loading — wait a few seconds and re-check
52
+ - The plugin's \`isReady()\` function may have a bug
53
+
54
+ ---
55
+
56
+ ## Step 3: Check Plugin Permissions
57
+
58
+ If the error mentions "not reviewed" or "permission":
59
+
60
+ **Plugin not reviewed (permission is \`off\`):**
61
+ 1. Call \`plugin_inspect\` with the plugin name to retrieve the adapter source code and a review token
62
+ 2. Review the code for security concerns (network requests, data access, DOM manipulation)
63
+ 3. Ask the user to confirm the review
64
+ 4. Call \`plugin_mark_reviewed\` with the plugin name, version, review token, and desired permission (\`ask\` or \`auto\`)
65
+
66
+ **Permission denied (user rejected approval):**
67
+ - In \`ask\` mode, the user sees an approval dialog for each tool call. If they click "Deny", the tool returns a permission error
68
+ - To avoid repeated prompts, the user can set the permission to \`auto\`:
69
+ \`\`\`bash
70
+ opentabs config set plugin-permission.<plugin> auto
71
+ \`\`\`
72
+ - Or set per-tool permissions:
73
+ \`\`\`bash
74
+ opentabs config set tool-permission.<plugin>.<tool> auto
75
+ \`\`\`
76
+
77
+ ---
78
+
79
+ ## Step 4: Check for Timeout Issues
80
+
81
+ If the error mentions "timeout" or "timed out":
82
+
83
+ - The default dispatch timeout is 30 seconds. Tools that report progress get an extended window (timeout resets on each progress update, up to 5 minutes max)
84
+ - Check if the tool is a long-running operation (e.g., large data export, file upload)
85
+ - Check if the target web app is slow to respond — use \`browser_get_network_requests\` to inspect API latency
86
+ - Check if the extension adapter is responsive:
87
+ \`\`\`
88
+ extension_check_adapter(plugin: "<plugin-name>")
89
+ \`\`\`
90
+
91
+ ---
92
+
93
+ ## Step 5: Check for Rate Limiting
94
+
95
+ If the error mentions "rate limit" or includes \`retryAfterMs\`:
96
+
97
+ - The target web app's API is throttling requests
98
+ - Wait for the \`retryAfterMs\` duration before retrying
99
+ - Reduce the frequency of tool calls to the affected plugin
100
+ - Check if the web app has a rate limit dashboard or API usage page
101
+
102
+ ---
103
+
104
+ ## Step 6: Check for Tool Not Found
105
+
106
+ If the error mentions "tool not found" or "unknown tool":
107
+
108
+ - Verify the tool name uses the correct prefix: \`<plugin>_<tool>\` (e.g., \`slack_send_message\`)
109
+ - Check if the plugin is installed and loaded: \`plugin_list_tabs\`
110
+ - The plugin may have been updated and the tool renamed — check the plugin's tool list
111
+
112
+ ---
113
+
114
+ ## Step 7: Inspect Server and Extension Logs
115
+
116
+ For deeper diagnosis, check the logs:
117
+
118
+ \`\`\`
119
+ extension_get_logs
120
+ \`\`\`
121
+
122
+ This returns recent extension logs including adapter injection events, WebSocket messages, and errors. Look for:
123
+ - Adapter injection failures (CSP violations, script errors)
124
+ - WebSocket disconnection events
125
+ - Tool dispatch errors
126
+
127
+ Also check the MCP server logs:
128
+ \`\`\`bash
129
+ opentabs logs
130
+ \`\`\`
131
+
132
+ ---
133
+
134
+ ## Step 8: Browser-Level Diagnostics
135
+
136
+ If the issue persists, use browser tools for deeper investigation:
137
+
138
+ \`\`\`
139
+ browser_get_console_logs(tabId: <tabId>)
140
+ \`\`\`
141
+
142
+ Check for JavaScript errors in the target web app's console.
143
+
144
+ \`\`\`
145
+ browser_enable_network_capture(tabId: <tabId>, urlFilter: "/api")
146
+ \`\`\`
147
+
148
+ Then reproduce the issue and check captured network requests:
149
+
150
+ \`\`\`
151
+ browser_get_network_requests(tabId: <tabId>)
152
+ \`\`\`
153
+
154
+ Look for failed API calls (4xx/5xx responses), CORS errors, or network timeouts.
155
+
156
+ ---
157
+
158
+ ## Quick Reference: Common Errors
159
+
160
+ | Error | Likely Cause | Resolution |
161
+ |-------|-------------|------------|
162
+ | Extension not connected | Extension not loaded or side panel closed | Reload extension, open side panel |
163
+ | Tab closed | No matching tab open | Open the web app in a browser tab |
164
+ | Tab unavailable | User not logged in or page loading | Log in, wait, re-check |
165
+ | Plugin not reviewed | Permission is \`off\` | Run the review flow (inspect → review → mark reviewed) |
166
+ | Permission denied | User rejected approval dialog | Set permission to \`auto\` via CLI |
167
+ | Dispatch timeout | Tool or API too slow | Check network, increase timeout, check adapter |
168
+ | Rate limited | API throttling | Wait for retryAfterMs, reduce call frequency |
169
+ | Tool not found | Wrong name or plugin not loaded | Verify plugin installed and tool name correct |
170
+ | Concurrent dispatch limit | 5 active dispatches per plugin | Wait for in-flight tools to complete |
171
+
172
+ ---
173
+
174
+ ## Step 9: Write Learnings Back
175
+
176
+ After resolving the issue, write any new troubleshooting patterns, error messages, or resolution steps back into the source files so future AI agents benefit automatically.
177
+
178
+ **Where to write:**
179
+
180
+ | What you learned | Write to |
181
+ |---|---|
182
+ | New error messages or resolution steps | \`platform/mcp-server/src/resources/troubleshooting.ts\` |
183
+ | New diagnostic patterns or gotchas | \`platform/mcp-server/src/prompts/troubleshoot.ts\` (this prompt) |
184
+ | Permission or config issues | \`platform/mcp-server/src/resources/cli.ts\` |
185
+
186
+ **Rules:**
187
+ - Check for duplicates before adding — scan existing error reference
188
+ - Keep patterns generic, not specific to a single user's environment
189
+ - Verify the server builds after editing: \`cd platform/mcp-server && npm run build\``;
190
+ };
191
+ //# sourceMappingURL=troubleshoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"troubleshoot.js","sourceRoot":"","sources":["../../src/prompts/troubleshoot.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAE7E,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,KAAa,EAAU,EAAE;IAC9D,MAAM,WAAW,GAAG,KAAK;QACvB,CAAC,CAAC,yCAAyC,KAAK,+DAA+D;QAC/G,CAAC,CAAC,+EAA+E,CAAC;IAEpF,OAAO,GAAG,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sFAuL+D,CAAC;AACvF,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"reload.d.ts","sourceRoot":"","sources":["../src/reload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AAW9H,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIxD,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,YAAY,CAAC;AAGjE,oFAAoF;AACpF,UAAU,YAAY;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AA2UD;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,aAAa,GACjB,OAAO,WAAW,EAClB,gBAAgB,iBAAiB,EAAE,EACnC,YAAY,GAAG,CAAC,MAAM,EAAE,wCAAwC,CAAC,EACjE,aAAa,OAAO,KACnB,OAAO,CAAC,YAAY,CAkGtB,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,mBAAmB,GACvB,OAAO,WAAW,EAClB,gBAAgB,iBAAiB,EAAE,EACnC,YAAY,GAAG,CAAC,MAAM,EAAE,wCAAwC,CAAC,KAChE,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA+BjD,CAAC;AAEF,YAAY,EAAE,YAAY,EAAE,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"reload.d.ts","sourceRoot":"","sources":["../src/reload.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AAW9H,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAGxD,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,YAAY,CAAC;AAGjE,oFAAoF;AACpF,UAAU,YAAY;IACpB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AA+UD;;;;;;;;;;;;;;GAcG;AACH,QAAA,MAAM,aAAa,GACjB,OAAO,WAAW,EAClB,gBAAgB,iBAAiB,EAAE,EACnC,YAAY,GAAG,CAAC,MAAM,EAAE,wCAAwC,CAAC,EACjE,aAAa,OAAO,KACnB,OAAO,CAAC,YAAY,CAkGtB,CAAC;AAEF;;;;;;;GAOG;AACH,QAAA,MAAM,mBAAmB,GACvB,OAAO,WAAW,EAClB,gBAAgB,iBAAiB,EAAE,EACnC,YAAY,GAAG,CAAC,MAAM,EAAE,wCAAwC,CAAC,KAChE,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA+BjD,CAAC;AAEF,YAAY,EAAE,YAAY,EAAE,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,CAAC"}
package/dist/reload.js CHANGED
@@ -20,9 +20,8 @@ import { startConfigWatching, startFileWatching, stopFileWatching } from './file
20
20
  import { sweepStaleSessions } from './http-routes.js';
21
21
  import { pruneStaleBuffers } from './log-buffer.js';
22
22
  import { log } from './logger.js';
23
- import { notifyToolListChanged, rebuildCachedBrowserTools, registerMcpHandlers } from './mcp-setup.js';
23
+ import { notifyAllListsChanged, rebuildCachedBrowserTools, registerMcpHandlers } from './mcp-setup.js';
24
24
  import { buildRegistry } from './registry.js';
25
- import { isCliSkipPermissions } from './skip-permissions.js';
26
25
  import { checkForUpdates } from './version-check.js';
27
26
  /**
28
27
  * globalThis key for the reload serialization chain.
@@ -121,7 +120,7 @@ const pruneStaleState = (state) => {
121
120
  const createFileWatcherCallbacks = (state, sessionServers, transports) => {
122
121
  const notifyAllClients = () => {
123
122
  for (const srv of sessionServers) {
124
- notifyToolListChanged(srv);
123
+ notifyAllListsChanged(srv);
125
124
  }
126
125
  };
127
126
  return {
@@ -175,6 +174,7 @@ const resetStaleReviewedVersions = (state) => {
175
174
  log.info(`Plugin "${pluginName}" updated from v${config.reviewedVersion} to v${plugin.version} — resetting permission to 'off'`);
176
175
  config.permission = 'off';
177
176
  config.reviewedVersion = undefined;
177
+ delete config.tools;
178
178
  resetCount++;
179
179
  }
180
180
  }
@@ -211,7 +211,10 @@ const reloadCore = async ({ state, sessionServers, transports }) => {
211
211
  const newPluginPermissions = { ...config.permissions };
212
212
  const newPluginPaths = [...config.localPlugins];
213
213
  const newDiscoveryErrors = errors;
214
- const newSkipPermissions = isCliSkipPermissions();
214
+ // Preserve the runtime skipPermissions value — it may have been toggled
215
+ // via "Restore approvals" in the side panel. Only read the env var on
216
+ // initial startup (when state.skipPermissions is still the default).
217
+ const newSkipPermissions = state.skipPermissions;
215
218
  // Build the new cached browser tools on a staging object so a throw here
216
219
  // does not partially update state. rebuildCachedBrowserTools only reads
217
220
  // .browserTools and writes .cachedBrowserTools.
@@ -394,7 +397,7 @@ const performReload = async (state, sessionServers, transports, isHotReload) =>
394
397
  }
395
398
  log.info(`Hot reload: re-registered ${reregistered}/${sessionServers.length} session(s), notifying of list changes`);
396
399
  for (const srv of sessionServers) {
397
- notifyToolListChanged(srv);
400
+ notifyAllListsChanged(srv);
398
401
  }
399
402
  }
400
403
  // Version check: async via `npm view`, best-effort on every reload
@@ -441,7 +444,7 @@ const performConfigReload = async (state, sessionServers, transports) => {
441
444
  // (performReload handles its own notification after handler re-registration,
442
445
  // so reloadCore itself does not notify — each caller is responsible.)
443
446
  for (const srv of sessionServers) {
444
- notifyToolListChanged(srv);
447
+ notifyAllListsChanged(srv);
445
448
  }
446
449
  log.info(`Config reload complete: ${state.registry.plugins.size} plugin(s) in ${Date.now() - startTs}ms`);
447
450
  return { plugins: state.registry.plugins.size, durationMs: Date.now() - startTs };