@opentabs-dev/mcp-server 0.0.64 → 0.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/browser-tools/click-element.js +3 -3
  2. package/dist/browser-tools/click-element.js.map +1 -1
  3. package/dist/browser-tools/extension-get-logs.d.ts +1 -1
  4. package/dist/browser-tools/get-console-logs.d.ts +1 -1
  5. package/dist/browser-tools/press-key.js +5 -5
  6. package/dist/browser-tools/press-key.js.map +1 -1
  7. package/dist/extension-handlers.d.ts +4 -1
  8. package/dist/extension-handlers.d.ts.map +1 -1
  9. package/dist/extension-handlers.js +28 -2
  10. package/dist/extension-handlers.js.map +1 -1
  11. package/dist/extension-protocol.d.ts.map +1 -1
  12. package/dist/extension-protocol.js +5 -1
  13. package/dist/extension-protocol.js.map +1 -1
  14. package/dist/loader.d.ts +2 -0
  15. package/dist/loader.d.ts.map +1 -1
  16. package/dist/loader.js +9 -0
  17. package/dist/loader.js.map +1 -1
  18. package/dist/mcp-prompts.d.ts +31 -4
  19. package/dist/mcp-prompts.d.ts.map +1 -1
  20. package/dist/mcp-prompts.js +190 -354
  21. package/dist/mcp-prompts.js.map +1 -1
  22. package/dist/mcp-resources.d.ts +53 -0
  23. package/dist/mcp-resources.d.ts.map +1 -0
  24. package/dist/mcp-resources.js +139 -0
  25. package/dist/mcp-resources.js.map +1 -0
  26. package/dist/mcp-setup.d.ts +12 -1
  27. package/dist/mcp-setup.d.ts.map +1 -1
  28. package/dist/mcp-setup.js +99 -34
  29. package/dist/mcp-setup.js.map +1 -1
  30. package/dist/plugin-management.d.ts +14 -1
  31. package/dist/plugin-management.d.ts.map +1 -1
  32. package/dist/plugin-management.js +55 -1
  33. package/dist/plugin-management.js.map +1 -1
  34. package/dist/prompts/audit-ai-docs.d.ts +6 -0
  35. package/dist/prompts/audit-ai-docs.d.ts.map +1 -0
  36. package/dist/prompts/audit-ai-docs.js +155 -0
  37. package/dist/prompts/audit-ai-docs.js.map +1 -0
  38. package/dist/prompts/build-plugin.d.ts +3 -0
  39. package/dist/prompts/build-plugin.d.ts.map +1 -0
  40. package/dist/prompts/build-plugin.js +455 -0
  41. package/dist/prompts/build-plugin.js.map +1 -0
  42. package/dist/prompts/contribute-learnings.d.ts +12 -0
  43. package/dist/prompts/contribute-learnings.d.ts.map +1 -0
  44. package/dist/prompts/contribute-learnings.js +107 -0
  45. package/dist/prompts/contribute-learnings.js.map +1 -0
  46. package/dist/prompts/plugin-icon.d.ts +5 -0
  47. package/dist/prompts/plugin-icon.d.ts.map +1 -0
  48. package/dist/prompts/plugin-icon.js +147 -0
  49. package/dist/prompts/plugin-icon.js.map +1 -0
  50. package/dist/prompts/setup-plugin.d.ts +3 -0
  51. package/dist/prompts/setup-plugin.d.ts.map +1 -0
  52. package/dist/prompts/setup-plugin.js +197 -0
  53. package/dist/prompts/setup-plugin.js.map +1 -0
  54. package/dist/prompts/troubleshoot.d.ts +3 -0
  55. package/dist/prompts/troubleshoot.d.ts.map +1 -0
  56. package/dist/prompts/troubleshoot.js +191 -0
  57. package/dist/prompts/troubleshoot.js.map +1 -0
  58. package/dist/reload.js +4 -4
  59. package/dist/resources/browser-tools.d.ts +3 -0
  60. package/dist/resources/browser-tools.d.ts.map +1 -0
  61. package/dist/resources/browser-tools.js +100 -0
  62. package/dist/resources/browser-tools.js.map +1 -0
  63. package/dist/resources/cli.d.ts +3 -0
  64. package/dist/resources/cli.d.ts.map +1 -0
  65. package/dist/resources/cli.js +217 -0
  66. package/dist/resources/cli.js.map +1 -0
  67. package/dist/resources/plugin-development.d.ts +3 -0
  68. package/dist/resources/plugin-development.d.ts.map +1 -0
  69. package/dist/resources/plugin-development.js +596 -0
  70. package/dist/resources/plugin-development.js.map +1 -0
  71. package/dist/resources/quick-start.d.ts +3 -0
  72. package/dist/resources/quick-start.d.ts.map +1 -0
  73. package/dist/resources/quick-start.js +210 -0
  74. package/dist/resources/quick-start.js.map +1 -0
  75. package/dist/resources/sdk-api.d.ts +3 -0
  76. package/dist/resources/sdk-api.d.ts.map +1 -0
  77. package/dist/resources/sdk-api.js +199 -0
  78. package/dist/resources/sdk-api.js.map +1 -0
  79. package/dist/resources/self-improvement.d.ts +10 -0
  80. package/dist/resources/self-improvement.d.ts.map +1 -0
  81. package/dist/resources/self-improvement.js +91 -0
  82. package/dist/resources/self-improvement.js.map +1 -0
  83. package/dist/resources/status.d.ts +5 -0
  84. package/dist/resources/status.d.ts.map +1 -0
  85. package/dist/resources/status.js +27 -0
  86. package/dist/resources/status.js.map +1 -0
  87. package/dist/resources/troubleshooting.d.ts +3 -0
  88. package/dist/resources/troubleshooting.d.ts.map +1 -0
  89. package/dist/resources/troubleshooting.js +167 -0
  90. package/dist/resources/troubleshooting.js.map +1 -0
  91. package/dist/state.d.ts +2 -0
  92. package/dist/state.d.ts.map +1 -1
  93. package/dist/state.js.map +1 -1
  94. package/package.json +1 -1
