mcpbrowser 0.3.56 → 0.3.58

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/README.md CHANGED
@@ -498,6 +498,31 @@ Logs go to `stderr` so they don't interfere with MCP protocol on `stdout`.
498
498
  - Keep the browser tab open (default behavior)
499
499
  - Use the same domain for related requests
500
500
 
501
+ **E401 error with `npx` / private npm registry?**
502
+
503
+ If your project has a `.npmrc` that points to a private registry (e.g., Azure Artifacts, GitHub Packages, Artifactory), `npx` will try to fetch `mcpbrowser` from that registry instead of npmjs.org and fail with `E401`.
504
+
505
+ **Fix:** Add `npm_config_registry` to the `env` block in your MCP config:
506
+ ```json
507
+ {
508
+ "mcpServers": {
509
+ "mcpbrowser": {
510
+ "command": "npx",
511
+ "args": ["-y", "mcpbrowser@latest"],
512
+ "env": {
513
+ "npm_config_registry": "https://registry.npmjs.org"
514
+ }
515
+ }
516
+ }
517
+ }
518
+ ```
519
+
520
+ **Alternative:** Install globally to skip `npx` entirely:
521
+ ```bash
522
+ npm install -g mcpbrowser
523
+ ```
524
+ Then use `"command": "mcpbrowser"` with no `args` in your MCP config.
525
+
501
526
  ## Links
502
527
 
