@browserless.io/mcp 1.6.0 → 1.6.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/README.md CHANGED
@@ -1,10 +1,6 @@
1
1
  # Browserless MCP Server
2
2
 
3
- <div align="center">
4
-
5
- [![MCP Badge](https://lobehub.com/badge/mcp/browserless-browserless-mcp?style=plastic)](https://lobehub.com/mcp/browserless-browserless-mcp)
6
-
7
- </div>
3
+ [![MCP Badge](https://lobehub.com/badge/mcp/browserless-browserless-mcp?style=for-the-badge)](https://lobehub.com/mcp/browserless-browserless-mcp)
8
4
 
9
5
  MCP (Model Context Protocol) server for [Browserless.io](https://browserless.io) — expose the Browserless smart scraper API to LLM clients like Claude Desktop, Cursor, VS Code, and Windsurf.
10
6
 
@@ -1,3 +1,15 @@
1
+ export interface AmplitudeEvent {
2
+ event_type: string;
3
+ time: number;
4
+ session_id?: number;
5
+ event_properties: Record<string, unknown> & {
6
+ token: string;
7
+ };
8
+ }
9
+ /**
10
+ * Simple djb2 hash — matches the enterprise repo's session ID hashing.
11
+ */
12
+ export declare function djb2(str: string): number;
1
13
  export declare class AmplitudeHelper {
2
14
  private sqsClient?;
3
15
  private queueUrl?;
@@ -1,5 +1,15 @@
1
1
  import { SQSClient, SendMessageBatchCommand, } from '@aws-sdk/client-sqs';
2
2
  import { randomUUID } from 'node:crypto';
3
+ /**
4
+ * Simple djb2 hash — matches the enterprise repo's session ID hashing.
5
+ */
6
+ export function djb2(str) {
7
+ let hash = 5381;
8
+ for (let i = 0; i < str.length; i++) {
9
+ hash = (hash * 33) ^ str.charCodeAt(i);
10
+ }
11
+ return hash >>> 0;
12
+ }
3
13
  export class AmplitudeHelper {
4
14
  sqsClient;
5
15
  queueUrl;
@@ -23,10 +33,7 @@ export class AmplitudeHelper {
23
33
  this.initialized = true;
24
34
  }
25
35
  async send(eventName, sessionId, properties) {
26
- if (!this.enabled ||
27
- !this.initialized ||
28
- !this.sqsClient ||
29
- !this.queueUrl) {
36
+ if (!this.enabled || !this.initialized || !this.sqsClient || !this.queueUrl) {
30
37
  return false;
31
38
  }
32
39
  const event = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserless.io/mcp",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "MCP (Model Context Protocol) server for the Browserless.io browser automation platform",
5
5
  "author": "browserless.io",
6
6
  "license": "SSPL-1.0",
@@ -45,7 +45,6 @@
45
45
  "build/src/**/*.d.ts",
46
46
  "build/src/**/*.md",
47
47
  "bin/*",
48
- "patches/**",
49
48
  "README.md"
50
49
  ],
51
50
  "scripts": {
@@ -59,7 +58,6 @@
59
58
  "coverage": "npm run build && c8 --reporter=text --reporter=html --reporter=lcov --check-coverage --lines 80 --branches 70 --functions 80 mocha",
60
59
  "start": "node build/src/index.js",
61
60
  "start:http": "TRANSPORT=httpStream PORT=8080 node build/src/index.js",
62
- "postinstall": "patch-package",
63
61
  "prepack": "npm run build",
64
62
  "prepare": "husky",
65
63
  "prettier": "prettier '{src,test,bin,.github}/**/*.{js,ts,json,yml,yaml,md}' --log-level error --write"
@@ -74,7 +72,6 @@
74
72
  "@aws-sdk/client-sqs": "^3.1053.0",
75
73
  "fastmcp": "^4.0.0",
76
74
  "ioredis": "^5.10.1",
77
- "patch-package": "^8.0.1",
78
75
  "ws": "^8.21.0",
79
76
  "zod": "^4.4.3"
80
77
  },
@@ -105,7 +102,8 @@
105
102
  "mocha": {
106
103
  "diff": "^8.0.3",
107
104
  "minimatch": "^10.2.1",
108
- "glob": "^11.0.0"
105
+ "glob": "^11.0.0",
106
+ "serialize-javascript": "^7.0.5"
109
107
  }
110
108
  }
111
109
  }
@@ -1,10 +0,0 @@
1
- import { z } from 'zod';
2
- /**
3
- * Build the schema for an optional profile field. The NUL refinement protects
4
- * the session-key separator used in agent-client.ts — a profile name
5
- * containing NUL could otherwise collide with another key.
6
- *
7
- * Dependency-clean (zod only) so it can be shared by the server tools and the
8
- * published `@browserless.io/mcp/schemas` surface without pulling in fastmcp.
9
- */
10
- export declare function profileField(whenLoaded: string, extra?: string): z.ZodOptional<z.ZodString>;
@@ -1,27 +0,0 @@
1
- import { z } from 'zod';
2
- // NUL is the session-key separator (KEY_SEP) in agent-client.ts. Computed via
3
- // fromCharCode so the literal control character never appears in source.
4
- const NUL = String.fromCharCode(0);
5
- /**
6
- * Build the schema for an optional profile field. The NUL refinement protects
7
- * the session-key separator used in agent-client.ts — a profile name
8
- * containing NUL could otherwise collide with another key.
9
- *
10
- * Dependency-clean (zod only) so it can be shared by the server tools and the
11
- * published `@browserless.io/mcp/schemas` surface without pulling in fastmcp.
12
- */
13
- export function profileField(whenLoaded, extra = '') {
14
- const description = `Optional name of an authentication profile to hydrate into the browser ${whenLoaded}. ` +
15
- "The profile's cookies, localStorage, and IndexedDB are restored into the session before the request runs. " +
16
- 'The profile must already exist for the API token in use — create one with Browserless.saveProfile in a live agent session first.' +
17
- extra;
18
- return z
19
- .string()
20
- .trim()
21
- .min(1)
22
- .refine((v) => !v.includes(NUL), {
23
- message: 'profile must not contain NUL characters',
24
- })
25
- .optional()
26
- .describe(description);
27
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Patch `globalThis.fetch` to extend `expires_in` on Supabase OAuth token
3
- * responses so clients don't thrash refresh against the ~60s default. Global
4
- * because FastMCP's OAuthProxy has no fetch hook; matched origin/path-exact.
5
- */
6
- export declare function installSupabaseTokenTtlPatch(supabaseUrl: string, ttlSeconds: number): void;
@@ -1,33 +0,0 @@
1
- /**
2
- * Patch `globalThis.fetch` to extend `expires_in` on Supabase OAuth token
3
- * responses so clients don't thrash refresh against the ~60s default. Global
4
- * because FastMCP's OAuthProxy has no fetch hook; matched origin/path-exact.
5
- */
6
- export function installSupabaseTokenTtlPatch(supabaseUrl, ttlSeconds) {
7
- const supabaseOrigin = new URL(supabaseUrl).origin;
8
- const TOKEN_PATHNAME = '/auth/v1/oauth/token';
9
- const originalFetch = globalThis.fetch;
10
- globalThis.fetch = async (...args) => {
11
- const response = await originalFetch(...args);
12
- const url = typeof args[0] === 'string'
13
- ? args[0]
14
- : args[0] instanceof URL
15
- ? args[0].toString()
16
- : args[0].url;
17
- const reqUrl = new URL(url);
18
- if (!response.ok ||
19
- reqUrl.origin !== supabaseOrigin ||
20
- reqUrl.pathname !== TOKEN_PATHNAME) {
21
- return response;
22
- }
23
- const body = (await response.json());
24
- if (typeof body.expires_in === 'number' && body.expires_in < ttlSeconds) {
25
- body.expires_in = ttlSeconds;
26
- }
27
- return new Response(JSON.stringify(body), {
28
- status: response.status,
29
- statusText: response.statusText,
30
- headers: response.headers,
31
- });
32
- };
33
- }
@@ -1,31 +0,0 @@
1
- diff --git a/node_modules/mcp-proxy/dist/stdio-CyOk7u4Q.mjs b/node_modules/mcp-proxy/dist/stdio-CyOk7u4Q.mjs
2
- index bfd727e..3350845 100644
3
- --- a/node_modules/mcp-proxy/dist/stdio-CyOk7u4Q.mjs
4
- +++ b/node_modules/mcp-proxy/dist/stdio-CyOk7u4Q.mjs
5
- @@ -15479,6 +15479,10 @@ const handleStreamRequest = async ({ activeTransports, authenticate, authMiddlew
6
- const sessionId = req.headers["mcp-session-id"];
7
- const activeTransport = sessionId ? activeTransports[sessionId] : void 0;
8
- if (!sessionId) {
9
- + if (stateless) {
10
- + res.writeHead(405, { Allow: "POST" }).end("Method Not Allowed");
11
- + return true;
12
- + }
13
- res.writeHead(400).end("No sessionId");
14
- return true;
15
- }
16
- diff --git a/node_modules/mcp-proxy/src/startHTTPServer.ts b/node_modules/mcp-proxy/src/startHTTPServer.ts
17
- index 80e8cb7..ac051a1 100644
18
- --- a/node_modules/mcp-proxy/src/startHTTPServer.ts
19
- +++ b/node_modules/mcp-proxy/src/startHTTPServer.ts
20
- @@ -686,6 +686,11 @@ const handleStreamRequest = async <T extends ServerLike>({
21
- | undefined = sessionId ? activeTransports[sessionId] : undefined;
22
-
23
- if (!sessionId) {
24
- + if (stateless) {
25
- + res.writeHead(405, { Allow: "POST" }).end("Method Not Allowed");
26
- +
27
- + return true;
28
- + }
29
- res.writeHead(400).end("No sessionId");
30
-
31
- return true;