@@ -5,13 +5,34 @@
5
5
  * Unlike instructions (sent on every session), prompts are pull-based — clients
6
6
  * fetch them on demand via `prompts/get` when the user invokes them.
7
7
  *
8
+ * Each prompt resolver returns messages that combine:
9
+ * 1. A user-role text message with the workflow/task instructions
10
+ * 2. Embedded resource content blocks for relevant guides and references
11
+ *
12
+ * Embedding resources directly into prompt messages ensures that MCP clients
13
+ * automatically receive the full context they need — they do not need to
14
+ * separately fetch resources via resources/read. This is the MCP-native
15
+ * mechanism for composing prompts with reference material.
16
+ *
8
17
  * Current prompts:
9
18
  * - `build_plugin`: Full workflow for building a new OpenTabs plugin
19
+ * - `troubleshoot`: Guided debugging workflow for diagnosing platform issues
20
+ * - `setup_plugin`: Step-by-step workflow for installing and configuring a plugin
21
+ * - `plugin_icon`: Add or update an SVG icon for a plugin
22
+ * - `audit_ai_docs`: Audit and improve AI-facing documentation (instructions, resources, prompts)
10
23
  */
24
+ import { getStaticResourceContent } from './mcp-resources.js';
25
+ import { auditAiDocsPromptText } from './prompts/audit-ai-docs.js';
26
+ import { buildPluginPromptText } from './prompts/build-plugin.js';
27
+ import { contributeLearningsPromptText } from './prompts/contribute-learnings.js';
28
+ import { pluginIconPromptText } from './prompts/plugin-icon.js';
29
+ import { setupPluginPromptText } from './prompts/setup-plugin.js';
30
+ import { troubleshootPromptText } from './prompts/troubleshoot.js';
11
31
  /** All registered prompts */
12
32
  export const PROMPTS = [
13
33
  {
14
34
  name: 'build_plugin',
35
+ title: 'Build a Plugin',
15
36
  description: 'Step-by-step workflow for building a new OpenTabs plugin for a web application. ' +
16
37
  'Covers site analysis, auth discovery, API mapping, scaffolding, implementation, and testing. ' +
17
38
  'Use this when you want to create a plugin that gives AI agents access to a web app.',
@@ -28,9 +49,100 @@ export const PROMPTS = [
28
49
  },
29
50
  ],
30
51
  },