503
528
  - [GitHub](https://github.com/cherchyk/MCPBrowser)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcpbrowser",
3
- "version": "0.3.56",
3
+ "version": "0.3.58",
4
4
  "mcpName": "io.github.cherchyk/mcpbrowser",
5
5
  "type": "module",
6
6
  "description": "MCP browser server — loads and interacts with web pages using the user's Chromium-based browser with full JavaScript execution. Handles authentication, SSO, and anti-bot protection automatically via the user's existing browser session.",
@@ -114,16 +114,16 @@ export const CLICK_ELEMENT_TOOL = {
114
114
  properties: {
115
115
  status: { type: "string", enum: ["success", "timeout", "error"] },
116
116
  durationMs: { type: "number" },
117
- error: { type: ["string", "null"] }
117
+ error: { type: "string" }
118
118
  },
119
119
  required: ["status", "durationMs"]
120
120
  },
121
121
  fallbackAttempt: {
122
- type: ["object", "null"],
122
+ type: "object",
123
123
  properties: {
124
124
  status: { type: "string", enum: ["success", "timeout", "error"] },
125
125
  durationMs: { type: "number" },
126
- error: { type: ["string", "null"] }
126
+ error: { type: "string" }
127
127
  },
128
128
  required: ["status", "durationMs"],
129
129
  description: "Present when fallbackUsed is true"
@@ -140,7 +140,7 @@ export const CLICK_ELEMENT_TOOL = {
140
140
  currentUrl: { type: "string", description: "URL after click" },
141
141
  message: { type: "string", description: "Status message" },
142
142
  html: {
143
- type: ["string", "null"],
143
+ type: "string",
144
144
  description: "Page HTML if returnHtml was true, null otherwise"
145
145
  },
146
146
  forms: { type: "array", items: { type: "object" }, description: "Detected forms with fields, selectors, and metadata (when returnHtml is true)" },
@@ -123,7 +123,7 @@ export const DETECT_FORMS_TOOL = {
123
123
  }
124
124
  },
125
125
  submitButton: {
126
- type: ["object", "null"],
126
+ type: "object",
127
127
  properties: {
128
128
  selector: { type: "string" },
129
129
  text: { type: "string" },
@@ -36,8 +36,13 @@ export class ExecuteJavascriptResponse extends MCPResponse {
36
36
  }
37
37
 
38
38
  _getAdditionalFields() {
39
+ // outputSchema declares result as type: 'string' (serialized).
40
+ // Ensure non-string values (numbers, objects, arrays) are stringified.
41
+ const serializedResult = this.result == null ? null
42
+ : typeof this.result === 'string' ? this.result
43
+ : JSON.stringify(this.result);
39
44
  return {
40
- result: this.result,
45
+ result: serializedResult,
41
46
  type: this.type,
42
47
  executionTimeMs: this.executionTimeMs,
43
48
  truncated: this.truncated,
@@ -74,14 +79,14 @@ export const EXECUTE_JAVASCRIPT_TOOL = {
74
79
  outputSchema: {
75
80
  type: 'object',
76
81
  properties: {
77
- result: { description: 'Serialized result of the script', nullable: true },
82
+ result: { type: 'string', description: 'Serialized result of the script', nullable: true },
78
83
  type: { type: 'string', description: 'Type of the returned result' },
79
84
  executionTimeMs: { type: 'number', description: 'Script execution duration' },
80
85
  truncated: { type: 'boolean', description: 'True if result was capped to size limit' },
81
86
  urlChanged: { type: 'boolean', description: 'True if page URL changed during execution' },
82
87
  currentUrl: { type: 'string', description: 'URL after execution' },
83
88
  nextSteps: { type: 'array', items: { type: 'string' } },
84
- error: { type: ['object', 'null'], description: 'Error object when script throws or times out' },
89
+ error: { type: 'object', description: 'Error object when script throws or times out' },
85
90
  recommendedPlugins: {
86
91
  type: 'array',
87
92
  items: { type: 'object' },
@@ -81,8 +81,9 @@ export const FETCH_WEBPAGE_TOOL = {
81
81
  url: { type: "string", description: "The URL to fetch" },
82
82
  browser: {
83
83
  type: "string",
84
- description: "Browser to use: 'chrome' or 'edge'. Leave empty for auto-detection. Uses CDP to connect to the user's existing browser session.",
85
- enum: ["", "chrome", "edge"]
84
+ enum: ["chrome", "edge", "brave"],
85
+ description: "Browser to use. Uses CDP to connect to the user's existing browser session.",
86
+ default: "chrome"
86
87
  },
87
88
  removeUnnecessaryHTML: { type: "boolean", description: "Remove Unnecessary HTML for size reduction by 90%.", default: true },
88
89
  selector: { type: "string", description: "CSS selector to extract a specific DOM subtree instead of the full page. Use to scope extraction and reduce response size (e.g., 'main', '[role=\"main\"]', 'body > div:first-child'). If no elements match, falls back to full page with a note." },
@@ -94,7 +94,7 @@ export const NAVIGATE_HISTORY_TOOL = {
94
94
  direction: { type: "string", enum: ["back", "forward"], description: "Navigation direction used" },
95
95
  previousUrl: { type: "string", description: "URL before navigation" },
96
96
  currentUrl: { type: "string", description: "URL after navigation" },
97
- html: { type: ["string", "null"], description: "Page HTML content after navigation (null if returnHtml=false)" },
97
+ html: { type: "string", description: "Page HTML content after navigation (null if returnHtml=false)" },
98
98
  nextSteps: {
99
99
  type: "array",
100
100
  items: { type: "string" },
@@ -105,7 +105,8 @@ export const SCROLL_PAGE_TOOL = {
105
105
  direction: {
106
106
  type: "string",
107
107
  enum: ["up", "down", "left", "right"],
108
- description: "Direction to scroll. Use with 'amount' parameter."
108
+ description: "Direction to scroll. Use with 'amount' parameter.",
109
+ default: "down"
109
110
  },
110
111
  amount: {
111
112
  type: "number",
@@ -100,7 +100,7 @@ export const TYPE_TEXT_TOOL = {
100
100
  currentUrl: { type: "string", description: "URL after typing" },
101
101
  message: { type: "string", description: "Success message" },
102
102
  html: {
103
- type: ["string", "null"],
103
+ type: "string",
104
104
  description: "Page HTML if returnHtml was true, null otherwise"
105
105
  },
106
106
  nextSteps: {
@@ -71,6 +71,17 @@ async function main() {
71
71
  }
72
72
  );
73
73
 
74
+ // Capture the negotiated MCP protocol version so the ListTools handler can
75
+ // strip fields that older clients cannot parse (outputSchema, annotations,
76
+ // title were added in MCP protocol 2025-03-26).
77
+ let negotiatedProtocolVersion = null;
78
+ const _origOnInitialize = server._oninitialize.bind(server);
79
+ server._oninitialize = async function(request) {
80
+ const result = await _origOnInitialize(request);
81
+ negotiatedProtocolVersion = result.protocolVersion;
82
+ return result;
83
+ };
84
+
74
85
  // Wire server to logger so logs flow to agent via notifications/message.
75
86
  attachLoggerServer(server);
76
87
 
@@ -106,7 +117,16 @@ async function main() {
106
117
  ...pluginTools
107
118
  ];
108
119
 
109
- server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));
120
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
121
+ // outputSchema, annotations, and title require MCP protocol 2025-03-26+.
122
+ // Strip them for clients that negotiated an older version (e.g. Antigravity/Gemini).
123
+ if (!negotiatedProtocolVersion || negotiatedProtocolVersion < '2025-03-26') {
124
+ return {
125
+ tools: tools.map(({ outputSchema, annotations, title, ...core }) => core)
126
+ };
127
+ }
128
+ return { tools };
129
+ });
110
130
 
111
131
  // --- Prompts handlers ---
112
132
  server.setRequestHandler(ListPromptsRequestSchema, async () => ({ prompts: PROMPTS }));