Skip to content

无法使用 #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
MarshalT opened this issue Mar 25, 2025 · 3 comments
Open

无法使用 #118

MarshalT opened this issue Mar 25, 2025 · 3 comments

Comments

@MarshalT
Copy link

(base) *******deMacBook-Air ~ % npx @agentdeskai/[email protected]
Attempting initial server discovery on startup...
Starting server discovery process
Will try hosts: 127.0.0.1, 127.0.0.1, localhost
Will try ports: 3025, 3026, 3027, 3028, 3029, 3030, 3031, 3032, 3033, 3034, 3035
Checking 127.0.0.1:3025...
Error checking 127.0.0.1:3025: fetch failed
Checking 127.0.0.1:3026...
Error checking 127.0.0.1:3026: fetch failed
Checking 127.0.0.1:3027...
Error checking 127.0.0.1:3027: fetch failed
Checking 127.0.0.1:3028...
Error checking 127.0.0.1:3028: fetch failed
Checking 127.0.0.1:3029...
Error checking 127.0.0.1:3029: fetch failed
Checking 127.0.0.1:3030...
Error checking 127.0.0.1:3030: fetch failed
Checking 127.0.0.1:3031...
Error checking 127.0.0.1:3031: fetch failed
Checking 127.0.0.1:3032...
Error checking 127.0.0.1:3032: fetch failed
Checking 127.0.0.1:3033...
Error checking 127.0.0.1:3033: fetch failed
Checking 127.0.0.1:3034...
Error checking 127.0.0.1:3034: fetch failed
Checking 127.0.0.1:3035...
Error checking 127.0.0.1:3035: fetch failed
Checking 127.0.0.1:3025...
Error checking 127.0.0.1:3025: fetch failed
Checking 127.0.0.1:3026...
Error checking 127.0.0.1:3026: fetch failed
Checking 127.0.0.1:3027...
Error checking 127.0.0.1:3027: fetch failed
Checking 127.0.0.1:3028...
Error checking 127.0.0.1:3028: fetch failed
Checking 127.0.0.1:3029...
Error checking 127.0.0.1:3029: fetch failed
Checking 127.0.0.1:3030...
Error checking 127.0.0.1:3030: fetch failed
Checking 127.0.0.1:3031...
Error checking 127.0.0.1:3031: fetch failed
Checking 127.0.0.1:3032...
Error checking 127.0.0.1:3032: fetch failed
Checking 127.0.0.1:3033...
Error checking 127.0.0.1:3033: fetch failed
Checking 127.0.0.1:3034...
Error checking 127.0.0.1:3034: fetch failed
Checking 127.0.0.1:3035...
Error checking 127.0.0.1:3035: fetch failed
Checking localhost:3025...
Error checking localhost:3025: fetch failed
Checking localhost:3026...
Error checking localhost:3026: fetch failed
Checking localhost:3027...
Error checking localhost:3027: fetch failed
Checking localhost:3028...
Error checking localhost:3028: fetch failed
Checking localhost:3029...
Error checking localhost:3029: fetch failed
Checking localhost:3030...
Error checking localhost:3030: fetch failed
Checking localhost:3031...
Error checking localhost:3031: fetch failed
Checking localhost:3032...
Error checking localhost:3032: fetch failed
Checking localhost:3033...
Error checking localhost:3033: fetch failed
Checking localhost:3034...
Error checking localhost:3034: fetch failed
Checking localhost:3035...
Error checking localhost:3035: fetch failed
No server found during discovery
Initial server discovery failed. Will try again when tools are used.

@tedjames
Copy link
Contributor

Hey, thanks for sharing! There are three components to run this MCP tool:

  1. Install our chrome extension
  2. Install the MCP server from this command within your IDE (different IDE have different configs but this command is generally a good starting point; please reference your IDEs docs for the proper config setup): npx @agentdeskai/browser-tools-mcp@latest
  3. Open a new terminal and run this command: npx @agentdeskai/browser-tools-server@latest