52
+ {
53
+ name: 'troubleshoot',
54
+ title: 'Troubleshoot Issues',
55
+ description: 'Guided debugging workflow for diagnosing OpenTabs platform issues. ' +
56
+ 'Walks through extension connectivity, plugin state, tab readiness, permissions, ' +
57
+ 'and common error scenarios with specific tool calls at each step. ' +
58
+ 'Use this when tools fail, the extension is disconnected, or the platform misbehaves.',
59
+ arguments: [
60
+ {
61
+ name: 'error',
62
+ description: 'The error message or symptom to diagnose (e.g., "Extension not connected", "Tab closed"). ' +
63
+ 'If omitted, runs a general health check workflow.',
64
+ required: false,
65
+ },
66
+ ],
67
+ },
68
+ {
69
+ name: 'setup_plugin',
70
+ title: 'Set Up a Plugin',
71
+ description: 'Step-by-step workflow for installing, configuring, reviewing, and testing an existing ' +
72
+ 'OpenTabs plugin from npm. Covers search, install, review flow, permission configuration, ' +
73
+ 'and verification. Use this when you want to add a plugin to the platform.',
74
+ arguments: [
75
+ {
76
+ name: 'name',
77
+ description: 'Plugin name or npm package name (e.g., "slack" or "@opentabs-dev/opentabs-plugin-slack")',
78
+ required: true,
79
+ },
80
+ ],
81
+ },
82
+ {
83
+ name: 'plugin_icon',
84
+ title: 'Add Plugin Icon',
85
+ description: 'Step-by-step workflow for adding or updating an SVG icon for an OpenTabs plugin. ' +
86
+ 'Covers obtaining the brand SVG, preparing it (square viewBox, size constraints), ' +
87
+ 'placing it, building, and verifying in the side panel.',
88
+ arguments: [
89
+ {
90
+ name: 'plugin',
91
+ description: 'Plugin name (e.g., "slack", "discord"). Used to locate the plugin directory.',
92
+ required: true,
93
+ },
94
+ ],
95
+ },
96
+ {
97
+ name: 'audit_ai_docs',
98
+ title: 'Audit AI Documentation',
99
+ description: 'Audit and improve AI-facing documentation served by the MCP server. ' +
100
+ 'Verifies accuracy of instructions, resources, and prompts against the actual codebase. ' +
101
+ 'Identifies gaps, stale content, and drift. Use this to keep AI docs up to date.',
102
+ arguments: [],
103
+ },
104
+ {
105
+ name: 'contribute_learnings',
106
+ title: 'Contribute Learnings',
107
+ description: 'Write new patterns, gotchas, and techniques back into MCP server source code after completing any task. ' +
108
+ 'Edits to these source files compile into the resources and prompts served to every future AI session, ' +
109
+ 'creating a self-improving loop. Invoke this after plugin development, troubleshooting, or any task that surfaced new knowledge.',
110
+ arguments: [
111
+ {
112
+ name: 'task',
113
+ description: 'Brief description of the task you completed (e.g., "built a plugin for Linear", "fixed CORS issue with Notion API"). ' +
114
+ 'If omitted, reviews the entire session for learnings.',
115
+ required: false,
116
+ },
117
+ ],
118
+ },
31
119
  ];
32
120
  /** Prompt name → definition for O(1) lookup */
33
121
  const PROMPT_MAP = new Map(PROMPTS.map(p => [p.name, p]));
