mcpbrowser 0.3.44 → 0.3.45

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 (41) hide show
  1. package/README.md +34 -34
  2. package/package.json +1 -1
  3. package/src/actions/accept-eula.js +5 -5
  4. package/src/actions/click-element.js +25 -25
  5. package/src/actions/close-tab.js +8 -8
  6. package/src/actions/execute-javascript.js +9 -9
  7. package/src/actions/fetch-page.js +15 -15
  8. package/src/actions/get-current-html.js +16 -16
  9. package/src/actions/navigate-history.js +21 -21
  10. package/src/actions/plugin-action.js +15 -15
  11. package/src/actions/plugin-info.js +10 -10
  12. package/src/actions/scroll-page.js +21 -21
  13. package/src/actions/take-screenshot.js +16 -16
  14. package/src/actions/type-text.js +28 -28
  15. package/src/cli/help.js +1 -1
  16. package/src/core/logger.js +51 -2
  17. package/src/core/plugin-loader.js +2 -2
  18. package/src/core/responses.js +4 -4
  19. package/src/mcp-browser.js +20 -12
  20. package/src/plugins/_example/index.js +2 -2
  21. package/src/plugins/gcal/actions/check-availability.js +1 -1
  22. package/src/plugins/gcal/actions/create-event.js +1 -1
  23. package/src/plugins/gcal/actions/delete-event.js +1 -1
  24. package/src/plugins/gcal/actions/edit-event.js +1 -1
  25. package/src/plugins/gcal/actions/list-events.js +1 -1
  26. package/src/plugins/gcal/actions/read-event.js +1 -1
  27. package/src/plugins/gcal/actions/rsvp-event.js +1 -1
  28. package/src/plugins/gcal/actions/search-events.js +1 -1
  29. package/src/plugins/gcal/helpers.js +2 -2
  30. package/src/plugins/gmail/actions/archive-email.js +1 -1
  31. package/src/plugins/gmail/actions/compose-email.js +1 -1
  32. package/src/plugins/gmail/actions/delete-email.js +1 -1
  33. package/src/plugins/gmail/actions/forward-email.js +1 -1
  34. package/src/plugins/gmail/actions/label-email.js +1 -1
  35. package/src/plugins/gmail/actions/list-emails.js +1 -1
  36. package/src/plugins/gmail/actions/mark-read.js +1 -1
  37. package/src/plugins/gmail/actions/mark-unread.js +1 -1
  38. package/src/plugins/gmail/actions/read-email.js +1 -1
  39. package/src/plugins/gmail/actions/reply-email.js +1 -1
  40. package/src/plugins/gmail/actions/search-emails.js +1 -1
  41. package/src/plugins/gmail/helpers.js +3 -3
@@ -17,7 +17,7 @@ import { getPluginNextSteps, getRecommendedPlugins } from '../core/plugin-loader
17
17
  // ============================================================================
18
18
 
19
19
  /**
20
- * Response for successful get_current_html operations
20
+ * Response for successful browser_get_current_html operations
21
21
  */