Do note the difference between:

  • browser-tools-server (local nodejs server that's a middleware for gathering logs)
    and
  • browser-tools-mcp (MCP server that you install into your IDE that communicates w/ the extension + browser-tools-server)

After that, open up your chrome dev tools and then the BrowserToolsMCP panel.

If you're still having issues try these steps:

  • Quit / close down your browser. Not just the window but all of Chrome itself.
  • Restart the local node server (browser-tools-server)
  • Make sure you only have ONE instance of chrome dev tools panel open

After that, it should work but if it doesn't let me know and I can share some more steps to gather logs/info about the issue!

@zxkke
Copy link

zxkke commented Mar 31, 2025

Image

Image

@zxkke
Copy link

zxkke commented Mar 31, 2025

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
// Listen for messages from the devtools panel
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === "GET_CURRENT_URL" && message.tabId) {
getCurrentTabUrl(message.tabId)
.then((url) => {
sendResponse({ success: true, url: url });
})
.catch((error) => {
sendResponse({ success: false, error: error.message });
});
return true; // Required to use sendResponse asynchronously
}

// Handle explicit request to update the server with the URL
if (message.type === "UPDATE_SERVER_URL" && message.tabId && message.url) {
console.log(
Background: Received request to update server with URL for tab ${message.tabId}: ${message.url}
);
updateServerWithUrl(
message.tabId,
message.url,
message.source || "explicit_update"
)
.then(() => {
if (sendResponse) sendResponse({ success: true });
})
.catch((error) => {
console.error("Background: Error updating server with URL:", error);
if (sendResponse)
sendResponse({ success: false, error: error.message });
});
return true; // Required to use sendResponse asynchronously
}

if (message.type === "CAPTURE_SCREENSHOT" && message.tabId) {
// First get the server settings
chrome.storage.local.get(["browserConnectorSettings"], (result) => {
const settings = result.browserConnectorSettings || {
serverHost: "localhost",
serverPort: 3025,
};

  // Validate server identity first
  validateServerIdentity(settings.serverHost, settings.serverPort)
    .then((isValid) => {
      if (!isValid) {
        console.error(
          "Cannot capture screenshot: Not connected to a valid browser tools server"
        );
        sendResponse({
          success: false,
          error:
            "Not connected to a valid browser tools server. Please check your connection settings.",
        });
        return;
      }

      // Continue with screenshot capture
      captureAndSendScreenshot(message, settings, sendResponse);
    })
    .catch((error) => {
      console.error("Error validating server:", error);
      sendResponse({
        success: false,
        error: "Failed to validate server identity: " + error.message,
      });
    });
});
return true; // Required to use sendResponse asynchronously

}
});

// Validate server identity
async function validateServerIdentity(host, port) {
try {
const response = await fetch(http://${host}:${port}/.identity, {
signal: AbortSignal.timeout(3000), // 3 second timeout
});

if (!response.ok) {
  console.error(`Invalid server response: ${response.status}`);
  return false;
}

const identity = await response.json();

// Validate the server signature
if (identity.signature !== "mcp-browser-connector-24x7") {
  console.error("Invalid server signature - not the browser tools server");
  return false;
}

return true;

} catch (error) {
console.error("Error validating server identity:", error);
return false;
}
}

// Helper function to process the tab and run the audit
function processTabForAudit(tab, tabId) {
const url = tab.url;

if (!url) {
console.error(No URL available for tab ${tabId});
return;
}

// Update our cache and the server with this URL
tabUrls.set(tabId, url);
updateServerWithUrl(tabId, url);
}

// Track URLs for each tab
const tabUrls = new Map();