122
+ /**
123
+ * Build an embedded resource content block from a resource URI.
124
+ * Returns null if the resource content is not available (dynamic or unknown).
125
+ */
126
+ const embedResource = (uri, mimeType) => {
127
+ const text = getStaticResourceContent(uri);
128
+ if (!text)
129
+ return null;
130
+ return { type: 'resource', resource: { uri, mimeType, text } };
131
+ };
132
+ /**
133
+ * Build prompt messages: a primary text message followed by embedded resources.
134
+ * Resources that fail to resolve (dynamic resources, unknown URIs) are silently skipped.
135
+ */
136
+ const buildMessages = (text, resourceUris) => {
137
+ const messages = [{ role: 'user', content: { type: 'text', text } }];
138
+ for (const { uri, mimeType } of resourceUris) {
139
+ const embedded = embedResource(uri, mimeType);
140
+ if (embedded) {
141
+ messages.push({ role: 'user', content: embedded });
142
+ }
143
+ }
144
+ return messages;
145
+ };
34
146
  /**
35
147
  * Resolve a prompt by name with the given arguments.
36
148
  * Returns null if the prompt name is not recognized.
@@ -39,10 +151,22 @@ export const resolvePrompt = (name, args) => {
39
151
  const def = PROMPT_MAP.get(name);
40
152
  if (!def)
41
153
  return null;
42
- if (name === 'build_plugin') {
43
- return resolveBuildPlugin(args);
154
+ switch (name) {
155
+ case 'build_plugin':
156
+ return resolveBuildPlugin(args);
157
+ case 'troubleshoot':
158
+ return resolveTroubleshoot(args);
159
+ case 'setup_plugin':
160
+ return resolveSetupPlugin(args);
161
+ case 'plugin_icon':
162
+ return resolvePluginIcon(args);
163
+ case 'audit_ai_docs':
164
+ return resolveAuditAiDocs();
165
+ case 'contribute_learnings':
166
+ return resolveContributeLearnings(args);
167
+ default:
168
+ return null;
44
169
  }
45
- return null;
46
170
  };
47
171
  // ---------------------------------------------------------------------------
48
172
  // build_plugin prompt
@@ -52,361 +176,73 @@ const resolveBuildPlugin = (args) => {
52
176
  const name = args.name ?? '';
53
177
  return {
54
178
  description: `Build an OpenTabs plugin for ${url}`,
55
- messages: [
56
- {
57
- role: 'user',
58
- content: {
59
- type: 'text',
60
- text: buildPluginPromptText(url, name),
61
- },
62
- },
63
- ],
179
+ messages: buildMessages(buildPluginPromptText(url, name), [
180
+ { uri: 'opentabs://guide/plugin-development', mimeType: 'text/markdown' },
181
+ { uri: 'opentabs://reference/sdk-api', mimeType: 'text/markdown' },
182
+ ]),
64
183
  };
65
184
  };
66
- const buildPluginPromptText = (url, name) => {
67
- const nameClause = name ? `The plugin name should be \`${name}\`.` : '';
68
- return `Build a production-ready OpenTabs plugin for ${url}. ${nameClause}
69
-
70
- Follow the complete workflow below. Each phase builds on the previous one — do not skip phases.
71
-
72
- ---
73
-
74
- ## Prerequisites
75
-
76
- - The user has the target web app open in a browser tab at ${url}
77
- - The MCP server is running (you are connected to it)
78
- - You have access to the filesystem for creating plugin source files
79
-
80
- ### Browser Tool Permissions
81
-
82
- Plugin development requires heavy use of browser tools (\`browser_execute_script\`, \`browser_navigate_tab\`, \`browser_get_tab_content\`, etc.). By default, tools have permission \`'off'\` (disabled) or \`'ask'\` (requires human approval).
83
-
84
- Ask the user if they want to enable \`skipPermissions\` to bypass approval prompts during development. Set the env var: \`OPENTABS_DANGEROUSLY_SKIP_PERMISSIONS=1\`. Warn them this bypasses human approval and should only be used during active plugin development.
85
-
86
- ---
87
-
88
- ## Phase 1: Research the Codebase
89
-
90
- Before writing any code, study the existing plugin infrastructure using the filesystem:
91
-
92
- 1. **Study the Plugin SDK** — read \`platform/plugin-sdk/CLAUDE.md\` and key source files (\`src/index.ts\`, \`src/plugin.ts\`, \`src/tool.ts\`). Understand:
93
- - \`OpenTabsPlugin\` abstract base class (name, displayName, description, urlPatterns, tools, isReady)
94
- - \`defineTool({ name, displayName, description, icon, input, output, handle })\` factory
95
- - \`ToolError\` static factories: \`.auth()\`, \`.notFound()\`, \`.rateLimited()\`, \`.timeout()\`, \`.validation()\`, \`.internal()\`
96
- - SDK utilities: \`fetchJSON\`, \`postJSON\`, \`getLocalStorage\`, \`waitForSelector\`, \`retry\`, \`sleep\`, \`log\`
97
- - All plugin code runs in the **browser page context** (not server-side)
98
-
99
- 2. **Study an existing plugin** (e.g., \`plugins/slack/\`) as the canonical reference:
100
- - \`src/index.ts\` — plugin class, imports all tools
101
- - \`src/slack-api.ts\` — API wrapper with auth extraction + error classification
102
- - \`src/tools/\` — one file per tool, shared schemas
103
- - \`package.json\` — the opentabs field, dependency versions, scripts
104
-
105
- 3. **Study \`plugins/CLAUDE.md\`** — plugin isolation rules and conventions
106
-
107
- ---
108
-
109
- ## Phase 2: Explore the Target Web App
110
-
111
- This is the most critical phase. Use browser tools to understand how the web app works.
112
-
113
- ### Step 1: Find the Tab
114
-
115
- \`\`\`
116
- plugin_list_tabs or browser_list_tabs → find the tab for ${url}
117
- \`\`\`
118
-
119
- ### Step 2: Analyze the Site
120
-
121
- \`\`\`
122
- plugin_analyze_site(url: "${url}")
123
- \`\`\`
124
-
125
- This gives you a comprehensive report: auth methods, API endpoints, framework detection, storage keys, and concrete tool suggestions.
126
-
127
- ### Step 3: Enable Network Capture and Explore
128
-
129
- \`\`\`
130
- browser_enable_network_capture(tabId, urlFilter: "/api")
131
- \`\`\`
132
-
133
- Navigate around in the app to trigger API calls, then read them:
134
-
135
- \`\`\`
136
- browser_get_network_requests(tabId)
137
- \`\`\`
138
-
139
- Study the captured traffic to understand:
140
- - API base URL
141
- - Whether the API is same-origin or cross-origin (critical for CORS)
142
- - Request format (JSON body vs form-encoded)
143
- - Required headers (content-type, custom headers)
144
- - Response shapes for each endpoint
145
- - Error response format
146
-
147
- ### Step 4: Check CORS Policy (for Cross-Origin APIs)
148
-
149
- If the API is on a different subdomain, verify CORS behavior:
150
-
151
- \`\`\`bash
152
- curl -sI -X OPTIONS https://api.example.com/endpoint \\
153
- -H "Origin: ${url}" \\
154
- -H "Access-Control-Request-Method: GET" \\
155
- -H "Access-Control-Request-Headers: Authorization,Content-Type" \\
156
- | grep -i "access-control"
157
- \`\`\`
158
-
159
- ### Step 5: Discover Auth Token
160
-
161
- **First, always check cookies with \`browser_get_cookies\`** to understand the auth model. Then probe the page:
162
-
163
- - **localStorage**: Direct access or iframe fallback if the app deletes \`window.localStorage\`
164
- - **Page globals**: \`window.__APP_STATE__\`, \`window.boot_data\`, \`window.__NEXT_DATA__\`
165
- - **Webpack module stores**: For React/webpack SPAs
166
- - **Cookies**: \`document.cookie\` for non-HttpOnly tokens
167
- - **Script tags**: Inline \`<script>\` tags with embedded config
168
-
169
- ### Step 6: Test the API
170
-
171
- Once you have the token, make a test API call with \`browser_execute_script\`:
172
-
173
- \`\`\`javascript
174
- const resp = await fetch('https://example.com/api/v2/me', {
175
- headers: { Authorization: 'Bearer ' + token },
176
- credentials: 'include',
177
- });
178
- const data = await resp.json();
179
- return data;
180
- \`\`\`
181
-
182
- ### Step 7: Map the API Surface
183
-
184
- Discover the key endpoints: user/profile, list resources, get single resource, create/update/delete, search, messaging, reactions.
185
-
186
- ---
187
-
188
- ## Phase 3: Scaffold the Plugin
189
-
190
- \`\`\`bash
191
- cd plugins/
192
- opentabs plugin create <name> --domain <domain> --display <DisplayName> --description "OpenTabs plugin for <DisplayName>"
193
- \`\`\`
194
-
195
- After scaffolding, compare \`package.json\` with an existing plugin (e.g., \`plugins/slack/package.json\`) and align:
196
- - Package name: \`@opentabs-dev/opentabs-plugin-<name>\` for official plugins
197
- - Version: Match the current platform version
198
- - Add: \`publishConfig\`, \`check\` script
199
- - Dependency versions: Match \`@opentabs-dev/plugin-sdk\` and \`@opentabs-dev/plugin-tools\` versions
200
-
201
- ---
202
-
203
- ## Phase 4: Implement
204
-
205
- ### File Structure
206
-
207
- \`\`\`
208
- src/
209
- index.ts # Plugin class — imports all tools, implements isReady()
210
- <name>-api.ts # API wrapper — auth extraction + error classification
211
- tools/
212
- schemas.ts # Shared Zod schemas + defensive mappers
213
- send-message.ts # One file per tool
214
- ...
215
- \`\`\`
216
-
217
- ### API Wrapper Pattern (\`<name>-api.ts\`)
218
-
219
- The API wrapper handles auth extraction, request construction, and error classification:
220
-
221
- \`\`\`typescript
222
- import { ToolError } from '@opentabs-dev/plugin-sdk';
223
-
224
- interface AppAuth {
225
- token: string;
226
- }
227
-
228
- const getAuth = (): AppAuth | null => {
229
- // Check globalThis persistence first (survives adapter re-injection)
230
- // Then try localStorage, page globals, cookies
231
- // Return null if not authenticated
185
+ // ---------------------------------------------------------------------------
186
+ // troubleshoot prompt
187
+ // ---------------------------------------------------------------------------
188
+ const resolveTroubleshoot = (args) => {
189
+ const error = args.error ?? '';
190
+ return {
191
+ description: error ? `Troubleshoot OpenTabs issue: ${error}` : 'Run a general OpenTabs health check',
192
+ messages: buildMessages(troubleshootPromptText(error), [
193
+ { uri: 'opentabs://guide/troubleshooting', mimeType: 'text/markdown' },
194
+ ]),
195
+ };
232
196
  };
233
-
234
- export const isAuthenticated = (): boolean => getAuth() !== null;
235
-
236
- export const waitForAuth = (): Promise<boolean> =>
237
- new Promise((resolve) => {
238
- let elapsed = 0;
239
- const interval = 500;
240
- const maxWait = 5000;
241
- const timer = setInterval(() => {
242
- elapsed += interval;
243
- if (isAuthenticated()) { clearInterval(timer); resolve(true); return; }
244
- if (elapsed >= maxWait) { clearInterval(timer); resolve(false); }
245
- }, interval);
246
- });
247
-
248
- export const api = async <T extends Record<string, unknown>>(
249
- endpoint: string,
250
- options: { method?: string; body?: Record<string, unknown>; query?: Record<string, string | number | boolean | undefined> } = {},
251
- ): Promise<T> => {
252
- const auth = getAuth();
253
- if (!auth) throw ToolError.auth('Not authenticated — please log in.');
254
-
255
- let url = \\\`https://example.com/api\\\${endpoint}\\\`;
256
- if (options.query) {
257
- const params = new URLSearchParams();
258
- for (const [key, value] of Object.entries(options.query)) {
259
- if (value !== undefined) params.append(key, String(value));
260
- }
261
- const qs = params.toString();
262
- if (qs) url += \\\`?\\\${qs}\\\`;
263
- }
264
-
265
- const headers: Record<string, string> = { Authorization: \\\`Bearer \\\${auth.token}\\\` };
266
- let fetchBody: string | undefined;
267
- if (options.body) {
268
- headers['Content-Type'] = 'application/json';
269
- fetchBody = JSON.stringify(options.body);
270
- }
271
-
272
- let response: Response;
273
- try {
274
- response = await fetch(url, {
275
- method: options.method ?? 'GET', headers, body: fetchBody,
276
- credentials: 'include', signal: AbortSignal.timeout(30_000),
277
- });
278
- } catch (err: unknown) {
279
- if (err instanceof DOMException && err.name === 'TimeoutError')
280
- throw ToolError.timeout(\\\`API request timed out: \\\${endpoint}\\\`);
281
- throw new ToolError(
282
- \\\`Network error: \\\${err instanceof Error ? err.message : String(err)}\\\`,
283
- 'network_error', { category: 'internal', retryable: true },
284
- );
285
- }
286
-
287
- if (!response.ok) {
288
- const errorBody = (await response.text().catch(() => '')).substring(0, 512);
289
- if (response.status === 429) throw ToolError.rateLimited(\\\`Rate limited: \\\${endpoint}\\\`);
290
- if (response.status === 401 || response.status === 403)
291
- throw ToolError.auth(\\\`Auth error (\\\${response.status}): \\\${errorBody}\\\`);
292
- if (response.status === 404) throw ToolError.notFound(\\\`Not found: \\\${endpoint}\\\`);
293
- throw ToolError.internal(\\\`API error (\\\${response.status}): \\\${endpoint} — \\\${errorBody}\\\`);
294
- }
295
-
296
- if (response.status === 204) return {} as T;
297
- return (await response.json()) as T;
197
+ // ---------------------------------------------------------------------------
198
+ // setup_plugin prompt
199
+ // ---------------------------------------------------------------------------
200
+ const resolveSetupPlugin = (args) => {
201
+ const name = args.name ?? 'my-plugin';
202
+ return {
203
+ description: `Set up the ${name} OpenTabs plugin`,
204
+ messages: buildMessages(setupPluginPromptText(name), [
205
+ { uri: 'opentabs://guide/quick-start', mimeType: 'text/markdown' },
206
+ ]),
207
+ };
208
+ };
209
+ // ---------------------------------------------------------------------------
210
+ // plugin_icon prompt
211
+ // ---------------------------------------------------------------------------
212
+ const resolvePluginIcon = (args) => {
213
+ const plugin = args.plugin ?? 'my-plugin';
214
+ return {
215
+ description: `Add or update icon for the ${plugin} plugin`,
216
+ messages: buildMessages(pluginIconPromptText(plugin), []),
217
+ };
298
218
  };
299
- \`\`\`
300
-
301
- ### Tool Pattern (one file per tool)
302
-
303
- \`\`\`typescript
304
- import { defineTool } from '@opentabs-dev/plugin-sdk';
305
- import { z } from 'zod';
306
- import { api } from '../<name>-api.js';
307
-
308
- export const sendMessage = defineTool({
309
- name: 'send_message',
310
- displayName: 'Send Message',
311
- description: 'Send a message to a channel. Supports markdown formatting.',
312
- summary: 'Send a message to a channel',
313
- icon: 'send',
314
- input: z.object({
315
- channel: z.string().describe('Channel ID to send the message to'),
316
- content: z.string().describe('Message text content'),
317
- }),
318
- output: z.object({
319
- id: z.string().describe('Message ID'),
320
- }),
321
- handle: async (params) => {
322
- const data = await api<Record<string, unknown>>(
323
- '/channels/' + params.channel + '/messages',
324
- { method: 'POST', body: { content: params.content } },
325
- );
326
- return { id: (data.id as string) ?? '' };
327
- },
219
+ // ---------------------------------------------------------------------------
220
+ // audit_ai_docs prompt
221
+ // ---------------------------------------------------------------------------
222
+ const resolveAuditAiDocs = () => ({
223
+ description: 'Audit and improve AI-facing documentation',
224
+ messages: buildMessages(auditAiDocsPromptText(), [
225
+ { uri: 'opentabs://guide/quick-start', mimeType: 'text/markdown' },
226
+ { uri: 'opentabs://guide/plugin-development', mimeType: 'text/markdown' },
227
+ { uri: 'opentabs://guide/troubleshooting', mimeType: 'text/markdown' },
228
+ { uri: 'opentabs://guide/self-improvement', mimeType: 'text/markdown' },
229
+ { uri: 'opentabs://reference/sdk-api', mimeType: 'text/markdown' },
230
+ { uri: 'opentabs://reference/cli', mimeType: 'text/markdown' },
231
+ { uri: 'opentabs://reference/browser-tools', mimeType: 'text/markdown' },
232
+ ]),
328
233
  });
329
- \`\`\`
330
-
331
- ### Plugin Class Pattern (\`index.ts\`)
332
-
333
- \`\`\`typescript
334
- import { OpenTabsPlugin } from '@opentabs-dev/plugin-sdk';
335
- import type { ToolDefinition } from '@opentabs-dev/plugin-sdk';
336
- import { isAuthenticated, waitForAuth } from './<name>-api.js';
337
- import { sendMessage } from './tools/send-message.js';
338
-
339
- class MyPlugin extends OpenTabsPlugin {
340
- readonly name = '<name>';
341
- readonly description = 'OpenTabs plugin for <DisplayName>';
342
- override readonly displayName = '<DisplayName>';
343
- readonly urlPatterns = ['*://*.example.com/*'];
344
- readonly tools: ToolDefinition[] = [sendMessage];
345
-
346
- async isReady(): Promise<boolean> {
347
- if (isAuthenticated()) return true;
348
- return waitForAuth();
349
- }
350
- }
351
-
352
- export default new MyPlugin();
353
- \`\`\`
354
-
355
- ---
356
-
357
- ## Phase 5: Build and Test
358
-
359
- ### Build
360
-
361
- \`\`\`bash
362
- cd plugins/<name>
363
- npm install
364
- npm run build
365
- \`\`\`
366
-
367
- ### Verify Plugin Loaded
368
-
369
- \`\`\`
370
- plugin_list_tabs(plugin: "<name>")
371
- \`\`\`
372
-
373
- Must show \`state: "ready"\` for the matching tab.
374
-
375
- ### Test Each Tool
376
-
377
- Systematically test read-only tools first (list, get, search), then write tools (send, create, delete). Test error cases: invalid IDs, missing permissions.
378
-
379
- ### Full Check Suite
380
-
381
- \`\`\`bash
382
- npm run check # build + type-check + lint + format:check
383
- \`\`\`
384
-
385
- ---
386
-
387
- ## Key Conventions
388
-
389
- - **One file per tool** in \`src/tools/\`
390
- - **Every Zod field gets \`.describe()\`** — this is what AI agents see in the tool schema
391
- - **\`description\` is for AI clients** — detailed, informative. \`summary\` is for humans — short, under 80 chars
392
- - **Defensive mapping** with fallback defaults (\`data.field ?? ''\`) — never trust API shapes
393
- - **Error classification is critical** — use \`ToolError\` factories, never throw raw errors
394
- - **\`credentials: 'include'\`** on all fetch calls
395
- - **30-second timeout** via \`AbortSignal.timeout(30_000)\`
396
- - **\`.js\` extension** on all imports (ESM requirement)
397
- - **No \`.transform()\`/\`.pipe()\`/\`.preprocess()\`** in Zod schemas (breaks JSON Schema serialization)
398
-
399
- ---
400
-
401
- ## Common Gotchas
402
-
403
- 1. **All plugin code runs in the browser** — no Node.js APIs
404
- 2. **SPAs hydrate asynchronously** — \`isReady()\` must poll (500ms interval, 5s max)
405
- 3. **Some apps delete browser APIs** — use iframe fallback for \`localStorage\`
406
- 4. **Tokens must persist on \`globalThis.__openTabs.tokenCache.<pluginName>\`** — module-level variables reset on extension reload
407
- 5. **HttpOnly cookies are invisible to plugin code** — use \`credentials: 'include'\` for the browser to send them automatically, detect auth status from DOM signals
408
- 6. **Parse error response bodies before classifying by HTTP status** — many apps reuse 403 for both auth and permission errors
409
- 7. **Cross-origin API + cookies: check CORS before choosing fetch strategy**
410
- 8. **Always run \`npm run format\` after writing code** — Biome config uses single quotes`;
234
+ // ---------------------------------------------------------------------------
235
+ // contribute_learnings prompt
236
+ // ---------------------------------------------------------------------------
237
+ const resolveContributeLearnings = (args) => {
238
+ const task = args.task ?? '';
239
+ return {
240
+ description: task ? `Contribute learnings from: ${task}` : 'Contribute learnings from recent session',
241
+ messages: buildMessages(contributeLearningsPromptText(task), [
242
+ { uri: 'opentabs://guide/self-improvement', mimeType: 'text/markdown' },
243
+ { uri: 'opentabs://guide/plugin-development', mimeType: 'text/markdown' },
244
+ { uri: 'opentabs://guide/troubleshooting', mimeType: 'text/markdown' },
245
+ ]),
246
+ };
411
247
  };
412
248
  //# sourceMappingURL=mcp-prompts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-prompts.js","sourceRoot":"","sources":["../src/mcp-prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA4BH,6BAA6B;AAC7B,MAAM,CAAC,MAAM,OAAO,GAAuB;IACzC;QACE,IAAI,EAAE,cAAc;QACpB,WAAW,EACT,kFAAkF;YAClF,+FAA+F;YAC/F,qFAAqF;QACvF,SAAS,EAAE;YACT;gBACE,IAAI,EAAE,KAAK;gBACX,WAAW,EAAE,qEAAqE;gBAClF,QAAQ,EAAE,IAAI;aACf;YACD;gBACE,IAAI,EAAE,MAAM;gBACZ,WAAW,EAAE,8EAA8E;gBAC3F,QAAQ,EAAE,KAAK;aAChB;SACF;KACF;CACF,CAAC;AAEF,+CAA+C;AAC/C,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE1D;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAE,IAA4B,EAAuB,EAAE;IAC/F,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACjC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,IAAI,KAAK,cAAc,EAAE,CAAC;QAC5B,OAAO,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC,CAAC;AAEF,8EAA8E;AAC9E,sBAAsB;AACtB,8EAA8E;AAE9E,MAAM,kBAAkB,GAAG,CAAC,IAA4B,EAAgB,EAAE;IACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,qBAAqB,CAAC;IAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAE7B,OAAO;QACL,WAAW,EAAE,gCAAgC,GAAG,EAAE;QAClD,QAAQ,EAAE;YACR;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE;oBACP,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,qBAAqB,CAAC,GAAG,EAAE,IAAI,CAAC;iBACvC;aACF;SACF;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,GAAW,EAAE,IAAY,EAAU,EAAE;IAClE,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,+BAA+B,IAAI,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAExE,OAAO,gDAAgD,GAAG,KAAK,UAAU;;;;;;;;6DAQd,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+DAwCD,GAAG;;;;;;4BAMtC,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA+Bf,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;0FAiQuE,CAAC;AAC3F,CAAC,CAAC"}
1
+ {"version":3,"file":"mcp-prompts.js","sourceRoot":"","sources":["../src/mcp-prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * MCP resource definitions for the OpenTabs server.
3
+ *
4
+ * Resources are static or dynamic documents that AI clients can fetch on demand
5
+ * via `resources/read`. Unlike instructions (sent on every session), resources
6
+ * are pull-based — clients discover them via `resources/list` and fetch content
7
+ * when they need deeper context.
8
+ *
9
+ * Static resources return pre-built markdown content (guides, references).
10
+ * The `opentabs://status` resource is dynamic — built from ServerState at read time.
11
+ *
12
+ * Resources include MCP annotations (audience, priority) that help AI clients
13
+ * decide which resources to auto-include and which to present to users:
14
+ * - audience: ['assistant'] — content intended for the AI model
15
+ * - audience: ['user', 'assistant'] — content useful for both parties
16
+ * - priority: 0.0–1.0 — importance hint (1.0 = effectively required)
17
+ */
18
+ import type { ServerState } from './state.js';
19
+ /** MCP resource annotations per the 2025-06-18 spec */
20
+ interface ResourceAnnotations {
21
+ audience?: Array<'user' | 'assistant'>;
22
+ priority?: number;
23
+ }
24
+ /** A resource definition for MCP resources/list */
25
+ export interface ResourceDefinition {
26
+ uri: string;
27
+ name: string;
28
+ title?: string;
29
+ description: string;
30
+ mimeType: string;
31
+ annotations?: ResourceAnnotations;
32
+ }
33
+ /** A resolved resource for MCP resources/read */
34
+ export interface ResolvedResource {
35
+ uri: string;
36
+ mimeType: string;
37
+ text: string;
38
+ }
39
+ /** Return all resource definitions for resources/list, including annotations. */
40
+ export declare const getAllResources: (_state: ServerState) => ResourceDefinition[];
41
+ /**
42
+ * Resolve a resource by URI, returning its content.
43
+ * Returns null if the URI is not recognized.
44
+ */
45
+ export declare const resolveResource: (state: ServerState, uri: string) => ResolvedResource | null;
46
+ /**
47
+ * Get the text content of a static resource by URI (without needing ServerState).
48
+ * Returns null for dynamic or unknown resources. Used by prompt resolvers to
49
+ * embed resource content directly into prompt messages.
50
+ */
51
+ export declare const getStaticResourceContent: (uri: string) => string | null;
52
+ export {};
53
+ //# sourceMappingURL=mcp-resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-resources.d.ts","sourceRoot":"","sources":["../src/mcp-resources.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAUH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,uDAAuD;AACvD,UAAU,mBAAmB;IAC3B,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mDAAmD;AACnD,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,mBAAmB,CAAC;CACnC;AAED,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAsFD,iFAAiF;AACjF,eAAO,MAAM,eAAe,GAAI,QAAQ,WAAW,KAAG,kBAAkB,EAQnE,CAAC;AAEN;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,WAAW,EAAE,KAAK,MAAM,KAAG,gBAAgB,GAAG,IAepF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GAAI,KAAK,MAAM,KAAG,MAAM,GAAG,IAAoC,CAAC"}