22
22
  export class GetCurrentHtmlSuccessResponse extends MCPResponse {
23
23
  /**
@@ -62,9 +62,9 @@ export class GetCurrentHtmlSuccessResponse extends MCPResponse {
62
62
  * @type {Tool}
63
63
  */
64
64
  export const GET_CURRENT_HTML_TOOL = {
65
- name: "get_current_html",
65
+ name: "browser_get_current_html",
66
66
  title: "Get Current HTML",
67
- description: "**BROWSER STATE EXTRACTION** - Retrieves current HTML from an already-loaded page WITHOUT navigating/reloading. Use this to check page state after interactions (click, type) or to re-examine the current page. Much faster than fetch_webpage since it only extracts HTML from the current page state.\n\n**PREREQUISITE**: Page MUST be loaded with fetch_webpage first. This tool reads from an already-loaded page in the browser.",
67
+ description: "**BROWSER STATE EXTRACTION** - Retrieves current HTML from an already-loaded page WITHOUT navigating/reloading. Use this to check page state after interactions (click, type) or to re-examine the current page. Much faster than browser_fetch_webpage since it only extracts HTML from the current page state.\n\n**PREREQUISITE**: Page MUST be loaded with browser_fetch_webpage first. This tool reads from an already-loaded page in the browser.",
68
68
  inputSchema: {
69
69
  type: "object",
70
70
  properties: {
@@ -109,7 +109,7 @@ export const GET_CURRENT_HTML_TOOL = {
109
109
  */
110
110
  export async function getCurrentHtml({ url, removeUnnecessaryHTML = true }) {
111
111
  const startTime = Date.now();
112
- logger.info(`get_current_html called: url=${url}`);
112
+ logger.info(`browser_get_current_html called: url=${url}`);
113
113
 
114
114
  if (!url) {
115
115
  throw new Error("url parameter is required");
@@ -126,7 +126,7 @@ export async function getCurrentHtml({ url, removeUnnecessaryHTML = true }) {
126
126
  try {
127
127
  await getBrowser();
128
128
  } catch (err) {
129
- logger.error(`get_current_html: Failed to connect to browser: ${err.message}`);
129
+ logger.error(`browser_get_current_html: Failed to connect to browser: ${err.message}`);
130
130
  return new InformationalResponse(
131
131
  `Browser connection failed: ${err.message}`,
132
132
  'The browser must be running with remote debugging enabled.',
@@ -143,15 +143,15 @@ export async function getCurrentHtml({ url, removeUnnecessaryHTML = true }) {
143
143
 
144
144
  if (!page) {
145
145
  const isConnectionLost = pageError && pageError.includes('connection');
146
- logger.debug(`get_current_html: ${pageError || 'No page found for ' + hostname}`);
146
+ logger.debug(`browser_get_current_html: ${pageError || 'No page found for ' + hostname}`);
147
147
  return new InformationalResponse(
148
148
  isConnectionLost ? `Page connection lost for ${hostname}` : `No open page found for ${hostname}`,
149
149
  isConnectionLost
150
150
  ? 'The browser tab was closed or the connection was lost. The page needs to be reloaded.'
151
151
  : 'The page must be loaded before you can get its current HTML',
152
152
  [
153
- "Use MCPBrowser's fetch_webpage tool to load the page first",
154
- "Then retry MCPBrowser's get_current_html with the same URL"
153
+ "Use MCPBrowser's browser_fetch_webpage tool to load the page first",
154
+ "Then retry MCPBrowser's browser_get_current_html with the same URL"
155
155
  ]
156
156
  );
157
157
  }
@@ -160,28 +160,28 @@ export async function getCurrentHtml({ url, removeUnnecessaryHTML = true }) {
160
160
  const currentUrl = page.url();
161
161
  const html = await extractAndProcessHtml(page, removeUnnecessaryHTML);
162
162
 
163
- logger.info(`get_current_html completed: got HTML from ${currentUrl}`);
163
+ logger.info(`browser_get_current_html completed: got HTML from ${currentUrl}`);
164
164
 
165
165
  return new GetCurrentHtmlSuccessResponse(
166
166
  currentUrl,
167
167
  html,
168
168
  [
169
169
  ...getPluginNextSteps(currentUrl, html),
170
- "Use MCPBrowser's click_element to interact with elements",
171
- "Use MCPBrowser's type_text to fill forms",
172
- "Use MCPBrowser's take_screenshot if page layout or visual content is hard to understand from HTML",
173
- "Use MCPBrowser's close_tab to free resources when done"
170
+ "Use MCPBrowser's browser_click_element to interact with elements",
171
+ "Use MCPBrowser's browser_type_text to fill forms",
172
+ "Use MCPBrowser's browser_take_screenshot if page layout or visual content is hard to understand from HTML",
173
+ "Use MCPBrowser's browser_close_tab to free resources when done"
174
174
  ],
175
175
  getRecommendedPlugins(currentUrl, html)
176
176
  );
177
177
  } catch (err) {
178
- logger.error(`get_current_html failed: ${err.message}`);
178
+ logger.error(`browser_get_current_html failed: ${err.message}`);
179
179
  return new InformationalResponse(
180
180
  `Failed to get HTML: ${err.message}`,
181
181
  'Could not extract HTML from the page. The page may have navigated away or the connection was lost.',
182
182
  [
183
- "Try MCPBrowser's fetch_webpage to reload the page",
184
- "Use MCPBrowser's close_tab and start fresh if needed"
183
+ "Try MCPBrowser's browser_fetch_webpage to reload the page",
184
+ "Use MCPBrowser's browser_close_tab and start fresh if needed"
185
185
  ]
186
186
  );
187
187
  }
@@ -17,7 +17,7 @@ import logger from '../core/logger.js';
17
17
  // ============================================================================
18
18
 
19
19
  /**
20
- * Response for successful navigate_history operations
20
+ * Response for successful browser_navigate_history operations
21
21
  */
22
22
  export class NavigateHistorySuccessResponse extends MCPResponse {
23
23
  /**
@@ -69,9 +69,9 @@ export class NavigateHistorySuccessResponse extends MCPResponse {
69
69
 
70
70
  /** @type {Tool} */
71
71
  export const NAVIGATE_HISTORY_TOOL = {
72
- name: "navigate_history",
72
+ name: "browser_navigate_history",
73
73
  title: "Navigate Back/Forward",
74
- description: "**BROWSER HISTORY NAVIGATION** - Navigate back or forward in browser history on an already-loaded page. Use after clicking links to return to the previous page, or to go forward after going back.\n\n**PREREQUISITE**: Page MUST be loaded with fetch_webpage first. This tool navigates the history of an existing browser tab.",
74
+ description: "**BROWSER HISTORY NAVIGATION** - Navigate back or forward in browser history on an already-loaded page. Use after clicking links to return to the previous page, or to go forward after going back.\n\n**PREREQUISITE**: Page MUST be loaded with browser_fetch_webpage first. This tool navigates the history of an existing browser tab.",
75
75
  inputSchema: {
76
76
  type: "object",
77
77
  properties: {
@@ -126,7 +126,7 @@ export const NAVIGATE_HISTORY_TOOL = {
126
126
  * @returns {Promise<MCPResponse>} Navigation result
127
127
  */
128
128
  export async function navigateHistory({ url, direction = 'back', returnHtml = true, removeUnnecessaryHTML = true }) {
129
- logger.info(`navigate_history called: url=${url}, direction=${direction}`);
129
+ logger.info(`browser_navigate_history called: url=${url}, direction=${direction}`);
130
130
 
131
131
  if (!url) {
132
132
  throw new Error("url parameter is required");
@@ -143,7 +143,7 @@ export async function navigateHistory({ url, direction = 'back', returnHtml = tr
143
143
  try {
144
144
  await getBrowser();
145
145
  } catch (err) {
146
- logger.error(`navigate_history: Failed to connect to browser: ${err.message}`);
146
+ logger.error(`browser_navigate_history: Failed to connect to browser: ${err.message}`);
147
147
  return new InformationalResponse(
148
148
  `Browser connection failed: ${err.message}`,
149
149
  'The browser must be running with remote debugging enabled.',
@@ -160,15 +160,15 @@ export async function navigateHistory({ url, direction = 'back', returnHtml = tr
160
160
 
161
161
  if (!page) {
162
162
  const isConnectionLost = pageError && pageError.includes('connection');
163
- logger.debug(`navigate_history: ${pageError || 'No page found for ' + hostname}`);
163
+ logger.debug(`browser_navigate_history: ${pageError || 'No page found for ' + hostname}`);
164
164
  return new InformationalResponse(
165
165
  isConnectionLost ? `Page connection lost for ${hostname}` : `No open page found for ${hostname}`,
166
166
  isConnectionLost
167
167
  ? 'The browser tab was closed or the connection was lost. The page needs to be reloaded.'
168
168
  : 'The page must be loaded before you can navigate its history.',
169
169
  [
170
- "Use MCPBrowser's fetch_webpage tool to load the page first",
171
- "Then retry MCPBrowser's navigate_history with the same URL"
170
+ "Use MCPBrowser's browser_fetch_webpage tool to load the page first",
171
+ "Then retry MCPBrowser's browser_navigate_history with the same URL"
172
172
  ]
173
173
  );
174
174
  }
@@ -186,15 +186,15 @@ export async function navigateHistory({ url, direction = 'back', returnHtml = tr
186
186
 
187
187
  // goBack/goForward return null if there's no history entry
188
188
  if (response === null) {
189
- logger.info(`navigate_history: No ${direction} history entry available`);
189
+ logger.info(`browser_navigate_history: No ${direction} history entry available`);
190
190
  return new InformationalResponse(
191
191
  `No ${direction} history entry available`,
192
192
  `The page has no ${direction} history to navigate to. This means you're already at the ${direction === 'back' ? 'first' : 'last'} page in the browsing history for this tab.`,
193
193
  [
194
194
  direction === 'back'
195
- ? "Use MCPBrowser's fetch_webpage to navigate to a different URL"
196
- : "Use MCPBrowser's navigate_history with direction='back' to go back instead",
197
- "Use MCPBrowser's get_current_html to check the current page content"
195
+ ? "Use MCPBrowser's browser_fetch_webpage to navigate to a different URL"
196
+ : "Use MCPBrowser's browser_navigate_history with direction='back' to go back instead",
197
+ "Use MCPBrowser's browser_get_current_html to check the current page content"
198
198
  ]
199
199
  );
200
200
  }
@@ -207,7 +207,7 @@ export async function navigateHistory({ url, direction = 'back', returnHtml = tr
207
207
  if (newHostname !== hostname) {
208
208
  domainPages.delete(hostname);
209
209
  domainPages.set(newHostname, page);
210
- logger.info(`navigate_history: Updated domainPages mapping: ${hostname} → ${newHostname}`);
210
+ logger.info(`browser_navigate_history: Updated domainPages mapping: ${hostname} → ${newHostname}`);
211
211
  }
212
212
  } catch {
213
213
  // If URL parsing fails, keep existing mapping
@@ -220,7 +220,7 @@ export async function navigateHistory({ url, direction = 'back', returnHtml = tr
220
220
  html = await extractAndProcessHtml(page, removeUnnecessaryHTML);
221
221
  }
222
222
 
223
- logger.info(`navigate_history completed: ${direction} from ${previousUrl} to ${currentUrl}`);
223
+ logger.info(`browser_navigate_history completed: ${direction} from ${previousUrl} to ${currentUrl}`);
224
224
 
225
225
  return new NavigateHistorySuccessResponse(
226
226
  direction,
@@ -228,20 +228,20 @@ export async function navigateHistory({ url, direction = 'back', returnHtml = tr
228
228
  currentUrl,
229
229
  html,
230
230
  [
231
- "Use MCPBrowser's navigate_history to go back or forward again",
232
- "Use MCPBrowser's click_element to interact with elements on the page",
233
- "Use MCPBrowser's get_current_html to re-read the page content",
234
- "Use MCPBrowser's fetch_webpage to navigate to a new URL"
231
+ "Use MCPBrowser's browser_navigate_history to go back or forward again",
232
+ "Use MCPBrowser's browser_click_element to interact with elements on the page",
233
+ "Use MCPBrowser's browser_get_current_html to re-read the page content",
234
+ "Use MCPBrowser's browser_fetch_webpage to navigate to a new URL"
235
235
  ]
236
236
  );
237
237
  } catch (err) {
238
- logger.error(`navigate_history failed: ${err.message}`);
238
+ logger.error(`browser_navigate_history failed: ${err.message}`);
239
239
  return new InformationalResponse(
240
240
  `Navigation ${direction} failed: ${err.message}`,
241
241
  'The browser could not navigate. The page may have been closed or the connection was lost.',
242
242
  [
243
- "Try MCPBrowser's fetch_webpage to reload the page",
244
- "Use MCPBrowser's close_tab and start fresh if needed"
243
+ "Try MCPBrowser's browser_fetch_webpage to reload the page",
244
+ "Use MCPBrowser's browser_close_tab and start fresh if needed"
245
245
  ]
246
246
  );
247
247
  }
@@ -2,7 +2,7 @@
2
2
  * plugin-action.js — MCP tool that dispatches to a plugin's action.
3
3
  * Looks up the plugin by name, finds the action, provides the browser
4
4
  * page object, and calls the action's execute function.
5
- * Part of the plugin dispatch pair (plugin_info + plugin_action).
5
+ * Part of the plugin dispatch pair (browser_plugin_info + browser_plugin_action).
6
6
  */
7
7
 
8
8
  import { MCPResponse, ErrorResponse } from '../core/responses.js';
@@ -36,9 +36,9 @@ export class PluginActionSuccessResponse extends MCPResponse {
36
36
 
37
37
  /** @type {Tool} */
38
38
  export const PLUGIN_ACTION_TOOL = {
39
- name: "plugin_action",
39
+ name: "browser_plugin_action",
40
40
  title: "Plugin Action",
41
- description: "Execute a site-specific plugin action. Use plugin_info first to discover available actions and their parameters. Plugins provide specialized automation for UI-heavy websites like Gmail, Outlook, PowerBI, AWS, and Azure — faster and more reliable than generic DOM interaction.",
41
+ description: "Execute a site-specific plugin action. Use browser_plugin_info first to discover available actions and their parameters. Plugins provide specialized automation for UI-heavy websites like Gmail, Outlook, PowerBI, AWS, and Azure — faster and more reliable than generic DOM interaction.",
42
42
  inputSchema: {
43
43
  type: "object",
44
44
  properties: {
@@ -52,7 +52,7 @@ export const PLUGIN_ACTION_TOOL = {
52
52
  },
53
53
  params: {
54
54
  type: "object",
55
- description: "Action parameters. Use plugin_info to discover accepted parameters.",
55
+ description: "Action parameters. Use browser_plugin_info to discover accepted parameters.",
56
56
  additionalProperties: true
57
57
  }
58
58
  },
@@ -86,7 +86,7 @@ export const PLUGIN_ACTION_TOOL = {
86
86
  * @returns {Promise<MCPResponse>}
87
87
  */
88
88
  export async function pluginAction({ plugin: pluginName, action: actionName, params = {} }) {
89
- logger.info(`plugin_action called: plugin=${pluginName} action=${actionName}`);
89
+ logger.info(`browser_plugin_action called: plugin=${pluginName} action=${actionName}`);
90
90
 
91
91
  const loadedPlugins = getLoadedPlugins();
92
92
 
@@ -96,7 +96,7 @@ export async function pluginAction({ plugin: pluginName, action: actionName, par
96
96
  const available = [...loadedPlugins.keys()].join(', ') || '(none)';
97
97
  return new ErrorResponse(
98
98
  `Unknown plugin: '${pluginName}'. Available plugins: ${available}`,
99
- ["Call plugin_info() to list all loaded plugins"]
99
+ ["Call browser_plugin_info() to list all loaded plugins"]
100
100
  );
101
101
  }
102
102
 
@@ -107,7 +107,7 @@ export async function pluginAction({ plugin: pluginName, action: actionName, par
107
107
  const validActions = actions.map(a => a.name).join(', ');
108
108
  return new ErrorResponse(
109
109
  `Unknown action '${actionName}' for plugin '${pluginName}'. Available actions: ${validActions}`,
110
- [`Call plugin_info({ plugin: '${pluginName}' }) to see all available actions and their parameters`]
110
+ [`Call browser_plugin_info({ plugin: '${pluginName}' }) to see all available actions and their parameters`]
111
111
  );
112
112
  }
113
113
 
@@ -136,17 +136,17 @@ export async function pluginAction({ plugin: pluginName, action: actionName, par
136
136
  if (!matchedPage) {
137
137
  const targetPatterns = pluginInstance.manifest.urlPatterns.join(', ');
138
138
  return new ErrorResponse(
139
- `Plugin '${pluginName}' requires ${targetPatterns} but no matching page is open. Use fetch_webpage to navigate to the correct site first.`,
140
- [`Use MCPBrowser's fetch_webpage to navigate to a page matching: ${targetPatterns}`, `Then retry plugin_action`]
139
+ `Plugin '${pluginName}' requires ${targetPatterns} but no matching page is open. Use browser_fetch_webpage to navigate to the correct site first.`,
140
+ [`Use MCPBrowser's browser_fetch_webpage to navigate to a page matching: ${targetPatterns}`, `Then retry browser_plugin_action`]
141
141
  );
142
142
  }
143
143
 
144
144
  page = matchedPage;
145
145
  } catch (err) {
146
- logger.error(`plugin_action: browser error — ${err.message}`);
146
+ logger.error(`browser_plugin_action: browser error — ${err.message}`);
147
147
  return new ErrorResponse(
148
148
  `Browser connection failed: ${err.message}`,
149
- ["Ensure the browser is running with remote debugging enabled", "Retry plugin_action after browser is connected"]
149
+ ["Ensure the browser is running with remote debugging enabled", "Retry browser_plugin_action after browser is connected"]
150
150
  );
151
151
  }
152
152
 
@@ -164,15 +164,15 @@ export async function pluginAction({ plugin: pluginName, action: actionName, par
164
164
  pluginName,
165
165
  actionName,
166
166
  result,
167
- [`Use plugin_info({ plugin: '${pluginName}' }) to see other available actions`]
167
+ [`Use browser_plugin_info({ plugin: '${pluginName}' }) to see other available actions`]
168
168
  );
169
169
  } catch (err) {
170
- logger.error(`plugin_action: "${pluginName}/${actionName}" failed — ${err.message}`);
170
+ logger.error(`browser_plugin_action: "${pluginName}/${actionName}" failed — ${err.message}`);
171
171
  return new ErrorResponse(
172
- `Plugin '${pluginName}' action '${actionName}' failed: ${err.message}. The site structure may have changed. You can fall back to generic MCPBrowser tools (click_element, get_current_html).`,
172
+ `Plugin '${pluginName}' action '${actionName}' failed: ${err.message}. The site structure may have changed. You can fall back to generic MCPBrowser tools (browser_click_element, browser_get_current_html).`,
173
173
  [
174
174
  "Check if the page is on the correct site",
175
- "Try MCPBrowser's get_current_html to inspect the page state",
175
+ "Try MCPBrowser's browser_get_current_html to inspect the page state",
176
176
  "Use generic MCPBrowser tools as a fallback"
177
177
  ]
178
178
  );
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * plugin-info.js — MCP tool that returns information about installed plugins,
3
3
  * their available actions, parameters, and high-level site context.
4
- * Part of the plugin dispatch pair (plugin_info + plugin_action).
4
+ * Part of the plugin dispatch pair (browser_plugin_info + browser_plugin_action).
5
5
  */
6
6
 
7
7
  import { MCPResponse, ErrorResponse } from '../core/responses.js';
@@ -53,9 +53,9 @@ export class PluginActionDetailResponse extends MCPResponse {
53
53
 
54
54
  /** @type {Tool} */
55
55
  export const PLUGIN_INFO_TOOL = {
56
- name: "plugin_info",
56
+ name: "browser_plugin_info",
57
57
  title: "Plugin Info",
58
- description: "Get information about an installed site plugin — its available actions, parameters, and site context. Call this after a plugin is detected (recommended in nextSteps) to discover what actions you can perform via plugin_action. You can also call with no arguments to list all loaded plugins.",
58
+ description: "Get information about an installed site plugin — its available actions, parameters, and site context. Call this after a plugin is detected (recommended in nextSteps) to discover what actions you can perform via browser_plugin_action. You can also call with no arguments to list all loaded plugins.",
59
59
  inputSchema: {
60
60
  type: "object",
61
61
  properties: {
@@ -96,7 +96,7 @@ export const PLUGIN_INFO_TOOL = {
96
96
  * @returns {MCPResponse}
97
97
  */
98
98
  export function pluginInfo({ plugin, action } = {}) {
99
- logger.info(`plugin_info called: plugin=${plugin || '(all)'} action=${action || '(all)'}`);
99
+ logger.info(`browser_plugin_info called: plugin=${plugin || '(all)'} action=${action || '(all)'}`);
100
100
 
101
101
  const loadedPlugins = getLoadedPlugins();
102
102
 
@@ -112,7 +112,7 @@ export function pluginInfo({ plugin, action } = {}) {
112
112
  }
113
113
 
114
114
  const nextSteps = plugins.length > 0
115
- ? plugins.map(p => `Call plugin_info({ plugin: '${p.name}' }) to see ${p.name}'s available actions`)
115
+ ? plugins.map(p => `Call browser_plugin_info({ plugin: '${p.name}' }) to see ${p.name}'s available actions`)
116
116
  : ["No plugins are currently loaded. Add plugin names to plugins.json and restart the server."];
117
117
 
118
118
  return new PluginListResponse(plugins, nextSteps);
@@ -125,7 +125,7 @@ export function pluginInfo({ plugin, action } = {}) {
125
125
  return new ErrorResponse(
126
126
  `Unknown plugin: '${plugin}'. Available plugins: ${available}`,
127
127
  loadedPlugins.size > 0
128
- ? [`Call plugin_info() with no arguments to list all plugins`]
128
+ ? [`Call browser_plugin_info() with no arguments to list all plugins`]
129
129
  : ["No plugins are currently loaded. Add plugin names to plugins.json and restart the server."]
130
130
  );
131
131
  }
@@ -138,14 +138,14 @@ export function pluginInfo({ plugin, action } = {}) {
138
138
  const validActions = actions.map(a => a.name).join(', ');
139
139
  return new ErrorResponse(
140
140
  `Unknown action '${action}' for plugin '${plugin}'. Available actions: ${validActions}`,
141
- [`Call plugin_info({ plugin: '${plugin}' }) to see all available actions`]
141
+ [`Call browser_plugin_info({ plugin: '${plugin}' }) to see all available actions`]
142
142
  );
143
143
  }
144
144
 
145
145
  return new PluginActionDetailResponse(
146
146
  plugin,
147
147
  { name: actionDef.name, description: actionDef.description, params: actionDef.params },
148
- [`Call plugin_action({ plugin: '${plugin}', action: '${action}', params: { ... } })`]
148
+ [`Call browser_plugin_action({ plugin: '${plugin}', action: '${action}', params: { ... } })`]
149
149
  );
150
150
  }
151
151
 
@@ -161,9 +161,9 @@ export function pluginInfo({ plugin, action } = {}) {
161
161
 
162
162
  const nextSteps = [
163
163
  ...(info.actions || []).slice(0, 3).map(a =>
164
- `Use plugin_action({ plugin: '${plugin}', action: '${a.name}' }) to ${a.description.toLowerCase()}`
164
+ `Use browser_plugin_action({ plugin: '${plugin}', action: '${a.name}' }) to ${a.description.toLowerCase()}`
165
165
  ),
166
- "Use fetch_webpage to navigate to the target site first if not already there"
166
+ "Use browser_fetch_webpage to navigate to the target site first if not already there"
167
167
  ];
168
168
 
169
169
  return new PluginInfoResponse(pluginDetail, nextSteps);
@@ -16,7 +16,7 @@ import logger from '../core/logger.js';
16
16
  // ============================================================================
17
17
 
18
18
  /**
19
- * Response for successful scroll_page operations
19
+ * Response for successful browser_scroll_page operations
20
20
  * Returns scroll result with new scroll position
21
21
  */
22
22
  export class ScrollPageSuccessResponse extends MCPResponse {
@@ -92,9 +92,9 @@ export class ScrollPageSuccessResponse extends MCPResponse {
92
92
  * @type {Tool}
93
93
  */
94
94
  export const SCROLL_PAGE_TOOL = {
95
- name: "scroll_page",
95
+ name: "browser_scroll_page",
96
96
  title: "Scroll Page",
97
- description: "**PAGE NAVIGATION** - Scrolls within an already-loaded page. Use before take_screenshot to capture different parts of the page, or to bring elements into view before interaction.\n\n**PREREQUISITE**: Page MUST be loaded with fetch_webpage first.\n\n**SCROLL MODES**:\n- By direction: Scroll up/down/left/right by pixel amount\n- To element: Scroll until a specific element is visible\n- To position: Scroll to absolute coordinates",
97
+ description: "**PAGE NAVIGATION** - Scrolls within an already-loaded page. Use before browser_take_screenshot to capture different parts of the page, or to bring elements into view before interaction.\n\n**PREREQUISITE**: Page MUST be loaded with browser_fetch_webpage first.\n\n**SCROLL MODES**:\n- By direction: Scroll up/down/left/right by pixel amount\n- To element: Scroll until a specific element is visible\n- To position: Scroll to absolute coordinates",
98
98
  inputSchema: {
99
99
  type: "object",
100
100
  properties: {
@@ -166,7 +166,7 @@ export const SCROLL_PAGE_TOOL = {
166
166
  * @returns {Promise<Object>} Result object with scroll position data
167
167
  */
168
168
  export async function scrollPage({ url, direction, amount = 500, selector, x, y }) {
169
- logger.info(`scroll_page called: url=${url}, direction=${direction}, amount=${amount}, selector=${selector}, x=${x}, y=${y}`);
169
+ logger.info(`browser_scroll_page called: url=${url}, direction=${direction}, amount=${amount}, selector=${selector}, x=${x}, y=${y}`);
170
170
 
171
171
  if (!url) {
172
172
  throw new Error("url parameter is required");
@@ -183,7 +183,7 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
183
183
  try {
184
184
  await getBrowser();
185
185
  } catch (err) {
186
- logger.error(`scroll_page: Failed to connect to browser: ${err.message}`);
186
+ logger.error(`browser_scroll_page: Failed to connect to browser: ${err.message}`);
187
187
  return new InformationalResponse(
188
188
  `Browser connection failed: ${err.message}`,
189
189
  'The browser must be running with remote debugging enabled.',
@@ -200,15 +200,15 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
200
200
 
201
201
  if (!page) {
202
202
  const isConnectionLost = pageError && pageError.includes('connection');
203
- logger.debug(`scroll_page: ${pageError || 'No page found for ' + hostname}`);
203
+ logger.debug(`browser_scroll_page: ${pageError || 'No page found for ' + hostname}`);
204
204
  return new InformationalResponse(
205
205
  isConnectionLost ? `Page connection lost for ${hostname}` : `No open page found for ${hostname}`,
206
206
  isConnectionLost
207
207
  ? 'The browser tab was closed or the connection was lost. The page needs to be reloaded.'
208
208
  : 'The page must be loaded before you can scroll',
209
209
  [
210
- "Use MCPBrowser's fetch_webpage tool to load the page first",
211
- "Then retry MCPBrowser's scroll_page with the same URL"
210
+ "Use MCPBrowser's browser_fetch_webpage tool to load the page first",
211
+ "Then retry MCPBrowser's browser_scroll_page with the same URL"
212
212
  ]
213
213
  );
214
214
  }
@@ -219,7 +219,7 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
219
219
  // Determine scroll mode and execute
220
220
  if (selector) {
221
221
  // Scroll to element mode
222
- logger.debug(`scroll_page: Scrolling to element: ${selector}`);
222
+ logger.debug(`browser_scroll_page: Scrolling to element: ${selector}`);
223
223
 
224
224
  const elementExists = await page.$(selector);
225
225
  if (!elementExists) {
@@ -227,7 +227,7 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
227
227
  `Element not found: ${selector}`,
228
228
  'The specified CSS selector did not match any element on the page.',
229
229
  [
230
- "Use MCPBrowser's get_current_html to inspect the page structure",
230
+ "Use MCPBrowser's browser_get_current_html to inspect the page structure",
231
231
  "Verify the CSS selector is correct",
232
232
  "Try a different selector"
233
233
  ]
@@ -243,7 +243,7 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
243
243
 
244
244
  } else if (typeof x === 'number' && typeof y === 'number') {
245
245
  // Absolute position mode
246
- logger.debug(`scroll_page: Scrolling to absolute position: (${x}, ${y})`);
246
+ logger.debug(`browser_scroll_page: Scrolling to absolute position: (${x}, ${y})`);
247
247
 
248
248
  await page.evaluate(({ scrollX, scrollY }) => {
249
249
  window.scrollTo(scrollX, scrollY);
@@ -251,7 +251,7 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
251
251
 
252
252
  } else if (direction) {
253
253
  // Directional scroll mode
254
- logger.debug(`scroll_page: Scrolling ${direction} by ${amount}px`);
254
+ logger.debug(`browser_scroll_page: Scrolling ${direction} by ${amount}px`);
255
255
 
256
256
  const scrollDeltas = {
257
257
  up: { x: 0, y: -amount },
@@ -271,7 +271,7 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
271
271
 
272
272
  } else {
273
273
  // No scroll parameters provided - just return current position
274
- logger.debug(`scroll_page: No scroll action specified, returning current position`);
274
+ logger.debug(`browser_scroll_page: No scroll action specified, returning current position`);
275
275
  }
276
276
 
277
277
  // Small delay to let scroll complete
@@ -287,7 +287,7 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
287
287
  viewportHeight: window.innerHeight
288
288
  }));
289
289
 
290
- logger.info(`scroll_page completed: position=(${scrollInfo.scrollX}, ${scrollInfo.scrollY}), page=(${scrollInfo.pageWidth}x${scrollInfo.pageHeight})`);
290
+ logger.info(`browser_scroll_page completed: position=(${scrollInfo.scrollX}, ${scrollInfo.scrollY}), page=(${scrollInfo.pageWidth}x${scrollInfo.pageHeight})`);
291
291
 
292
292
  return new ScrollPageSuccessResponse(
293
293
  currentUrl,
@@ -298,20 +298,20 @@ export async function scrollPage({ url, direction, amount = 500, selector, x, y
298
298
  scrollInfo.viewportWidth,
299
299
  scrollInfo.viewportHeight,
300
300
  [
301
- "Use MCPBrowser's take_screenshot to capture the current view",
302
- "Use MCPBrowser's scroll_page again to navigate further",
303
- "Use MCPBrowser's click_element to interact with visible elements",
304
- "Use MCPBrowser's get_current_html to get the page content"
301
+ "Use MCPBrowser's browser_take_screenshot to capture the current view",
302
+ "Use MCPBrowser's browser_scroll_page again to navigate further",
303
+ "Use MCPBrowser's browser_click_element to interact with visible elements",
304
+ "Use MCPBrowser's browser_get_current_html to get the page content"
305
305
  ]
306
306
  );
307
307
  } catch (err) {
308
- logger.error(`scroll_page failed: ${err.message}`);
308
+ logger.error(`browser_scroll_page failed: ${err.message}`);
309
309
  return new InformationalResponse(
310
310
  `Failed to scroll page: ${err.message}`,
311
311
  'Could not scroll the page. The page may have navigated away or the connection was lost.',
312
312
  [
313
- "Try MCPBrowser's fetch_webpage to reload the page",
314
- "Use MCPBrowser's close_tab and start fresh if needed"
313
+ "Try MCPBrowser's browser_fetch_webpage to reload the page",
314
+ "Use MCPBrowser's browser_close_tab and start fresh if needed"
315
315
  ]
316
316
  );
317
317
  }
@@ -16,7 +16,7 @@ import logger from '../core/logger.js';
16
16
  // ============================================================================
17
17
 
18
18
  /**
19
- * Response for successful take_screenshot operations
19
+ * Response for successful browser_take_screenshot operations
20
20
  * Returns screenshot as base64-encoded image
21
21
  */
22
22
  export class TakeScreenshotSuccessResponse extends MCPResponse {
@@ -87,9 +87,9 @@ export class TakeScreenshotSuccessResponse extends MCPResponse {
87
87
  * @type {Tool}
88
88
  */
89
89
  export const TAKE_SCREENSHOT_TOOL = {
90
- name: "take_screenshot",
90
+ name: "browser_take_screenshot",
91
91
  title: "Take Screenshot",
92
- description: "**VISUAL CAPTURE** - Takes a screenshot of an already-loaded page for visual analysis. Useful when HTML parsing is insufficient or you need to see visual layout, images, charts, or rendered content. Returns a PNG image.\n\n**PREREQUISITE**: Page MUST be loaded with fetch_webpage first. This tool captures the current visual state of the page.",
92
+ description: "**VISUAL CAPTURE** - Takes a screenshot of an already-loaded page for visual analysis. Useful when HTML parsing is insufficient or you need to see visual layout, images, charts, or rendered content. Returns a PNG image.\n\n**PREREQUISITE**: Page MUST be loaded with browser_fetch_webpage first. This tool captures the current visual state of the page.",
93
93
  inputSchema: {
94
94
  type: "object",
95
95
  properties: {
@@ -129,7 +129,7 @@ export const TAKE_SCREENSHOT_TOOL = {
129
129
  * @returns {Promise<Object>} Result object with screenshot data
130
130
  */
131
131
  export async function takeScreenshot({ url, fullPage = false }) {
132
- logger.info(`take_screenshot called: url=${url}, fullPage=${fullPage}`);
132
+ logger.info(`browser_take_screenshot called: url=${url}, fullPage=${fullPage}`);
133
133
 
134
134
  if (!url) {
135
135
  throw new Error("url parameter is required");
@@ -146,7 +146,7 @@ export async function takeScreenshot({ url, fullPage = false }) {
146
146
  try {
147
147
  await getBrowser();
148
148
  } catch (err) {
149
- logger.error(`take_screenshot: Failed to connect to browser: ${err.message}`);
149
+ logger.error(`browser_take_screenshot: Failed to connect to browser: ${err.message}`);
150
150
  return new InformationalResponse(
151
151
  `Browser connection failed: ${err.message}`,
152
152
  'The browser must be running with remote debugging enabled.',
@@ -163,15 +163,15 @@ export async function takeScreenshot({ url, fullPage = false }) {
163
163
 
164
164
  if (!page) {
165
165
  const isConnectionLost = pageError && pageError.includes('connection');
166
- logger.debug(`take_screenshot: ${pageError || 'No page found for ' + hostname}`);
166
+ logger.debug(`browser_take_screenshot: ${pageError || 'No page found for ' + hostname}`);
167
167
  return new InformationalResponse(
168
168
  isConnectionLost ? `Page connection lost for ${hostname}` : `No open page found for ${hostname}`,
169
169
  isConnectionLost
170
170
  ? 'The browser tab was closed or the connection was lost. The page needs to be reloaded.'
171
171
  : 'The page must be loaded before you can take a screenshot',
172
172
  [
173
- "Use MCPBrowser's fetch_webpage tool to load the page first",
174
- "Then retry MCPBrowser's take_screenshot with the same URL"
173
+ "Use MCPBrowser's browser_fetch_webpage tool to load the page first",
174
+ "Then retry MCPBrowser's browser_take_screenshot with the same URL"
175
175
  ]
176
176
  );
177
177
  }
@@ -186,27 +186,27 @@ export async function takeScreenshot({ url, fullPage = false }) {
186
186
  fullPage: fullPage
187
187
  });
188
188
 
189
- logger.info(`take_screenshot completed: captured from ${currentUrl} (fullPage=${fullPage})`);
189
+ logger.info(`browser_take_screenshot completed: captured from ${currentUrl} (fullPage=${fullPage})`);
190
190
 
191
191
  return new TakeScreenshotSuccessResponse(
192
192
  currentUrl,
193
193
  screenshotBuffer,
194
194
  'image/png',
195
195
  [
196
- "Use MCPBrowser's get_current_html if you need the HTML instead",
197
- "Use MCPBrowser's click_element to interact with elements",
198
- "Use MCPBrowser's type_text to fill forms",
199
- "Use MCPBrowser's close_tab to free resources when done"
196
+ "Use MCPBrowser's browser_get_current_html if you need the HTML instead",
197
+ "Use MCPBrowser's browser_click_element to interact with elements",
198
+ "Use MCPBrowser's browser_type_text to fill forms",
199
+ "Use MCPBrowser's browser_close_tab to free resources when done"
200
200
  ]
201
201
  );
202
202
  } catch (err) {
203
- logger.error(`take_screenshot failed: ${err.message}`);
203
+ logger.error(`browser_take_screenshot failed: ${err.message}`);
204
204
  return new InformationalResponse(
205
205
  `Failed to take screenshot: ${err.message}`,
206
206
  'Could not capture screenshot from the page. The page may have navigated away or the connection was lost.',
207
207
  [
208
- "Try MCPBrowser's fetch_webpage to reload the page",
209
- "Use MCPBrowser's close_tab and start fresh if needed"
208
+ "Try MCPBrowser's browser_fetch_webpage to reload the page",
209
+ "Use MCPBrowser's browser_close_tab and start fresh if needed"
210
210
  ]
211
211
  );
212
212
  }