// Function to get the current URL for a tab
async function getCurrentTabUrl(tabId) {
try {
console.log("Background: Getting URL for tab", tabId);

// First check if we have it cached
if (tabUrls.has(tabId)) {
  const cachedUrl = tabUrls.get(tabId);
  console.log("Background: Found cached URL:", cachedUrl);
  return cachedUrl;
}

// Otherwise get it from the tab
try {
  const tab = await chrome.tabs.get(tabId);
  if (tab && tab.url) {
    // Cache the URL
    tabUrls.set(tabId, tab.url);
    console.log("Background: Got URL from tab:", tab.url);
    return tab.url;
  } else {
    console.log("Background: Tab exists but no URL found");
  }
} catch (tabError) {
  console.error("Background: Error getting tab:", tabError);
}

// If we can't get the tab directly, try querying for active tabs
try {
  const tabs = await chrome.tabs.query({
    active: true,
    currentWindow: true,
  });
  if (tabs && tabs.length > 0 && tabs[0].url) {
    const activeUrl = tabs[0].url;
    console.log("Background: Got URL from active tab:", activeUrl);
    // Cache this URL as well
    tabUrls.set(tabId, activeUrl);
    return activeUrl;
  }
} catch (queryError) {
  console.error("Background: Error querying tabs:", queryError);
}

console.log("Background: Could not find URL for tab", tabId);
return null;

} catch (error) {
console.error("Background: Error getting tab URL:", error);
return null;
}
}

// Listen for tab updates to detect page refreshes and URL changes
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
// Track URL changes
if (changeInfo.url) {
console.log(URL changed in tab ${tabId} to ${changeInfo.url});
tabUrls.set(tabId, changeInfo.url);

// Send URL update to server if possible
updateServerWithUrl(tabId, changeInfo.url, "tab_url_change");

}

// Check if this is a page refresh (status becoming "complete")
if (changeInfo.status === "complete") {
// Update URL in our cache
if (tab.url) {
tabUrls.set(tabId, tab.url);
// Send URL update to server if possible
updateServerWithUrl(tabId, tab.url, "page_complete");
}

retestConnectionOnRefresh(tabId);

}
});

// Listen for tab activation (switching between tabs)
chrome.tabs.onActivated.addListener((activeInfo) => {
const tabId = activeInfo.tabId;
console.log(Tab activated: ${tabId});

// Get the URL of the newly activated tab
chrome.tabs.get(tabId, (tab) => {
if (chrome.runtime.lastError) {
console.error("Error getting tab info:", chrome.runtime.lastError);
return;
}

if (tab && tab.url) {
  console.log(`Active tab changed to ${tab.url}`);

  // Update our cache
  tabUrls.set(tabId, tab.url);

  // Send URL update to server
  updateServerWithUrl(tabId, tab.url, "tab_activated");
}

});
});

// Function to update the server with the current URL
async function updateServerWithUrl(tabId, url, source = "background_update") {
if (!url) {
console.error("Cannot update server with empty URL");
return;
}

console.log(Updating server with URL for tab ${tabId}: ${url});

// Get the saved settings
chrome.storage.local.get(["browserConnectorSettings"], async (result) => {
const settings = result.browserConnectorSettings || {
serverHost: "localhost",
serverPort: 3025,
};

// Maximum number of retry attempts
const maxRetries = 3;
let retryCount = 0;
let success = false;

while (retryCount < maxRetries && !success) {
  try {
    // Send the URL to the server
    const serverUrl = `http://${settings.serverHost}:${settings.serverPort}/current-url`;
    console.log(
      `Attempt ${
        retryCount + 1
      }/${maxRetries} to update server with URL: ${url}`
    );

    const response = await fetch(serverUrl, {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        url: url,
        tabId: tabId,
        timestamp: Date.now(),
        source: source,
      }),
      // Add a timeout to prevent hanging requests
      signal: AbortSignal.timeout(5000),
    });

    if (response.ok) {
      const responseData = await response.json();
      console.log(
        `Successfully updated server with URL: ${url}`,
        responseData
      );
      success = true;
    } else {
      console.error(
        `Server returned error: ${response.status} ${response.statusText}`
      );
      retryCount++;
      // Wait before retrying
      await new Promise((resolve) => setTimeout(resolve, 500));
    }
  } catch (error) {
    console.error(`Error updating server with URL: ${error.message}`);
    retryCount++;
    // Wait before retrying
    await new Promise((resolve) => setTimeout(resolve, 500));
  }
}

if (!success) {
  console.error(
    `Failed to update server with URL after ${maxRetries} attempts`
  );
}

});
}

