@mcp-b/chrome-devtools-mcp 1.5.3 → 1.5.5

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.
@@ -507,7 +507,9 @@ export class McpContext {
507
507
  }
508
508
  const [snapshotId] = uid.split('_');
509
509
  if (this.#textSnapshot.snapshotId !== snapshotId) {
510
- throw new Error('This uid is coming from a stale snapshot. Call take_snapshot to get a fresh snapshot.');
510
+ throw new Error(`This uid (${uid}) is from an old snapshot. The page has changed since then. ` +
511
+ 'Always call take_snapshot immediately before using UIDs from it. ' +
512
+ 'Workflow: 1) take_snapshot, 2) use the UIDs from that response, 3) repeat for each action.');
511
513
  }
512
514
  const node = this.#textSnapshot?.idToNode.get(uid);
513
515
  if (!node) {
package/build/src/main.js CHANGED
@@ -22,7 +22,7 @@ import { WebMCPToolHub } from './tools/WebMCPToolHub.js';
22
22
  * @remarks If moved, update release-please config.
23
23
  */
24
24
  // x-release-please-start-version
25
- const VERSION = '1.5.3';
25
+ const VERSION = '1.5.5';
26
26
  // x-release-please-end
27
27
  process.on('unhandledRejection', (reason, promise) => {
28
28
  logger('Unhandled promise rejection', promise, reason);
@@ -9,7 +9,7 @@ import { ToolCategory } from './categories.js';
9
9
  import { defineTool } from './ToolDefinition.js';
10
10
  export const click = defineTool({
11
11
  name: 'click',
12
- description: `Clicks on the provided element`,
12
+ description: `Clicks on the provided element. IMPORTANT: Always call take_snapshot first to get a fresh uid - UIDs expire when the page changes.`,
13
13
  annotations: {
14
14
  category: ToolCategory.INPUT,
15
15
  readOnlyHint: false,
@@ -9,8 +9,9 @@ import { defineTool, timeoutSchema } from './ToolDefinition.js';
9
9
  export const takeSnapshot = defineTool({
10
10
  name: 'take_snapshot',
11
11
  description: `Take a text snapshot of the currently selected page based on the a11y tree. The snapshot lists page elements along with a unique
12
- identifier (uid). Always use the latest snapshot. Prefer taking a snapshot over taking a screenshot. The snapshot indicates the element selected
13
- in the DevTools Elements panel (if any).`,
12
+ identifier (uid). IMPORTANT: UIDs expire when the page changes. Always take a fresh snapshot immediately before using UIDs for click/type/etc.
13
+ Workflow: 1) take_snapshot, 2) find the uid you need, 3) use it in click/type, 4) take_snapshot again for next action.
14
+ Prefer taking a snapshot over taking a screenshot. The snapshot indicates the element selected in the DevTools Elements panel (if any).`,
14
15
  annotations: {
15
16
  category: ToolCategory.DEBUGGING,
16
17
  // Not read-only due to filePath param.
@@ -86,8 +86,8 @@ export const listWebMCPTools = defineTool({
86
86
  description: 'List all WebMCP tools registered across all pages, with diff since last call. ' +
87
87
  'First call returns full list. Subsequent calls return only added/removed tools. ' +
88
88
  'Use full=true to force complete list. ' +
89
- 'Tools are shown with their callable names (e.g., webmcp_localhost_3000_page0_test_add). ' +
90
- 'Call these tools directly by name instead of using a separate call tool.',
89
+ 'To call these tools, use call_webmcp_tool with the ORIGINAL tool name (without the webmcp_ prefix). ' +
90
+ 'Example: call_webmcp_tool({ name: "idp_config_get" }) NOT "webmcp_localhost_3000_page0_idp_config_get".',
91
91
  annotations: {
92
92
  title: 'Diff Website MCP Tools',
93
93
  category: ToolCategory.WEBMCP,
@@ -117,21 +117,33 @@ export const listWebMCPTools = defineTool({
117
117
  response.appendResponseLine('Navigate to a page with @mcp-b/global loaded to discover tools.');
118
118
  return;
119
119
  }
120
- response.appendResponseLine(`${tools.length} WebMCP tool(s) registered:`);
120
+ response.appendResponseLine(`Found ${tools.length} WebMCP tool(s):`);
121
121
  response.appendResponseLine('');
122
+ // Group tools by page
123
+ const toolsByPage = new Map();
122
124
  for (const tool of tools) {
123
- response.appendResponseLine(`- ${tool.toolId}`);
124
- response.appendResponseLine(` Original: ${tool.originalName}`);
125
- response.appendResponseLine(` Domain: ${tool.domain} (page ${tool.pageIdx})`);
126
- if (tool.description) {
127
- response.appendResponseLine(` Description: ${tool.description}`);
125
+ if (!toolsByPage.has(tool.pageIdx)) {
126
+ toolsByPage.set(tool.pageIdx, []);
127
+ }
128
+ toolsByPage.get(tool.pageIdx).push(tool);
129
+ }
130
+ // Sort pages by index
131
+ const sortedPages = Array.from(toolsByPage.keys()).sort((a, b) => a - b);
132
+ for (const pageIdx of sortedPages) {
133
+ const pageTools = toolsByPage.get(pageIdx);
134
+ const domain = pageTools[0].domain;
135
+ response.appendResponseLine(`Page ${pageIdx}: ${domain}`);
136
+ for (const tool of pageTools) {
137
+ response.appendResponseLine(` • ${tool.originalName}`);
138
+ if (tool.description) {
139
+ response.appendResponseLine(` ${tool.description}`);
140
+ }
128
141
  }
129
142
  response.appendResponseLine('');
130
143
  }
131
- response.appendResponseLine('IMPORTANT: These tools are available in your MCP tool list.');
132
- response.appendResponseLine('Call them directly using: mcp__chrome-devtools__<toolId>');
144
+ response.appendResponseLine('To call a tool: call_webmcp_tool({ name: "tool_name", arguments: {...} })');
133
145
  if (tools.length > 0) {
134
- response.appendResponseLine(`Example: mcp__chrome-devtools__${tools[0].toolId}`);
146
+ response.appendResponseLine(`Example: call_webmcp_tool({ name: "${tools[0].originalName}" })`);
135
147
  }
136
148
  return;
137
149
  }
@@ -141,29 +153,61 @@ export const listWebMCPTools = defineTool({
141
153
  toolHub.setLastSeenToolIds(currentToolIds);
142
154
  if (added.length === 0 && removed.length === 0) {
143
155
  response.appendResponseLine('No changes since last poll.');
156
+ response.appendResponseLine('');
144
157
  if (tools.length > 0) {
145
- const toolNames = tools.map(t => t.originalName).join(', ');
146
- response.appendResponseLine(`${tools.length} tools available: ${toolNames}`);
158
+ // Group tools by page
159
+ const toolsByPage = new Map();
160
+ for (const tool of tools) {
161
+ if (!toolsByPage.has(tool.pageIdx)) {
162
+ toolsByPage.set(tool.pageIdx, []);
163
+ }
164
+ toolsByPage.get(tool.pageIdx).push(tool);
165
+ }
166
+ response.appendResponseLine(`${tools.length} tool(s) available:`);
167
+ const sortedPages = Array.from(toolsByPage.keys()).sort((a, b) => a - b);
168
+ for (const pageIdx of sortedPages) {
169
+ const pageTools = toolsByPage.get(pageIdx);
170
+ const toolNames = pageTools.map(t => t.originalName).join(', ');
171
+ response.appendResponseLine(` Page ${pageIdx}: ${toolNames}`);
172
+ }
147
173
  }
148
174
  return;
149
175
  }
150
176
  if (added.length > 0) {
151
- response.appendResponseLine(`Added (${added.length}):`);
177
+ response.appendResponseLine(`Added ${added.length} new tool(s):`);
178
+ response.appendResponseLine('');
179
+ // Group by page
180
+ const addedByPage = new Map();
152
181
  for (const tool of added) {
153
- response.appendResponseLine(`+ ${tool.toolId}`);
154
- if (tool.description) {
155
- response.appendResponseLine(` ${tool.description}`);
182
+ if (!addedByPage.has(tool.pageIdx)) {
183
+ addedByPage.set(tool.pageIdx, []);
156
184
  }
185
+ addedByPage.get(tool.pageIdx).push(tool);
157
186
  }
158
- response.appendResponseLine('');
159
- response.appendResponseLine('NEW TOOLS AVAILABLE: Your MCP tool list has been updated.');
160
- response.appendResponseLine(`Call them using: mcp__chrome-devtools__${added[0].toolId}`);
187
+ const sortedPages = Array.from(addedByPage.keys()).sort((a, b) => a - b);
188
+ for (const pageIdx of sortedPages) {
189
+ const pageTools = addedByPage.get(pageIdx);
190
+ const domain = pageTools[0].domain;
191
+ response.appendResponseLine(`Page ${pageIdx}: ${domain}`);
192
+ for (const tool of pageTools) {
193
+ response.appendResponseLine(` + ${tool.originalName}`);
194
+ if (tool.description) {
195
+ response.appendResponseLine(` ${tool.description}`);
196
+ }
197
+ }
198
+ response.appendResponseLine('');
199
+ }
200
+ response.appendResponseLine(`Call with: call_webmcp_tool({ name: "${added[0].originalName}" })`);
161
201
  response.appendResponseLine('');
162
202
  }
163
203
  if (removed.length > 0) {
164
- response.appendResponseLine(`Removed (${removed.length}):`);
204
+ response.appendResponseLine(`Removed ${removed.length} tool(s)`);
205
+ response.appendResponseLine('');
165
206
  for (const id of removed) {
166
- response.appendResponseLine(`- ${id}`);
207
+ // Extract original name from toolId format: webmcp_{domain}_page{idx}_{name}
208
+ const parts = id.split('_');
209
+ const name = parts.slice(3).join('_'); // Everything after page index
210
+ response.appendResponseLine(` - ${name || id}`);
167
211
  }
168
212
  }
169
213
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-b/chrome-devtools-mcp",
3
- "version": "1.5.3",
3
+ "version": "1.5.5",
4
4
  "description": "MCP server for Chrome DevTools with WebMCP integration for connecting to website MCP tools",
5
5
  "keywords": [
6
6
  "mcp",