@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,538 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type WebSocket from 'ws';
|
|
3
|
+
import type {
|
|
4
|
+
ScrapeFormatSchema,
|
|
5
|
+
SmartScraperParamsSchema,
|
|
6
|
+
SmartScraperResponseSchema,
|
|
7
|
+
} from '../tools/smartscraper.js';
|
|
8
|
+
import type { FunctionParamsSchema } from '../tools/function.js';
|
|
9
|
+
import type { DownloadParamsSchema } from '../tools/download.js';
|
|
10
|
+
import type { ExportParamsSchema } from '../tools/export.js';
|
|
11
|
+
import type {
|
|
12
|
+
SearchSourceSchema,
|
|
13
|
+
SearchCategorySchema,
|
|
14
|
+
TimeBasedOptionsSchema,
|
|
15
|
+
SearchParamsSchema,
|
|
16
|
+
} from '../tools/search.js';
|
|
17
|
+
import type { SitemapModeSchema, MapParamsSchema } from '../tools/map.js';
|
|
18
|
+
import type {
|
|
19
|
+
LighthouseCategorySchema,
|
|
20
|
+
PerformanceParamsSchema,
|
|
21
|
+
} from '../tools/performance.js';
|
|
22
|
+
import type {
|
|
23
|
+
CrawlStatusSchema,
|
|
24
|
+
PageStatusSchema,
|
|
25
|
+
CrawlSitemapModeSchema,
|
|
26
|
+
CrawlFormatSchema,
|
|
27
|
+
CrawlParamsSchema,
|
|
28
|
+
} from '../tools/crawl.js';
|
|
29
|
+
import type { AgentParamsSchema } from '../tools/agent.js';
|
|
30
|
+
import type { ProxyOptionsSchema } from '../lib/agent-client.js';
|
|
31
|
+
|
|
32
|
+
/* ------------------------------------------------------------------ */
|
|
33
|
+
/* Session & auth */
|
|
34
|
+
/* ------------------------------------------------------------------ */
|
|
35
|
+
|
|
36
|
+
export interface BrowserlessSession extends Record<string, unknown> {
|
|
37
|
+
token: string;
|
|
38
|
+
apiUrl: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface SupabaseJwtPayload {
|
|
42
|
+
sub?: string;
|
|
43
|
+
email?: string;
|
|
44
|
+
app_metadata?: {
|
|
45
|
+
accountId?: string;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* ------------------------------------------------------------------ */
|
|
50
|
+
/* Config */
|
|
51
|
+
/* ------------------------------------------------------------------ */
|
|
52
|
+
|
|
53
|
+
export interface McpConfig {
|
|
54
|
+
browserlessToken?: string;
|
|
55
|
+
browserlessApiUrl: string;
|
|
56
|
+
transport: 'stdio' | 'httpStream';
|
|
57
|
+
port: number;
|
|
58
|
+
requestTimeout: number;
|
|
59
|
+
maxRetries: number;
|
|
60
|
+
cacheTtlMs: number;
|
|
61
|
+
analyticsEnabled: boolean;
|
|
62
|
+
sqsQueueUrl?: string;
|
|
63
|
+
sqsRegion: string;
|
|
64
|
+
oauthEnabled: boolean;
|
|
65
|
+
supabaseUrl: string;
|
|
66
|
+
supabaseOAuthClientId: string;
|
|
67
|
+
supabaseOAuthClientSecret: string;
|
|
68
|
+
supabaseServiceRoleKey: string;
|
|
69
|
+
mcpBaseUrl: string;
|
|
70
|
+
redisUrl?: string;
|
|
71
|
+
oauthAllowedRedirectUriPatterns: string[];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* ------------------------------------------------------------------ */
|
|
75
|
+
/* Analytics */
|
|
76
|
+
/* ------------------------------------------------------------------ */
|
|
77
|
+
|
|
78
|
+
export interface AnalyticsEvent {
|
|
79
|
+
event_type: string;
|
|
80
|
+
time: number;
|
|
81
|
+
session_id?: number;
|
|
82
|
+
event_properties: Record<string, unknown> & { token: string };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* ------------------------------------------------------------------ */
|
|
86
|
+
/* Retry */
|
|
87
|
+
/* ------------------------------------------------------------------ */
|
|
88
|
+
|
|
89
|
+
export interface RetryOptions {
|
|
90
|
+
maxRetries: number;
|
|
91
|
+
baseDelayMs: number;
|
|
92
|
+
shouldRetry?: (error: Error) => boolean;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* ------------------------------------------------------------------ */
|
|
96
|
+
/* Agent protocol */
|
|
97
|
+
/* ------------------------------------------------------------------ */
|
|
98
|
+
|
|
99
|
+
export interface AgentMessage {
|
|
100
|
+
id: number;
|
|
101
|
+
method: string;
|
|
102
|
+
params?: Record<string, unknown>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface AgentError {
|
|
106
|
+
code?: string;
|
|
107
|
+
message: string;
|
|
108
|
+
retryable?: boolean;
|
|
109
|
+
suggestion?: string;
|
|
110
|
+
snapshot?: SnapshotResult;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export interface AgentResponse {
|
|
114
|
+
id: number;
|
|
115
|
+
result?: unknown;
|
|
116
|
+
error?: AgentError;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface SnapshotElement {
|
|
120
|
+
ref: number;
|
|
121
|
+
role: string;
|
|
122
|
+
name: string;
|
|
123
|
+
selector: string;
|
|
124
|
+
tag: string;
|
|
125
|
+
text?: string;
|
|
126
|
+
value?: string;
|
|
127
|
+
type?: string;
|
|
128
|
+
placeholder?: string;
|
|
129
|
+
id?: string;
|
|
130
|
+
href?: string;
|
|
131
|
+
disabled?: boolean;
|
|
132
|
+
checked?: boolean;
|
|
133
|
+
focused?: boolean;
|
|
134
|
+
required?: boolean;
|
|
135
|
+
ariaLabel?: string;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export interface TabInfo {
|
|
139
|
+
targetId: string;
|
|
140
|
+
url: string;
|
|
141
|
+
title: string;
|
|
142
|
+
active: boolean;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface SnapshotResult {
|
|
146
|
+
url: string;
|
|
147
|
+
title: string;
|
|
148
|
+
elements: SnapshotElement[];
|
|
149
|
+
time: number;
|
|
150
|
+
tabs?: TabInfo[];
|
|
151
|
+
activeTargetId?: string | null;
|
|
152
|
+
detectedChallenges?: string[];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export interface ActiveSession {
|
|
156
|
+
ws: WebSocket;
|
|
157
|
+
msgId: number;
|
|
158
|
+
// Identity fields: these feed the session-cache key (see getSessionKey).
|
|
159
|
+
// Mutating them post-creation would desync the cache, so they're readonly.
|
|
160
|
+
readonly apiUrl: string;
|
|
161
|
+
readonly token: string;
|
|
162
|
+
readonly proxy?: ProxyOptions;
|
|
163
|
+
readonly profile?: string;
|
|
164
|
+
reconnecting?: Promise<WebSocket>;
|
|
165
|
+
skillState: SkillFireState;
|
|
166
|
+
lastUsedAt: number;
|
|
167
|
+
lastUrl?: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* ------------------------------------------------------------------ */
|
|
171
|
+
/* Error classifier */
|
|
172
|
+
/* ------------------------------------------------------------------ */
|
|
173
|
+
|
|
174
|
+
export type ErrorCategory =
|
|
175
|
+
| 'SELECTOR_MISS'
|
|
176
|
+
| 'SESSION_LOST'
|
|
177
|
+
| 'UNAUTHORIZED'
|
|
178
|
+
| 'FORBIDDEN'
|
|
179
|
+
| 'NOT_FOUND'
|
|
180
|
+
| 'SERVER_ERROR'
|
|
181
|
+
| 'NAVIGATION_FAILED'
|
|
182
|
+
| 'TIMEOUT'
|
|
183
|
+
| 'INVALID_PARAMS'
|
|
184
|
+
| 'UNKNOWN';
|
|
185
|
+
|
|
186
|
+
export interface ClassifiedError {
|
|
187
|
+
category: ErrorCategory;
|
|
188
|
+
code?: string;
|
|
189
|
+
status?: number;
|
|
190
|
+
recovery: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface ClassifyInput {
|
|
194
|
+
err: AgentError | { code?: string; message: string; status?: number };
|
|
195
|
+
cmd: { method: string; params: Record<string, unknown> };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* ------------------------------------------------------------------ */
|
|
199
|
+
/* Skills */
|
|
200
|
+
/* ------------------------------------------------------------------ */
|
|
201
|
+
|
|
202
|
+
export type SkillId =
|
|
203
|
+
| 'shadow-dom'
|
|
204
|
+
| 'cookie-consent'
|
|
205
|
+
| 'modals'
|
|
206
|
+
| 'captchas'
|
|
207
|
+
| 'snapshot-misses'
|
|
208
|
+
| 'dynamic-content'
|
|
209
|
+
| 'screenshots'
|
|
210
|
+
| 'tabs'
|
|
211
|
+
| 'autonomous-login';
|
|
212
|
+
|
|
213
|
+
export interface DetectContext {
|
|
214
|
+
snapshot?: SnapshotResult;
|
|
215
|
+
error?: AgentError;
|
|
216
|
+
cmd?: { method: string; params: Record<string, unknown> };
|
|
217
|
+
resp?: unknown;
|
|
218
|
+
apiUrl?: string;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
export interface SkillFireState {
|
|
222
|
+
fired: Map<SkillId, number>;
|
|
223
|
+
cmdIndex: number;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* A single predicate evaluated against a DetectContext. Predicates compose
|
|
228
|
+
* via Trigger (AND-clause) and SkillSpec.triggers (OR of AND-clauses).
|
|
229
|
+
*/
|
|
230
|
+
export type Predicate =
|
|
231
|
+
| {
|
|
232
|
+
kind: 'snapshot.has-element';
|
|
233
|
+
roles?: string[];
|
|
234
|
+
nameRegex?: RegExp;
|
|
235
|
+
selectorPrefix?: string;
|
|
236
|
+
}
|
|
237
|
+
| { kind: 'snapshot.has-input-type'; type: string }
|
|
238
|
+
| { kind: 'snapshot.url-match'; regex: RegExp }
|
|
239
|
+
| { kind: 'snapshot.has-detected-challenge' }
|
|
240
|
+
| { kind: 'snapshot.tabs-at-least'; count: number }
|
|
241
|
+
| { kind: 'snapshot.element-cap-hit' }
|
|
242
|
+
| { kind: 'error.code'; codes: string[] }
|
|
243
|
+
| { kind: 'error.message-match'; regex: RegExp }
|
|
244
|
+
| { kind: 'command.method'; methods: string[] }
|
|
245
|
+
| { kind: 'command.method-prefix'; prefix: string }
|
|
246
|
+
| { kind: 'command.selector-not-deep' };
|
|
247
|
+
|
|
248
|
+
/** AND-clause: every predicate must match. */
|
|
249
|
+
export type Trigger = Predicate[];
|
|
250
|
+
|
|
251
|
+
export interface SkillSpec {
|
|
252
|
+
id: SkillId;
|
|
253
|
+
path: string;
|
|
254
|
+
cloudOnly?: boolean;
|
|
255
|
+
refireAfter?: number;
|
|
256
|
+
/** OR of triggers; each trigger is an AND-clause of predicates. */
|
|
257
|
+
triggers: Trigger[];
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export interface Skill extends SkillSpec {
|
|
261
|
+
body: string;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* ------------------------------------------------------------------ */
|
|
265
|
+
/* Zod-inferred parameter & response types */
|
|
266
|
+
/* ------------------------------------------------------------------ */
|
|
267
|
+
|
|
268
|
+
export type ScrapeFormat = z.infer<typeof ScrapeFormatSchema>;
|
|
269
|
+
export type SmartScraperParams = z.infer<typeof SmartScraperParamsSchema>;
|
|
270
|
+
export type SmartScraperResponse = z.infer<typeof SmartScraperResponseSchema>;
|
|
271
|
+
export type FunctionParams = z.infer<typeof FunctionParamsSchema>;
|
|
272
|
+
export type DownloadParams = z.infer<typeof DownloadParamsSchema>;
|
|
273
|
+
export type ExportParams = z.infer<typeof ExportParamsSchema>;
|
|
274
|
+
export type ProxyOptions = z.infer<typeof ProxyOptionsSchema>;
|
|
275
|
+
export type SearchSource = z.infer<typeof SearchSourceSchema>;
|
|
276
|
+
export type SearchCategory = z.infer<typeof SearchCategorySchema>;
|
|
277
|
+
export type TimeBasedOptions = z.infer<typeof TimeBasedOptionsSchema>;
|
|
278
|
+
export type SearchParams = z.infer<typeof SearchParamsSchema>;
|
|
279
|
+
export type SitemapMode = z.infer<typeof SitemapModeSchema>;
|
|
280
|
+
export type MapParams = z.infer<typeof MapParamsSchema>;
|
|
281
|
+
export type LighthouseCategory = z.infer<typeof LighthouseCategorySchema>;
|
|
282
|
+
export type PerformanceParams = z.infer<typeof PerformanceParamsSchema>;
|
|
283
|
+
export type CrawlStatus = z.infer<typeof CrawlStatusSchema>;
|
|
284
|
+
export type PageStatus = z.infer<typeof PageStatusSchema>;
|
|
285
|
+
export type CrawlSitemapMode = z.infer<typeof CrawlSitemapModeSchema>;
|
|
286
|
+
export type CrawlFormat = z.infer<typeof CrawlFormatSchema>;
|
|
287
|
+
export type CrawlParams = z.infer<typeof CrawlParamsSchema>;
|
|
288
|
+
export type AgentParams = z.infer<typeof AgentParamsSchema>;
|
|
289
|
+
|
|
290
|
+
/* ------------------------------------------------------------------ */
|
|
291
|
+
/* Generic HTTP response wrapper used by function / download / export */
|
|
292
|
+
/* ------------------------------------------------------------------ */
|
|
293
|
+
|
|
294
|
+
export interface GenericApiResult {
|
|
295
|
+
/** Response body as text (may be base64-encoded for binary) */
|
|
296
|
+
data: string;
|
|
297
|
+
/** Content-Type header value */
|
|
298
|
+
contentType: string;
|
|
299
|
+
/** Content-Disposition header value, if any */
|
|
300
|
+
contentDisposition: string | null;
|
|
301
|
+
/** HTTP status code */
|
|
302
|
+
statusCode: number;
|
|
303
|
+
/** Whether the request succeeded (2xx) */
|
|
304
|
+
ok: boolean;
|
|
305
|
+
/** Size in bytes of the response body */
|
|
306
|
+
size: number;
|
|
307
|
+
/** Whether the data field is base64-encoded binary */
|
|
308
|
+
isBinary: boolean;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/* ------------------------------------------------------------------ */
|
|
312
|
+
/* Search */
|
|
313
|
+
/* ------------------------------------------------------------------ */
|
|
314
|
+
|
|
315
|
+
export interface SearchResultBase {
|
|
316
|
+
title: string;
|
|
317
|
+
url: string;
|
|
318
|
+
description: string;
|
|
319
|
+
position?: number;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export interface ScrapedContent {
|
|
323
|
+
markdown?: string;
|
|
324
|
+
html?: string;
|
|
325
|
+
links?: string[];
|
|
326
|
+
screenshot?: string;
|
|
327
|
+
metadata?: {
|
|
328
|
+
statusCode: number | null;
|
|
329
|
+
strategy?: string;
|
|
330
|
+
error?: string;
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export interface WebSearchResult extends SearchResultBase, ScrapedContent {}
|
|
335
|
+
|
|
336
|
+
export interface NewsSearchResult extends WebSearchResult {
|
|
337
|
+
date?: string;
|
|
338
|
+
imageUrl?: string;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export interface ImageSearchResult {
|
|
342
|
+
title?: string;
|
|
343
|
+
imageUrl?: string;
|
|
344
|
+
imageWidth?: number;
|
|
345
|
+
imageHeight?: number;
|
|
346
|
+
url?: string;
|
|
347
|
+
position?: number;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export interface SearchResponseData {
|
|
351
|
+
web?: WebSearchResult[];
|
|
352
|
+
news?: NewsSearchResult[];
|
|
353
|
+
images?: ImageSearchResult[];
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export interface SearchResponse {
|
|
357
|
+
success: boolean;
|
|
358
|
+
data: SearchResponseData;
|
|
359
|
+
totalResults: number;
|
|
360
|
+
error?: string;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/* ------------------------------------------------------------------ */
|
|
364
|
+
/* Map */
|
|
365
|
+
/* ------------------------------------------------------------------ */
|
|
366
|
+
|
|
367
|
+
export interface MapLink {
|
|
368
|
+
url: string;
|
|
369
|
+
title?: string;
|
|
370
|
+
description?: string;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
export interface MapResponse {
|
|
374
|
+
success: boolean;
|
|
375
|
+
links?: MapLink[];
|
|
376
|
+
error?: string;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/* ------------------------------------------------------------------ */
|
|
380
|
+
/* Performance */
|
|
381
|
+
/* ------------------------------------------------------------------ */
|
|
382
|
+
|
|
383
|
+
export interface PerformanceResponse {
|
|
384
|
+
data: Record<string, unknown>;
|
|
385
|
+
type: string;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/* ------------------------------------------------------------------ */
|
|
389
|
+
/* Crawl */
|
|
390
|
+
/* ------------------------------------------------------------------ */
|
|
391
|
+
|
|
392
|
+
export interface CrawlStartResponse {
|
|
393
|
+
success: boolean;
|
|
394
|
+
id: string;
|
|
395
|
+
url: string;
|
|
396
|
+
error?: string;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export interface CrawlPageMetadata {
|
|
400
|
+
title: string | null;
|
|
401
|
+
description: string | null;
|
|
402
|
+
language: string | null;
|
|
403
|
+
scrapedAt: string | null;
|
|
404
|
+
sourceURL: string;
|
|
405
|
+
statusCode: number | null;
|
|
406
|
+
error: string | null;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
export interface CrawlPageResult {
|
|
410
|
+
status: PageStatus;
|
|
411
|
+
contentUrl: string | null;
|
|
412
|
+
metadata: CrawlPageMetadata;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
export interface CrawlStatusResponse {
|
|
416
|
+
status: CrawlStatus;
|
|
417
|
+
total: number;
|
|
418
|
+
completed: number;
|
|
419
|
+
failed: number;
|
|
420
|
+
expiresAt: string | null;
|
|
421
|
+
next: string | null;
|
|
422
|
+
data: CrawlPageResult[];
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/* ------------------------------------------------------------------ */
|
|
426
|
+
/* API client requests, results, and interface */
|
|
427
|
+
/* ------------------------------------------------------------------ */
|
|
428
|
+
|
|
429
|
+
export interface SmartScrapeRequest {
|
|
430
|
+
url: string;
|
|
431
|
+
formats?: ScrapeFormat[];
|
|
432
|
+
timeout?: number;
|
|
433
|
+
profile?: string;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export type SmartScrapeResult = SmartScraperResponse & { cacheHit: boolean };
|
|
437
|
+
|
|
438
|
+
export interface FunctionRequest {
|
|
439
|
+
code: string;
|
|
440
|
+
context?: Record<string, unknown>;
|
|
441
|
+
timeout?: number;
|
|
442
|
+
profile?: string;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export interface DownloadRequest {
|
|
446
|
+
code: string;
|
|
447
|
+
context?: Record<string, unknown>;
|
|
448
|
+
timeout?: number;
|
|
449
|
+
profile?: string;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
export interface ExportRequest {
|
|
453
|
+
url: string;
|
|
454
|
+
gotoOptions?: Record<string, unknown>;
|
|
455
|
+
bestAttempt?: boolean;
|
|
456
|
+
includeResources?: boolean;
|
|
457
|
+
waitForTimeout?: number;
|
|
458
|
+
timeout?: number;
|
|
459
|
+
profile?: string;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
export interface SearchRequest {
|
|
463
|
+
query: string;
|
|
464
|
+
limit?: number;
|
|
465
|
+
lang?: string;
|
|
466
|
+
country?: string;
|
|
467
|
+
location?: string;
|
|
468
|
+
tbs?: TimeBasedOptions;
|
|
469
|
+
sources?: SearchSource[];
|
|
470
|
+
categories?: SearchCategory[];
|
|
471
|
+
scrapeOptions?: {
|
|
472
|
+
formats?: string[];
|
|
473
|
+
onlyMainContent?: boolean;
|
|
474
|
+
includeTags?: string[];
|
|
475
|
+
excludeTags?: string[];
|
|
476
|
+
};
|
|
477
|
+
timeout?: number;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export interface MapRequest {
|
|
481
|
+
url: string;
|
|
482
|
+
search?: string;
|
|
483
|
+
limit?: number;
|
|
484
|
+
sitemap?: SitemapMode;
|
|
485
|
+
includeSubdomains?: boolean;
|
|
486
|
+
ignoreQueryParameters?: boolean;
|
|
487
|
+
timeout?: number;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
export interface PerformanceRequest {
|
|
491
|
+
url: string;
|
|
492
|
+
categories?: LighthouseCategory[];
|
|
493
|
+
budgets?: Array<Record<string, unknown>>;
|
|
494
|
+
timeout?: number;
|
|
495
|
+
profile?: string;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
export interface CrawlRequest {
|
|
499
|
+
url: string;
|
|
500
|
+
limit?: number;
|
|
501
|
+
maxDepth?: number;
|
|
502
|
+
maxRetries?: number;
|
|
503
|
+
allowExternalLinks?: boolean;
|
|
504
|
+
allowSubdomains?: boolean;
|
|
505
|
+
sitemap?: CrawlSitemapMode;
|
|
506
|
+
includePaths?: string[];
|
|
507
|
+
excludePaths?: string[];
|
|
508
|
+
delay?: number;
|
|
509
|
+
scrapeOptions?: {
|
|
510
|
+
formats?: CrawlFormat[];
|
|
511
|
+
onlyMainContent?: boolean;
|
|
512
|
+
includeTags?: string[];
|
|
513
|
+
excludeTags?: string[];
|
|
514
|
+
waitFor?: number;
|
|
515
|
+
headers?: Record<string, string>;
|
|
516
|
+
timeout?: number;
|
|
517
|
+
};
|
|
518
|
+
timeout?: number;
|
|
519
|
+
profile?: string;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export interface CrawlCancelResponse {
|
|
523
|
+
status: 'cancelled';
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
export interface ApiClient {
|
|
527
|
+
smartScrape(params: SmartScrapeRequest): Promise<SmartScrapeResult>;
|
|
528
|
+
runFunction(params: FunctionRequest): Promise<GenericApiResult>;
|
|
529
|
+
download(params: DownloadRequest): Promise<GenericApiResult>;
|
|
530
|
+
exportPage(params: ExportRequest): Promise<GenericApiResult>;
|
|
531
|
+
search(params: SearchRequest): Promise<SearchResponse>;
|
|
532
|
+
map(params: MapRequest): Promise<MapResponse>;
|
|
533
|
+
performance(params: PerformanceRequest): Promise<PerformanceResponse>;
|
|
534
|
+
crawl(params: CrawlRequest): Promise<CrawlStartResponse>;
|
|
535
|
+
getCrawl(crawlId: string, skip?: number): Promise<CrawlStatusResponse>;
|
|
536
|
+
cancelCrawl(crawlId: string): Promise<CrawlCancelResponse>;
|
|
537
|
+
getStatus(): Promise<{ ok: boolean; message: string }>;
|
|
538
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { parseCsv } from './lib/utils.js';
|
|
2
|
+
export const DEFAULT_API_URL = 'https://production-sfo.browserless.io';
|
|
3
|
+
// Baseline allow-list of redirect URIs for MCP clients that legitimately DCR
|
|
4
|
+
// against the hosted mcp.browserless.io deployment. Extend at runtime via
|
|
5
|
+
// OAUTH_ADDITIONAL_REDIRECT_URI_PATTERNS for additional clients.
|
|
6
|
+
const DEFAULT_ALLOWED_REDIRECT_URI_PATTERNS = [
|
|
7
|
+
'http://localhost:*', // Claude Desktop, VS Code, Windsurf, and anything else using a local loopback callback
|
|
8
|
+
'http://127.0.0.1:*',
|
|
9
|
+
'https://claude.ai/api/mcp/auth_callback', // Claude.ai web custom connectors
|
|
10
|
+
'https://chatgpt.com/connector/oauth/*', // ChatGPT / OpenAI Apps SDK connector (current per-connector callback id)
|
|
11
|
+
'https://chatgpt.com/connector_platform_oauth_redirect', // ChatGPT MCP connector (legacy, still honored for already-published apps)
|
|
12
|
+
'cursor://anysphere.cursor-mcp/oauth/callback', // Cursor (private-use URI scheme registered by the desktop app)
|
|
13
|
+
'https://api.devin.ai/mcp/oauth/callback', // Devin prod
|
|
14
|
+
'https://api.beta.devin.ai/mcp/oauth/callback', // Devin beta
|
|
15
|
+
'https://api.itsdev.in/mcp/oauth/callback', // Devin dev
|
|
16
|
+
];
|
|
17
|
+
export function getConfig() {
|
|
18
|
+
return {
|
|
19
|
+
browserlessToken: process.env.BROWSERLESS_TOKEN,
|
|
20
|
+
browserlessApiUrl: process.env.BROWSERLESS_API_URL ?? DEFAULT_API_URL,
|
|
21
|
+
transport: process.env.TRANSPORT ?? 'stdio',
|
|
22
|
+
port: parseInt(process.env.PORT ?? '8080', 10),
|
|
23
|
+
requestTimeout: parseInt(process.env.BROWSERLESS_TIMEOUT ?? '30000', 10),
|
|
24
|
+
maxRetries: parseInt(process.env.BROWSERLESS_MAX_RETRIES ?? '3', 10),
|
|
25
|
+
cacheTtlMs: parseInt(process.env.BROWSERLESS_CACHE_TTL ?? '60000', 10),
|
|
26
|
+
analyticsEnabled: process.env.ANALYTICS_ENABLED === 'true',
|
|
27
|
+
sqsQueueUrl: process.env.SQS_QUEUE_URL,
|
|
28
|
+
sqsRegion: process.env.SQS_REGION ?? 'us-west-2',
|
|
29
|
+
// OAuth (Supabase)
|
|
30
|
+
oauthEnabled: process.env.OAUTH_ENABLED === 'true',
|
|
31
|
+
supabaseUrl: process.env.SUPABASE_URL ?? '',
|
|
32
|
+
supabaseOAuthClientId: process.env.SUPABASE_OAUTH_CLIENT_ID ?? '',
|
|
33
|
+
supabaseOAuthClientSecret: process.env.SUPABASE_OAUTH_CLIENT_SECRET ?? '',
|
|
34
|
+
supabaseServiceRoleKey: process.env.SUPABASE_SERVICE_ROLE_KEY ?? '',
|
|
35
|
+
mcpBaseUrl: process.env.MCP_BASE_URL ?? 'https://mcp.browserless.io',
|
|
36
|
+
redisUrl: process.env.REDIS_URL || undefined,
|
|
37
|
+
oauthAllowedRedirectUriPatterns: [
|
|
38
|
+
...DEFAULT_ALLOWED_REDIRECT_URI_PATTERNS,
|
|
39
|
+
...parseCsv(process.env.OAUTH_ADDITIONAL_REDIRECT_URI_PATTERNS),
|
|
40
|
+
],
|
|
41
|
+
};
|
|
42
|
+
}
|