// Clean up when tabs are closed
chrome.tabs.onRemoved.addListener((tabId) => {
tabUrls.delete(tabId);
});

// Function to retest connection when a page is refreshed
async function retestConnectionOnRefresh(tabId) {
console.log(Page refreshed in tab ${tabId}, retesting connection...);

// Get the saved settings
chrome.storage.local.get(["browserConnectorSettings"], async (result) => {
const settings = result.browserConnectorSettings || {
serverHost: "localhost",
serverPort: 3025,
};

// Test the connection with the last known host and port
const isConnected = await validateServerIdentity(
  settings.serverHost,
  settings.serverPort
);

// Notify all devtools instances about the connection status
chrome.runtime.sendMessage({
  type: "CONNECTION_STATUS_UPDATE",
  isConnected: isConnected,
  tabId: tabId,
});

// Always notify for page refresh, whether connected or not
// This ensures any ongoing discovery is cancelled and restarted
chrome.runtime.sendMessage({
  type: "INITIATE_AUTO_DISCOVERY",
  reason: "page_refresh",
  tabId: tabId,
  forceRestart: true, // Add a flag to indicate this should force restart any ongoing processes
});

if (!isConnected) {
  console.log(
    "Connection test failed after page refresh, initiating auto-discovery..."
  );
} else {
  console.log("Connection test successful after page refresh");
}

});
}

// Function to capture and send screenshot
function captureAndSendScreenshot(message, settings, sendResponse) {
// Get the inspected window's tab
chrome.tabs.get(message.tabId, (tab) => {
if (chrome.runtime.lastError) {
console.error("Error getting tab:", chrome.runtime.lastError);
sendResponse({
success: false,
error: chrome.runtime.lastError.message,
});
return;
}

// Get all windows to find the one containing our tab
chrome.windows.getAll({ populate: true }, (windows) => {
  const targetWindow = windows.find((w) =>
    w.tabs.some((t) => t.id === message.tabId)
  );

  if (!targetWindow) {
    console.error("Could not find window containing the inspected tab");
    sendResponse({
      success: false,
      error: "Could not find window containing the inspected tab",
    });
    return;
  }

  // Capture screenshot of the window containing our tab
  chrome.tabs.captureVisibleTab(
    targetWindow.id,
    { format: "png" },
    (dataUrl) => {
      // Ignore DevTools panel capture error if it occurs
      if (
        chrome.runtime.lastError &&
        !chrome.runtime.lastError.message.includes("devtools://")
      ) {
        console.error(
          "Error capturing screenshot:",
          chrome.runtime.lastError
        );
        sendResponse({
          success: false,
          error: chrome.runtime.lastError.message,
        });
        return;
      }

      // Send screenshot data to browser connector using configured settings
      const serverUrl = `http://${settings.serverHost}:${settings.serverPort}/screenshot`;
      console.log(`Sending screenshot to ${serverUrl}`);

      fetch(serverUrl, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          data: dataUrl,
          path: message.screenshotPath,
        }),
      })
        .then((response) => response.json())
        .then((result) => {
          if (result.error) {
            console.error("Error from server:", result.error);
            sendResponse({ success: false, error: result.error });
          } else {
            console.log("Screenshot saved successfully:", result.path);
            // Send success response even if DevTools capture failed
            sendResponse({
              success: true,
              path: result.path,
              title: tab.title || "Current Tab",
            });
          }
        })
        .catch((error) => {
          console.error("Error sending screenshot data:", error);
          sendResponse({
            success: false,
            error: error.message || "Failed to save screenshot",
          });
        });
    }
  );
});

});
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants