@browserless.io/mcp 1.6.0
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/LICENSE +557 -0
- package/README.md +280 -0
- package/bin/cli.js +2 -0
- package/build/src/@types/types.d.ts +538 -0
- package/build/src/config.d.ts +3 -0
- package/build/src/config.js +42 -0
- package/build/src/index.d.ts +4 -0
- package/build/src/index.js +153 -0
- package/build/src/lib/account-resolver.d.ts +17 -0
- package/build/src/lib/account-resolver.js +78 -0
- package/build/src/lib/agent-client.d.ts +58 -0
- package/build/src/lib/agent-client.js +530 -0
- package/build/src/lib/agent-format.d.ts +35 -0
- package/build/src/lib/agent-format.js +155 -0
- package/build/src/lib/amplitude.d.ts +11 -0
- package/build/src/lib/amplitude.js +65 -0
- package/build/src/lib/analytics.d.ts +18 -0
- package/build/src/lib/analytics.js +79 -0
- package/build/src/lib/api-client.d.ts +17 -0
- package/build/src/lib/api-client.js +357 -0
- package/build/src/lib/bounded-event-store.d.ts +22 -0
- package/build/src/lib/bounded-event-store.js +69 -0
- package/build/src/lib/cache.d.ts +12 -0
- package/build/src/lib/cache.js +49 -0
- package/build/src/lib/define-tool.d.ts +71 -0
- package/build/src/lib/define-tool.js +71 -0
- package/build/src/lib/error-classifier.d.ts +4 -0
- package/build/src/lib/error-classifier.js +125 -0
- package/build/src/lib/redis-oauth-proxy.d.ts +13 -0
- package/build/src/lib/redis-oauth-proxy.js +214 -0
- package/build/src/lib/retry.d.ts +2 -0
- package/build/src/lib/retry.js +19 -0
- package/build/src/lib/schema-fields.d.ts +10 -0
- package/build/src/lib/schema-fields.js +27 -0
- package/build/src/lib/supabase-token-patch.d.ts +6 -0
- package/build/src/lib/supabase-token-patch.js +33 -0
- package/build/src/lib/utils.d.ts +27 -0
- package/build/src/lib/utils.js +67 -0
- package/build/src/prompts/extract-content.d.ts +2 -0
- package/build/src/prompts/extract-content.js +33 -0
- package/build/src/prompts/scrape-url.d.ts +2 -0
- package/build/src/prompts/scrape-url.js +36 -0
- package/build/src/resources/api-docs.d.ts +3 -0
- package/build/src/resources/api-docs.js +54 -0
- package/build/src/resources/status.d.ts +3 -0
- package/build/src/resources/status.js +30 -0
- package/build/src/skills/autonomous-login.md +95 -0
- package/build/src/skills/captchas.md +48 -0
- package/build/src/skills/cookie-consent.md +50 -0
- package/build/src/skills/dynamic-content.md +72 -0
- package/build/src/skills/index.d.ts +9 -0
- package/build/src/skills/index.js +221 -0
- package/build/src/skills/modals.md +56 -0
- package/build/src/skills/screenshots.md +53 -0
- package/build/src/skills/shadow-dom.md +64 -0
- package/build/src/skills/snapshot-misses.md +67 -0
- package/build/src/skills/system-prompt.d.ts +2 -0
- package/build/src/skills/system-prompt.js +128 -0
- package/build/src/skills/tabs.md +77 -0
- package/build/src/tools/agent.d.ts +15 -0
- package/build/src/tools/agent.js +299 -0
- package/build/src/tools/crawl.d.ts +75 -0
- package/build/src/tools/crawl.js +426 -0
- package/build/src/tools/download.d.ts +11 -0
- package/build/src/tools/download.js +92 -0
- package/build/src/tools/export.d.ts +28 -0
- package/build/src/tools/export.js +129 -0
- package/build/src/tools/function.d.ts +24 -0
- package/build/src/tools/function.js +144 -0
- package/build/src/tools/map.d.ts +23 -0
- package/build/src/tools/map.js +129 -0
- package/build/src/tools/performance.d.ts +25 -0
- package/build/src/tools/performance.js +103 -0
- package/build/src/tools/schemas.d.ts +466 -0
- package/build/src/tools/schemas.js +487 -0
- package/build/src/tools/search.d.ts +67 -0
- package/build/src/tools/search.js +184 -0
- package/build/src/tools/smartscraper.d.ts +42 -0
- package/build/src/tools/smartscraper.js +136 -0
- package/package.json +111 -0
- package/patches/mcp-proxy+6.4.0.patch +31 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { FastMCP, OAuthProvider } from 'fastmcp';
|
|
5
|
+
import { OAuthProxy } from 'fastmcp/auth';
|
|
6
|
+
import { getConfig } from './config.js';
|
|
7
|
+
import { registerSmartScraperTool } from './tools/smartscraper.js';
|
|
8
|
+
import { registerFunctionTool } from './tools/function.js';
|
|
9
|
+
import { registerDownloadTool } from './tools/download.js';
|
|
10
|
+
import { registerExportTool } from './tools/export.js';
|
|
11
|
+
import { registerAgentTools } from './tools/agent.js';
|
|
12
|
+
import { registerSearchTool } from './tools/search.js';
|
|
13
|
+
import { registerMapTool } from './tools/map.js';
|
|
14
|
+
import { registerCrawlTool } from './tools/crawl.js';
|
|
15
|
+
import { registerPerformanceTool } from './tools/performance.js';
|
|
16
|
+
import { registerApiDocsResource } from './resources/api-docs.js';
|
|
17
|
+
import { registerStatusResource } from './resources/status.js';
|
|
18
|
+
import { registerScrapeUrlPrompt } from './prompts/scrape-url.js';
|
|
19
|
+
import { registerExtractContentPrompt } from './prompts/extract-content.js';
|
|
20
|
+
import { AnalyticsHelper } from './lib/analytics.js';
|
|
21
|
+
import { resolveApiKey, installSupabaseTokenTtlPatch, } from './lib/account-resolver.js';
|
|
22
|
+
import { BoundedEventStore } from './lib/bounded-event-store.js';
|
|
23
|
+
import { RedisOAuthProxy } from './lib/redis-oauth-proxy.js';
|
|
24
|
+
import { Redis } from 'ioredis';
|
|
25
|
+
const pkg = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '..', '..', 'package.json'), 'utf-8'));
|
|
26
|
+
const config = getConfig();
|
|
27
|
+
// Override Supabase's short-lived (~60s) OAuth token TTL so MCP clients don't
|
|
28
|
+
// thrash refresh. Narrowly scoped to the Supabase token endpoint; see
|
|
29
|
+
// installSupabaseTokenTtlPatch in account-resolver.ts for the full rationale.
|
|
30
|
+
if (config.oauthEnabled && config.supabaseUrl) {
|
|
31
|
+
installSupabaseTokenTtlPatch(config.supabaseUrl, 3600);
|
|
32
|
+
}
|
|
33
|
+
const analytics = new AnalyticsHelper(config.analyticsEnabled, config.sqsQueueUrl, config.sqsRegion);
|
|
34
|
+
// Passthrough OAuth provider: disables FastMCP's token-swap mode so the MCP client
|
|
35
|
+
// receives the raw Supabase JWT directly.
|
|
36
|
+
const redisClient = config.redisUrl ? new Redis(config.redisUrl) : undefined;
|
|
37
|
+
if (redisClient) {
|
|
38
|
+
redisClient.on('error', (err) => console.error('[browserless-mcp] Redis error:', err.message));
|
|
39
|
+
// Redis is only configured for the hosted httpStream deployment (REDIS_URL is
|
|
40
|
+
// not set in stdio mode), so writing the "connected" line to stdout doesn't
|
|
41
|
+
// interfere with MCP-over-stdio protocol framing.
|
|
42
|
+
redisClient.on('ready', () => console.log('[browserless-mcp] Redis connected for OAuth state storage'));
|
|
43
|
+
}
|
|
44
|
+
class PassthroughOAuthProvider extends OAuthProvider {
|
|
45
|
+
createProxy() {
|
|
46
|
+
const proxyConfig = {
|
|
47
|
+
allowedRedirectUriPatterns: config.oauthAllowedRedirectUriPatterns,
|
|
48
|
+
baseUrl: this.config.baseUrl,
|
|
49
|
+
consentRequired: false,
|
|
50
|
+
enableTokenSwap: false,
|
|
51
|
+
scopes: this.config.scopes ?? [],
|
|
52
|
+
upstreamAuthorizationEndpoint: this.genericConfig.authorizationEndpoint,
|
|
53
|
+
upstreamClientId: this.config.clientId,
|
|
54
|
+
upstreamClientSecret: this.config.clientSecret,
|
|
55
|
+
upstreamTokenEndpoint: this.genericConfig.tokenEndpoint,
|
|
56
|
+
upstreamTokenEndpointAuthMethod: this.genericConfig.tokenEndpointAuthMethod ?? 'client_secret_basic',
|
|
57
|
+
};
|
|
58
|
+
if (redisClient) {
|
|
59
|
+
return new RedisOAuthProxy(proxyConfig, redisClient);
|
|
60
|
+
}
|
|
61
|
+
return new OAuthProxy(proxyConfig);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const oauthProvider = config.oauthEnabled && config.transport === 'httpStream'
|
|
65
|
+
? new PassthroughOAuthProvider({
|
|
66
|
+
baseUrl: config.mcpBaseUrl,
|
|
67
|
+
clientId: config.supabaseOAuthClientId,
|
|
68
|
+
clientSecret: config.supabaseOAuthClientSecret,
|
|
69
|
+
authorizationEndpoint: `${config.supabaseUrl}/auth/v1/oauth/authorize`,
|
|
70
|
+
tokenEndpoint: `${config.supabaseUrl}/auth/v1/oauth/token`,
|
|
71
|
+
scopes: ['email'],
|
|
72
|
+
consentRequired: false,
|
|
73
|
+
})
|
|
74
|
+
: undefined;
|
|
75
|
+
// Hybrid authenticate, in order: (1) Authorization header with a plain API
|
|
76
|
+
// key or (2) ?token= query param → direct token session; (3) Authorization
|
|
77
|
+
// header with a Supabase JWT → resolve the Browserless API key via PostgREST.
|
|
78
|
+
const hybridAuthenticate = config.transport === 'httpStream'
|
|
79
|
+
? async (request) => {
|
|
80
|
+
const params = new URLSearchParams(request.url?.split('?')[1] ?? '');
|
|
81
|
+
const authHeader = request.headers.authorization;
|
|
82
|
+
const headerToken = authHeader?.startsWith('Bearer ')
|
|
83
|
+
? authHeader.slice(7)
|
|
84
|
+
: authHeader;
|
|
85
|
+
const apiUrl = request.headers['x-browserless-api-url'] ??
|
|
86
|
+
params.get('browserlessUrl') ??
|
|
87
|
+
config.browserlessApiUrl;
|
|
88
|
+
// JWTs have 3 dot-separated base64url segments; plain API keys do not.
|
|
89
|
+
const isJwt = headerToken ? headerToken.split('.').length === 3 : false;
|
|
90
|
+
// 1. Authorization header with plain API key
|
|
91
|
+
if (headerToken && !isJwt) {
|
|
92
|
+
return { token: headerToken, apiUrl };
|
|
93
|
+
}
|
|
94
|
+
// 2. ?token= query param
|
|
95
|
+
const directToken = params.get('token') || undefined;
|
|
96
|
+
if (directToken) {
|
|
97
|
+
return { token: directToken, apiUrl };
|
|
98
|
+
}
|
|
99
|
+
// 3. Authorization header with JWT → decode Supabase token directly
|
|
100
|
+
if (isJwt && headerToken) {
|
|
101
|
+
const { apiKey } = await resolveApiKey(config.supabaseUrl, config.supabaseServiceRoleKey, headerToken);
|
|
102
|
+
return { token: apiKey, apiUrl };
|
|
103
|
+
}
|
|
104
|
+
throw new Error('No Browserless API token provided. ' +
|
|
105
|
+
'Pass it as Authorization: Bearer <token> header, ' +
|
|
106
|
+
'?token= query parameter, or authenticate via OAuth.');
|
|
107
|
+
}
|
|
108
|
+
: undefined;
|
|
109
|
+
const server = new FastMCP({
|
|
110
|
+
name: 'browserless-mcp',
|
|
111
|
+
version: pkg.version,
|
|
112
|
+
...(oauthProvider ? { auth: oauthProvider } : {}),
|
|
113
|
+
authenticate: hybridAuthenticate,
|
|
114
|
+
});
|
|
115
|
+
registerSmartScraperTool(server, config, analytics);
|
|
116
|
+
registerFunctionTool(server, config, analytics);
|
|
117
|
+
registerDownloadTool(server, config, analytics);
|
|
118
|
+
registerExportTool(server, config, analytics);
|
|
119
|
+
registerAgentTools(server, config, analytics);
|
|
120
|
+
registerSearchTool(server, config, analytics);
|
|
121
|
+
registerMapTool(server, config, analytics);
|
|
122
|
+
registerCrawlTool(server, config, analytics);
|
|
123
|
+
registerPerformanceTool(server, config, analytics);
|
|
124
|
+
registerApiDocsResource(server, config);
|
|
125
|
+
registerStatusResource(server, config);
|
|
126
|
+
registerScrapeUrlPrompt(server);
|
|
127
|
+
registerExtractContentPrompt(server);
|
|
128
|
+
server.on('connect', (event) => {
|
|
129
|
+
const id = event.session.sessionId ?? 'stdio';
|
|
130
|
+
console.error(`[browserless-mcp] Client connected: ${id}`);
|
|
131
|
+
});
|
|
132
|
+
server.on('disconnect', (event) => {
|
|
133
|
+
const id = event.session.sessionId ?? 'stdio';
|
|
134
|
+
console.error(`[browserless-mcp] Client disconnected: ${id}`);
|
|
135
|
+
});
|
|
136
|
+
if (config.transport === 'httpStream') {
|
|
137
|
+
server.start({
|
|
138
|
+
transportType: 'httpStream',
|
|
139
|
+
httpStream: {
|
|
140
|
+
port: config.port,
|
|
141
|
+
host: '0.0.0.0',
|
|
142
|
+
eventStore: new BoundedEventStore(10_000),
|
|
143
|
+
stateless: false,
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
console.error(`[browserless-mcp] HTTP Streamable server listening on port ${config.port}`);
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
server.start({
|
|
150
|
+
transportType: 'stdio',
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
export { server };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
interface ResolvedAccount {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
email: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a Browserless API key from a Supabase access token (JWT)
|
|
7
|
+
* by extracting app_metadata.accountId and querying Supabase PostgREST.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveApiKey(supabaseUrl: string, serviceRoleKey: string, accessToken: string): Promise<ResolvedAccount>;
|
|
10
|
+
export declare function clearResolverCache(): void;
|
|
11
|
+
/**
|
|
12
|
+
* Patch `globalThis.fetch` to extend `expires_in` on Supabase OAuth token
|
|
13
|
+
* responses so clients don't thrash refresh against the ~60s default. Global
|
|
14
|
+
* because FastMCP's OAuthProxy has no fetch hook; matched origin/path-exact.
|
|
15
|
+
*/
|
|
16
|
+
export declare function installSupabaseTokenTtlPatch(supabaseUrl: string, ttlSeconds: number): void;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { ResponseCache } from './cache.js';
|
|
2
|
+
import { decodeJwtPayload } from './utils.js';
|
|
3
|
+
const CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
4
|
+
const cache = new ResponseCache(CACHE_TTL_MS);
|
|
5
|
+
/**
|
|
6
|
+
* Resolves a Browserless API key from a Supabase access token (JWT)
|
|
7
|
+
* by extracting app_metadata.accountId and querying Supabase PostgREST.
|
|
8
|
+
*/
|
|
9
|
+
export async function resolveApiKey(supabaseUrl, serviceRoleKey, accessToken) {
|
|
10
|
+
const payload = decodeJwtPayload(accessToken);
|
|
11
|
+
const accountId = payload.app_metadata?.accountId;
|
|
12
|
+
if (!accountId) {
|
|
13
|
+
throw new Error('Supabase JWT does not contain app_metadata.accountId. ' +
|
|
14
|
+
'The user may not have a Browserless account.');
|
|
15
|
+
}
|
|
16
|
+
const cached = cache.get(`account:${accountId}`);
|
|
17
|
+
if (cached) {
|
|
18
|
+
return cached;
|
|
19
|
+
}
|
|
20
|
+
const url = `${supabaseUrl}/rest/v1/accounts?account_id=eq.${encodeURIComponent(accountId)}&select=api_key,email`;
|
|
21
|
+
const response = await fetch(url, {
|
|
22
|
+
headers: {
|
|
23
|
+
apikey: serviceRoleKey,
|
|
24
|
+
Authorization: `Bearer ${serviceRoleKey}`,
|
|
25
|
+
Accept: 'application/json',
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error(`Supabase REST API returned ${response.status}: ${response.statusText}`);
|
|
30
|
+
}
|
|
31
|
+
const rows = (await response.json());
|
|
32
|
+
const account = rows[0];
|
|
33
|
+
if (!account?.api_key || !account?.email) {
|
|
34
|
+
throw new Error('Account not found or missing api_key/email.');
|
|
35
|
+
}
|
|
36
|
+
const resolved = {
|
|
37
|
+
apiKey: account.api_key,
|
|
38
|
+
email: account.email,
|
|
39
|
+
};
|
|
40
|
+
cache.set(`account:${accountId}`, resolved);
|
|
41
|
+
return resolved;
|
|
42
|
+
}
|
|
43
|
+
export function clearResolverCache() {
|
|
44
|
+
cache.clear();
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Patch `globalThis.fetch` to extend `expires_in` on Supabase OAuth token
|
|
48
|
+
* responses so clients don't thrash refresh against the ~60s default. Global
|
|
49
|
+
* because FastMCP's OAuthProxy has no fetch hook; matched origin/path-exact.
|
|
50
|
+
*/
|
|
51
|
+
export function installSupabaseTokenTtlPatch(supabaseUrl, ttlSeconds) {
|
|
52
|
+
const supabaseOrigin = new URL(supabaseUrl).origin;
|
|
53
|
+
const TOKEN_PATHNAME = '/auth/v1/oauth/token';
|
|
54
|
+
const originalFetch = globalThis.fetch;
|
|
55
|
+
globalThis.fetch = async (...args) => {
|
|
56
|
+
const response = await originalFetch(...args);
|
|
57
|
+
const url = typeof args[0] === 'string'
|
|
58
|
+
? args[0]
|
|
59
|
+
: args[0] instanceof URL
|
|
60
|
+
? args[0].toString()
|
|
61
|
+
: args[0].url;
|
|
62
|
+
const reqUrl = new URL(url);
|
|
63
|
+
if (!response.ok ||
|
|
64
|
+
reqUrl.origin !== supabaseOrigin ||
|
|
65
|
+
reqUrl.pathname !== TOKEN_PATHNAME) {
|
|
66
|
+
return response;
|
|
67
|
+
}
|
|
68
|
+
const body = (await response.json());
|
|
69
|
+
if (typeof body.expires_in === 'number' && body.expires_in < ttlSeconds) {
|
|
70
|
+
body.expires_in = ttlSeconds;
|
|
71
|
+
}
|
|
72
|
+
return new Response(JSON.stringify(body), {
|
|
73
|
+
status: response.status,
|
|
74
|
+
statusText: response.statusText,
|
|
75
|
+
headers: response.headers,
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { ActiveSession, AgentResponse, ProxyOptions } from '../@types/types.js';
|
|
3
|
+
export type { ProxyOptions, ActiveSession, AgentMessage, AgentResponse, AgentError, } from '../@types/types.js';
|
|
4
|
+
export declare const ProxyOptionsSchema: z.ZodObject<{
|
|
5
|
+
proxy: z.ZodOptional<z.ZodEnum<{
|
|
6
|
+
residential: "residential";
|
|
7
|
+
}>>;
|
|
8
|
+
proxyCountry: z.ZodOptional<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
9
|
+
proxyState: z.ZodOptional<z.ZodString>;
|
|
10
|
+
proxyCity: z.ZodOptional<z.ZodString>;
|
|
11
|
+
proxySticky: z.ZodOptional<z.ZodBoolean>;
|
|
12
|
+
proxyLocaleMatch: z.ZodOptional<z.ZodBoolean>;
|
|
13
|
+
proxyPreset: z.ZodOptional<z.ZodString>;
|
|
14
|
+
externalProxyServer: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
export declare const PROXY_FIELDS: Array<keyof ProxyOptions>;
|
|
17
|
+
/**
|
|
18
|
+
* Thrown when the agent WebSocket upgrade is rejected with a non-101 HTTP
|
|
19
|
+
* response. Carries the status code and body so the tool layer can render a
|
|
20
|
+
* status-specific UserError.
|
|
21
|
+
*/
|
|
22
|
+
export declare class UpgradeError extends Error {
|
|
23
|
+
readonly statusCode: number;
|
|
24
|
+
readonly statusMessage: string;
|
|
25
|
+
readonly body: string;
|
|
26
|
+
constructor(statusCode: number, statusMessage: string, body: string);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* UpgradeError specialization for the profile-not-found case (404 on the WS
|
|
30
|
+
* upgrade when `?profile=` was supplied). Mirrors api-client.ts so all tools
|
|
31
|
+
* surface profile errors through the same UserError pattern.
|
|
32
|
+
*/
|
|
33
|
+
export declare class ProfileNotFoundError extends UpgradeError {
|
|
34
|
+
readonly profile: string;
|
|
35
|
+
constructor(profile: string, statusMessage: string, body: string);
|
|
36
|
+
}
|
|
37
|
+
export declare const isRetryableUpgradeError: (err: unknown) => boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Build a stable, credential-free key segment for a proxy config — identical
|
|
40
|
+
* configs fingerprint the same regardless of key order. `externalProxyServer`
|
|
41
|
+
* is SHA-256 hashed so credentials never land in the eviction log.
|
|
42
|
+
*/
|
|
43
|
+
export declare const proxyFingerprint: (proxy?: ProxyOptions) => string;
|
|
44
|
+
/**
|
|
45
|
+
* Build the WebSocket URL for `/chromium/agent`: normalize trailing slashes,
|
|
46
|
+
* swap http(s)→ws(s), and append `token` plus proxy params. Boolean proxy
|
|
47
|
+
* flags follow the API's presence-only contract (set only when truthy).
|
|
48
|
+
*/
|
|
49
|
+
export declare const buildAgentWsUrl: (apiUrl: string, token: string, proxy?: ProxyOptions, profile?: string) => string;
|
|
50
|
+
export declare const getOrCreateSession: (mcpSessionId: string | undefined, apiUrl: string, token: string, proxy?: ProxyOptions, profile?: string) => Promise<ActiveSession>;
|
|
51
|
+
export declare const send: (session: ActiveSession, method: string, params?: Record<string, unknown>, timeoutMs?: number) => Promise<AgentResponse>;
|
|
52
|
+
export declare const closeSession: (mcpSessionId: string | undefined, token: string, proxy?: ProxyOptions, profile?: string) => void;
|
|
53
|
+
/**
|
|
54
|
+
* Force-destroy a session after a browser crash or unrecoverable state, so
|
|
55
|
+
* the next call reconnects fresh. Unlike `closeSession`, it also drops any
|
|
56
|
+
* in-flight connect for the key so a concurrent caller can't reuse a dead WS.
|
|
57
|
+
*/
|
|
58
|
+
export declare const destroySession: (mcpSessionId: string | undefined, token: string, proxy?: ProxyOptions, profile?: string) => void;
|