mcp-web-inspector 0.2.0 → 0.2.1

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.
package/dist/index.js CHANGED
@@ -5,6 +5,13 @@ import { createToolDefinitions } from "./tools/common/registry.js";
5
5
  import { setupRequestHandlers } from "./requestHandler.js";
6
6
  import { parseArgs } from "node:util";
7
7
  import { setSessionConfig } from "./toolHandler.js";
8
+ import { readFileSync } from "node:fs";
9
+ import { fileURLToPath } from "node:url";
10
+ import { dirname, join } from "node:path";
11
+ // Get package.json version
12
+ const __dirname = dirname(fileURLToPath(import.meta.url));
13
+ const packageJson = JSON.parse(readFileSync(join(__dirname, "../package.json"), "utf-8"));
14
+ const VERSION = packageJson.version;
8
15
  // Parse command line arguments
9
16
  const { values } = parseArgs({
10
17
  options: {
@@ -33,9 +40,10 @@ const sessionConfig = {
33
40
  };
34
41
  setSessionConfig(sessionConfig);
35
42
  async function runServer() {
43
+ console.error(`Starting mcp-web-inspector v${VERSION}`);
36
44
  const server = new Server({
37
45
  name: "mcp-web-inspector",
38
- version: "0.1.0",
46
+ version: VERSION,
39
47
  }, {
40
48
  capabilities: {
41
49
  resources: {},
@@ -7,7 +7,7 @@ export class EvaluateTool extends BrowserToolBase {
7
7
  static getMetadata(sessionConfig) {
8
8
  return {
9
9
  name: "evaluate",
10
- description: "Execute JavaScript in the browser console. ⚠️ AVOID for common tasks - use specialized tools instead: inspect_dom() for page structure, compare_positions() for alignment, measure_element() for spacing, query_selector() for finding elements. Only use evaluate() for custom logic not covered by other tools.",
10
+ description: "Execute JavaScript in the browser console and return the result (JSON-stringified). Automatically detects common patterns and suggests specialized tools when applicable. ⚠️ AVOID for common tasks - use specialized tools instead: inspect_dom() for page structure, compare_positions() for alignment, measure_element() for spacing/dimensions, query_selector() for finding elements. Only use evaluate() for custom logic not covered by other tools.",
11
11
  inputSchema: {
12
12
  type: "object",
13
13
  properties: {
@@ -25,41 +25,59 @@ export class EvaluateTool extends BrowserToolBase {
25
25
  const scriptLower = script.toLowerCase();
26
26
  // Pattern: DOM inspection/querying
27
27
  if (scriptLower.match(/queryselector|getelementby|getelement|innerhtml|outerhtml|children|childnodes/)) {
28
- suggestions.push('📍 DOM Inspection - Use inspect_dom({ selector: "..." }) for page structure');
28
+ suggestions.push('📍 DOM Inspection - Use inspect_dom({ selector: "..." })\n' +
29
+ ' Why: Returns semantic structure with test IDs, ARIA roles, interactive elements\n' +
30
+ ' Token savings: ~60% fewer tokens than parsing raw HTML');
29
31
  }
30
32
  // Pattern: Getting text content
31
33
  if (scriptLower.match(/textcontent|innertext/)) {
32
- suggestions.push('📝 Text Content - Use get_visible_text() or find_by_text({ text: "..." })');
34
+ suggestions.push('📝 Text Content\n' +
35
+ ' • get_visible_text() - Extract all visible text\n' +
36
+ ' • find_by_text({ text: "..." }) - Locate elements by content');
33
37
  }
34
38
  // Pattern: Getting element position/size/layout
35
39
  if (scriptLower.match(/getboundingclientrect|offsetwidth|offsetheight|offsetleft|offsettop|clientwidth|clientheight/)) {
36
- suggestions.push('📏 Element Measurements - Use measure_element({ selector: "..." })');
40
+ suggestions.push('📏 Element Measurements - Use measure_element({ selector: "..." })\n' +
41
+ ' Why: Returns position, size, gaps to siblings, and visibility state\n' +
42
+ ' Better than: Manual getBoundingClientRect() + visibility checks');
37
43
  }
38
44
  // Pattern: Walking up DOM tree / checking parents
39
45
  if (scriptLower.match(/parentelement|parentnode|offsetparent|closest/) ||
40
46
  (scriptLower.match(/while.*parent/) && scriptLower.match(/getcomputedstyle/))) {
41
- suggestions.push('🔼 Parent Chain - Use inspect_ancestors({ selector: "..." }) to see parent constraints');
47
+ suggestions.push('🔼 Parent Chain - Use inspect_ancestors({ selector: "..." })\n' +
48
+ ' Why: Shows width constraints, margins, overflow, flexbox/grid context\n' +
49
+ ' Detects: Clipping points (🎯), centering via auto margins, layout issues');
42
50
  }
43
51
  // Pattern: Checking visibility
44
52
  if (scriptLower.match(/offsetparent|visibility|display.*none|opacity/)) {
45
- suggestions.push('👁️ Visibility Check - Use element_visibility({ selector: "..." })');
53
+ suggestions.push('👁️ Visibility Check - Use element_visibility({ selector: "..." })\n' +
54
+ ' Returns: isVisible, inViewport, opacity, display, visibility properties\n' +
55
+ ' More reliable: Handles edge cases (opacity:0, visibility:hidden, etc.)');
46
56
  }
47
57
  // Pattern: Getting computed styles
48
58
  if (scriptLower.match(/getcomputedstyle|style\.|currentstyle/)) {
49
- suggestions.push('🎨 CSS Styles - Use get_computed_styles({ selector: "..." })');
59
+ suggestions.push('🎨 CSS Styles - Use get_computed_styles({ selector: "..." })\n' +
60
+ ' Why: Returns filtered, relevant styles in compact format\n' +
61
+ ' Token savings: ~70% fewer tokens than full getComputedStyle() dump');
50
62
  }
51
63
  // Pattern: Checking element existence
52
64
  if (scriptLower.match(/\!=\s*null|\!==\s*null/) && scriptLower.match(/queryselector/)) {
53
- suggestions.push('✓ Element Existence - Use element_exists({ selector: "..." })');
65
+ suggestions.push('✓ Element Existence - Use element_exists({ selector: "..." })\n' +
66
+ ' Returns: Boolean + element summary if found\n' +
67
+ ' Simpler: No need for null checks');
54
68
  }
55
69
  // Pattern: Finding test IDs
56
70
  if (scriptLower.match(/data-testid|data-test|data-cy/)) {
57
- suggestions.push('🔍 Test IDs - Use get_test_ids() to discover all test identifiers');
71
+ suggestions.push('🔍 Test IDs - Use get_test_ids()\n' +
72
+ ' Returns: All test identifiers grouped by type\n' +
73
+ ' Detects: Duplicates and validation issues');
58
74
  }
59
75
  // Pattern: Comparing positions/alignment
60
76
  if (scriptLower.match(/getboundingclientrect.*getboundingclientrect/) ||
61
77
  (scriptLower.match(/\.left|\.top|\.right|\.bottom/) && scriptLower.match(/===|==|!==|!=/))) {
62
- suggestions.push('⚖️ Position Comparison - Use compare_positions({ selector1: "...", selector2: "..." })');
78
+ suggestions.push('⚖️ Position Comparison - Use compare_positions({ selector1: "...", selector2: "..." })\n' +
79
+ ' Returns: Alignment status (left/right/top/bottom/center), pixel gaps\n' +
80
+ ' Perfect for: Checking if elements are aligned or overlapping');
63
81
  }
64
82
  return suggestions;
65
83
  }
@@ -76,10 +94,7 @@ export class EvaluateTool extends BrowserToolBase {
76
94
  resultStr = String(result);
77
95
  }
78
96
  const messages = [
79
- `✓ Executed JavaScript:`,
80
- `${args.script}`,
81
- ``,
82
- `Result:`,
97
+ `✓ JavaScript execution result:`,
83
98
  `${resultStr}`
84
99
  ];
85
100
  // Detect if specialized tools would be better
@@ -221,7 +221,7 @@ describe('Browser Interaction Tools', () => {
221
221
  const result = await evaluateTool.execute(args, mockContext);
222
222
  expect(mockEvaluate).toHaveBeenCalledWith('return document.title');
223
223
  expect(result.isError).toBe(false);
224
- expect(result.content[0].text).toContain('Executed JavaScript');
224
+ expect(result.content[0].text).toContain('JavaScript execution result');
225
225
  });
226
226
  test('should suggest inspect_dom for querySelector usage', async () => {
227
227
  const args = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-web-inspector",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Web Inspector MCP: Give LLMs visual superpowers to see, debug, and test any web page.",
5
5
  "license": "MIT",
6
6
  "author": "Anton",