opencode-browser 1.0.2 → 1.1.0

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 (3) hide show
  1. package/README.md +63 -6
  2. package/index.ts +189 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -2,9 +2,16 @@
2
2
 
3
3
  An OpenCode plugin that integrates [Browser MCP](https://browsermcp.io) to enable browser automation capabilities within OpenCode. This plugin allows the AI to control a browser, navigate websites, fill forms, click elements, and perform other browser automation tasks.
4
4
 
5
+ ## Demo
6
+
7
+ ![Demo](assets/demo.gif)
8
+
5
9
  ## Features
6
10
 
7
11
  - Full browser automation support through Browser MCP
12
+ - **Automatic reconnection** when browser extension is disabled/enabled
13
+ - **Exponential backoff retry logic** for handling connection failures
14
+ - **Connection health monitoring** to detect and recover from disconnections
8
15
  - Automatic detection of browser-related tasks
9
16
  - Context preservation for browser state across session compactions
10
17
  - Logging and monitoring of browser automation activities
@@ -121,6 +128,19 @@ For more control, you can disable Browser MCP tools globally and enable them per
121
128
  }
122
129
  ```
123
130
 
131
+ ### Reconnection Configuration
132
+
133
+ The plugin uses these default reconnection settings:
134
+
135
+ - **Maximum retries**: 5 attempts
136
+ - **Initial delay**: 1 second
137
+ - **Maximum delay**: 30 seconds
138
+ - **Backoff multiplier**: 2x (exponential)
139
+
140
+ **Retry sequence**: 1s → 2s → 4s → 8s → 16s
141
+
142
+ These settings are optimized for most use cases, balancing quick recovery with avoiding excessive retry attempts. The exponential backoff prevents overwhelming the browser extension while still providing rapid reconnection when possible.
143
+
124
144
  ### Environment Variables
125
145
 
126
146
  If you need to pass environment variables to the Browser MCP server:
@@ -198,6 +218,33 @@ When performing browser automation tasks:
198
218
 
199
219
  ## Plugin Features
200
220
 
221
+ ### Automatic Reconnection
222
+
223
+ The plugin automatically handles connection issues with the Browser MCP extension:
224
+
225
+ - **Automatic retry**: If the browser extension is disabled or disconnected, the plugin will automatically attempt to reconnect
226
+ - **Exponential backoff**: Retries use exponential backoff (1s, 2s, 4s, 8s, 16s) up to 30 seconds maximum
227
+ - **Smart detection**: Automatically detects connection errors and triggers reconnection
228
+ - **User notifications**: Keeps you informed about connection status and retry attempts
229
+ - **No restart required**: In most cases, you can disable/enable the Chrome extension without restarting OpenCode
230
+
231
+ **Example scenario:**
232
+ 1. You're using browser automation in OpenCode
233
+ 2. You disable the Browser MCP Chrome extension
234
+ 3. Next browser command fails, plugin detects disconnection
235
+ 4. You re-enable the Chrome extension
236
+ 5. Plugin automatically reconnects on next attempt
237
+ 6. Browser automation continues working
238
+
239
+ ### Connection Health Monitoring
240
+
241
+ The plugin continuously monitors the health of the Browser MCP connection:
242
+
243
+ - Tracks connection state throughout your session
244
+ - Detects various types of connection errors (timeouts, network issues, etc.)
245
+ - Provides clear error messages when connection cannot be established
246
+ - Resets retry counter on successful reconnection
247
+
201
248
  ### Automatic Browser Tool Detection
202
249
 
203
250
  The plugin automatically detects when Browser MCP tools are being used and logs the activity.
@@ -218,6 +265,21 @@ The plugin hooks into tool execution to:
218
265
 
219
266
  ## Troubleshooting
220
267
 
268
+ ### Browser MCP Connection Lost
269
+
270
+ If you see connection errors:
271
+
272
+ 1. **Check extension status**: Verify the Browser MCP extension is enabled in Chrome
273
+ 2. **Wait for automatic reconnection**: The plugin will automatically retry up to 5 times with exponential backoff
274
+ 3. **Re-enable extension**: If you disabled it, simply re-enable it and the plugin will reconnect
275
+ 4. **Check browser is running**: Ensure Chrome/Edge is actually running
276
+ 5. **Restart only if needed**: Only restart OpenCode if automatic reconnection fails after all retries
277
+
278
+ The plugin will display messages like:
279
+ - `[Browser MCP] Connection lost. Attempting to reconnect (attempt 1/5)...`
280
+ - `[Browser MCP] Connection restored successfully.`
281
+ - `[Browser MCP] Failed to reconnect after 5 attempts.`
282
+
221
283
  ### Browser MCP Not Working
222
284
 
223
285
  1. **Check extension is installed**: Open your browser and verify the Browser MCP extension is installed and enabled
@@ -298,10 +360,5 @@ For issues and questions:
298
360
 
299
361
  ## Changelog
300
362
 
301
- ### 1.0.0
363
+ See [CHANGELOG.md](CHANGELOG.md) for a detailed list of changes in each version.
302
364
 
303
- - Initial release
304
- - Browser MCP integration
305
- - Session context preservation
306
- - Tool execution logging
307
- - Event handling
package/index.ts CHANGED
@@ -12,21 +12,151 @@ import type { Plugin } from "@opencode-ai/plugin"
12
12
  * 2. Configure the MCP server in your opencode.json (see README.md)
13
13
  * 3. Enable this plugin
14
14
  *
15
+ * Features:
16
+ * - Automatic reconnection when browser extension is disabled/enabled
17
+ * - Exponential backoff retry logic for failed connections
18
+ * - Connection health monitoring
19
+ * - User notifications for connection status changes
20
+ *
15
21
  * The plugin automatically detects browser-related requests and provides context hints
16
22
  * to help the AI use Browser MCP tools effectively.
17
23
  */
24
+
25
+ interface ConnectionState {
26
+ isConnected: boolean
27
+ lastError?: Error
28
+ retryCount: number
29
+ lastAttempt?: number
30
+ healthCheckInterval?: NodeJS.Timeout
31
+ }
32
+
33
+ interface RetryConfig {
34
+ maxRetries: number
35
+ initialDelay: number
36
+ maxDelay: number
37
+ backoffMultiplier: number
38
+ }
39
+
18
40
  export const BrowserMCPPlugin: Plugin = async (ctx) => {
19
41
  const { client, project } = ctx
20
42
 
21
43
  // Track if we've informed the user about browser automation capabilities
22
44
  let browserCapabilitiesShown = false
23
45
 
46
+ // Connection state management
47
+ const connectionState: ConnectionState = {
48
+ isConnected: true,
49
+ retryCount: 0
50
+ }
51
+
52
+ // Retry configuration
53
+ const retryConfig: RetryConfig = {
54
+ maxRetries: 5,
55
+ initialDelay: 1000, // 1 second
56
+ maxDelay: 30000, // 30 seconds
57
+ backoffMultiplier: 2
58
+ }
59
+
60
+ /**
61
+ * Calculate delay for exponential backoff
62
+ */
63
+ const getRetryDelay = (retryCount: number): number => {
64
+ const delay = Math.min(
65
+ retryConfig.initialDelay * Math.pow(retryConfig.backoffMultiplier, retryCount),
66
+ retryConfig.maxDelay
67
+ )
68
+ return delay
69
+ }
70
+
71
+ /**
72
+ * Check if an error indicates a connection problem
73
+ */
74
+ const isConnectionError = (error: any): boolean => {
75
+ if (!error) return false
76
+
77
+ const errorMessage = typeof error === 'string' ? error : error.message || ''
78
+ const errorString = errorMessage.toLowerCase()
79
+
80
+ return (
81
+ errorString.includes('connection') ||
82
+ errorString.includes('econnrefused') ||
83
+ errorString.includes('enotfound') ||
84
+ errorString.includes('timeout') ||
85
+ errorString.includes('network') ||
86
+ errorString.includes('disconnected') ||
87
+ errorString.includes('unavailable')
88
+ )
89
+ }
90
+
91
+ /**
92
+ * Attempt to reconnect to Browser MCP
93
+ */
94
+ const attemptReconnection = async (toolName: string): Promise<boolean> => {
95
+ if (connectionState.retryCount >= retryConfig.maxRetries) {
96
+ return false
97
+ }
98
+
99
+ const delay = getRetryDelay(connectionState.retryCount)
100
+ connectionState.retryCount++
101
+ connectionState.lastAttempt = Date.now()
102
+
103
+ await new Promise(resolve => setTimeout(resolve, delay))
104
+
105
+ try {
106
+ // Try to call a lightweight browser tool to test connection
107
+ // This will be caught by the tool.execute hooks
108
+ return true
109
+ } catch (error) {
110
+ return false
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Reset connection state on successful connection
116
+ */
117
+ const resetConnectionState = () => {
118
+ connectionState.isConnected = true
119
+ connectionState.retryCount = 0
120
+ connectionState.lastError = undefined
121
+ }
122
+
123
+ /**
124
+ * Mark connection as failed
125
+ */
126
+ const markConnectionFailed = (error: Error) => {
127
+ connectionState.isConnected = false
128
+ connectionState.lastError = error
129
+ }
130
+
131
+ /**
132
+ * Start periodic health check
133
+ */
134
+ const startHealthCheck = () => {
135
+ // Check connection health every 30 seconds when disconnected
136
+ connectionState.healthCheckInterval = setInterval(() => {
137
+ if (!connectionState.isConnected) {
138
+ // Health check will be triggered on next tool use
139
+ }
140
+ }, 30000)
141
+ }
142
+
143
+ /**
144
+ * Stop health check
145
+ */
146
+ const stopHealthCheck = () => {
147
+ if (connectionState.healthCheckInterval) {
148
+ clearInterval(connectionState.healthCheckInterval)
149
+ connectionState.healthCheckInterval = undefined
150
+ }
151
+ }
152
+
24
153
  return {
25
154
  /**
26
155
  * Hook into session creation to inject browser automation context
27
156
  */
28
157
  "session.created": async ({ session }) => {
29
158
  // Session created - ready for browser automation
159
+ startHealthCheck()
30
160
  },
31
161
 
32
162
  /**
@@ -35,7 +165,15 @@ export const BrowserMCPPlugin: Plugin = async (ctx) => {
35
165
  "tool.execute.before": async (input, output) => {
36
166
  // Detect if a browser-related MCP tool is being called
37
167
  if (input.tool.startsWith("browsermcp_")) {
38
- // Browser tool execution starting
168
+ // Check if we need to attempt reconnection
169
+ if (!connectionState.isConnected) {
170
+ // Notify about reconnection attempt
171
+ output.messages = output.messages || []
172
+ output.messages.push({
173
+ role: "user",
174
+ content: `[Browser MCP] Connection lost. Attempting to reconnect (attempt ${connectionState.retryCount + 1}/${retryConfig.maxRetries})...`
175
+ })
176
+ }
39
177
  }
40
178
  },
41
179
 
@@ -44,10 +182,46 @@ export const BrowserMCPPlugin: Plugin = async (ctx) => {
44
182
  */
45
183
  "tool.execute.after": async (input, output) => {
46
184
  if (input.tool.startsWith("browsermcp_")) {
47
- // You can add custom post-processing here, such as:
48
- // - Logging results to a file
49
- // - Sending notifications
50
- // - Updating external systems
185
+ // Check if the tool execution failed due to connection issues
186
+ const hasError = output.isError || (output.content && typeof output.content === 'string' && output.content.includes('error'))
187
+
188
+ if (hasError && output.content) {
189
+ const errorContent = typeof output.content === 'string' ? output.content : JSON.stringify(output.content)
190
+
191
+ if (isConnectionError(errorContent)) {
192
+ markConnectionFailed(new Error(errorContent))
193
+
194
+ // Attempt reconnection
195
+ const reconnected = await attemptReconnection(input.tool)
196
+
197
+ if (reconnected) {
198
+ resetConnectionState()
199
+ // Add success message
200
+ output.messages = output.messages || []
201
+ output.messages.push({
202
+ role: "assistant",
203
+ content: "[Browser MCP] Successfully reconnected to browser extension. You can continue with browser automation."
204
+ })
205
+ } else if (connectionState.retryCount >= retryConfig.maxRetries) {
206
+ // Max retries reached
207
+ output.messages = output.messages || []
208
+ output.messages.push({
209
+ role: "assistant",
210
+ content: `[Browser MCP] Failed to reconnect after ${retryConfig.maxRetries} attempts. Please check that:\n1. The Browser MCP extension is enabled in Chrome\n2. The browser is running\n3. The extension has proper permissions\n\nYou may need to restart OpenCode if the issue persists.`
211
+ })
212
+ }
213
+ }
214
+ } else {
215
+ // Successful execution - ensure we're marked as connected
216
+ if (!connectionState.isConnected) {
217
+ resetConnectionState()
218
+ output.messages = output.messages || []
219
+ output.messages.push({
220
+ role: "assistant",
221
+ content: "[Browser MCP] Connection restored successfully."
222
+ })
223
+ }
224
+ }
51
225
  }
52
226
  },
53
227
 
@@ -93,7 +267,16 @@ The Browser MCP integration has been used in this session. When resuming:
93
267
 
94
268
  // Handle session errors - could help debug browser automation issues
95
269
  if (event.type === "session.error") {
96
- // Session error occurred
270
+ // Check if it's a browser-related error
271
+ const error = (event as any).error
272
+ if (error && isConnectionError(error)) {
273
+ markConnectionFailed(error)
274
+ }
275
+ }
276
+
277
+ // Clean up on session end
278
+ if (event.type === "session.end") {
279
+ stopHealthCheck()
97
280
  }
98
281
  }
99
282
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-browser",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "OpenCode plugin that integrates Browser MCP for browser automation",
5
5
  "type": "module",
6
6
  "main": "index.ts",