@opentabs-dev/mcp-server 0.0.64 → 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/extension-get-logs.d.ts +1 -1
- package/dist/browser-tools/get-console-logs.d.ts +1 -1
- package/dist/browser-tools/press-key.js +5 -5
- package/dist/browser-tools/press-key.js.map +1 -1
- package/dist/extension-handlers.d.ts +4 -1
- package/dist/extension-handlers.d.ts.map +1 -1
- package/dist/extension-handlers.js +28 -2
- package/dist/extension-handlers.js.map +1 -1
- package/dist/extension-protocol.d.ts.map +1 -1
- package/dist/extension-protocol.js +5 -1
- package/dist/extension-protocol.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 +31 -4
- package/dist/mcp-prompts.d.ts.map +1 -1
- package/dist/mcp-prompts.js +190 -354
- package/dist/mcp-prompts.js.map +1 -1
- 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 +12 -1
- package/dist/mcp-setup.d.ts.map +1 -1
- package/dist/mcp-setup.js +99 -34
- 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.js +4 -4
- 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 +2 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/** Quick Start Guide resource content. */
|
|
2
|
+
export const QUICK_START_CONTENT = `# OpenTabs Quick Start Guide
|
|
3
|
+
|
|
4
|
+
## What is OpenTabs?
|
|
5
|
+
|
|
6
|
+
OpenTabs is a platform that gives AI agents access to web applications through the user's authenticated browser session. It consists of:
|
|
7
|
+
|
|
8
|
+
- **MCP Server** — runs on localhost, serves tools to AI clients via Streamable HTTP
|
|
9
|
+
- **Chrome Extension** — injects plugin adapters into matching browser tabs, relays tool calls
|
|
10
|
+
- **Plugin SDK** — allows anyone to create plugins as standalone npm packages
|
|
11
|
+
|
|
12
|
+
When connected, your AI client gets browser tools (tab management, screenshots, DOM interaction, network capture) and plugin tools (e.g., \`slack_send_message\`, \`github_list_repos\`) that operate in the user's authenticated context.
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
\`\`\`bash
|
|
17
|
+
npm install -g @opentabs-dev/cli
|
|
18
|
+
\`\`\`
|
|
19
|
+
|
|
20
|
+
## Starting the Server
|
|
21
|
+
|
|
22
|
+
\`\`\`bash
|
|
23
|
+
opentabs start
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
On first run, this:
|
|
27
|
+
1. Creates \`~/.opentabs/\` (config, logs, extension files)
|
|
28
|
+
2. Generates a WebSocket auth secret at \`~/.opentabs/extension/auth.json\`
|
|
29
|
+
3. Prints MCP client configuration blocks for Claude Code, Cursor, and Windsurf
|
|
30
|
+
4. Starts the MCP server on \`http://127.0.0.1:9515/mcp\`
|
|
31
|
+
|
|
32
|
+
To re-display the configuration blocks later:
|
|
33
|
+
|
|
34
|
+
\`\`\`bash
|
|
35
|
+
opentabs start --show-config
|
|
36
|
+
\`\`\`
|
|
37
|
+
|
|
38
|
+
## Loading the Chrome Extension
|
|
39
|
+
|
|
40
|
+
1. Open \`chrome://extensions/\` in Chrome
|
|
41
|
+
2. Enable **Developer mode** (top-right toggle)
|
|
42
|
+
3. Click **Load unpacked** and select \`~/.opentabs/extension\`
|
|
43
|
+
|
|
44
|
+
The extension icon appears in the toolbar. Click it to open the side panel showing plugin states and tool permissions.
|
|
45
|
+
|
|
46
|
+
## Configuring Your MCP Client
|
|
47
|
+
|
|
48
|
+
Get the auth secret:
|
|
49
|
+
|
|
50
|
+
\`\`\`bash
|
|
51
|
+
opentabs config show --json --show-secret | jq -r .secret
|
|
52
|
+
\`\`\`
|
|
53
|
+
|
|
54
|
+
### Claude Code
|
|
55
|
+
|
|
56
|
+
CLI method (recommended):
|
|
57
|
+
|
|
58
|
+
\`\`\`bash
|
|
59
|
+
claude mcp add --transport http opentabs http://127.0.0.1:9515/mcp \\
|
|
60
|
+
--header "Authorization: Bearer YOUR_SECRET_HERE"
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
Or merge into \`~/.claude.json\`:
|
|
64
|
+
|
|
65
|
+
\`\`\`json
|
|
66
|
+
{
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"opentabs": {
|
|
69
|
+
"type": "streamable-http",
|
|
70
|
+
"url": "http://127.0.0.1:9515/mcp",
|
|
71
|
+
"headers": {
|
|
72
|
+
"Authorization": "Bearer YOUR_SECRET_HERE"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
\`\`\`
|
|
78
|
+
|
|
79
|
+
### Cursor
|
|
80
|
+
|
|
81
|
+
Add to \`.cursor/mcp.json\`:
|
|
82
|
+
|
|
83
|
+
\`\`\`json
|
|
84
|
+
{
|
|
85
|
+
"mcpServers": {
|
|
86
|
+
"opentabs": {
|
|
87
|
+
"type": "http",
|
|
88
|
+
"url": "http://127.0.0.1:9515/mcp",
|
|
89
|
+
"headers": {
|
|
90
|
+
"Authorization": "Bearer YOUR_SECRET_HERE"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
\`\`\`
|
|
96
|
+
|
|
97
|
+
### Windsurf
|
|
98
|
+
|
|
99
|
+
Add to \`~/.codeium/windsurf/mcp_config.json\`:
|
|
100
|
+
|
|
101
|
+
\`\`\`json
|
|
102
|
+
{
|
|
103
|
+
"mcpServers": {
|
|
104
|
+
"opentabs": {
|
|
105
|
+
"serverUrl": "http://127.0.0.1:9515/mcp",
|
|
106
|
+
"headers": {
|
|
107
|
+
"Authorization": "Bearer YOUR_SECRET_HERE"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
\`\`\`
|
|
113
|
+
|
|
114
|
+
### OpenCode
|
|
115
|
+
|
|
116
|
+
Add to \`opencode.json\` in the project root:
|
|
117
|
+
|
|
118
|
+
\`\`\`json
|
|
119
|
+
{
|
|
120
|
+
"mcp": {
|
|
121
|
+
"opentabs": {
|
|
122
|
+
"type": "remote",
|
|
123
|
+
"url": "http://127.0.0.1:9515/mcp",
|
|
124
|
+
"headers": {
|
|
125
|
+
"Authorization": "Bearer YOUR_SECRET_HERE"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
\`\`\`
|
|
131
|
+
|
|
132
|
+
## Installing a Plugin
|
|
133
|
+
|
|
134
|
+
\`\`\`bash
|
|
135
|
+
opentabs plugin search # Browse available plugins
|
|
136
|
+
opentabs plugin install <name> # Install (e.g., opentabs plugin install slack)
|
|
137
|
+
\`\`\`
|
|
138
|
+
|
|
139
|
+
After installing, open the target web app in Chrome (e.g., \`app.slack.com\` for Slack). The extension detects the matching tab and loads the plugin adapter.
|
|
140
|
+
|
|
141
|
+
## Plugin Review Flow
|
|
142
|
+
|
|
143
|
+
Plugins start with permission \`'off'\` and must be reviewed before use. When you call a tool on an unreviewed plugin, the error response guides you through the review:
|
|
144
|
+
|
|
145
|
+
1. Call \`plugin_inspect\` with the plugin name to retrieve the adapter source code and a review token
|
|
146
|
+
2. Review the code for security (the response includes review guidance)
|
|
147
|
+
3. If the code is safe, call \`plugin_mark_reviewed\` with the review token and desired permission (\`'ask'\` or \`'auto'\`)
|
|
148
|
+
4. The plugin is now active — its tools are available
|
|
149
|
+
|
|
150
|
+
When a plugin updates to a new version, its permission resets to \`'off'\` and requires re-review.
|
|
151
|
+
|
|
152
|
+
## Permission Model
|
|
153
|
+
|
|
154
|
+
Every tool has a 3-state permission:
|
|
155
|
+
|
|
156
|
+
| Permission | Behavior |
|
|
157
|
+
|------------|----------|
|
|
158
|
+
| \`'off'\` | Disabled — tool call returns an error |
|
|
159
|
+
| \`'ask'\` | Requires human approval via the side panel dialog |
|
|
160
|
+
| \`'auto'\` | Executes immediately without user confirmation |
|
|
161
|
+
|
|
162
|
+
Configure permissions via CLI:
|
|
163
|
+
|
|
164
|
+
\`\`\`bash
|
|
165
|
+
opentabs config set plugin-permission.<plugin> ask
|
|
166
|
+
opentabs config set tool-permission.<plugin>.<tool> auto
|
|
167
|
+
\`\`\`
|
|
168
|
+
|
|
169
|
+
To bypass all permission checks (development only):
|
|
170
|
+
|
|
171
|
+
\`\`\`bash
|
|
172
|
+
OPENTABS_DANGEROUSLY_SKIP_PERMISSIONS=1 opentabs start
|
|
173
|
+
\`\`\`
|
|
174
|
+
|
|
175
|
+
## Available Tool Categories
|
|
176
|
+
|
|
177
|
+
### Plugin Tools (\`<plugin>_<tool>\`)
|
|
178
|
+
Execute inside the web page context using the user's authenticated browser session. Each plugin exposes domain-specific tools (e.g., \`slack_send_message\`, \`github_create_issue\`).
|
|
179
|
+
|
|
180
|
+
### Browser Tools (\`browser_*\`) — 40 built-in tools
|
|
181
|
+
General-purpose tools organized by category:
|
|
182
|
+
- **Tab Management** — open, close, list, switch tabs
|
|
183
|
+
- **Content Retrieval** — read page content, HTML, take screenshots
|
|
184
|
+
- **DOM Interaction** — click elements, type text, query selectors
|
|
185
|
+
- **Scroll & Navigation** — scroll, navigate, go back/forward
|
|
186
|
+
- **Storage & Cookies** — read/write localStorage, sessionStorage, cookies
|
|
187
|
+
- **Network Capture** — capture and inspect network requests, WebSocket frames, HAR export
|
|
188
|
+
- **Console** — read browser console logs
|
|
189
|
+
- **Site Analysis** — comprehensive analysis of a web page for plugin development
|
|
190
|
+
|
|
191
|
+
### Extension Tools (\`extension_*\`)
|
|
192
|
+
Diagnostics: extension state, logs, adapter injection status, WebSocket connectivity.
|
|
193
|
+
|
|
194
|
+
## Multi-Tab Targeting
|
|
195
|
+
|
|
196
|
+
When multiple tabs match a plugin, use \`plugin_list_tabs\` to discover available tabs and their IDs. Pass the optional \`tabId\` parameter to any plugin tool to target a specific tab. Without \`tabId\`, the platform auto-selects the best-ranked tab.
|
|
197
|
+
|
|
198
|
+
## Verifying the Setup
|
|
199
|
+
|
|
200
|
+
\`\`\`bash
|
|
201
|
+
opentabs status # Check server, extension, and plugin status
|
|
202
|
+
opentabs doctor # Run diagnostics and suggest fixes
|
|
203
|
+
\`\`\`
|
|
204
|
+
|
|
205
|
+
From your AI client, you can also:
|
|
206
|
+
1. Fetch \`opentabs://status\` to get a JSON snapshot of the server state
|
|
207
|
+
2. Call \`extension_get_state\` to verify the Chrome extension is connected
|
|
208
|
+
3. Call \`plugin_list_tabs\` to see which plugin tabs are ready
|
|
209
|
+
`;
|
|
210
|
+
//# sourceMappingURL=quick-start.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quick-start.js","sourceRoot":"","sources":["../../src/resources/quick-start.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAE1C,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+MlC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** SDK API Reference resource content. */
|
|
2
|
+
export declare const SDK_API_CONTENT = "# SDK API Reference\n\nAll exports from `@opentabs-dev/plugin-sdk`. Utilities run in the browser page context.\n\n## Core Classes\n\n### OpenTabsPlugin\n\nAbstract base class for all plugins. Extend and export a singleton instance.\n\n```typescript\nabstract class OpenTabsPlugin {\n abstract readonly name: string;\n abstract readonly displayName: string;\n abstract readonly description: string;\n abstract readonly urlPatterns: string[];\n abstract readonly tools: ToolDefinition[];\n abstract isReady(): Promise<boolean>;\n\n // Optional lifecycle hooks\n teardown?(): void;\n onActivate?(): void;\n onDeactivate?(): void;\n onNavigate?(url: string): void;\n onToolInvocationStart?(toolName: string): void;\n onToolInvocationEnd?(toolName: string, success: boolean, durationMs: number): void;\n}\n```\n\n### defineTool\n\nType-safe factory for tool definitions:\n\n```typescript\nfunction defineTool<TInput, TOutput>(config: ToolDefinition<TInput, TOutput>): ToolDefinition<TInput, TOutput>\n```\n\n### ToolDefinition\n\n```typescript\ninterface ToolDefinition<TInput, TOutput> {\n name: string;\n displayName?: string;\n description: string;\n summary?: string;\n icon?: LucideIconName; // Lucide icon in kebab-case (default: 'wrench')\n group?: string;\n input: TInput; // Zod object schema\n output: TOutput; // Zod schema\n handle(params: z.infer<TInput>, context?: ToolHandlerContext): Promise<z.infer<TOutput>>;\n}\n```\n\n### ToolHandlerContext\n\n```typescript\ninterface ToolHandlerContext {\n reportProgress(opts: { progress?: number; total?: number; message?: string }): void;\n}\n```\n\n## DOM Utilities\n\n| Function | Signature | Description |\n|----------|-----------|-------------|\n| `waitForSelector` | `<T extends Element>(selector, opts?) => Promise<T>` | Wait for element to appear (MutationObserver, default 10s) |\n| `waitForSelectorRemoval` | `(selector, opts?) => Promise<void>` | Wait for element to be removed (default 10s) |\n| `querySelectorAll` | `<T extends Element>(selector) => T[]` | Returns real array (not NodeList) |\n| `getTextContent` | `(selector) => string \\| null` | Trimmed textContent of first match |\n| `observeDOM` | `(selector, callback, opts?) => () => void` | MutationObserver, returns cleanup function |\n\nOptions: `{ timeout?: number; signal?: AbortSignal }` for wait functions. `{ childList?: boolean; attributes?: boolean; subtree?: boolean }` for observeDOM.\n\n## Fetch Utilities\n\nAll fetch utilities use `credentials: 'include'` to leverage the page's authenticated session. Default timeout: 30s.\n\n| Function | Signature | Description |\n|----------|-----------|-------------|\n| `fetchFromPage` | `(url, init?) => Promise<Response>` | Fetch with session cookies, throws ToolError on non-ok |\n| `fetchJSON` | `<T>(url, init?, schema?) => Promise<T>` | GET + JSON parse. Optional Zod validation |\n| `postJSON` | `<T>(url, body, init?, schema?) => Promise<T>` | POST JSON body + parse response |\n| `putJSON` | `<T>(url, body, init?, schema?) => Promise<T>` | PUT JSON body + parse response |\n| `patchJSON` | `<T>(url, body, init?, schema?) => Promise<T>` | PATCH JSON body + parse response |\n| `deleteJSON` | `<T>(url, init?, schema?) => Promise<T>` | DELETE + parse response |\n| `postForm` | `<T>(url, body, init?, schema?) => Promise<T>` | POST URL-encoded form (Record<string,string>) |\n| `postFormData` | `<T>(url, body, init?, schema?) => Promise<T>` | POST multipart/form-data (FormData) |\n\nWhen a Zod schema is passed as the last argument, the response is validated against it.\n\nHelper functions:\n- `httpStatusToToolError(response, message)` \u2014 maps HTTP status to ToolError category\n- `parseRetryAfterMs(value)` \u2014 parses Retry-After header to milliseconds\n\nOptions extend `RequestInit` with `{ timeout?: number }`.\n\n## Storage Utilities\n\n| Function | Signature | Description |\n|----------|-----------|-------------|\n| `getLocalStorage` | `(key) => string \\| null` | Safe localStorage read (null on SecurityError) |\n| `setLocalStorage` | `(key, value) => void` | Safe localStorage write |\n| `removeLocalStorage` | `(key) => void` | Safe localStorage remove |\n| `getSessionStorage` | `(key) => string \\| null` | Safe sessionStorage read |\n| `setSessionStorage` | `(key, value) => void` | Safe sessionStorage write |\n| `removeSessionStorage` | `(key) => void` | Safe sessionStorage remove |\n| `getCookie` | `(name) => string \\| null` | Parse cookie by name from document.cookie |\n\nAll storage functions catch SecurityError (sandboxed iframes) and return null / no-op silently.\n\n## Page State Utilities\n\n| Function | Signature | Description |\n|----------|-----------|-------------|\n| `getPageGlobal` | `(path) => unknown` | Deep property access on globalThis via dot-notation (e.g., `'app.auth.token'`) |\n| `getCurrentUrl` | `() => string` | Returns window.location.href |\n| `getPageTitle` | `() => string` | Returns document.title |\n\n`getPageGlobal` blocks access to `__proto__`, `constructor`, `prototype`.\n\n## Timing Utilities\n\n| Function | Signature | Description |\n|----------|-----------|-------------|\n| `sleep` | `(ms, opts?) => Promise<void>` | Promisified setTimeout. Options: `{ signal?: AbortSignal }` |\n| `retry` | `<T>(fn, opts?) => Promise<T>` | Retry with configurable attempts, delay, backoff |\n| `waitUntil` | `(predicate, opts?) => Promise<void>` | Poll predicate at interval until true |\n\n**retry options:** `{ maxAttempts?: 3, delay?: 1000, backoff?: false, maxDelay?: 30000, signal?: AbortSignal }`\n\n**waitUntil options:** `{ interval?: 200, timeout?: 10000, signal?: AbortSignal }`\n\n## Logging\n\n```typescript\nimport { log } from '@opentabs-dev/plugin-sdk';\n\nlog.debug(message, ...args);\nlog.info(message, ...args);\nlog.warn(message, ...args);\nlog.error(message, ...args);\n```\n\nLog entries route through the extension to the MCP server and connected clients. Falls back to `console` methods outside the adapter runtime. Args are safely serialized (handles circular refs, DOM nodes, functions).\n\n## Error Handling\n\n### ToolError\n\nStructured error class with metadata for AI clients:\n\n```typescript\nclass ToolError extends Error {\n readonly code: string;\n readonly retryable: boolean;\n readonly retryAfterMs: number | undefined;\n readonly category: ErrorCategory | undefined;\n\n static auth(message, code?): ToolError; // category: 'auth', not retryable\n static notFound(message, code?): ToolError; // category: 'not_found', not retryable\n static rateLimited(message, retryAfterMs?, code?): ToolError; // category: 'rate_limit', retryable\n static validation(message, code?): ToolError; // category: 'validation', not retryable\n static timeout(message, code?): ToolError; // category: 'timeout', retryable\n static internal(message, code?): ToolError; // category: 'internal', not retryable\n}\n```\n\n`ErrorCategory`: `'auth' | 'rate_limit' | 'not_found' | 'validation' | 'internal' | 'timeout'`\n\n## Lifecycle Hooks\n\nOptional methods on `OpenTabsPlugin`:\n\n| Hook | When Called |\n|------|------------|\n| `onActivate()` | After adapter registered on `globalThis.__openTabs.adapters` |\n| `onDeactivate()` | Before adapter removal |\n| `teardown()` | Before re-injection on plugin update |\n| `onNavigate(url)` | On in-page URL changes (pushState, replaceState, popstate, hashchange) |\n| `onToolInvocationStart(toolName)` | Before each tool handler call |\n| `onToolInvocationEnd(toolName, success, durationMs)` | After each tool handler call |\n\nErrors in hooks are caught and logged \u2014 they do not affect tool execution.\n\n## Re-exports from @opentabs-dev/shared\n\n| Export | Description |\n|--------|-------------|\n| `ManifestTool` | Tool metadata type for plugin manifests |\n| `Manifest` | Complete plugin manifest type (`PluginManifest`) |\n| `validatePluginName(name)` | Validates plugin name against `NAME_REGEX` and `RESERVED_NAMES` |\n| `validateUrlPattern(pattern)` | Validates Chrome match patterns |\n| `NAME_REGEX` | Regex for valid plugin names |\n| `RESERVED_NAMES` | Set of reserved plugin names |\n| `LucideIconName` | String literal union of valid Lucide icon names |\n| `LUCIDE_ICON_NAMES` | Array of all valid Lucide icon names |\n";
|
|
3
|
+
//# sourceMappingURL=sdk-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-api.d.ts","sourceRoot":"","sources":["../../src/resources/sdk-api.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAE1C,eAAO,MAAM,eAAe,ypQAoM3B,CAAC"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/** SDK API Reference resource content. */
|
|
2
|
+
export const SDK_API_CONTENT = `# SDK API Reference
|
|
3
|
+
|
|
4
|
+
All exports from \`@opentabs-dev/plugin-sdk\`. Utilities run in the browser page context.
|
|
5
|
+
|
|
6
|
+
## Core Classes
|
|
7
|
+
|
|
8
|
+
### OpenTabsPlugin
|
|
9
|
+
|
|
10
|
+
Abstract base class for all plugins. Extend and export a singleton instance.
|
|
11
|
+
|
|
12
|
+
\`\`\`typescript
|
|
13
|
+
abstract class OpenTabsPlugin {
|
|
14
|
+
abstract readonly name: string;
|
|
15
|
+
abstract readonly displayName: string;
|
|
16
|
+
abstract readonly description: string;
|
|
17
|
+
abstract readonly urlPatterns: string[];
|
|
18
|
+
abstract readonly tools: ToolDefinition[];
|
|
19
|
+
abstract isReady(): Promise<boolean>;
|
|
20
|
+
|
|
21
|
+
// Optional lifecycle hooks
|
|
22
|
+
teardown?(): void;
|
|
23
|
+
onActivate?(): void;
|
|
24
|
+
onDeactivate?(): void;
|
|
25
|
+
onNavigate?(url: string): void;
|
|
26
|
+
onToolInvocationStart?(toolName: string): void;
|
|
27
|
+
onToolInvocationEnd?(toolName: string, success: boolean, durationMs: number): void;
|
|
28
|
+
}
|
|
29
|
+
\`\`\`
|
|
30
|
+
|
|
31
|
+
### defineTool
|
|
32
|
+
|
|
33
|
+
Type-safe factory for tool definitions:
|
|
34
|
+
|
|
35
|
+
\`\`\`typescript
|
|
36
|
+
function defineTool<TInput, TOutput>(config: ToolDefinition<TInput, TOutput>): ToolDefinition<TInput, TOutput>
|
|
37
|
+
\`\`\`
|
|
38
|
+
|
|
39
|
+
### ToolDefinition
|
|
40
|
+
|
|
41
|
+
\`\`\`typescript
|
|
42
|
+
interface ToolDefinition<TInput, TOutput> {
|
|
43
|
+
name: string;
|
|
44
|
+
displayName?: string;
|
|
45
|
+
description: string;
|
|
46
|
+
summary?: string;
|
|
47
|
+
icon?: LucideIconName; // Lucide icon in kebab-case (default: 'wrench')
|
|
48
|
+
group?: string;
|
|
49
|
+
input: TInput; // Zod object schema
|
|
50
|
+
output: TOutput; // Zod schema
|
|
51
|
+
handle(params: z.infer<TInput>, context?: ToolHandlerContext): Promise<z.infer<TOutput>>;
|
|
52
|
+
}
|
|
53
|
+
\`\`\`
|
|
54
|
+
|
|
55
|
+
### ToolHandlerContext
|
|
56
|
+
|
|
57
|
+
\`\`\`typescript
|
|
58
|
+
interface ToolHandlerContext {
|
|
59
|
+
reportProgress(opts: { progress?: number; total?: number; message?: string }): void;
|
|
60
|
+
}
|
|
61
|
+
\`\`\`
|
|
62
|
+
|
|
63
|
+
## DOM Utilities
|
|
64
|
+
|
|
65
|
+
| Function | Signature | Description |
|
|
66
|
+
|----------|-----------|-------------|
|
|
67
|
+
| \`waitForSelector\` | \`<T extends Element>(selector, opts?) => Promise<T>\` | Wait for element to appear (MutationObserver, default 10s) |
|
|
68
|
+
| \`waitForSelectorRemoval\` | \`(selector, opts?) => Promise<void>\` | Wait for element to be removed (default 10s) |
|
|
69
|
+
| \`querySelectorAll\` | \`<T extends Element>(selector) => T[]\` | Returns real array (not NodeList) |
|
|
70
|
+
| \`getTextContent\` | \`(selector) => string \\| null\` | Trimmed textContent of first match |
|
|
71
|
+
| \`observeDOM\` | \`(selector, callback, opts?) => () => void\` | MutationObserver, returns cleanup function |
|
|
72
|
+
|
|
73
|
+
Options: \`{ timeout?: number; signal?: AbortSignal }\` for wait functions. \`{ childList?: boolean; attributes?: boolean; subtree?: boolean }\` for observeDOM.
|
|
74
|
+
|
|
75
|
+
## Fetch Utilities
|
|
76
|
+
|
|
77
|
+
All fetch utilities use \`credentials: 'include'\` to leverage the page's authenticated session. Default timeout: 30s.
|
|
78
|
+
|
|
79
|
+
| Function | Signature | Description |
|
|
80
|
+
|----------|-----------|-------------|
|
|
81
|
+
| \`fetchFromPage\` | \`(url, init?) => Promise<Response>\` | Fetch with session cookies, throws ToolError on non-ok |
|
|
82
|
+
| \`fetchJSON\` | \`<T>(url, init?, schema?) => Promise<T>\` | GET + JSON parse. Optional Zod validation |
|
|
83
|
+
| \`postJSON\` | \`<T>(url, body, init?, schema?) => Promise<T>\` | POST JSON body + parse response |
|
|
84
|
+
| \`putJSON\` | \`<T>(url, body, init?, schema?) => Promise<T>\` | PUT JSON body + parse response |
|
|
85
|
+
| \`patchJSON\` | \`<T>(url, body, init?, schema?) => Promise<T>\` | PATCH JSON body + parse response |
|
|
86
|
+
| \`deleteJSON\` | \`<T>(url, init?, schema?) => Promise<T>\` | DELETE + parse response |
|
|
87
|
+
| \`postForm\` | \`<T>(url, body, init?, schema?) => Promise<T>\` | POST URL-encoded form (Record<string,string>) |
|
|
88
|
+
| \`postFormData\` | \`<T>(url, body, init?, schema?) => Promise<T>\` | POST multipart/form-data (FormData) |
|
|
89
|
+
|
|
90
|
+
When a Zod schema is passed as the last argument, the response is validated against it.
|
|
91
|
+
|
|
92
|
+
Helper functions:
|
|
93
|
+
- \`httpStatusToToolError(response, message)\` — maps HTTP status to ToolError category
|
|
94
|
+
- \`parseRetryAfterMs(value)\` — parses Retry-After header to milliseconds
|
|
95
|
+
|
|
96
|
+
Options extend \`RequestInit\` with \`{ timeout?: number }\`.
|
|
97
|
+
|
|
98
|
+
## Storage Utilities
|
|
99
|
+
|
|
100
|
+
| Function | Signature | Description |
|
|
101
|
+
|----------|-----------|-------------|
|
|
102
|
+
| \`getLocalStorage\` | \`(key) => string \\| null\` | Safe localStorage read (null on SecurityError) |
|
|
103
|
+
| \`setLocalStorage\` | \`(key, value) => void\` | Safe localStorage write |
|
|
104
|
+
| \`removeLocalStorage\` | \`(key) => void\` | Safe localStorage remove |
|
|
105
|
+
| \`getSessionStorage\` | \`(key) => string \\| null\` | Safe sessionStorage read |
|
|
106
|
+
| \`setSessionStorage\` | \`(key, value) => void\` | Safe sessionStorage write |
|
|
107
|
+
| \`removeSessionStorage\` | \`(key) => void\` | Safe sessionStorage remove |
|
|
108
|
+
| \`getCookie\` | \`(name) => string \\| null\` | Parse cookie by name from document.cookie |
|
|
109
|
+
|
|
110
|
+
All storage functions catch SecurityError (sandboxed iframes) and return null / no-op silently.
|
|
111
|
+
|
|
112
|
+
## Page State Utilities
|
|
113
|
+
|
|
114
|
+
| Function | Signature | Description |
|
|
115
|
+
|----------|-----------|-------------|
|
|
116
|
+
| \`getPageGlobal\` | \`(path) => unknown\` | Deep property access on globalThis via dot-notation (e.g., \`'app.auth.token'\`) |
|
|
117
|
+
| \`getCurrentUrl\` | \`() => string\` | Returns window.location.href |
|
|
118
|
+
| \`getPageTitle\` | \`() => string\` | Returns document.title |
|
|
119
|
+
|
|
120
|
+
\`getPageGlobal\` blocks access to \`__proto__\`, \`constructor\`, \`prototype\`.
|
|
121
|
+
|
|
122
|
+
## Timing Utilities
|
|
123
|
+
|
|
124
|
+
| Function | Signature | Description |
|
|
125
|
+
|----------|-----------|-------------|
|
|
126
|
+
| \`sleep\` | \`(ms, opts?) => Promise<void>\` | Promisified setTimeout. Options: \`{ signal?: AbortSignal }\` |
|
|
127
|
+
| \`retry\` | \`<T>(fn, opts?) => Promise<T>\` | Retry with configurable attempts, delay, backoff |
|
|
128
|
+
| \`waitUntil\` | \`(predicate, opts?) => Promise<void>\` | Poll predicate at interval until true |
|
|
129
|
+
|
|
130
|
+
**retry options:** \`{ maxAttempts?: 3, delay?: 1000, backoff?: false, maxDelay?: 30000, signal?: AbortSignal }\`
|
|
131
|
+
|
|
132
|
+
**waitUntil options:** \`{ interval?: 200, timeout?: 10000, signal?: AbortSignal }\`
|
|
133
|
+
|
|
134
|
+
## Logging
|
|
135
|
+
|
|
136
|
+
\`\`\`typescript
|
|
137
|
+
import { log } from '@opentabs-dev/plugin-sdk';
|
|
138
|
+
|
|
139
|
+
log.debug(message, ...args);
|
|
140
|
+
log.info(message, ...args);
|
|
141
|
+
log.warn(message, ...args);
|
|
142
|
+
log.error(message, ...args);
|
|
143
|
+
\`\`\`
|
|
144
|
+
|
|
145
|
+
Log entries route through the extension to the MCP server and connected clients. Falls back to \`console\` methods outside the adapter runtime. Args are safely serialized (handles circular refs, DOM nodes, functions).
|
|
146
|
+
|
|
147
|
+
## Error Handling
|
|
148
|
+
|
|
149
|
+
### ToolError
|
|
150
|
+
|
|
151
|
+
Structured error class with metadata for AI clients:
|
|
152
|
+
|
|
153
|
+
\`\`\`typescript
|
|
154
|
+
class ToolError extends Error {
|
|
155
|
+
readonly code: string;
|
|
156
|
+
readonly retryable: boolean;
|
|
157
|
+
readonly retryAfterMs: number | undefined;
|
|
158
|
+
readonly category: ErrorCategory | undefined;
|
|
159
|
+
|
|
160
|
+
static auth(message, code?): ToolError; // category: 'auth', not retryable
|
|
161
|
+
static notFound(message, code?): ToolError; // category: 'not_found', not retryable
|
|
162
|
+
static rateLimited(message, retryAfterMs?, code?): ToolError; // category: 'rate_limit', retryable
|
|
163
|
+
static validation(message, code?): ToolError; // category: 'validation', not retryable
|
|
164
|
+
static timeout(message, code?): ToolError; // category: 'timeout', retryable
|
|
165
|
+
static internal(message, code?): ToolError; // category: 'internal', not retryable
|
|
166
|
+
}
|
|
167
|
+
\`\`\`
|
|
168
|
+
|
|
169
|
+
\`ErrorCategory\`: \`'auth' | 'rate_limit' | 'not_found' | 'validation' | 'internal' | 'timeout'\`
|
|
170
|
+
|
|
171
|
+
## Lifecycle Hooks
|
|
172
|
+
|
|
173
|
+
Optional methods on \`OpenTabsPlugin\`:
|
|
174
|
+
|
|
175
|
+
| Hook | When Called |
|
|
176
|
+
|------|------------|
|
|
177
|
+
| \`onActivate()\` | After adapter registered on \`globalThis.__openTabs.adapters\` |
|
|
178
|
+
| \`onDeactivate()\` | Before adapter removal |
|
|
179
|
+
| \`teardown()\` | Before re-injection on plugin update |
|
|
180
|
+
| \`onNavigate(url)\` | On in-page URL changes (pushState, replaceState, popstate, hashchange) |
|
|
181
|
+
| \`onToolInvocationStart(toolName)\` | Before each tool handler call |
|
|
182
|
+
| \`onToolInvocationEnd(toolName, success, durationMs)\` | After each tool handler call |
|
|
183
|
+
|
|
184
|
+
Errors in hooks are caught and logged — they do not affect tool execution.
|
|
185
|
+
|
|
186
|
+
## Re-exports from @opentabs-dev/shared
|
|
187
|
+
|
|
188
|
+
| Export | Description |
|
|
189
|
+
|--------|-------------|
|
|
190
|
+
| \`ManifestTool\` | Tool metadata type for plugin manifests |
|
|
191
|
+
| \`Manifest\` | Complete plugin manifest type (\`PluginManifest\`) |
|
|
192
|
+
| \`validatePluginName(name)\` | Validates plugin name against \`NAME_REGEX\` and \`RESERVED_NAMES\` |
|
|
193
|
+
| \`validateUrlPattern(pattern)\` | Validates Chrome match patterns |
|
|
194
|
+
| \`NAME_REGEX\` | Regex for valid plugin names |
|
|
195
|
+
| \`RESERVED_NAMES\` | Set of reserved plugin names |
|
|
196
|
+
| \`LucideIconName\` | String literal union of valid Lucide icon names |
|
|
197
|
+
| \`LUCIDE_ICON_NAMES\` | Array of all valid Lucide icon names |
|
|
198
|
+
`;
|
|
199
|
+
//# sourceMappingURL=sdk-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdk-api.js","sourceRoot":"","sources":["../../src/resources/sdk-api.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAE1C,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoM9B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-improvement guide resource — explains how the MCP server's AI-facing
|
|
3
|
+
* content forms a self-improving loop and how agents contribute back.
|
|
4
|
+
*
|
|
5
|
+
* This resource is served at `opentabs://guide/self-improvement` and is
|
|
6
|
+
* designed so any connected AI agent can discover the contribution architecture
|
|
7
|
+
* without needing a human to explain it.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SELF_IMPROVEMENT_CONTENT = "# Self-Improvement Architecture\n\n## How It Works\n\nThe OpenTabs MCP server serves AI-facing content through three mechanisms:\n\n| Mechanism | MCP method | When delivered | Source files |\n|---|---|---|---|\n| **Instructions** | `initialize` response | Pushed to every session automatically | `platform/mcp-server/src/mcp-setup.ts` (`SERVER_INSTRUCTIONS` constant) |\n| **Resources** | `resources/read` | Pulled on demand by the client | `platform/mcp-server/src/resources/*.ts` |\n| **Prompts** | `prompts/get` | User-triggered (slash commands, explicit invocation) | `platform/mcp-server/src/prompts/*.ts` |\n\nThese source files are **TypeScript string constants** that compile into the content this server serves. When an AI agent edits them and the server rebuilds, every future AI session receives those edits automatically. This creates a self-improving loop \u2014 each session that builds a plugin, fixes an issue, or discovers a gotcha makes every subsequent session better.\n\n## Why You Should Care\n\nEvery piece of guidance you received in this session \u2014 the `build_plugin` workflow, the gotcha list, the auth extraction patterns \u2014 was written by a previous AI session that completed a similar task. If that session had not contributed back, you would be starting from scratch. Your contributions have the same impact: the next AI session that builds a plugin will benefit from patterns you discovered today. Failing to contribute means the next session will encounter the same issues you just solved, without your solution.\n\n## The Contribution Cycle\n\n1. **AI receives context** \u2014 on connect, the server pushes instructions. During a task, the AI fetches resources and invokes prompts for detailed guidance.\n2. **AI completes a task** \u2014 building a plugin, troubleshooting an issue, configuring the platform.\n3. **AI invokes contribute_learnings** \u2014 either explicitly or via the mandatory Phase 7 of the `build_plugin` workflow.\n4. **AI writes learnings back** \u2014 edits the TypeScript source files that compile into resources and prompts.\n5. **Server rebuilds** \u2014 the edited files produce updated content.\n6. **Next AI session benefits** \u2014 receives the improved instructions, resources, and prompts.\n\n## File-to-Content Mapping\n\n| What you learned | Write to | Served as |\n|---|---|---|\n| Plugin dev patterns, gotchas, conventions | `platform/mcp-server/src/resources/plugin-development.ts` | `opentabs://guide/plugin-development` resource |\n| Plugin dev workflow steps, code templates | `platform/mcp-server/src/prompts/build-plugin.ts` | `build_plugin` prompt |\n| Icon handling patterns | `platform/mcp-server/src/prompts/plugin-icon.ts` | `plugin_icon` prompt |\n| Troubleshooting patterns, error resolution | `platform/mcp-server/src/resources/troubleshooting.ts` | `opentabs://guide/troubleshooting` resource |\n| Troubleshooting workflow improvements | `platform/mcp-server/src/prompts/troubleshoot.ts` | `troubleshoot` prompt |\n| Plugin setup patterns | `platform/mcp-server/src/prompts/setup-plugin.ts` | `setup_plugin` prompt |\n| CLI or config changes | `platform/mcp-server/src/resources/cli.ts` | `opentabs://reference/cli` resource |\n| SDK utility additions | `platform/mcp-server/src/resources/sdk-api.ts` | `opentabs://reference/sdk-api` resource |\n| Browser tool documentation | `platform/mcp-server/src/resources/browser-tools.ts` | `opentabs://reference/browser-tools` resource |\n| Quick start improvements | `platform/mcp-server/src/resources/quick-start.ts` | `opentabs://guide/quick-start` resource |\n| Self-improvement loop changes | `platform/mcp-server/src/resources/self-improvement.ts` | `opentabs://guide/self-improvement` resource (this file) |\n| Contribution workflow itself | `platform/mcp-server/src/prompts/contribute-learnings.ts` | `contribute_learnings` prompt |\n| New workflow triggers or instruction gaps | `platform/mcp-server/src/mcp-setup.ts` (`SERVER_INSTRUCTIONS`) | MCP initialize instructions |\n| Audit workflow improvements | `platform/mcp-server/src/prompts/audit-ai-docs.ts` | `audit_ai_docs` prompt |\n\n## Rules for Contributing\n\n1. **Check for duplicates** \u2014 read the target file first and scan existing content before adding.\n2. **Keep learnings generic** \u2014 no app-specific details (e.g., no \"Notion uses space IDs\"). Write patterns that apply to any web app.\n3. **Be concise and factual** \u2014 write for AI consumption, not human narratives.\n4. **Add to the right section** \u2014 place gotchas in gotcha lists, patterns in pattern sections.\n5. **Preserve existing structure** \u2014 match the formatting and style of surrounding content.\n6. **Verify the build** \u2014 run `cd platform/mcp-server && npm run build` after editing. The build must succeed.\n7. **Write ONLY to source files** \u2014 do not write to local markdown files, CLAUDE.md files, or the docs site. Only the source files listed above compile into MCP-served content.\n\n## How to Trigger the Contribution Workflow\n\nThere are three ways the contribution workflow is triggered:\n\n1. **build_plugin Phase 7** \u2014 the `build_plugin` prompt's final phase (Phase 7: Write Learnings Back) explicitly directs you to invoke `contribute_learnings` after completing a plugin build. This is mandatory and built into the workflow.\n2. **SERVER_INSTRUCTIONS mandate** \u2014 the server instructions sent to every session state that contribution is MANDATORY after completing ANY task, not just plugin builds.\n3. **Proactive invocation** \u2014 you can invoke `contribute_learnings` at any time during a session if you discover something worth sharing.\n\nTo invoke explicitly:\n\n```\ncontribute_learnings(task: \"brief description of what you just did\")\n```\n\nThis prompt provides the full step-by-step workflow for identifying learnings, choosing the right file, writing the content, and verifying the build.\n\n## Verifying Your Contribution Works\n\nAfter editing a source file and running `cd platform/mcp-server && npm run build`, the compiled content updates immediately. Any new MCP session that connects will receive your updated resources and prompts. You can verify by calling `resources/read` with the resource URI \u2014 it will return your updated content.\n\n## Why This Matters for Bootstrapping\n\nWhen you are asked to build a plugin for a web service, the `build_plugin` prompt provides a complete workflow including site analysis, API discovery, scaffolding, implementation, and testing. That workflow was written and refined by previous AI sessions \u2014 each one contributing patterns they discovered. After you finish building, you contribute back, and the next session receives your improvements.\n\nThis means the platform becomes progressively better at plugin development with each use, without requiring human intervention to update documentation or workflows.\n";
|
|
10
|
+
//# sourceMappingURL=self-improvement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-improvement.d.ts","sourceRoot":"","sources":["../../src/resources/self-improvement.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,wBAAwB,qwNAiFpC,CAAC"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-improvement guide resource — explains how the MCP server's AI-facing
|
|
3
|
+
* content forms a self-improving loop and how agents contribute back.
|
|
4
|
+
*
|
|
5
|
+
* This resource is served at `opentabs://guide/self-improvement` and is
|
|
6
|
+
* designed so any connected AI agent can discover the contribution architecture
|
|
7
|
+
* without needing a human to explain it.
|
|
8
|
+
*/
|
|
9
|
+
export const SELF_IMPROVEMENT_CONTENT = `# Self-Improvement Architecture
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
The OpenTabs MCP server serves AI-facing content through three mechanisms:
|
|
14
|
+
|
|
15
|
+
| Mechanism | MCP method | When delivered | Source files |
|
|
16
|
+
|---|---|---|---|
|
|
17
|
+
| **Instructions** | \`initialize\` response | Pushed to every session automatically | \`platform/mcp-server/src/mcp-setup.ts\` (\`SERVER_INSTRUCTIONS\` constant) |
|
|
18
|
+
| **Resources** | \`resources/read\` | Pulled on demand by the client | \`platform/mcp-server/src/resources/*.ts\` |
|
|
19
|
+
| **Prompts** | \`prompts/get\` | User-triggered (slash commands, explicit invocation) | \`platform/mcp-server/src/prompts/*.ts\` |
|
|
20
|
+
|
|
21
|
+
These source files are **TypeScript string constants** that compile into the content this server serves. When an AI agent edits them and the server rebuilds, every future AI session receives those edits automatically. This creates a self-improving loop — each session that builds a plugin, fixes an issue, or discovers a gotcha makes every subsequent session better.
|
|
22
|
+
|
|
23
|
+
## Why You Should Care
|
|
24
|
+
|
|
25
|
+
Every piece of guidance you received in this session — the \`build_plugin\` workflow, the gotcha list, the auth extraction patterns — was written by a previous AI session that completed a similar task. If that session had not contributed back, you would be starting from scratch. Your contributions have the same impact: the next AI session that builds a plugin will benefit from patterns you discovered today. Failing to contribute means the next session will encounter the same issues you just solved, without your solution.
|
|
26
|
+
|
|
27
|
+
## The Contribution Cycle
|
|
28
|
+
|
|
29
|
+
1. **AI receives context** — on connect, the server pushes instructions. During a task, the AI fetches resources and invokes prompts for detailed guidance.
|
|
30
|
+
2. **AI completes a task** — building a plugin, troubleshooting an issue, configuring the platform.
|
|
31
|
+
3. **AI invokes contribute_learnings** — either explicitly or via the mandatory Phase 7 of the \`build_plugin\` workflow.
|
|
32
|
+
4. **AI writes learnings back** — edits the TypeScript source files that compile into resources and prompts.
|
|
33
|
+
5. **Server rebuilds** — the edited files produce updated content.
|
|
34
|
+
6. **Next AI session benefits** — receives the improved instructions, resources, and prompts.
|
|
35
|
+
|
|
36
|
+
## File-to-Content Mapping
|
|
37
|
+
|
|
38
|
+
| What you learned | Write to | Served as |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| Plugin dev patterns, gotchas, conventions | \`platform/mcp-server/src/resources/plugin-development.ts\` | \`opentabs://guide/plugin-development\` resource |
|
|
41
|
+
| Plugin dev workflow steps, code templates | \`platform/mcp-server/src/prompts/build-plugin.ts\` | \`build_plugin\` prompt |
|
|
42
|
+
| Icon handling patterns | \`platform/mcp-server/src/prompts/plugin-icon.ts\` | \`plugin_icon\` prompt |
|
|
43
|
+
| Troubleshooting patterns, error resolution | \`platform/mcp-server/src/resources/troubleshooting.ts\` | \`opentabs://guide/troubleshooting\` resource |
|
|
44
|
+
| Troubleshooting workflow improvements | \`platform/mcp-server/src/prompts/troubleshoot.ts\` | \`troubleshoot\` prompt |
|
|
45
|
+
| Plugin setup patterns | \`platform/mcp-server/src/prompts/setup-plugin.ts\` | \`setup_plugin\` prompt |
|
|
46
|
+
| CLI or config changes | \`platform/mcp-server/src/resources/cli.ts\` | \`opentabs://reference/cli\` resource |
|
|
47
|
+
| SDK utility additions | \`platform/mcp-server/src/resources/sdk-api.ts\` | \`opentabs://reference/sdk-api\` resource |
|
|
48
|
+
| Browser tool documentation | \`platform/mcp-server/src/resources/browser-tools.ts\` | \`opentabs://reference/browser-tools\` resource |
|
|
49
|
+
| Quick start improvements | \`platform/mcp-server/src/resources/quick-start.ts\` | \`opentabs://guide/quick-start\` resource |
|
|
50
|
+
| Self-improvement loop changes | \`platform/mcp-server/src/resources/self-improvement.ts\` | \`opentabs://guide/self-improvement\` resource (this file) |
|
|
51
|
+
| Contribution workflow itself | \`platform/mcp-server/src/prompts/contribute-learnings.ts\` | \`contribute_learnings\` prompt |
|
|
52
|
+
| New workflow triggers or instruction gaps | \`platform/mcp-server/src/mcp-setup.ts\` (\`SERVER_INSTRUCTIONS\`) | MCP initialize instructions |
|
|
53
|
+
| Audit workflow improvements | \`platform/mcp-server/src/prompts/audit-ai-docs.ts\` | \`audit_ai_docs\` prompt |
|
|
54
|
+
|
|
55
|
+
## Rules for Contributing
|
|
56
|
+
|
|
57
|
+
1. **Check for duplicates** — read the target file first and scan existing content before adding.
|
|
58
|
+
2. **Keep learnings generic** — no app-specific details (e.g., no "Notion uses space IDs"). Write patterns that apply to any web app.
|
|
59
|
+
3. **Be concise and factual** — write for AI consumption, not human narratives.
|
|
60
|
+
4. **Add to the right section** — place gotchas in gotcha lists, patterns in pattern sections.
|
|
61
|
+
5. **Preserve existing structure** — match the formatting and style of surrounding content.
|
|
62
|
+
6. **Verify the build** — run \`cd platform/mcp-server && npm run build\` after editing. The build must succeed.
|
|
63
|
+
7. **Write ONLY to source files** — do not write to local markdown files, CLAUDE.md files, or the docs site. Only the source files listed above compile into MCP-served content.
|
|
64
|
+
|
|
65
|
+
## How to Trigger the Contribution Workflow
|
|
66
|
+
|
|
67
|
+
There are three ways the contribution workflow is triggered:
|
|
68
|
+
|
|
69
|
+
1. **build_plugin Phase 7** — the \`build_plugin\` prompt's final phase (Phase 7: Write Learnings Back) explicitly directs you to invoke \`contribute_learnings\` after completing a plugin build. This is mandatory and built into the workflow.
|
|
70
|
+
2. **SERVER_INSTRUCTIONS mandate** — the server instructions sent to every session state that contribution is MANDATORY after completing ANY task, not just plugin builds.
|
|
71
|
+
3. **Proactive invocation** — you can invoke \`contribute_learnings\` at any time during a session if you discover something worth sharing.
|
|
72
|
+
|
|
73
|
+
To invoke explicitly:
|
|
74
|
+
|
|
75
|
+
\`\`\`
|
|
76
|
+
contribute_learnings(task: "brief description of what you just did")
|
|
77
|
+
\`\`\`
|
|
78
|
+
|
|
79
|
+
This prompt provides the full step-by-step workflow for identifying learnings, choosing the right file, writing the content, and verifying the build.
|
|
80
|
+
|
|
81
|
+
## Verifying Your Contribution Works
|
|
82
|
+
|
|
83
|
+
After editing a source file and running \`cd platform/mcp-server && npm run build\`, the compiled content updates immediately. Any new MCP session that connects will receive your updated resources and prompts. You can verify by calling \`resources/read\` with the resource URI — it will return your updated content.
|
|
84
|
+
|
|
85
|
+
## Why This Matters for Bootstrapping
|
|
86
|
+
|
|
87
|
+
When you are asked to build a plugin for a web service, the \`build_plugin\` prompt provides a complete workflow including site analysis, API discovery, scaffolding, implementation, and testing. That workflow was written and refined by previous AI sessions — each one contributing patterns they discovered. After you finish building, you contribute back, and the next session receives your improvements.
|
|
88
|
+
|
|
89
|
+
This means the platform becomes progressively better at plugin development with each use, without requiring human intervention to update documentation or workflows.
|
|
90
|
+
`;
|
|
91
|
+
//# sourceMappingURL=self-improvement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"self-improvement.js","sourceRoot":"","sources":["../../src/resources/self-improvement.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,wBAAwB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiFvC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/resources/status.ts"],"names":[],"mappings":"AAAA,uCAAuC;AAEvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,+DAA+D;AAC/D,eAAO,MAAM,mBAAmB,GAAI,OAAO,WAAW,KAAG,MA4BxD,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Dynamic status resource builder. */
|
|
2
|
+
/** Build the dynamic status resource JSON from server state */
|
|
3
|
+
export const buildStatusResource = (state) => {
|
|
4
|
+
const plugins = [...state.registry.plugins.values()].map(p => ({
|
|
5
|
+
name: p.name,
|
|
6
|
+
displayName: p.displayName,
|
|
7
|
+
toolCount: p.tools.length,
|
|
8
|
+
tools: p.tools.map(t => `${p.name}_${t.name}`),
|
|
9
|
+
tabState: state.tabMapping.get(p.name)?.state ?? 'closed',
|
|
10
|
+
tabs: (state.tabMapping.get(p.name)?.tabs ?? []).map(t => ({
|
|
11
|
+
tabId: t.tabId,
|
|
12
|
+
url: t.url,
|
|
13
|
+
title: t.title,
|
|
14
|
+
ready: t.ready,
|
|
15
|
+
})),
|
|
16
|
+
}));
|
|
17
|
+
return JSON.stringify({
|
|
18
|
+
extensionConnected: state.extensionWs !== null,
|
|
19
|
+
plugins,
|
|
20
|
+
failedPlugins: [...state.registry.failures],
|
|
21
|
+
browserToolCount: state.cachedBrowserTools.length,
|
|
22
|
+
pluginToolCount: [...state.registry.plugins.values()].reduce((sum, p) => sum + p.tools.length, 0),
|
|
23
|
+
skipPermissions: state.skipPermissions,
|
|
24
|
+
uptime: Math.round((Date.now() - state.startedAt) / 1000),
|
|
25
|
+
}, null, 2);
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/resources/status.ts"],"names":[],"mappings":"AAAA,uCAAuC;AAIvC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAkB,EAAU,EAAE;IAChE,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7D,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM;QACzB,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,QAAQ;QACzD,IAAI,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACzD,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC,CAAC;KACJ,CAAC,CAAC,CAAC;IAEJ,OAAO,IAAI,CAAC,SAAS,CACnB;QACE,kBAAkB,EAAE,KAAK,CAAC,WAAW,KAAK,IAAI;QAC9C,OAAO;QACP,aAAa,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC3C,gBAAgB,EAAE,KAAK,CAAC,kBAAkB,CAAC,MAAM;QACjD,eAAe,EAAE,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QACjG,eAAe,EAAE,KAAK,CAAC,eAAe;QACtC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;KAC1D,EACD,IAAI,EACJ,CAAC,CACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/** Troubleshooting Guide resource content. */
|
|
2
|
+
export declare const TROUBLESHOOTING_CONTENT = "# Troubleshooting Guide\n\nCommon errors when using OpenTabs, their causes, and resolution steps.\n\n## Quick Diagnosis\n\nBefore diving into specific errors, run these diagnostic commands:\n\n```bash\nopentabs status # Server, extension, and plugin state\nopentabs doctor # Comprehensive setup diagnostics\n```\n\nFrom your AI client:\n- Call `extension_get_state` \u2014 extension health and WebSocket status\n- Call `plugin_list_tabs` \u2014 per-plugin tab readiness\n- Fetch `opentabs://status` \u2014 full server state snapshot\n\n## Error Reference\n\n### Extension Not Connected\n\n**Error:** `Extension not connected. Please ensure the OpenTabs Chrome extension is running.`\n\n**Cause:** The Chrome extension WebSocket connection to the MCP server is not active.\n\n**Resolution:**\n1. Verify server is running: `opentabs status`\n2. Check extension is loaded: open `chrome://extensions`, verify OpenTabs is enabled\n3. Reload extension: click the refresh icon on the OpenTabs card in `chrome://extensions`\n4. Close and reopen the side panel\n5. If still failing, run `opentabs doctor` for full diagnostics\n6. Check for stale auth secret: `opentabs config rotate-secret --confirm`, then reload extension\n\n### Tab Closed\n\n**Error:** `Tab closed: <message>`\n\n**Cause:** No browser tab matches the plugin's URL patterns, or the matching tab was closed during dispatch.\n\n**Resolution:**\n1. Open the target web application in Chrome\n2. Verify the URL matches the plugin's `urlPatterns` (`opentabs status` shows patterns)\n3. Call `plugin_list_tabs` to verify the tab is detected\n4. Retry the tool call\n\n### Tab Unavailable\n\n**Error:** `Tab unavailable: <message>`\n\n**Cause:** A tab matches the plugin's URL patterns but `isReady()` returns false. The user is likely not logged in.\n\n**Resolution:**\n1. Log into the web application in the matching browser tab\n2. Refresh the tab (Ctrl+R / Cmd+R)\n3. Wait 5 seconds for the readiness probe to complete\n4. Call `plugin_list_tabs` to check the `ready` field\n5. Retry the tool call\n\n### Plugin Not Reviewed\n\n**Error:** `Plugin \"<name>\" (v<version>) has not been reviewed yet.`\n\n**Cause:** New plugins start with permission `'off'` and require a security review before use.\n\n**Resolution (AI client flow):**\n1. Call `plugin_inspect({\"plugin\": \"<name>\"})` \u2014 retrieves adapter source code + review token\n2. Review the code for security concerns (data exfiltration, credential access, suspicious network requests)\n3. Share findings with the user\n4. If approved, call `plugin_mark_reviewed({\"plugin\": \"<name>\", \"version\": \"<ver>\", \"reviewToken\": \"<token>\", \"permission\": \"auto\"})`\n\n**Resolution (side panel):** Open the side panel, click the shield icon on the plugin card, and confirm.\n\n### Plugin Updated \u2014 Re-Review Required\n\n**Error:** `Plugin \"<name>\" has been updated from v<old> to v<new> and needs re-review.`\n\n**Cause:** Plugin version changed since last review. Permission resets to `'off'` on version change.\n\n**Resolution:** Same as \"Plugin Not Reviewed\" above \u2014 call `plugin_inspect` and re-review.\n\n### Tool Disabled\n\n**Error:** `Tool \"<name>\" is currently disabled. Ask the user to enable it in the OpenTabs side panel.`\n\n**Cause:** The tool's permission is set to `'off'`.\n\n**Resolution:**\n- User enables in side panel, OR\n- `opentabs config set tool-permission.<plugin>.<tool> ask`\n- `opentabs config set plugin-permission.<plugin> ask`\n\n### Permission Denied by User\n\n**Error:** `Tool \"<name>\" was denied by the user.`\n\n**Cause:** Tool permission is `'ask'` and the user clicked \"Deny\" in the approval dialog.\n\n**Resolution:** Do NOT retry immediately. Ask the user if they want to approve the action. To skip future prompts: `opentabs config set tool-permission.<plugin>.<tool> auto`\n\n### Too Many Concurrent Dispatches\n\n**Error:** `Too many concurrent dispatches for plugin \"<name>\" (limit: 5). Wait for in-flight requests to complete.`\n\n**Cause:** More than 5 simultaneous tool calls to the same plugin.\n\n**Resolution:** Wait 100-500ms for in-flight dispatches to complete, then retry.\n\n### Dispatch Timeout\n\n**Error:** `Dispatch <label> timed out after <ms>ms`\n\n**Cause:** Tool handler did not respond within 30 seconds (or 5 minutes with progress reporting).\n\n**Resolution:**\n1. Check if the tab is responsive (take a screenshot, check console logs)\n2. Refresh the target tab if unresponsive\n3. For legitimately long operations, the plugin should use `context.reportProgress()` to extend the timeout\n4. Break long operations into multiple tool calls\n\n**Timeout rules:**\n- Default: 30s per dispatch\n- Progress resets the timer: each `reportProgress()` call extends by 30s\n- Absolute ceiling: 5 minutes regardless of progress\n\n### Schema Validation Error\n\n**Error:** `Invalid arguments for tool \"<name>\": - <field>: <issue>`\n\n**Cause:** Tool arguments don't match the JSON Schema defined by the plugin.\n\n**Resolution:** Check the tool's input schema via `tools/list` and ensure all required fields are provided with correct types.\n\n### Tool Not Found\n\n**Error:** `Tool <name> not found`\n\n**Cause:** The prefixed tool name doesn't exist in the registry. Plugin may not be installed.\n\n**Resolution:**\n1. Run `opentabs status` to verify the plugin is installed\n2. Check the tool name (format: `<plugin>_<tool>`, e.g., `slack_send_message`)\n3. Reinstall: `opentabs plugin install <name>`\n\n### Rate Limited\n\n**Error:** Tool response includes `retryable: true` and `retryAfterMs`.\n\n**Cause:** The target web application's API returned HTTP 429.\n\n**Resolution:** Wait the specified `retryAfterMs` before retrying. The `ToolError.rateLimited` metadata includes the exact delay.\n\n## Diagnostic Tools Reference\n\n| Tool | What it checks |\n|------|---------------|\n| `extension_get_state` | WebSocket status, registered plugins, active captures |\n| `extension_get_logs` | Extension background script logs, injection warnings |\n| `extension_check_adapter({\"plugin\": \"<name>\"})` | Adapter injection status, hash match, isReady() result |\n| `plugin_list_tabs` | Per-plugin tab matching and readiness |\n| `browser_get_console_logs` | Browser console errors (requires network capture) |\n| `opentabs status` | Server uptime, extension connection, plugin states |\n| `opentabs doctor` | Full setup diagnostics with fix suggestions |\n| `opentabs logs --plugin <name>` | Server-side plugin-specific logs |\n";
|
|
3
|
+
//# sourceMappingURL=troubleshooting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"troubleshooting.d.ts","sourceRoot":"","sources":["../../src/resources/troubleshooting.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAE9C,eAAO,MAAM,uBAAuB,s5MAoKnC,CAAC"}
|