@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.
- package/dist/browser-tools/click-element.js +3 -3
- package/dist/browser-tools/click-element.js.map +1 -1
- package/dist/browser-tools/press-key.js +5 -5
- package/dist/browser-tools/press-key.js.map +1 -1
- package/dist/dev-proxy.js +19 -7
- package/dist/dev-proxy.js.map +1 -1
- package/dist/extension-handlers.d.ts +11 -2
- package/dist/extension-handlers.d.ts.map +1 -1
- package/dist/extension-handlers.js +73 -7
- package/dist/extension-handlers.js.map +1 -1
- package/dist/extension-protocol.d.ts.map +1 -1
- package/dist/extension-protocol.js +10 -1
- package/dist/extension-protocol.js.map +1 -1
- package/dist/http-routes.d.ts.map +1 -1
- package/dist/http-routes.js +56 -0
- package/dist/http-routes.js.map +1 -1
- package/dist/loader.d.ts +2 -0
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +9 -0
- package/dist/loader.js.map +1 -1
- package/dist/mcp-prompts.d.ts +71 -0
- package/dist/mcp-prompts.d.ts.map +1 -0
- package/dist/mcp-prompts.js +248 -0
- package/dist/mcp-prompts.js.map +1 -0
- package/dist/mcp-resources.d.ts +53 -0
- package/dist/mcp-resources.d.ts.map +1 -0
- package/dist/mcp-resources.js +139 -0
- package/dist/mcp-resources.js.map +1 -0
- package/dist/mcp-setup.d.ts +13 -1
- package/dist/mcp-setup.d.ts.map +1 -1
- package/dist/mcp-setup.js +166 -2
- package/dist/mcp-setup.js.map +1 -1
- package/dist/plugin-management.d.ts +14 -1
- package/dist/plugin-management.d.ts.map +1 -1
- package/dist/plugin-management.js +55 -1
- package/dist/plugin-management.js.map +1 -1
- package/dist/prompts/audit-ai-docs.d.ts +6 -0
- package/dist/prompts/audit-ai-docs.d.ts.map +1 -0
- package/dist/prompts/audit-ai-docs.js +155 -0
- package/dist/prompts/audit-ai-docs.js.map +1 -0
- package/dist/prompts/build-plugin.d.ts +3 -0
- package/dist/prompts/build-plugin.d.ts.map +1 -0
- package/dist/prompts/build-plugin.js +455 -0
- package/dist/prompts/build-plugin.js.map +1 -0
- package/dist/prompts/contribute-learnings.d.ts +12 -0
- package/dist/prompts/contribute-learnings.d.ts.map +1 -0
- package/dist/prompts/contribute-learnings.js +107 -0
- package/dist/prompts/contribute-learnings.js.map +1 -0
- package/dist/prompts/plugin-icon.d.ts +5 -0
- package/dist/prompts/plugin-icon.d.ts.map +1 -0
- package/dist/prompts/plugin-icon.js +147 -0
- package/dist/prompts/plugin-icon.js.map +1 -0
- package/dist/prompts/setup-plugin.d.ts +3 -0
- package/dist/prompts/setup-plugin.d.ts.map +1 -0
- package/dist/prompts/setup-plugin.js +197 -0
- package/dist/prompts/setup-plugin.js.map +1 -0
- package/dist/prompts/troubleshoot.d.ts +3 -0
- package/dist/prompts/troubleshoot.d.ts.map +1 -0
- package/dist/prompts/troubleshoot.js +191 -0
- package/dist/prompts/troubleshoot.js.map +1 -0
- package/dist/reload.d.ts.map +1 -1
- package/dist/reload.js +9 -6
- package/dist/reload.js.map +1 -1
- package/dist/resources/browser-tools.d.ts +3 -0
- package/dist/resources/browser-tools.d.ts.map +1 -0
- package/dist/resources/browser-tools.js +100 -0
- package/dist/resources/browser-tools.js.map +1 -0
- package/dist/resources/cli.d.ts +3 -0
- package/dist/resources/cli.d.ts.map +1 -0
- package/dist/resources/cli.js +217 -0
- package/dist/resources/cli.js.map +1 -0
- package/dist/resources/plugin-development.d.ts +3 -0
- package/dist/resources/plugin-development.d.ts.map +1 -0
- package/dist/resources/plugin-development.js +596 -0
- package/dist/resources/plugin-development.js.map +1 -0
- package/dist/resources/quick-start.d.ts +3 -0
- package/dist/resources/quick-start.d.ts.map +1 -0
- package/dist/resources/quick-start.js +210 -0
- package/dist/resources/quick-start.js.map +1 -0
- package/dist/resources/sdk-api.d.ts +3 -0
- package/dist/resources/sdk-api.d.ts.map +1 -0
- package/dist/resources/sdk-api.js +199 -0
- package/dist/resources/sdk-api.js.map +1 -0
- package/dist/resources/self-improvement.d.ts +10 -0
- package/dist/resources/self-improvement.d.ts.map +1 -0
- package/dist/resources/self-improvement.js +91 -0
- package/dist/resources/self-improvement.js.map +1 -0
- package/dist/resources/status.d.ts +5 -0
- package/dist/resources/status.d.ts.map +1 -0
- package/dist/resources/status.js +27 -0
- package/dist/resources/status.js.map +1 -0
- package/dist/resources/troubleshooting.d.ts +3 -0
- package/dist/resources/troubleshooting.d.ts.map +1 -0
- package/dist/resources/troubleshooting.js +167 -0
- package/dist/resources/troubleshooting.js.map +1 -0
- package/dist/state.d.ts +6 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +9 -3
- package/dist/state.js.map +1 -1
- 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 @@
|
|
|
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 @@
|
|
|
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"}
|
package/dist/reload.d.ts.map
CHANGED
|
@@ -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;
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 };
|