@roxybrowser/openapi 1.0.10-beta.0 → 1.0.10-beta.2

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/lib/cli.cjs ADDED
@@ -0,0 +1,3113 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ var commander = require('commander');
5
+ var index_js = require('@modelcontextprotocol/sdk/server/index.js');
6
+ var stdio_js = require('@modelcontextprotocol/sdk/server/stdio.js');
7
+ var types_js = require('@modelcontextprotocol/sdk/types.js');
8
+
9
+ // src/types.ts
10
+ var ConfigError = class extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = "ConfigError";
14
+ }
15
+ };
16
+
17
+ // src/utils/index.ts
18
+ var DEFAULT_CONFIG = {
19
+ apiHost: "http://127.0.0.1:50000",
20
+ timeout: 3e4
21
+ };
22
+ var ENV_KEYS = {
23
+ apiHost: "ROXY_API_HOST",
24
+ apiKey: "ROXY_API_KEY",
25
+ timeout: "ROXY_TIMEOUT"
26
+ };
27
+ function resolveConfig() {
28
+ const envHost = process.env[ENV_KEYS.apiHost];
29
+ const envKey = process.env[ENV_KEYS.apiKey];
30
+ const envTimeout = process.env[ENV_KEYS.timeout];
31
+ return {
32
+ apiHost: envHost ?? DEFAULT_CONFIG.apiHost,
33
+ apiKey: envKey ?? "",
34
+ timeout: envTimeout != null && envTimeout !== "" ? Number.parseInt(envTimeout, 10) : DEFAULT_CONFIG.timeout
35
+ };
36
+ }
37
+ function requireConfig() {
38
+ const config = resolveConfig();
39
+ if (!config.apiKey || config.apiKey.trim() === "") {
40
+ throw new ConfigError(
41
+ "API key is required. Set ROXY_API_KEY or pass --api-key. Get your key from RoxyBrowser: API \u2192 API\u914D\u7F6E \u2192 API Key"
42
+ );
43
+ }
44
+ return config;
45
+ }
46
+ async function request(endpoint, options = {}) {
47
+ const config = requireConfig();
48
+ const url = `${config.apiHost.replace(/\/$/, "")}${endpoint}`;
49
+ const controller = new AbortController();
50
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
51
+ try {
52
+ const response = await fetch(url, {
53
+ ...options,
54
+ headers: {
55
+ "Content-Type": "application/json",
56
+ "token": config.apiKey,
57
+ ...options.headers
58
+ },
59
+ signal: controller.signal
60
+ });
61
+ clearTimeout(timeoutId);
62
+ if (!response.ok) {
63
+ const responseText = await response.text().catch(() => "Unknown error");
64
+ throw new Error(
65
+ `HTTP ${response.status}: ${response.statusText} ${responseText}`
66
+ );
67
+ }
68
+ const result = await response.json();
69
+ return result;
70
+ } catch (error) {
71
+ clearTimeout(timeoutId);
72
+ throw error;
73
+ }
74
+ }
75
+
76
+ // src/modules/account.ts
77
+ var ListAccounts = class {
78
+ name = "roxy_list_accounts";
79
+ description = "Get list of accounts (platform credentials) in specified workspace";
80
+ inputSchema = {
81
+ type: "object",
82
+ properties: {
83
+ workspaceId: {
84
+ type: "number",
85
+ description: "Workspace ID"
86
+ },
87
+ accountId: {
88
+ type: "number",
89
+ description: "Account ID to filter by"
90
+ },
91
+ pageIndex: {
92
+ type: "number",
93
+ description: "Page index for pagination (default: 1)",
94
+ default: 1
95
+ },
96
+ pageSize: {
97
+ type: "number",
98
+ description: "Number of items per page (default: 15)",
99
+ default: 15
100
+ }
101
+ },
102
+ required: ["workspaceId"]
103
+ };
104
+ get schema() {
105
+ return {
106
+ name: this.name,
107
+ description: this.description,
108
+ inputSchema: this.inputSchema
109
+ };
110
+ }
111
+ async handle(params) {
112
+ const searchParams = new URLSearchParams();
113
+ searchParams.append("workspaceId", params.workspaceId.toString());
114
+ if (params.accountId)
115
+ searchParams.append("accountId", params.accountId.toString());
116
+ if (params.pageIndex)
117
+ searchParams.append("page_index", params.pageIndex.toString());
118
+ if (params.pageSize)
119
+ searchParams.append("page_size", params.pageSize.toString());
120
+ const result = await request(`/account/list?${searchParams}`, {
121
+ method: "GET"
122
+ });
123
+ const data = result.data;
124
+ let text = "";
125
+ if (result.code !== 0) {
126
+ text = `\u274C **Failed to list accounts:**
127
+
128
+ error message: ${result.msg}`;
129
+ } else {
130
+ text = `Found ${data.total} accounts in workspace ${params.workspaceId}:
131
+
132
+ ${data.rows.map(
133
+ (account) => `**${account.platformName}** (ID: ${account.id})
134
+ - Username: ${account.platformUserName}
135
+ - Platform URL: ${account.platformUrl}
136
+ - Remarks: ${account.platformRemarks || "N/A"}
137
+ - Created: ${account.createTime}`
138
+ ).join("\n\n")}`;
139
+ }
140
+ return {
141
+ content: [
142
+ {
143
+ type: "text",
144
+ text
145
+ }
146
+ ]
147
+ };
148
+ }
149
+ };
150
+ var CreateAccount = class {
151
+ name = "roxy_create_account";
152
+ description = "Create a new platform account with credentials";
153
+ inputSchema = {
154
+ type: "object",
155
+ properties: {
156
+ workspaceId: {
157
+ type: "number",
158
+ description: "Workspace ID"
159
+ },
160
+ platformUrl: {
161
+ type: "string",
162
+ description: "Business platform URL (e.g., https://www.tiktok.com/)"
163
+ },
164
+ platformUserName: {
165
+ type: "string",
166
+ description: "Account username"
167
+ },
168
+ platformPassword: {
169
+ type: "string",
170
+ description: "Account password"
171
+ },
172
+ platformEfa: {
173
+ type: "string",
174
+ description: "Account EFA"
175
+ },
176
+ platformCookies: {
177
+ type: "array",
178
+ description: "Account cookies",
179
+ items: {
180
+ type: "object",
181
+ properties: {
182
+ name: { type: "string" },
183
+ value: { type: "string" },
184
+ domain: { type: "string" }
185
+ },
186
+ required: ["name", "value", "domain"]
187
+ }
188
+ },
189
+ platformName: {
190
+ type: "string",
191
+ description: "Platform name"
192
+ },
193
+ platformRemarks: {
194
+ type: "string",
195
+ description: "Platform remarks/notes"
196
+ }
197
+ },
198
+ required: ["workspaceId", "platformUrl", "platformUserName", "platformPassword"]
199
+ };
200
+ get schema() {
201
+ return {
202
+ name: this.name,
203
+ description: this.description,
204
+ inputSchema: this.inputSchema
205
+ };
206
+ }
207
+ async handle(params) {
208
+ if (!params.workspaceId || !params.platformUrl || !params.platformUserName || !params.platformPassword) {
209
+ return {
210
+ content: [
211
+ {
212
+ type: "text",
213
+ text: "\u274C **Failed to create account:**\n\n workspaceId, platformUrl, platformUserName, and platformPassword are required"
214
+ }
215
+ ]
216
+ };
217
+ }
218
+ const { workspaceId, ...accountData } = params;
219
+ const result = await request("/account/create", {
220
+ method: "POST",
221
+ body: JSON.stringify({ workspaceId, ...accountData })
222
+ });
223
+ let text = "";
224
+ if (result.code !== 0) {
225
+ text = `\u274C **Failed to create account:**
226
+
227
+ error message: ${result.msg}`;
228
+ } else {
229
+ text = `\u2705 **Account Created Successfully**
230
+
231
+ **Platform:** ${params.platformName || params.platformUrl}
232
+ **Username:** ${params.platformUserName}
233
+ **Platform URL:** ${params.platformUrl}${params.platformRemarks ? `
234
+ **Remarks:** ${params.platformRemarks}` : ""}${params.platformEfa ? `
235
+ **EFA:** ${params.platformEfa}` : ""}${params.platformCookies && params.platformCookies.length > 0 ? `
236
+ **Cookies:** ${params.platformCookies.length} cookie(s)` : ""}
237
+
238
+ *Account has been created successfully.*`;
239
+ }
240
+ return {
241
+ content: [
242
+ {
243
+ type: "text",
244
+ text
245
+ }
246
+ ]
247
+ };
248
+ }
249
+ };
250
+ var BatchCreateAccounts = class {
251
+ name = "roxy_batch_create_accounts";
252
+ description = "Batch create multiple platform accounts";
253
+ inputSchema = {
254
+ type: "object",
255
+ properties: {
256
+ workspaceId: {
257
+ type: "number",
258
+ description: "Workspace ID"
259
+ },
260
+ accountList: {
261
+ type: "array",
262
+ description: "Array of account configurations",
263
+ items: {
264
+ type: "object",
265
+ properties: {
266
+ platformUrl: { type: "string" },
267
+ platformUserName: { type: "string" },
268
+ platformPassword: { type: "string" },
269
+ platformEfa: { type: "string" },
270
+ platformCookies: {
271
+ type: "array",
272
+ items: {
273
+ type: "object",
274
+ properties: {
275
+ name: { type: "string" },
276
+ value: { type: "string" },
277
+ domain: { type: "string" }
278
+ },
279
+ required: ["name", "value", "domain"]
280
+ }
281
+ },
282
+ platformName: { type: "string" },
283
+ platformRemarks: { type: "string" }
284
+ },
285
+ required: ["platformUrl", "platformUserName", "platformPassword"]
286
+ }
287
+ }
288
+ },
289
+ required: ["workspaceId", "accountList"]
290
+ };
291
+ get schema() {
292
+ return {
293
+ name: this.name,
294
+ description: this.description,
295
+ inputSchema: this.inputSchema
296
+ };
297
+ }
298
+ async handle(params) {
299
+ if (!params.workspaceId || !params.accountList || params.accountList.length === 0) {
300
+ return {
301
+ content: [
302
+ {
303
+ type: "text",
304
+ text: "\u274C **Failed to batch create accounts:**\n\n workspaceId and accountList are required"
305
+ }
306
+ ]
307
+ };
308
+ }
309
+ const { workspaceId, accountList } = params;
310
+ const result = await request("/account/batch_create", {
311
+ method: "POST",
312
+ body: JSON.stringify({ workspaceId, accountList })
313
+ });
314
+ let text = "";
315
+ if (result.code !== 0) {
316
+ text = `\u274C **Failed to batch create accounts:**
317
+
318
+ error message: ${result.msg}`;
319
+ } else {
320
+ text = `\u2705 **Batch Account Creation Successful**
321
+
322
+ **Count:** ${params.accountList.length} account(s)
323
+ **Workspace:** ${params.workspaceId}
324
+
325
+ *All accounts have been created successfully.*`;
326
+ }
327
+ return {
328
+ content: [
329
+ {
330
+ type: "text",
331
+ text
332
+ }
333
+ ]
334
+ };
335
+ }
336
+ };
337
+ var ModifyAccount = class {
338
+ name = "roxy_modify_account";
339
+ description = "Modify/update an existing platform account";
340
+ inputSchema = {
341
+ type: "object",
342
+ properties: {
343
+ workspaceId: {
344
+ type: "number",
345
+ description: "Workspace ID"
346
+ },
347
+ id: {
348
+ type: "number",
349
+ description: "Account ID to modify"
350
+ },
351
+ platformUrl: {
352
+ type: "string",
353
+ description: "Business platform URL"
354
+ },
355
+ platformUserName: {
356
+ type: "string",
357
+ description: "Account username"
358
+ },
359
+ platformPassword: {
360
+ type: "string",
361
+ description: "Account password"
362
+ },
363
+ platformEfa: {
364
+ type: "string",
365
+ description: "Account EFA"
366
+ },
367
+ platformCookies: {
368
+ type: "array",
369
+ description: "Account cookies",
370
+ items: {
371
+ type: "object",
372
+ properties: {
373
+ name: { type: "string" },
374
+ value: { type: "string" },
375
+ domain: { type: "string" }
376
+ },
377
+ required: ["name", "value", "domain"]
378
+ }
379
+ },
380
+ platformName: {
381
+ type: "string",
382
+ description: "Platform name"
383
+ },
384
+ platformRemarks: {
385
+ type: "string",
386
+ description: "Platform remarks/notes"
387
+ }
388
+ },
389
+ required: ["workspaceId", "id"]
390
+ };
391
+ get schema() {
392
+ return {
393
+ name: this.name,
394
+ description: this.description,
395
+ inputSchema: this.inputSchema
396
+ };
397
+ }
398
+ async handle(params) {
399
+ if (!params.workspaceId || !params.id) {
400
+ return {
401
+ content: [
402
+ {
403
+ type: "text",
404
+ text: "\u274C **Failed to modify account:**\n\n workspaceId and id are required"
405
+ }
406
+ ]
407
+ };
408
+ }
409
+ const { workspaceId, ...accountData } = params;
410
+ const result = await request("/account/modify", {
411
+ method: "POST",
412
+ body: JSON.stringify({ workspaceId, ...accountData })
413
+ });
414
+ let text = "";
415
+ if (result.code !== 0) {
416
+ text = `\u274C **Failed to modify account:**
417
+
418
+ error message: ${result.msg}`;
419
+ } else {
420
+ text = `\u2705 **Account Modified Successfully**
421
+
422
+ **Account ID:** ${params.id}${params.platformName ? `
423
+ **Platform:** ${params.platformName}` : ""}${params.platformUrl ? `
424
+ **Platform URL:** ${params.platformUrl}` : ""}${params.platformUserName ? `
425
+ **Username:** ${params.platformUserName}` : ""}${params.platformRemarks ? `
426
+ **Remarks:** ${params.platformRemarks}` : ""}
427
+
428
+ *Account configuration has been updated.*`;
429
+ }
430
+ return {
431
+ content: [
432
+ {
433
+ type: "text",
434
+ text
435
+ }
436
+ ]
437
+ };
438
+ }
439
+ };
440
+ var DeleteAccounts = class {
441
+ name = "roxy_delete_accounts";
442
+ description = "Delete one or more platform accounts";
443
+ inputSchema = {
444
+ type: "object",
445
+ properties: {
446
+ workspaceId: {
447
+ type: "number",
448
+ description: "Workspace ID"
449
+ },
450
+ ids: {
451
+ type: "array",
452
+ items: { type: "number" },
453
+ description: "Array of account IDs to delete"
454
+ }
455
+ },
456
+ required: ["workspaceId", "ids"]
457
+ };
458
+ get schema() {
459
+ return {
460
+ name: this.name,
461
+ description: this.description,
462
+ inputSchema: this.inputSchema
463
+ };
464
+ }
465
+ async handle(params) {
466
+ if (!params.workspaceId || !params.ids || params.ids.length === 0) {
467
+ return {
468
+ content: [
469
+ {
470
+ type: "text",
471
+ text: "\u274C **Failed to delete accounts:**\n\n workspaceId and ids are required"
472
+ }
473
+ ]
474
+ };
475
+ }
476
+ const { workspaceId, ids } = params;
477
+ const result = await request("/account/delete", {
478
+ method: "POST",
479
+ body: JSON.stringify({ workspaceId, ids })
480
+ });
481
+ let text = "";
482
+ if (result.code !== 0) {
483
+ text = `\u274C **Failed to delete accounts:**
484
+
485
+ error message: ${result.msg}`;
486
+ } else {
487
+ text = `\u2705 **Accounts Deleted Successfully**
488
+
489
+ **Count:** ${params.ids.length} account(s)
490
+ **Workspace:** ${params.workspaceId}
491
+
492
+ **Deleted Account IDs:**
493
+ ${params.ids.map((id, index) => ` ${index + 1}. ${id}`).join("\n")}
494
+
495
+ \u26A0\uFE0F **Warning:** Deleted accounts cannot be recovered.`;
496
+ }
497
+ return {
498
+ content: [
499
+ {
500
+ type: "text",
501
+ text
502
+ }
503
+ ]
504
+ };
505
+ }
506
+ };
507
+ var listAccounts = new ListAccounts();
508
+ var createAccount = new CreateAccount();
509
+ var batchCreateAccounts = new BatchCreateAccounts();
510
+ var modifyAccount = new ModifyAccount();
511
+ var deleteAccounts = new DeleteAccounts();
512
+
513
+ // src/modules/proxy.ts
514
+ var channelList = [
515
+ {
516
+ label: "IPRust.io",
517
+ type: "checkChannel",
518
+ value: "http://iprust.io/ip.json"
519
+ },
520
+ {
521
+ label: "IP-API",
522
+ type: "checkChannel",
523
+ value: "http://pro.ip-api.com/json?key=c1ulk9X5j8NKqTV"
524
+ },
525
+ {
526
+ label: "IP123.in",
527
+ type: "checkChannel",
528
+ value: "http://ip123.in/ip.json"
529
+ },
530
+ {
531
+ label: "IPinfo",
532
+ type: "checkChannel",
533
+ value: "http://ipinfo.io"
534
+ }
535
+ ];
536
+ var ProxyList = class {
537
+ name = "roxy_list_proxies";
538
+ /**
539
+ * 仅当用户没有指定商店时调用
540
+ */
541
+ description = "Get list of proxy configurations. If you want to get the list of proxies configurations you've bought, please use `roxy_store_proxies`.";
542
+ inputSchema = {
543
+ type: "object",
544
+ properties: {
545
+ workspaceId: {
546
+ type: "number",
547
+ description: "Workspace ID"
548
+ },
549
+ id: {
550
+ type: "number",
551
+ description: "Filter by proxy ID"
552
+ },
553
+ pageIndex: {
554
+ type: "number",
555
+ description: "Page index for pagination (default: 1)",
556
+ default: 1
557
+ },
558
+ pageSize: {
559
+ type: "number",
560
+ description: "Number of items per page (default: 15)",
561
+ default: 15
562
+ }
563
+ },
564
+ required: ["workspaceId"]
565
+ };
566
+ get schema() {
567
+ return {
568
+ name: this.name,
569
+ description: this.description,
570
+ inputSchema: this.inputSchema
571
+ };
572
+ }
573
+ async handle(params) {
574
+ const searchParams = new URLSearchParams();
575
+ searchParams.append("workspaceId", params.workspaceId);
576
+ if (params.id)
577
+ searchParams.append("id", params.id);
578
+ if (params.page_index)
579
+ searchParams.append("page_index", params.pageIndex);
580
+ if (params.page_size)
581
+ searchParams.append("page_size", params.pageSize);
582
+ if (!params.workspaceId) {
583
+ throw new Error("workspaceId is required");
584
+ }
585
+ const result = await request(`/proxy/list?${searchParams}`);
586
+ let text = "";
587
+ if (result.code === 0) {
588
+ const data = result.data;
589
+ const proxyListText = data.rows.length > 0 ? data.rows.map((proxy, index) => {
590
+ const statusText = proxy.checkStatus === 1 ? "\u2705 available" : proxy.checkStatus === 2 ? "\u274C unavailable" : "\u23F3 not checked";
591
+ const name = `proxy (id: ${proxy.id}) ${proxy.remark ? `remark: ${proxy.remark}` : ""}`;
592
+ const location = proxy.lastCountry ? `${proxy.lastCity || ""}${proxy.lastCity && proxy.lastCountry ? ", " : ""}${proxy.lastCountry}` : null;
593
+ let baseInfo = `${index + 1}. ${statusText} **${name}**
594
+ protocol: ${proxy.protocol || "N/A"}
595
+ ipType: ${proxy.ipType || "N/A"}
596
+ bind profile count: ${proxy.bindCount || "N/A"}
597
+ Detection channel: ${proxy.checkChannel || "N/A"}`;
598
+ const ipInfo = [];
599
+ if (proxy.host && proxy.port) {
600
+ ipInfo.push(...[proxy.host, ":", proxy.port]);
601
+ if (proxy.proxyUserName && proxy.proxyPassword) {
602
+ ipInfo.push(...["@", proxy.proxyUserName, ":", proxy.proxyPassword]);
603
+ }
604
+ }
605
+ if (location) {
606
+ baseInfo += `
607
+ ${ipInfo.length > 0 ? `${ipInfo.join("")}
608
+ ` : ""}
609
+ \u{1F4CD} ${location}`;
610
+ }
611
+ return baseInfo;
612
+ }).join("\n\n") : "";
613
+ text = `\u{1F4CB} **proxy list** (total: ${data.total})
614
+
615
+ ${proxyListText}`;
616
+ } else {
617
+ text = `\u274C **get proxy list failed**
618
+
619
+ ${result.msg}`;
620
+ }
621
+ return { content: [{ type: "text", text }] };
622
+ }
623
+ };
624
+ var ProxyStore = class {
625
+ name = "roxy_store_proxies";
626
+ description = "Get list of proxy configurations in the Proxy Store";
627
+ inputSchema = {
628
+ type: "object",
629
+ properties: {
630
+ workspaceId: {
631
+ type: "number",
632
+ description: "Workspace ID"
633
+ },
634
+ pageIndex: {
635
+ type: "number",
636
+ description: "Page index for pagination (default: 1)",
637
+ default: 1
638
+ },
639
+ pageSize: {
640
+ type: "number",
641
+ description: "Number of items per page (default: 15)",
642
+ default: 15
643
+ },
644
+ type: {
645
+ type: "number",
646
+ description: "Type of proxies to get (0: list_use, 1: available_list)",
647
+ default: 0
648
+ }
649
+ },
650
+ required: ["workspaceId"]
651
+ };
652
+ get schema() {
653
+ return {
654
+ name: this.name,
655
+ description: this.description,
656
+ inputSchema: this.inputSchema
657
+ };
658
+ }
659
+ async handle(params) {
660
+ const searchParams = new URLSearchParams();
661
+ searchParams.append("workspaceId", params.workspaceId.toString());
662
+ if (params.page_index)
663
+ searchParams.append("page_index", params.page_index.toString());
664
+ if (params.page_size)
665
+ searchParams.append("page_size", params.page_size.toString());
666
+ if (params.type)
667
+ searchParams.append("type", params.type.toString());
668
+ const result = await request(`/proxy/bought_list?${searchParams}`);
669
+ let text = "";
670
+ if (result.code === 0) {
671
+ const data = result.data;
672
+ const proxyListText = data.rows.length > 0 ? data.rows.map((proxy, index) => {
673
+ const statusText = proxy.checkStatus === 1 ? "\u2705 available" : proxy.checkStatus === 2 ? "\u274C unavailable" : "\u23F3 not checked";
674
+ const name = `proxy (id: ${proxy.id}) ${proxy.remark ? `remark: ${proxy.remark}` : ""}`;
675
+ const location = proxy.lastCountry ? `${proxy.lastCity || ""}${proxy.lastCity && proxy.lastCountry ? ", " : ""}${proxy.lastCountry}` : null;
676
+ let baseInfo = `${index + 1}. ${statusText} **${name}**
677
+ protocol: ${proxy.protocol || "N/A"}
678
+ ipType: ${proxy.ipType || "N/A"}
679
+ bind profile count: ${proxy.bindCount || "N/A"}
680
+ Detection channel: ${proxy.checkChannel || "N/A"}
681
+ expire date: ${proxy.expireDate}`;
682
+ const ipInfo = [proxy.host, ":", proxy.port];
683
+ if (proxy.proxyUserName) {
684
+ ipInfo.push(...[proxy.proxyUserName, "@", proxy.proxyPassword]);
685
+ }
686
+ if (location) {
687
+ baseInfo += `
688
+ ${ipInfo.join("")}
689
+ \u{1F4CD} ${location}`;
690
+ }
691
+ return baseInfo;
692
+ }).join("\n\n") : "";
693
+ text = `\u{1F4CB} **proxy store** (total: ${data.total})
694
+
695
+ ${proxyListText}`;
696
+ } else {
697
+ text = `\u274C **get proxy store failed**
698
+
699
+ ${result.msg}`;
700
+ }
701
+ return { content: [{ type: "text", text }] };
702
+ }
703
+ };
704
+ var CreateProxy = class {
705
+ name = "roxy_create_proxy";
706
+ description = "Create a new proxy configuration with automatic IP detection";
707
+ inputSchema = {
708
+ type: "object",
709
+ properties: {
710
+ workspaceId: {
711
+ type: "number",
712
+ description: "Workspace ID"
713
+ },
714
+ protocol: {
715
+ type: "string",
716
+ enum: ["HTTP", "HTTPS", "SOCKS5", "SSH"],
717
+ description: "Proxy protocol type"
718
+ },
719
+ host: {
720
+ type: "string",
721
+ description: "Proxy host/IP address"
722
+ },
723
+ port: {
724
+ type: "string",
725
+ description: "Proxy port"
726
+ },
727
+ proxyUserName: {
728
+ type: "string",
729
+ description: "Proxy username"
730
+ },
731
+ proxyPassword: {
732
+ type: "string",
733
+ description: "Proxy password"
734
+ },
735
+ ipType: {
736
+ type: "string",
737
+ enum: ["IPV4", "IPV6"],
738
+ description: "IP type (default: IPV4)"
739
+ },
740
+ checkChannel: {
741
+ type: "string",
742
+ enum: channelList.map((item) => item.label),
743
+ description: "IP detection channel (default: IP123.in)"
744
+ },
745
+ refreshUrl: {
746
+ type: "string",
747
+ description: "Refresh URL for dynamic proxies"
748
+ },
749
+ remark: {
750
+ type: "string",
751
+ description: "Proxy remark/notes"
752
+ }
753
+ },
754
+ required: ["workspaceId", "protocol", "host", "port"]
755
+ };
756
+ get schema() {
757
+ return {
758
+ name: this.name,
759
+ description: this.description,
760
+ inputSchema: this.inputSchema
761
+ };
762
+ }
763
+ async handle(params) {
764
+ if (!params.workspaceId || !params.protocol || !params.host || !params.port) {
765
+ return {
766
+ content: [
767
+ {
768
+ type: "text",
769
+ text: "\u274C **Failed to create proxy:**\n\n workspaceId, protocol, host, and port are required"
770
+ }
771
+ ]
772
+ };
773
+ }
774
+ const { workspaceId, ipType = "IPV4", checkChannel = "IP123.in", ...proxyData } = params;
775
+ const proxyParams = {
776
+ workspaceId,
777
+ ...proxyData,
778
+ ipType,
779
+ checkChannel: checkChannel ? channelList.find((item) => item.label === checkChannel)?.value : null,
780
+ proxyCategory: params.protocol
781
+ };
782
+ const result = await request("/proxy/create", {
783
+ method: "POST",
784
+ body: JSON.stringify(proxyParams)
785
+ });
786
+ let text = "";
787
+ if (result.code !== 0) {
788
+ if (result.data) {
789
+ text = `\u274C **Failed to create proxy:**
790
+
791
+ error message: ${result.msg}
792
+
793
+ ${result.data.map((item) => ` - index: ${item.index}, error message: ${item.msg.join(", ")}`).join("\n")}`;
794
+ } else {
795
+ text = `\u274C **Failed to create proxy:**
796
+
797
+ error message: ${result.msg}`;
798
+ }
799
+ } else {
800
+ text = `\u2705 **Proxy Created Successfully**
801
+
802
+ **Protocol:** ${params.protocol}
803
+ **Host:** ${params.host}:${params.port}${params.proxyUserName ? `
804
+ **Username:** ${params.proxyUserName}` : ""}${params.remark ? `
805
+ **Remark:** ${params.remark}` : ""}${params.checkChannel ? `
806
+ **Check Channel:** ${params.checkChannel}` : ""}
807
+
808
+ *Proxy configuration created. IP detection will be performed automatically.*`;
809
+ }
810
+ return {
811
+ content: [
812
+ {
813
+ type: "text",
814
+ text
815
+ }
816
+ ]
817
+ };
818
+ }
819
+ };
820
+ var BatchCreateProxies = class {
821
+ name = "roxy_batch_create_proxies";
822
+ description = "Batch create multiple proxy configurations";
823
+ inputSchema = {
824
+ type: "object",
825
+ properties: {
826
+ workspaceId: {
827
+ type: "number",
828
+ description: "Workspace ID"
829
+ },
830
+ // checkChannel: {
831
+ // type: 'string',
832
+ // enum: channelList.map(item => item.label),
833
+ // description: 'Default IP detection channel for all proxies',
834
+ // },
835
+ proxyList: {
836
+ type: "array",
837
+ description: "Array of proxy configurations",
838
+ items: {
839
+ type: "object",
840
+ properties: {
841
+ protocol: { type: "string", enum: ["HTTP", "HTTPS", "SOCKS5", "SSH"] },
842
+ host: { type: "string" },
843
+ port: { type: "string" },
844
+ proxyUserName: { type: "string" },
845
+ proxyPassword: { type: "string" },
846
+ ipType: { type: "string", enum: ["IPV4", "IPV6"] },
847
+ checkChannel: { type: "string", enum: channelList.map((item) => item.label) },
848
+ refreshUrl: { type: "string" },
849
+ remark: { type: "string" }
850
+ },
851
+ required: ["protocol", "host", "port"]
852
+ }
853
+ }
854
+ },
855
+ required: ["workspaceId", "proxyList"]
856
+ };
857
+ get schema() {
858
+ return {
859
+ name: this.name,
860
+ description: this.description,
861
+ inputSchema: this.inputSchema
862
+ };
863
+ }
864
+ async handle(params) {
865
+ if (!params.workspaceId || !params.proxyList || params.proxyList.length === 0) {
866
+ return {
867
+ content: [
868
+ {
869
+ type: "text",
870
+ text: "\u274C **Failed to batch create proxies:**\n\n workspaceId and proxyList are required"
871
+ }
872
+ ]
873
+ };
874
+ }
875
+ const { workspaceId, proxyList: proxyList2 } = params;
876
+ proxyList2.forEach((item) => {
877
+ item.ipType = item.ipType ? item.ipType : "IPV4";
878
+ item.checkChannel = item.checkChannel ? channelList.find((channel) => channel.label === item.checkChannel)?.value : null;
879
+ });
880
+ const result = await request("/proxy/batch_create", {
881
+ method: "POST",
882
+ body: JSON.stringify({ workspaceId, proxyList: proxyList2 })
883
+ });
884
+ let text = "";
885
+ if (result.code !== 0) {
886
+ if (result.data) {
887
+ text = `\u274C **Failed to batch create proxies:**
888
+
889
+ error message: ${result.msg}
890
+
891
+ ${result.data.map((item) => ` - index: ${item.index}, error message: ${item.msg.join(", ")}`).join("\n")}`;
892
+ } else {
893
+ text = `\u274C **Failed to batch create proxies:**
894
+
895
+ error message: ${result.msg}`;
896
+ }
897
+ } else {
898
+ text = `\u2705 **Batch Proxy Creation Successful**
899
+
900
+ **Count:** ${params.proxyList.length} proxy/proxies
901
+ **Workspace:** ${params.workspaceId}${params.checkChannel ? `
902
+ **Default Check Channel:** ${params.checkChannel}` : ""}
903
+
904
+ *All proxies have been created. IP detection will be performed automatically.*`;
905
+ }
906
+ return {
907
+ content: [
908
+ {
909
+ type: "text",
910
+ text
911
+ }
912
+ ]
913
+ };
914
+ }
915
+ };
916
+ var DetectProxy = class {
917
+ name = "roxy_detect_proxy";
918
+ description = "Detect/test a proxy configuration and update its IP information";
919
+ inputSchema = {
920
+ type: "object",
921
+ properties: {
922
+ workspaceId: {
923
+ type: "number",
924
+ description: "Workspace ID"
925
+ },
926
+ id: {
927
+ type: "number",
928
+ description: "Proxy ID to detect"
929
+ }
930
+ },
931
+ required: ["workspaceId", "id"]
932
+ };
933
+ get schema() {
934
+ return {
935
+ name: this.name,
936
+ description: this.description,
937
+ inputSchema: this.inputSchema
938
+ };
939
+ }
940
+ async handle(params) {
941
+ if (!params.workspaceId || !params.id) {
942
+ return {
943
+ content: [
944
+ {
945
+ type: "text",
946
+ text: "\u274C **Failed to detect proxy:**\n\n workspaceId and id are required"
947
+ }
948
+ ]
949
+ };
950
+ }
951
+ const { workspaceId, id } = params;
952
+ const result = await request("/proxy/detect", {
953
+ method: "POST",
954
+ body: JSON.stringify({ workspaceId, id })
955
+ });
956
+ let text = "";
957
+ if (result.code !== 0) {
958
+ text = `\u274C **Failed to detect proxy:**
959
+
960
+ error message: ${result.msg}`;
961
+ } else {
962
+ const data = result.data;
963
+ if (data) {
964
+ text = `\u2705 **Proxy Detection ${data.checkStatus === 1 ? "Success" : data.checkStatus === 2 ? "Failed" : ""}**
965
+
966
+ **ip address:** ${data.lastIp}
967
+ **country:** ${data.lastCountry}
968
+ **city:** ${data.lastCity}
969
+ **timezone:** ${data.timezone ? data.timezone : "N/A"}
970
+ `;
971
+ } else {
972
+ text = `\u2705 **Proxy Detection Started**
973
+
974
+ **Proxy ID:** ${params.id}
975
+ **Workspace:** ${params.workspaceId}
976
+
977
+ *Proxy detection is in progress. This may take a few seconds. Use \`roxy_list_proxies\` | \`roxy_store_proxies\` to check the updated status.*
978
+ `;
979
+ }
980
+ }
981
+ return {
982
+ content: [
983
+ {
984
+ type: "text",
985
+ text
986
+ }
987
+ ]
988
+ };
989
+ }
990
+ };
991
+ var ModifyProxy = class {
992
+ name = "roxy_modify_proxy";
993
+ description = "Modify/update an existing proxy configuration";
994
+ inputSchema = {
995
+ type: "object",
996
+ properties: {
997
+ workspaceId: {
998
+ type: "number",
999
+ description: "Workspace ID"
1000
+ },
1001
+ id: {
1002
+ type: "number",
1003
+ description: "Proxy ID to modify"
1004
+ },
1005
+ protocol: {
1006
+ type: "string",
1007
+ enum: ["HTTP", "HTTPS", "SOCKS5", "SSH"],
1008
+ description: "Proxy protocol type"
1009
+ },
1010
+ host: {
1011
+ type: "string",
1012
+ description: "Proxy host/IP address"
1013
+ },
1014
+ port: {
1015
+ type: "string",
1016
+ description: "Proxy port"
1017
+ },
1018
+ proxyUserName: {
1019
+ type: "string",
1020
+ description: "Proxy username"
1021
+ },
1022
+ proxyPassword: {
1023
+ type: "string",
1024
+ description: "Proxy password"
1025
+ },
1026
+ ipType: {
1027
+ type: "string",
1028
+ enum: ["IPV4", "IPV6"],
1029
+ description: "IP type"
1030
+ },
1031
+ checkChannel: {
1032
+ type: "string",
1033
+ enum: channelList.map((item) => item.label),
1034
+ description: "IP detection channel"
1035
+ },
1036
+ refreshUrl: {
1037
+ type: "string",
1038
+ description: "Refresh URL for dynamic proxies"
1039
+ },
1040
+ remark: {
1041
+ type: "string",
1042
+ description: "Proxy remark/notes"
1043
+ }
1044
+ },
1045
+ required: ["workspaceId", "id"]
1046
+ };
1047
+ get schema() {
1048
+ return {
1049
+ name: this.name,
1050
+ description: this.description,
1051
+ inputSchema: this.inputSchema
1052
+ };
1053
+ }
1054
+ async handle(params) {
1055
+ if (!params.workspaceId || !params.id) {
1056
+ return {
1057
+ content: [
1058
+ {
1059
+ type: "text",
1060
+ text: "\u274C **Failed to modify proxy:**\n\n workspaceId and id are required"
1061
+ }
1062
+ ]
1063
+ };
1064
+ }
1065
+ const { workspaceId, checkChannel = "IPRust.io", ...proxyData } = params;
1066
+ const proxyParams = {
1067
+ workspaceId,
1068
+ ...proxyData,
1069
+ checkChannel: checkChannel ? channelList.find((item) => item.label === checkChannel)?.value : null,
1070
+ proxyCategory: params.protocol
1071
+ };
1072
+ const result = await request("/proxy/modify", {
1073
+ method: "POST",
1074
+ body: JSON.stringify(proxyParams)
1075
+ });
1076
+ let text = "";
1077
+ if (result.code !== 0) {
1078
+ text = `\u274C **Failed to modify proxy:**
1079
+
1080
+ error message: ${result.msg}`;
1081
+ } else {
1082
+ text = `\u2705 **Proxy Modified Successfully**
1083
+
1084
+ **Proxy ID:** ${params.id}${params.protocol ? `
1085
+ **Protocol:** ${params.protocol}` : ""}${params.host ? `
1086
+ **Host:** ${params.host}${params.port ? `:${params.port}` : ""}` : ""}${params.remark ? `
1087
+ **Remark:** ${params.remark}` : ""}
1088
+
1089
+ *Proxy configuration has been updated. Use \`roxy_detect_proxy\` to test the new configuration.*`;
1090
+ }
1091
+ return {
1092
+ content: [
1093
+ {
1094
+ type: "text",
1095
+ text
1096
+ }
1097
+ ]
1098
+ };
1099
+ }
1100
+ };
1101
+ var DeleteProxies = class {
1102
+ name = "roxy_delete_proxies";
1103
+ description = "Delete one or more proxy configurations";
1104
+ inputSchema = {
1105
+ type: "object",
1106
+ properties: {
1107
+ workspaceId: {
1108
+ type: "number",
1109
+ description: "Workspace ID"
1110
+ },
1111
+ ids: {
1112
+ type: "array",
1113
+ items: { type: "number" },
1114
+ description: "Array of proxy IDs to delete"
1115
+ }
1116
+ },
1117
+ required: ["workspaceId", "ids"]
1118
+ };
1119
+ get schema() {
1120
+ return {
1121
+ name: this.name,
1122
+ description: this.description,
1123
+ inputSchema: this.inputSchema
1124
+ };
1125
+ }
1126
+ async handle(params) {
1127
+ if (!params.workspaceId || !params.ids || params.ids.length === 0) {
1128
+ return {
1129
+ content: [
1130
+ {
1131
+ type: "text",
1132
+ text: "\u274C **Failed to delete proxies:**\n\n workspaceId and ids are required"
1133
+ }
1134
+ ]
1135
+ };
1136
+ }
1137
+ const { workspaceId, ids } = params;
1138
+ const result = await request("/proxy/delete", {
1139
+ method: "POST",
1140
+ body: JSON.stringify({ workspaceId, ids })
1141
+ });
1142
+ let text = "";
1143
+ if (result.code !== 0) {
1144
+ text = `\u274C **Failed to delete proxies:**
1145
+
1146
+ error message: ${result.msg}`;
1147
+ } else {
1148
+ text = `\u2705 **Proxies Deleted Successfully**
1149
+
1150
+ **Count:** ${params.ids.length} proxy/proxies
1151
+ **Workspace:** ${params.workspaceId}
1152
+
1153
+ **Deleted Proxy IDs:**
1154
+ ${params.ids.map((id, index) => ` ${index + 1}. ${id}`).join("\n")}
1155
+
1156
+ \u26A0\uFE0F **Warning:** Deleted proxies cannot be recovered.`;
1157
+ }
1158
+ return {
1159
+ content: [
1160
+ {
1161
+ type: "text",
1162
+ text
1163
+ }
1164
+ ]
1165
+ };
1166
+ }
1167
+ };
1168
+ var proxyList = new ProxyList();
1169
+ var proxyStore = new ProxyStore();
1170
+ var createProxy = new CreateProxy();
1171
+ var batchCreateProxies = new BatchCreateProxies();
1172
+ var detectProxy = new DetectProxy();
1173
+ var modifyProxy = new ModifyProxy();
1174
+ var deleteProxies = new DeleteProxies();
1175
+
1176
+ // src/modules/browser.ts
1177
+ var osversion_windows = [
1178
+ {
1179
+ label: "11",
1180
+ type: "osVersion-Windows",
1181
+ value: "11"
1182
+ },
1183
+ {
1184
+ label: "10",
1185
+ type: "osVersion-Windows",
1186
+ value: "10"
1187
+ },
1188
+ {
1189
+ label: "8",
1190
+ type: "osVersion-Windows",
1191
+ value: "8"
1192
+ },
1193
+ {
1194
+ label: "7",
1195
+ type: "osVersion-Windows",
1196
+ value: "7"
1197
+ }
1198
+ ];
1199
+ var osversion_macos = [
1200
+ {
1201
+ label: "15.3.2",
1202
+ type: "osVersion-macOS",
1203
+ value: "15.3.2"
1204
+ },
1205
+ {
1206
+ label: "15.3.1",
1207
+ type: "osVersion-macOS",
1208
+ value: "15.3.1"
1209
+ },
1210
+ {
1211
+ label: "15.3",
1212
+ type: "osVersion-macOS",
1213
+ value: "15.3"
1214
+ },
1215
+ {
1216
+ label: "15.2",
1217
+ type: "osVersion-macOS",
1218
+ value: "15.2"
1219
+ },
1220
+ {
1221
+ label: "15.1",
1222
+ type: "osVersion-macOS",
1223
+ value: "15.1"
1224
+ },
1225
+ {
1226
+ label: "15.0.1",
1227
+ type: "osVersion-macOS",
1228
+ value: "15.0.1"
1229
+ },
1230
+ {
1231
+ label: "15.0",
1232
+ type: "osVersion-macOS",
1233
+ value: "15.0"
1234
+ },
1235
+ {
1236
+ label: "14.7.4",
1237
+ type: "osVersion-macOS",
1238
+ value: "14.7.4"
1239
+ },
1240
+ {
1241
+ label: "14.7.3",
1242
+ type: "osVersion-macOS",
1243
+ value: "14.7.3"
1244
+ },
1245
+ {
1246
+ label: "14.7.2",
1247
+ type: "osVersion-macOS",
1248
+ value: "14.7.2"
1249
+ },
1250
+ {
1251
+ label: "14.7.1",
1252
+ type: "osVersion-macOS",
1253
+ value: "14.7.1"
1254
+ },
1255
+ {
1256
+ label: "14.7",
1257
+ type: "osVersion-macOS",
1258
+ value: "14.7"
1259
+ },
1260
+ {
1261
+ label: "14.6.1",
1262
+ type: "osVersion-macOS",
1263
+ value: "14.6.1"
1264
+ },
1265
+ {
1266
+ label: "14.6",
1267
+ type: "osVersion-macOS",
1268
+ value: "14.6"
1269
+ },
1270
+ {
1271
+ label: "14.5",
1272
+ type: "osVersion-macOS",
1273
+ value: "14.5"
1274
+ },
1275
+ {
1276
+ label: "14.4.1",
1277
+ type: "osVersion-macOS",
1278
+ value: "14.4.1"
1279
+ },
1280
+ {
1281
+ label: "14.4",
1282
+ type: "osVersion-macOS",
1283
+ value: "14.4"
1284
+ },
1285
+ {
1286
+ label: "14.3.1",
1287
+ type: "osVersion-macOS",
1288
+ value: "14.3.1"
1289
+ },
1290
+ {
1291
+ label: "14.3",
1292
+ type: "osVersion-macOS",
1293
+ value: "14.3"
1294
+ },
1295
+ {
1296
+ label: "14.2.1",
1297
+ type: "osVersion-macOS",
1298
+ value: "14.2.1"
1299
+ },
1300
+ {
1301
+ label: "14.2",
1302
+ type: "osVersion-macOS",
1303
+ value: "14.2"
1304
+ },
1305
+ {
1306
+ label: "14.1",
1307
+ type: "osVersion-macOS",
1308
+ value: "14.1"
1309
+ },
1310
+ {
1311
+ label: "13.7.4",
1312
+ type: "osVersion-macOS",
1313
+ value: "13.7.4"
1314
+ },
1315
+ {
1316
+ label: "13.7.3",
1317
+ type: "osVersion-macOS",
1318
+ value: "13.7.3"
1319
+ },
1320
+ {
1321
+ label: "13.7.2",
1322
+ type: "osVersion-macOS",
1323
+ value: "13.7.2"
1324
+ },
1325
+ {
1326
+ label: "13.7.1",
1327
+ type: "osVersion-macOS",
1328
+ value: "13.7.1"
1329
+ },
1330
+ {
1331
+ label: "13.7",
1332
+ type: "osVersion-macOS",
1333
+ value: "13.7"
1334
+ },
1335
+ {
1336
+ label: "ALL",
1337
+ type: "osVersion-macOS",
1338
+ value: "ALL"
1339
+ }
1340
+ ];
1341
+ var osversion_linux = [
1342
+ {
1343
+ label: "ALL",
1344
+ type: "osVersion-Linux",
1345
+ value: "ALL"
1346
+ }
1347
+ ];
1348
+ var osversion_android = [
1349
+ {
1350
+ label: "15",
1351
+ type: "osVersion-Android",
1352
+ value: "15"
1353
+ },
1354
+ {
1355
+ label: "14",
1356
+ type: "osVersion-Android",
1357
+ value: "14"
1358
+ },
1359
+ {
1360
+ label: "13",
1361
+ type: "osVersion-Android",
1362
+ value: "13"
1363
+ },
1364
+ {
1365
+ label: "12",
1366
+ type: "osVersion-Android",
1367
+ value: "12"
1368
+ },
1369
+ {
1370
+ label: "11",
1371
+ type: "osVersion-Android",
1372
+ value: "11"
1373
+ },
1374
+ {
1375
+ label: "10",
1376
+ type: "osVersion-Android",
1377
+ value: "10"
1378
+ },
1379
+ {
1380
+ label: "9",
1381
+ type: "osVersion-Android",
1382
+ value: "9"
1383
+ }
1384
+ ];
1385
+ var osversion_ios = [
1386
+ {
1387
+ label: "18.2",
1388
+ type: "osVersion-IOS",
1389
+ value: "18.2"
1390
+ },
1391
+ {
1392
+ label: "18.1",
1393
+ type: "osVersion-IOS",
1394
+ value: "18.1"
1395
+ },
1396
+ {
1397
+ label: "18.0",
1398
+ type: "osVersion-IOS",
1399
+ value: "18.0"
1400
+ },
1401
+ {
1402
+ label: "17.0",
1403
+ type: "osVersion-IOS",
1404
+ value: "17.0"
1405
+ },
1406
+ {
1407
+ label: "16.6",
1408
+ type: "osVersion-IOS",
1409
+ value: "16.6"
1410
+ },
1411
+ {
1412
+ label: "16.5",
1413
+ type: "osVersion-IOS",
1414
+ value: "16.5"
1415
+ },
1416
+ {
1417
+ label: "16.4",
1418
+ type: "osVersion-IOS",
1419
+ value: "16.4"
1420
+ },
1421
+ {
1422
+ label: "16.3",
1423
+ type: "osVersion-IOS",
1424
+ value: "16.3"
1425
+ },
1426
+ {
1427
+ label: "16.2",
1428
+ type: "osVersion-IOS",
1429
+ value: "16.2"
1430
+ },
1431
+ {
1432
+ label: "16.1",
1433
+ type: "osVersion-IOS",
1434
+ value: "16.1"
1435
+ },
1436
+ {
1437
+ label: "16.0",
1438
+ type: "osVersion-IOS",
1439
+ value: "16.0"
1440
+ },
1441
+ {
1442
+ label: "15.7",
1443
+ type: "osVersion-IOS",
1444
+ value: "15.7"
1445
+ },
1446
+ {
1447
+ label: "15.6",
1448
+ type: "osVersion-IOS",
1449
+ value: "15.6"
1450
+ },
1451
+ {
1452
+ label: "15.5",
1453
+ type: "osVersion-IOS",
1454
+ value: "15.5"
1455
+ },
1456
+ {
1457
+ label: "15.4",
1458
+ type: "osVersion-IOS",
1459
+ value: "15.4"
1460
+ },
1461
+ {
1462
+ label: "15.3",
1463
+ type: "osVersion-IOS",
1464
+ value: "15.3"
1465
+ },
1466
+ {
1467
+ label: "15.2",
1468
+ type: "osVersion-IOS",
1469
+ value: "15.2"
1470
+ },
1471
+ {
1472
+ label: "15.1",
1473
+ type: "osVersion-IOS",
1474
+ value: "15.1"
1475
+ },
1476
+ {
1477
+ label: "15.0",
1478
+ type: "osVersion-IOS",
1479
+ value: "15.0"
1480
+ },
1481
+ {
1482
+ label: "14.7",
1483
+ type: "osVersion-IOS",
1484
+ value: "14.7"
1485
+ },
1486
+ {
1487
+ label: "14.6",
1488
+ type: "osVersion-IOS",
1489
+ value: "14.6"
1490
+ },
1491
+ {
1492
+ label: "14.5",
1493
+ type: "osVersion-IOS",
1494
+ value: "14.5"
1495
+ },
1496
+ {
1497
+ label: "14.4",
1498
+ type: "osVersion-IOS",
1499
+ value: "14.4"
1500
+ },
1501
+ {
1502
+ label: "14.3",
1503
+ type: "osVersion-IOS",
1504
+ value: "14.3"
1505
+ },
1506
+ {
1507
+ label: "14.2",
1508
+ type: "osVersion-IOS",
1509
+ value: "14.2"
1510
+ },
1511
+ {
1512
+ label: "14.1",
1513
+ type: "osVersion-IOS",
1514
+ value: "14.1"
1515
+ },
1516
+ {
1517
+ label: "14.0",
1518
+ type: "osVersion-IOS",
1519
+ value: "14.0"
1520
+ }
1521
+ ];
1522
+ var coreVersion = [
1523
+ {
1524
+ label: "RoxyChrome 144",
1525
+ type: "coreVersion",
1526
+ value: "144"
1527
+ },
1528
+ {
1529
+ label: "RoxyChrome 143",
1530
+ type: "coreVersion",
1531
+ value: "143"
1532
+ },
1533
+ {
1534
+ label: "RoxyChrome 142",
1535
+ type: "coreVersion",
1536
+ value: "142"
1537
+ },
1538
+ {
1539
+ label: "RoxyChrome 141",
1540
+ type: "coreVersion",
1541
+ value: "141"
1542
+ },
1543
+ {
1544
+ label: "RoxyChrome 140",
1545
+ type: "coreVersion",
1546
+ value: "140"
1547
+ },
1548
+ {
1549
+ label: "RoxyChrome 139",
1550
+ type: "coreVersion",
1551
+ value: "139"
1552
+ },
1553
+ {
1554
+ label: "RoxyChrome 138",
1555
+ type: "coreVersion",
1556
+ value: "138"
1557
+ },
1558
+ {
1559
+ label: "RoxyChrome 137",
1560
+ type: "coreVersion",
1561
+ value: "137"
1562
+ },
1563
+ {
1564
+ label: "RoxyChrome 136",
1565
+ type: "coreVersion",
1566
+ value: "136"
1567
+ },
1568
+ {
1569
+ label: "RoxyChrome 135",
1570
+ type: "coreVersion",
1571
+ value: "135"
1572
+ },
1573
+ {
1574
+ label: "RoxyChrome 133",
1575
+ type: "coreVersion",
1576
+ value: "133"
1577
+ },
1578
+ {
1579
+ label: "RoxyChrome 130",
1580
+ type: "coreVersion",
1581
+ value: "130"
1582
+ },
1583
+ {
1584
+ label: "RoxyChrome 125",
1585
+ type: "coreVersion",
1586
+ value: "125"
1587
+ },
1588
+ {
1589
+ label: "RoxyChrome 117",
1590
+ type: "coreVersion",
1591
+ value: "117"
1592
+ },
1593
+ {
1594
+ label: "RoxyChrome 109",
1595
+ type: "coreVersion",
1596
+ value: "109"
1597
+ }
1598
+ ];
1599
+ function osVersionString() {
1600
+ return `Windows: ${osversion_windows.map((item) => item.value).join(",")}; macOS: ${osversion_macos.map((item) => item.value).join(",")}; Linux: ${osversion_linux.map((item) => item.value).join(",")}; Android: ${osversion_android.map((item) => item.value).join(",")}; IOS: ${osversion_ios.map((item) => item.value).join(",")}`;
1601
+ }
1602
+ var CreateBrowser = class {
1603
+ name = "roxy_create_browser";
1604
+ description = "Create a browser with complete configuration control - for expert users needing full parameter access";
1605
+ inputSchema = {
1606
+ type: "object",
1607
+ properties: {
1608
+ workspaceId: {
1609
+ type: "number",
1610
+ description: "Workspace ID"
1611
+ },
1612
+ windowName: {
1613
+ type: "string",
1614
+ description: "Browser window name"
1615
+ },
1616
+ coreVersion: {
1617
+ type: "string",
1618
+ enum: coreVersion.map((item) => item.value),
1619
+ description: "Browser core version. If not provided, the latest available core version will be used."
1620
+ },
1621
+ os: {
1622
+ type: "string",
1623
+ enum: ["Windows", "macOS", "Linux", "IOS", "Android"],
1624
+ description: "Operating system (default: Windows)"
1625
+ },
1626
+ osVersion: {
1627
+ type: "string",
1628
+ description: osVersionString()
1629
+ },
1630
+ userAgent: {
1631
+ type: "string",
1632
+ description: "Custom user agent"
1633
+ },
1634
+ cookie: {
1635
+ type: "array",
1636
+ description: "Cookie list",
1637
+ items: { type: "object" }
1638
+ },
1639
+ searchEngine: {
1640
+ type: "string",
1641
+ enum: ["Google", "Microsoft Bing", "Yahoo", "Yandex", "DuckDuckGo"],
1642
+ description: "Default search engine"
1643
+ },
1644
+ labelIds: {
1645
+ type: "array",
1646
+ items: { type: "number" },
1647
+ description: "Label IDs to assign"
1648
+ },
1649
+ defaultOpenUrl: {
1650
+ type: "array",
1651
+ items: { type: "string" },
1652
+ description: "URLs to open by default"
1653
+ },
1654
+ windowRemark: {
1655
+ type: "string",
1656
+ description: "Window remarks/notes"
1657
+ },
1658
+ projectId: {
1659
+ type: "number",
1660
+ description: "Project ID"
1661
+ },
1662
+ windowPlatformList: {
1663
+ type: "array",
1664
+ items: {
1665
+ type: "object",
1666
+ properties: {
1667
+ // 平台账号id,非必传,通过平台账号列表接口【roxy_list_accounts】获取,可以判定已在平台账号列表中的账号,有该参数时其他参数不需要传。
1668
+ id: { type: "number", description: "Platform account ID, which can be obtained from [roxy_list_accounts] (field: id). Used to bind an account that already exists in the platform account list. If this parameter is provided, other parameters do not need to be passed." },
1669
+ platformUrl: { type: "string", description: "Platform URL" },
1670
+ platformUserName: { type: "string", description: "Platform username" },
1671
+ platformPassword: { type: "string", description: "Platform password" },
1672
+ platformEfa: { type: "string", description: "Platform EFA" },
1673
+ platformRemarks: { type: "string", description: "Platform remarks" }
1674
+ }
1675
+ },
1676
+ description: "Platform account information"
1677
+ },
1678
+ proxyInfo: {
1679
+ type: "object",
1680
+ description: "Complete proxy configuration object",
1681
+ properties: {
1682
+ // 如果有 moduleId ,则其他参数不可传递 (moduleId 可通过 roxy_list_proxies 或 roxy_store_proxies 获取) 优先使用该参数来绑定代理IP
1683
+ moduleId: { type: "number", description: `If moduleId is provided, no other parameters may be passed. (moduleId can be obtained via ${proxyList.name} or ${proxyStore.name}. field: id) Priority to use this parameter to bind proxy IP` },
1684
+ proxyMethod: { type: "string", enum: ["custom", "choose", "api"] },
1685
+ proxyCategory: { type: "string", enum: ["noproxy", "HTTP", "HTTPS", "SOCKS5", "SSH"] },
1686
+ ipType: { type: "string", enum: ["IPV4", "IPV6"] },
1687
+ protocol: { type: "string", enum: ["HTTP", "HTTPS", "SOCKS5"] },
1688
+ host: { type: "string" },
1689
+ port: { type: "string" },
1690
+ proxyUserName: { type: "string" },
1691
+ proxyPassword: { type: "string" },
1692
+ refreshUrl: { type: "string" },
1693
+ checkChannel: { type: "string", enum: ["IPRust.io", "IP-API", "IP123.in"] }
1694
+ }
1695
+ },
1696
+ fingerInfo: {
1697
+ type: "object",
1698
+ description: "Complete fingerprint configuration",
1699
+ properties: {
1700
+ // Language and timezone
1701
+ isLanguageBaseIp: { type: "boolean", description: "Follow IP for browser language" },
1702
+ language: { type: "string", description: "Custom browser language" },
1703
+ isDisplayLanguageBaseIp: { type: "boolean", description: "Follow IP for display language" },
1704
+ displayLanguage: { type: "string", description: "Custom display language" },
1705
+ isTimeZone: { type: "boolean", description: "Follow IP for timezone" },
1706
+ timeZone: { type: "string", description: "Custom timezone" },
1707
+ // Geolocation
1708
+ position: { type: "number", enum: [0, 1, 2], description: "Geolocation prompt: 0=ask, 1=allow, 2=deny" },
1709
+ isPositionBaseIp: { type: "boolean", description: "Follow IP for geolocation" },
1710
+ longitude: { type: "string", description: "Custom longitude" },
1711
+ latitude: { type: "string", description: "Custom latitude" },
1712
+ precisionPos: { type: "string", description: "Precision in meters" },
1713
+ // Media settings
1714
+ forbidAudio: { type: "boolean", description: "Enable/disable sound" },
1715
+ forbidImage: { type: "boolean", description: "Enable/disable image loading" },
1716
+ forbiddenPictureSize: { type: "number", description: "Image load size threshold (bytes). When forbidImage is false, set forbiddenPictureSize = 0 to disable all image loading. Default 0." },
1717
+ forbidMedia: { type: "boolean", description: "Enable/disable video playback" },
1718
+ // Window settings
1719
+ openWidth: { type: "string", description: "Window width" },
1720
+ openHeight: { type: "string", description: "Window height" },
1721
+ openBookmarks: { type: "boolean", description: "Enable bookmarks" },
1722
+ positionSwitch: { type: "boolean", description: "Window position switch" },
1723
+ windowRatioPosition: { type: "string", description: "Window position ratio" },
1724
+ isDisplayName: { type: "boolean", description: "Show window name in title bar" },
1725
+ // Sync settings
1726
+ syncBookmark: { type: "boolean", description: "Sync bookmarks" },
1727
+ syncHistory: { type: "boolean", description: "Sync history" },
1728
+ syncTab: { type: "boolean", description: "Sync tabs" },
1729
+ syncCookie: { type: "boolean", description: "Sync cookies" },
1730
+ syncExtensions: { type: "boolean", description: "Sync extensions" },
1731
+ syncPassword: { type: "boolean", description: "Sync saved passwords" },
1732
+ syncIndexedDb: { type: "boolean", description: "Sync IndexedDB" },
1733
+ syncLocalStorage: { type: "boolean", description: "Sync LocalStorage" },
1734
+ // Cleanup settings
1735
+ clearCacheFile: { type: "boolean", description: "Clear cache files on startup" },
1736
+ clearCookie: { type: "boolean", description: "Clear cookies on startup" },
1737
+ clearLocalStorage: { type: "boolean", description: "Clear LocalStorage on startup" },
1738
+ // Advanced settings
1739
+ randomFingerprint: { type: "boolean", description: "Generate random fingerprint" },
1740
+ forbidSavePassword: { type: "boolean", description: "Disable password save prompts" },
1741
+ stopOpenNet: { type: "boolean", description: "Stop opening if network fails" },
1742
+ stopOpenIP: { type: "boolean", description: "Stop opening if IP changes" },
1743
+ stopOpenPosition: { type: "boolean", description: "Stop opening if IP location changes" },
1744
+ openWorkbench: { type: "number", enum: [0, 1, 2], description: "Open workbench: 0=close, 1=open, 2=follow app" },
1745
+ // Display settings
1746
+ resolutionType: { type: "boolean", description: "Custom resolution vs follow system" },
1747
+ resolutionX: { type: "string", description: "Custom resolution width" },
1748
+ resolutionY: { type: "string", description: "Custom resolution height" },
1749
+ fontType: { type: "boolean", description: "Random fonts vs system fonts" },
1750
+ // Browser fingerprint settings
1751
+ webRTC: { type: "number", enum: [0, 1, 2], description: "WebRTC: 0=replace, 1=real, 2=disable" },
1752
+ webGL: { type: "boolean", description: "WebGL: random vs real" },
1753
+ webGLInfo: { type: "boolean", description: "WebGL info: custom vs real" },
1754
+ webGLManufacturer: { type: "string", description: "Custom WebGL manufacturer" },
1755
+ webGLRender: { type: "string", description: "Custom WebGL renderer" },
1756
+ webGpu: { type: "string", enum: ["webgl", "real", "block"], description: "WebGPU setting" },
1757
+ canvas: { type: "boolean", description: "Canvas: random vs real" },
1758
+ audioContext: { type: "boolean", description: "AudioContext: random vs real" },
1759
+ speechVoices: { type: "boolean", description: "Speech Voices: random vs real" },
1760
+ doNotTrack: { type: "boolean", description: "Enable Do Not Track" },
1761
+ clientRects: { type: "boolean", description: "ClientRects: random vs real" },
1762
+ deviceInfo: { type: "boolean", description: "Media devices: random vs real" },
1763
+ deviceNameSwitch: { type: "boolean", description: "Device names: random vs real" },
1764
+ macInfo: { type: "boolean", description: "MAC address: custom vs real" },
1765
+ // Hardware settings
1766
+ hardwareConcurrent: { type: "string", description: "Hardware concurrency" },
1767
+ deviceMemory: { type: "string", description: "Device memory" },
1768
+ // Security settings
1769
+ disableSsl: { type: "boolean", description: "SSL fingerprint settings" },
1770
+ disableSslList: { type: "array", items: { type: "string" }, description: "SSL feature list" },
1771
+ portScanProtect: { type: "boolean", description: "Port scan protection" },
1772
+ portScanList: { type: "string", description: "Port scan whitelist" },
1773
+ useGpu: { type: "boolean", description: "Use GPU acceleration" },
1774
+ sandboxPermission: { type: "boolean", description: "Disable sandbox" },
1775
+ startupParam: { type: "string", description: "Browser startup parameters (--headless=new startup headless)" }
1776
+ }
1777
+ }
1778
+ },
1779
+ required: ["workspaceId"]
1780
+ };
1781
+ get schema() {
1782
+ return {
1783
+ name: this.name,
1784
+ description: this.description,
1785
+ inputSchema: this.inputSchema
1786
+ };
1787
+ }
1788
+ async handle(params) {
1789
+ const result = await request("/browser/create", {
1790
+ method: "POST",
1791
+ body: JSON.stringify(params)
1792
+ });
1793
+ const data = result.data;
1794
+ let text = "";
1795
+ if (result.code !== 0) {
1796
+ text = `\u274C **Failed to create browser:**
1797
+
1798
+ error message: ${result.msg}`;
1799
+ } else {
1800
+ text = `\u2705 **Simple Browser Created**
1801
+
1802
+ **Browser ID:** \`${data.dirId}\`
1803
+ *Use this browser ID with \`roxy_open_browsers\` to start the browser and get CDP endpoints for automation.*`;
1804
+ }
1805
+ return {
1806
+ content: [
1807
+ {
1808
+ type: "text",
1809
+ text
1810
+ }
1811
+ ]
1812
+ };
1813
+ }
1814
+ };
1815
+ var createBrowser = new CreateBrowser();
1816
+ var BatchCreateBrowsers = class {
1817
+ name = "roxy_batch_create_browsers";
1818
+ description = "Create multiple browsers in batch by passing an array of browser configurations";
1819
+ inputSchema = {
1820
+ type: "object",
1821
+ properties: {
1822
+ browsers: {
1823
+ type: "array",
1824
+ description: "Array of browser configuration objects to create",
1825
+ items: {
1826
+ type: "object",
1827
+ properties: createBrowser.inputSchema.properties,
1828
+ required: ["workspaceId"]
1829
+ }
1830
+ }
1831
+ },
1832
+ required: ["browsers"]
1833
+ };
1834
+ get schema() {
1835
+ return {
1836
+ name: this.name,
1837
+ description: this.description,
1838
+ inputSchema: this.inputSchema
1839
+ };
1840
+ }
1841
+ async handle(params) {
1842
+ if (!Array.isArray(params.browsers) || params.browsers.length === 0) {
1843
+ return {
1844
+ content: [
1845
+ {
1846
+ type: "text",
1847
+ text: "\u274C **Failed to create browsers:**\n\n browsers array is required and must not be empty"
1848
+ }
1849
+ ]
1850
+ };
1851
+ }
1852
+ const results = [];
1853
+ const createPromises = params.browsers.map(async (browserParams, index) => {
1854
+ try {
1855
+ const result = await request("/browser/create", {
1856
+ method: "POST",
1857
+ body: JSON.stringify(browserParams)
1858
+ });
1859
+ if (result.code !== 0) {
1860
+ return {
1861
+ index,
1862
+ success: false,
1863
+ error: result.msg
1864
+ };
1865
+ }
1866
+ return {
1867
+ index,
1868
+ success: true,
1869
+ dirId: result.data?.dirId
1870
+ };
1871
+ } catch (error) {
1872
+ return {
1873
+ index,
1874
+ success: false,
1875
+ error: error.message || "Unknown error"
1876
+ };
1877
+ }
1878
+ });
1879
+ const createResults = await Promise.all(createPromises);
1880
+ results.push(...createResults);
1881
+ const successResults = results.filter((r) => r.success);
1882
+ const failureResults = results.filter((r) => !r.success);
1883
+ const successText = successResults.length > 0 ? `\u2705 **Successfully created ${successResults.length} browsers**
1884
+
1885
+ ${successResults.map(
1886
+ (r) => ` - #${r.index + 1}${r.dirId ? ` (ID: \`${r.dirId}\`)` : ""}`
1887
+ ).join("\n")}` : "";
1888
+ const failureText = failureResults.length > 0 ? `\u274C **Failed to create ${failureResults.length} browsers:**
1889
+
1890
+ ${failureResults.map(
1891
+ (r) => ` - #${r.index + 1}: ${r.error}`
1892
+ ).join("\n")}` : "";
1893
+ const summaryLines = [
1894
+ `**Total Requests:** ${results.length}`,
1895
+ `**Success:** ${successResults.length}`,
1896
+ `**Failed:** ${failureResults.length}`,
1897
+ "",
1898
+ ...[successText, failureText].filter(Boolean)
1899
+ ];
1900
+ const summaryText = summaryLines.join("\n");
1901
+ return {
1902
+ content: [
1903
+ {
1904
+ type: "text",
1905
+ text: summaryText
1906
+ }
1907
+ ]
1908
+ };
1909
+ }
1910
+ };
1911
+ var batchCreateBrowsers = new BatchCreateBrowsers();
1912
+ var UpdateBrowser = class {
1913
+ name = "roxy_update_browser";
1914
+ description = "Update a browser with complete configuration control - for expert users needing full parameter access";
1915
+ inputSchema = {
1916
+ type: "object",
1917
+ properties: {
1918
+ ...createBrowser.inputSchema.properties
1919
+ },
1920
+ required: ["workspaceId", "dirId"]
1921
+ };
1922
+ get schema() {
1923
+ return {
1924
+ name: this.name,
1925
+ description: this.description,
1926
+ inputSchema: this.inputSchema
1927
+ };
1928
+ }
1929
+ async handle(params) {
1930
+ const result = await request("/browser/mdf", {
1931
+ method: "POST",
1932
+ body: JSON.stringify(params)
1933
+ });
1934
+ let text = "";
1935
+ if (result.code !== 0) {
1936
+ text = `\u274C **Failed to update browser:**
1937
+
1938
+ error message: ${result.msg}`;
1939
+ } else {
1940
+ text = "\u2705 **Browser Updated Successfully**";
1941
+ }
1942
+ return {
1943
+ content: [
1944
+ {
1945
+ type: "text",
1946
+ text
1947
+ }
1948
+ ]
1949
+ };
1950
+ }
1951
+ };
1952
+ var OpenBrowser = class {
1953
+ name = "roxy_open_browsers";
1954
+ description = "Open one or multiple browsers and return their CDP WebSocket endpoints for automation";
1955
+ inputSchema = {
1956
+ type: "object",
1957
+ properties: {
1958
+ workspaceId: {
1959
+ type: "number",
1960
+ description: "Workspace ID"
1961
+ },
1962
+ dirIds: {
1963
+ type: "array",
1964
+ items: { type: "string" },
1965
+ description: "Array of browser directory IDs to open"
1966
+ },
1967
+ forceOpen: {
1968
+ type: "boolean",
1969
+ // 即使浏览器已被其他用户打开,还是强制打开
1970
+ description: "Force open browser even if it is already opened by other users (default: true)",
1971
+ default: true
1972
+ },
1973
+ args: {
1974
+ type: "array",
1975
+ items: { type: "string" },
1976
+ description: "Optional browser startup arguments (--headless=new startup headless)"
1977
+ }
1978
+ },
1979
+ required: ["workspaceId", "dirIds"]
1980
+ };
1981
+ get schema() {
1982
+ return {
1983
+ name: this.name,
1984
+ description: this.description,
1985
+ inputSchema: this.inputSchema
1986
+ };
1987
+ }
1988
+ async handle(params) {
1989
+ const { workspaceId, dirIds, forceOpen = true, args } = params;
1990
+ if (!workspaceId || !Array.isArray(dirIds) || dirIds.length === 0) {
1991
+ return {
1992
+ content: [
1993
+ {
1994
+ type: "text",
1995
+ text: "\u274C **Failed to open browsers:**\n\n workspaceId and dirIds are required, and dirIds must not be empty"
1996
+ }
1997
+ ]
1998
+ };
1999
+ }
2000
+ const results = [];
2001
+ const openPromises = dirIds.map(async (dirId) => {
2002
+ try {
2003
+ const result = await request("/browser/open", {
2004
+ method: "POST",
2005
+ body: JSON.stringify({
2006
+ workspaceId,
2007
+ dirId,
2008
+ forceOpen,
2009
+ args
2010
+ })
2011
+ });
2012
+ if (result.code !== 0) {
2013
+ return {
2014
+ dirId,
2015
+ success: false,
2016
+ error: result.msg
2017
+ };
2018
+ }
2019
+ return {
2020
+ dirId,
2021
+ success: true,
2022
+ data: result.data
2023
+ };
2024
+ } catch (error) {
2025
+ return {
2026
+ dirId,
2027
+ success: false,
2028
+ error: error.message || "Unknown error"
2029
+ };
2030
+ }
2031
+ });
2032
+ const openResults = await Promise.all(openPromises);
2033
+ results.push(...openResults);
2034
+ const successResults = results.filter((r) => r.success);
2035
+ const failureResults = results.filter((r) => !r.success);
2036
+ const successText = successResults.length > 0 ? [
2037
+ `\u2705 **Successfully opened ${successResults.length} browser(s):**`,
2038
+ "",
2039
+ ...successResults.map((r) => {
2040
+ const data = r.data || {};
2041
+ return [
2042
+ `**Browser ${data.dirId || r.dirId || "Unknown"}** (PID:${data.pid ?? "Unknown"})`,
2043
+ ` - CDP WebSocket: \`${data.ws ?? "N/A"}\``,
2044
+ ` - HTTP Endpoint: \`${data.http ?? "N/A"}\``,
2045
+ ` - Core Version: ${data.coreVersion ?? "Unknown"}`
2046
+ ].join("\n");
2047
+ })
2048
+ ].join("\n") : "";
2049
+ const failureText = failureResults.length > 0 ? [
2050
+ `\u274C **Failed to open ${failureResults.length} browser(s):**`,
2051
+ "",
2052
+ ...failureResults.map(
2053
+ (r) => ` - ${r.dirId}: ${r.error}`
2054
+ )
2055
+ ].join("\n") : "";
2056
+ const summaryLines = [
2057
+ `**Workspace:** ${workspaceId}`,
2058
+ `**Total Requests:** ${results.length}`,
2059
+ `**Success:** ${successResults.length}`,
2060
+ `**Failed:** ${failureResults.length}`,
2061
+ "",
2062
+ ...[successText, failureText].filter(Boolean)
2063
+ ];
2064
+ const summaryText = summaryLines.join("\n");
2065
+ return {
2066
+ content: [
2067
+ {
2068
+ type: "text",
2069
+ text: summaryText
2070
+ }
2071
+ ]
2072
+ };
2073
+ }
2074
+ };
2075
+ var ListBrowsers = class {
2076
+ name = "roxy_list_browsers";
2077
+ description = "Get list of browsers in specified workspace/project";
2078
+ inputSchema = {
2079
+ type: "object",
2080
+ properties: {
2081
+ workspaceId: {
2082
+ type: "number",
2083
+ description: "Workspace ID"
2084
+ },
2085
+ projectIds: {
2086
+ type: "string",
2087
+ description: "Comma-separated project IDs"
2088
+ },
2089
+ windowName: {
2090
+ type: "string",
2091
+ description: "Filter by browser window name"
2092
+ },
2093
+ pageIndex: {
2094
+ type: "number",
2095
+ description: "Page index for pagination (default: 1)",
2096
+ default: 1
2097
+ },
2098
+ pageSize: {
2099
+ type: "number",
2100
+ description: "Number of items per page (default: 15)",
2101
+ default: 15
2102
+ }
2103
+ },
2104
+ required: ["workspaceId"]
2105
+ };
2106
+ get schema() {
2107
+ return {
2108
+ name: this.name,
2109
+ description: this.description,
2110
+ inputSchema: this.inputSchema
2111
+ };
2112
+ }
2113
+ async handle(params) {
2114
+ const searchParams = new URLSearchParams();
2115
+ searchParams.append("workspaceId", params.workspaceId.toString());
2116
+ if (params.projectIds)
2117
+ searchParams.append("projectIds", params.projectIds);
2118
+ if (params.windowName)
2119
+ searchParams.append("windowName", params.windowName);
2120
+ if (params.pageIndex)
2121
+ searchParams.append("page_index", params.pageIndex.toString());
2122
+ if (params.pageSize)
2123
+ searchParams.append("page_size", params.pageSize.toString());
2124
+ const result = await request(`/browser/list_v3?${searchParams}`, {
2125
+ method: "GET"
2126
+ });
2127
+ const data = result.data;
2128
+ let text = "";
2129
+ if (result.code !== 0) {
2130
+ text = `\u274C **Failed to list browsers:**
2131
+
2132
+ error message: ${result.msg}`;
2133
+ } else {
2134
+ text = `Found ${data.total} browsers in workspace ${params.workspaceId}:
2135
+
2136
+ ${data.rows.map(
2137
+ (browser) => `**${browser.windowName || "Unnamed"}** (ID: ${browser.dirId})
2138
+ - Project: ${browser.projectId}
2139
+ - Sort: ${browser.sortNum}
2140
+ - OS: ${browser.os}
2141
+ - Status: ${browser.status}`
2142
+ ).join("\n\n")}`;
2143
+ }
2144
+ return {
2145
+ content: [
2146
+ {
2147
+ type: "text",
2148
+ text
2149
+ }
2150
+ ]
2151
+ };
2152
+ }
2153
+ };
2154
+ var CloseBrowsers = class {
2155
+ name = "roxy_close_browsers";
2156
+ description = "Close multiple browsers by their directory IDs";
2157
+ inputSchema = {
2158
+ type: "object",
2159
+ properties: {
2160
+ dirIds: {
2161
+ type: "array",
2162
+ items: { type: "string" },
2163
+ description: "Array of browser directory IDs to close"
2164
+ }
2165
+ },
2166
+ required: ["dirIds"]
2167
+ };
2168
+ get schema() {
2169
+ return {
2170
+ name: this.name,
2171
+ description: this.description,
2172
+ inputSchema: this.inputSchema
2173
+ };
2174
+ }
2175
+ async handle(params) {
2176
+ if (!params.dirIds || params.dirIds.length === 0) {
2177
+ return {
2178
+ content: [
2179
+ {
2180
+ type: "text",
2181
+ text: "\u274C **Failed to close browsers:**\n\n dirIds are required"
2182
+ }
2183
+ ]
2184
+ };
2185
+ }
2186
+ const results = [];
2187
+ const closePromises = params.dirIds.map(async (dirId) => {
2188
+ try {
2189
+ const result = await request("/browser/close", {
2190
+ method: "POST",
2191
+ body: JSON.stringify({ dirId })
2192
+ });
2193
+ if (result.code !== 0) {
2194
+ return { dirId, success: false, error: result.msg };
2195
+ }
2196
+ return { dirId, success: true };
2197
+ } catch (error) {
2198
+ return { dirId, success: false, error: error.message || "Unknown error" };
2199
+ }
2200
+ });
2201
+ const closeResults = await Promise.all(closePromises);
2202
+ results.push(...closeResults);
2203
+ const successCount = results.filter((r) => r.success).length;
2204
+ const failureCount = results.filter((r) => !r.success).length;
2205
+ const successText = successCount > 0 ? `\u2705 Successfully closed ${successCount} browsers` : "";
2206
+ const failureText = failureCount > 0 ? `\u274C Failed to close ${failureCount} browsers:
2207
+ ${results.filter((r) => !r.success).map(
2208
+ (r) => ` - ${r.dirId}: ${r.error}`
2209
+ ).join("\n")}` : "";
2210
+ return {
2211
+ content: [
2212
+ {
2213
+ type: "text",
2214
+ text: [successText, failureText].filter(Boolean).join("\n\n")
2215
+ }
2216
+ ]
2217
+ };
2218
+ }
2219
+ };
2220
+ var DeleteBrowsers = class {
2221
+ name = "roxy_delete_browsers";
2222
+ description = "Delete multiple browsers permanently by their directory IDs";
2223
+ inputSchema = {
2224
+ type: "object",
2225
+ properties: {
2226
+ workspaceId: {
2227
+ type: "number",
2228
+ description: "Workspace ID"
2229
+ },
2230
+ dirIds: {
2231
+ type: "array",
2232
+ items: { type: "string" },
2233
+ description: "Array of browser directory IDs to delete"
2234
+ }
2235
+ },
2236
+ required: ["workspaceId", "dirIds"]
2237
+ };
2238
+ get schema() {
2239
+ return {
2240
+ name: this.name,
2241
+ description: this.description,
2242
+ inputSchema: this.inputSchema
2243
+ };
2244
+ }
2245
+ async handle(params) {
2246
+ if (!params.workspaceId || !params.dirIds || params.dirIds.length === 0) {
2247
+ return {
2248
+ content: [
2249
+ {
2250
+ type: "text",
2251
+ text: "\u274C **Failed to delete browsers:**\n\n workspaceId and dirIds are required"
2252
+ }
2253
+ ]
2254
+ };
2255
+ }
2256
+ const result = await request("/browser/delete", {
2257
+ method: "POST",
2258
+ body: JSON.stringify({
2259
+ workspaceId: params.workspaceId,
2260
+ dirIds: params.dirIds,
2261
+ isSoftDelete: true
2262
+ })
2263
+ });
2264
+ let text = "";
2265
+ if (result.code !== 0) {
2266
+ text = `\u274C **Browser Deletion Failed**
2267
+
2268
+ **Error:** ${result.msg}
2269
+ **Workspace:** ${params.workspaceId}
2270
+ **Failed Browsers:** ${params.dirIds.length}
2271
+
2272
+ **Browser IDs:**
2273
+ ${params.dirIds.map((dirId, index) => ` ${index + 1}. \`${dirId}\``).join("\n")}`;
2274
+ } else {
2275
+ text = `\u2705 **Browsers Deleted Successfully**
2276
+
2277
+ **Count:** ${params.dirIds.length} browser(s)
2278
+ **Workspace:** ${params.workspaceId}
2279
+
2280
+ **Deleted Browsers:**
2281
+ ${params.dirIds.map((dirId, index) => ` ${index + 1}. \`${dirId}\``).join("\n")}`;
2282
+ }
2283
+ return {
2284
+ content: [
2285
+ {
2286
+ type: "text",
2287
+ text
2288
+ }
2289
+ ]
2290
+ };
2291
+ }
2292
+ };
2293
+ var GetBrowserDetail = class {
2294
+ name = "roxy_get_browser_detail";
2295
+ description = "Get detailed information for a specific browser window";
2296
+ inputSchema = {
2297
+ type: "object",
2298
+ properties: {
2299
+ workspaceId: {
2300
+ type: "number",
2301
+ description: "Workspace ID"
2302
+ },
2303
+ dirId: {
2304
+ type: "string",
2305
+ description: "Browser directory ID"
2306
+ }
2307
+ },
2308
+ required: ["workspaceId", "dirId"]
2309
+ };
2310
+ get schema() {
2311
+ return {
2312
+ name: this.name,
2313
+ description: this.description,
2314
+ inputSchema: this.inputSchema
2315
+ };
2316
+ }
2317
+ async handle(params) {
2318
+ if (!params.workspaceId || !params.dirId) {
2319
+ return {
2320
+ content: [
2321
+ {
2322
+ type: "text",
2323
+ text: "\u274C **Failed to get browser detail:**\n\n workspaceId and dirId are required"
2324
+ }
2325
+ ]
2326
+ };
2327
+ }
2328
+ const searchParams = new URLSearchParams();
2329
+ searchParams.append("workspaceId", params.workspaceId.toString());
2330
+ searchParams.append("dirId", params.dirId);
2331
+ const result = await request(`/browser/detail?${searchParams}`, {
2332
+ method: "GET"
2333
+ });
2334
+ let text = "";
2335
+ if (result.code !== 0) {
2336
+ text = `\u274C **Failed to get browser detail:**
2337
+
2338
+ error message: ${result.msg}`;
2339
+ } else {
2340
+ const detail = result.data.rows && result.data.rows.length > 0 ? result.data.rows[0] : null;
2341
+ if (!detail) {
2342
+ text = "\u274C **Browser not found or no data returned**";
2343
+ } else {
2344
+ const cookieCount = detail.cookie?.length || 0;
2345
+ const { cookie: _cookie, ...detailWithoutCookies } = detail;
2346
+ text = `**Browser Details Summary**
2347
+
2348
+ **ID:** \`${detail.dirId}\`
2349
+ **Name:** ${detail.windowName}
2350
+ **Sort Number:** ${detail.windowSortNum}
2351
+ **Project:** ${detail.projectName} (ID: ${detail.projectId})
2352
+ **OS:** ${detail.os} ${detail.osVersion}
2353
+ **Core Version:** ${detail.coreVersion}
2354
+ **Search Engine:** ${detail.searchEngine}
2355
+ **Open Status:** ${detail.openStatus ? "\u2705 Opened" : "\u274C Closed"}
2356
+ **Cookies:** ${cookieCount} stored (excluded from response to save tokens)
2357
+
2358
+ **Full Details (JSON):**
2359
+ \`\`\`json
2360
+ ${JSON.stringify(detailWithoutCookies, null, 2)}
2361
+ \`\`\``;
2362
+ }
2363
+ }
2364
+ return {
2365
+ content: [
2366
+ {
2367
+ type: "text",
2368
+ text
2369
+ }
2370
+ ]
2371
+ };
2372
+ }
2373
+ };
2374
+ var ClearLocalCache = class {
2375
+ name = "roxy_clear_local_cache";
2376
+ description = "Clear local cache for specified browsers";
2377
+ inputSchema = {
2378
+ type: "object",
2379
+ properties: {
2380
+ dirIds: {
2381
+ type: "array",
2382
+ items: { type: "string" },
2383
+ description: "Array of browser directory IDs"
2384
+ }
2385
+ },
2386
+ required: ["dirIds"]
2387
+ };
2388
+ get schema() {
2389
+ return {
2390
+ name: this.name,
2391
+ description: this.description,
2392
+ inputSchema: this.inputSchema
2393
+ };
2394
+ }
2395
+ async handle(params) {
2396
+ if (!params.dirIds || params.dirIds.length === 0) {
2397
+ return {
2398
+ content: [
2399
+ {
2400
+ type: "text",
2401
+ text: "\u274C **Failed to clear local cache:**\n\n dirIds are required"
2402
+ }
2403
+ ]
2404
+ };
2405
+ }
2406
+ const result = await request("/browser/clear_local_cache", {
2407
+ method: "POST",
2408
+ body: JSON.stringify({ dirIds: params.dirIds })
2409
+ });
2410
+ let text = "";
2411
+ if (result.code !== 0) {
2412
+ text = `\u274C **Failed to clear local cache:**
2413
+
2414
+ error message: ${result.msg}`;
2415
+ } else {
2416
+ text = `\u2705 **Local Cache Cleared**
2417
+
2418
+ **Browser Count:** ${params.dirIds.length}
2419
+
2420
+ **Browser IDs:**
2421
+ ${params.dirIds.map((id, index) => ` ${index + 1}. \`${id}\``).join("\n")}`;
2422
+ }
2423
+ return {
2424
+ content: [
2425
+ {
2426
+ type: "text",
2427
+ text
2428
+ }
2429
+ ]
2430
+ };
2431
+ }
2432
+ };
2433
+ var ClearServerCache = class {
2434
+ name = "roxy_clear_server_cache";
2435
+ description = "Clear server-side cache for specified browsers";
2436
+ inputSchema = {
2437
+ type: "object",
2438
+ properties: {
2439
+ workspaceId: {
2440
+ type: "number",
2441
+ description: "Workspace ID"
2442
+ },
2443
+ dirIds: {
2444
+ type: "array",
2445
+ items: { type: "string" },
2446
+ description: "Array of browser directory IDs"
2447
+ }
2448
+ },
2449
+ required: ["workspaceId", "dirIds"]
2450
+ };
2451
+ get schema() {
2452
+ return {
2453
+ name: this.name,
2454
+ description: this.description,
2455
+ inputSchema: this.inputSchema
2456
+ };
2457
+ }
2458
+ async handle(params) {
2459
+ if (!params.workspaceId || !params.dirIds || params.dirIds.length === 0) {
2460
+ return {
2461
+ content: [
2462
+ {
2463
+ type: "text",
2464
+ text: "\u274C **Failed to clear server cache:**\n\n workspaceId and dirIds are required"
2465
+ }
2466
+ ]
2467
+ };
2468
+ }
2469
+ const result = await request("/browser/clear_server_cache", {
2470
+ method: "POST",
2471
+ body: JSON.stringify({
2472
+ workspaceId: params.workspaceId,
2473
+ dirIds: params.dirIds
2474
+ })
2475
+ });
2476
+ let text = "";
2477
+ if (result.code !== 0) {
2478
+ text = `\u274C **Failed to clear server cache:**
2479
+
2480
+ error message: ${result.msg}`;
2481
+ } else {
2482
+ text = `\u2705 **Server Cache Cleared**
2483
+
2484
+ **Workspace:** ${params.workspaceId}
2485
+ **Browser Count:** ${params.dirIds.length}
2486
+
2487
+ **Browser IDs:**
2488
+ ${params.dirIds.map((id, index) => ` ${index + 1}. \`${id}\``).join("\n")}`;
2489
+ }
2490
+ return {
2491
+ content: [
2492
+ {
2493
+ type: "text",
2494
+ text
2495
+ }
2496
+ ]
2497
+ };
2498
+ }
2499
+ };
2500
+ var RandomFingerprint = class {
2501
+ name = "roxy_random_fingerprint";
2502
+ description = "Randomize browser fingerprint for a specific browser";
2503
+ inputSchema = {
2504
+ type: "object",
2505
+ properties: {
2506
+ workspaceId: {
2507
+ type: "number",
2508
+ description: "Workspace ID"
2509
+ },
2510
+ dirId: {
2511
+ type: "string",
2512
+ description: "Browser directory ID"
2513
+ }
2514
+ },
2515
+ required: ["workspaceId", "dirId"]
2516
+ };
2517
+ get schema() {
2518
+ return {
2519
+ name: this.name,
2520
+ description: this.description,
2521
+ inputSchema: this.inputSchema
2522
+ };
2523
+ }
2524
+ async handle(params) {
2525
+ if (!params.workspaceId || !params.dirId) {
2526
+ return {
2527
+ content: [
2528
+ {
2529
+ type: "text",
2530
+ text: "\u274C **Failed to randomize fingerprint:**\n\n workspaceId and dirId are required"
2531
+ }
2532
+ ]
2533
+ };
2534
+ }
2535
+ const result = await request("/browser/random_env", {
2536
+ method: "POST",
2537
+ body: JSON.stringify({
2538
+ workspaceId: params.workspaceId,
2539
+ dirId: params.dirId
2540
+ })
2541
+ });
2542
+ let text = "";
2543
+ if (result.code !== 0) {
2544
+ text = `\u274C **Failed to randomize fingerprint:**
2545
+
2546
+ error message: ${result.msg}`;
2547
+ } else {
2548
+ text = `\u2705 **Browser Fingerprint Randomized**
2549
+
2550
+ **Browser ID:** \`${params.dirId}\`
2551
+ **Workspace:** ${params.workspaceId}
2552
+
2553
+ *Browser fingerprint has been randomized. Restart the browser to apply changes.*`;
2554
+ }
2555
+ return {
2556
+ content: [
2557
+ {
2558
+ type: "text",
2559
+ text
2560
+ }
2561
+ ]
2562
+ };
2563
+ }
2564
+ };
2565
+ var ListLabels = class {
2566
+ name = "roxy_list_labels";
2567
+ description = "Get list of labels in specified workspace";
2568
+ inputSchema = {
2569
+ type: "object",
2570
+ properties: {
2571
+ workspaceId: {
2572
+ type: "number",
2573
+ description: "Workspace ID"
2574
+ }
2575
+ },
2576
+ required: ["workspaceId"]
2577
+ };
2578
+ get schema() {
2579
+ return {
2580
+ name: this.name,
2581
+ description: this.description,
2582
+ inputSchema: this.inputSchema
2583
+ };
2584
+ }
2585
+ async handle(params) {
2586
+ if (!params.workspaceId) {
2587
+ return {
2588
+ content: [
2589
+ {
2590
+ type: "text",
2591
+ text: "\u274C **Failed to list labels:**\n\n workspaceId is required"
2592
+ }
2593
+ ]
2594
+ };
2595
+ }
2596
+ const searchParams = new URLSearchParams();
2597
+ searchParams.append("workspaceId", params.workspaceId.toString());
2598
+ const result = await request(`/browser/label?${searchParams}`, {
2599
+ method: "GET"
2600
+ });
2601
+ let text = "";
2602
+ if (result.code !== 0) {
2603
+ text = `\u274C **Failed to list labels:**
2604
+
2605
+ error message: ${result.msg}`;
2606
+ } else {
2607
+ const labels = result.data || [];
2608
+ text = `Found ${labels.length} labels in workspace ${params.workspaceId}:
2609
+
2610
+ ${labels.map(
2611
+ (label) => `**${label.name}** (ID: ${label.id})
2612
+ - Color: ${label.color}`
2613
+ ).join("\n\n")}`;
2614
+ }
2615
+ return {
2616
+ content: [
2617
+ {
2618
+ type: "text",
2619
+ text
2620
+ }
2621
+ ]
2622
+ };
2623
+ }
2624
+ };
2625
+ var GetConnectionInfo = class {
2626
+ name = "roxy_get_connection_info";
2627
+ description = "Get connection information (CDP endpoints, PIDs) for currently opened browsers";
2628
+ inputSchema = {
2629
+ type: "object",
2630
+ properties: {
2631
+ dirIds: {
2632
+ type: "array",
2633
+ items: { type: "string" },
2634
+ description: "Array of browser directory IDs to query (optional, returns all if not specified)"
2635
+ }
2636
+ }
2637
+ };
2638
+ get schema() {
2639
+ return {
2640
+ name: this.name,
2641
+ description: this.description,
2642
+ inputSchema: this.inputSchema
2643
+ };
2644
+ }
2645
+ async handle(params) {
2646
+ const searchParams = new URLSearchParams();
2647
+ if (params.dirIds && params.dirIds.length > 0) {
2648
+ searchParams.append("dirIds", params.dirIds.join(","));
2649
+ }
2650
+ const queryString = searchParams.toString();
2651
+ const endpoint = queryString ? `/browser/connection_info?${queryString}` : "/browser/connection_info";
2652
+ const result = await request(endpoint, {
2653
+ method: "GET"
2654
+ });
2655
+ let text = "";
2656
+ if (result.code !== 0) {
2657
+ text = `\u274C **Failed to get connection info:**
2658
+
2659
+ error message: ${result.msg}`;
2660
+ } else {
2661
+ const connections = result.data || [];
2662
+ if (connections.length === 0) {
2663
+ text = "\u26A0\uFE0F No opened browsers found.\n\nUse `roxy_open_browsers` to open browsers first.";
2664
+ } else {
2665
+ text = `Found ${connections.length} opened browser(s):
2666
+
2667
+ ${connections.map(
2668
+ (conn) => `**${conn.windowName || "Unnamed"}** (${conn.dirId})
2669
+ - PID: ${conn.pid}
2670
+ - CDP WebSocket: \`${conn.ws}\`
2671
+ - HTTP Endpoint: \`${conn.http}\`
2672
+ - Core Version: ${conn.coreVersion}
2673
+ - Driver: ${conn.driver}`
2674
+ ).join("\n\n")}`;
2675
+ }
2676
+ }
2677
+ return {
2678
+ content: [
2679
+ {
2680
+ type: "text",
2681
+ text
2682
+ }
2683
+ ]
2684
+ };
2685
+ }
2686
+ };
2687
+ var openBrowser = new OpenBrowser();
2688
+ var updateBrowser = new UpdateBrowser();
2689
+ var listBrowsers = new ListBrowsers();
2690
+ var closeBrowsers = new CloseBrowsers();
2691
+ var deleteBrowsers = new DeleteBrowsers();
2692
+ var getBrowserDetail = new GetBrowserDetail();
2693
+ var clearLocalCache = new ClearLocalCache();
2694
+ var clearServerCache = new ClearServerCache();
2695
+ var randomFingerprint = new RandomFingerprint();
2696
+ var listLabels = new ListLabels();
2697
+ var getConnectionInfo = new GetConnectionInfo();
2698
+
2699
+ // src/modules/other.ts
2700
+ var ListWorkspaces = class {
2701
+ name = "roxy_list_workspaces";
2702
+ description = "Get list of all workspaces and their projects from RoxyBrowser";
2703
+ inputSchema = {
2704
+ type: "object",
2705
+ properties: {
2706
+ pageIndex: {
2707
+ type: "number",
2708
+ description: "Page index for pagination (default: 1)",
2709
+ default: 1
2710
+ },
2711
+ pageSize: {
2712
+ type: "number",
2713
+ description: "Number of items per page (default: 15)",
2714
+ default: 15
2715
+ }
2716
+ }
2717
+ };
2718
+ get schema() {
2719
+ return {
2720
+ name: this.name,
2721
+ description: this.description,
2722
+ inputSchema: this.inputSchema
2723
+ };
2724
+ }
2725
+ async handle(params) {
2726
+ const { pageIndex = 1, pageSize = 15 } = params || {};
2727
+ const searchParams = new URLSearchParams();
2728
+ searchParams.append("page_index", pageIndex.toString());
2729
+ searchParams.append("page_size", pageSize.toString());
2730
+ const result = await request(`/browser/workspace?${searchParams}`, {
2731
+ method: "GET"
2732
+ });
2733
+ let text = "";
2734
+ if (result.code !== 0) {
2735
+ text = `\u274C **Failed to list workspaces:**
2736
+
2737
+ error message: ${result.msg}`;
2738
+ } else {
2739
+ const data = result.data;
2740
+ text = `Found ${data.total} workspaces:
2741
+
2742
+ ${data.rows.map(
2743
+ (ws) => `**${ws.workspaceName}** (ID: ${ws.id})
2744
+ ${ws.project_details.map(
2745
+ (proj) => ` - ${proj.projectName} (ID: ${proj.projectId})`
2746
+ ).join("\n")}`
2747
+ ).join("\n\n")}`;
2748
+ }
2749
+ return {
2750
+ content: [
2751
+ {
2752
+ type: "text",
2753
+ text
2754
+ }
2755
+ ]
2756
+ };
2757
+ }
2758
+ };
2759
+ var HealthCheck = class {
2760
+ name = "roxy_health_check";
2761
+ description = "Check if the target server is alive and healthy. This tool performs a health check to verify server connectivity and status.";
2762
+ inputSchema = {
2763
+ type: "object",
2764
+ properties: {
2765
+ includeWorkspaceCheck: {
2766
+ type: "boolean",
2767
+ description: "Include workspace connectivity tests (optional, default: true)",
2768
+ default: true
2769
+ },
2770
+ includeBrowserCheck: {
2771
+ type: "boolean",
2772
+ description: "Include browser availability checks (optional, default: true)",
2773
+ default: true
2774
+ },
2775
+ verbose: {
2776
+ type: "boolean",
2777
+ description: "Include detailed diagnostic information (optional, default: false)",
2778
+ default: false
2779
+ }
2780
+ }
2781
+ };
2782
+ get schema() {
2783
+ return {
2784
+ name: this.name,
2785
+ description: this.description,
2786
+ inputSchema: this.inputSchema
2787
+ };
2788
+ }
2789
+ async handle(params) {
2790
+ const { includeWorkspaceCheck = true, includeBrowserCheck = true, verbose = false } = params || {};
2791
+ let healthStatus = "unknown";
2792
+ let healthError = "";
2793
+ try {
2794
+ const healthResult = await request("/health", {
2795
+ method: "GET"
2796
+ });
2797
+ if (healthResult.code === 0 || healthResult.code === void 0) {
2798
+ healthStatus = "healthy";
2799
+ } else {
2800
+ healthStatus = "unhealthy";
2801
+ healthError = healthResult.msg || "Health check failed";
2802
+ }
2803
+ } catch (error) {
2804
+ healthStatus = "unhealthy";
2805
+ healthError = error.message || "Failed to connect to server";
2806
+ }
2807
+ let text = `## \u{1F50D} \u5065\u5EB7\u68C0\u67E5\u62A5\u544A / Health Check Report
2808
+
2809
+ `;
2810
+ text += `### \u{1F310} \u670D\u52A1\u5668\u72B6\u6001 / Server Status
2811
+ `;
2812
+ text += `- **\u670D\u52A1\u5668\u8FDE\u63A5 / Server Connection**: ${healthStatus === "healthy" ? "\u2705 \u6B63\u5E38" : "\u274C \u5F02\u5E38"}
2813
+ `;
2814
+ if (healthStatus !== "healthy" && healthError) {
2815
+ text += `- **\u9519\u8BEF\u4FE1\u606F / Error**: ${healthError}
2816
+ `;
2817
+ }
2818
+ if (includeWorkspaceCheck && healthStatus === "healthy") {
2819
+ try {
2820
+ const workspaceResult = await request("/browser/workspace?page_index=1&page_size=5", {
2821
+ method: "GET"
2822
+ });
2823
+ if (workspaceResult.code === 0) {
2824
+ const workspaces = workspaceResult.data;
2825
+ text += `
2826
+ ### \u{1F4C1} \u5DE5\u4F5C\u533A\u4FE1\u606F / Workspace Information
2827
+ `;
2828
+ text += `- **\u53EF\u7528\u5DE5\u4F5C\u533A / Available Workspaces**: ${workspaces.total}
2829
+ `;
2830
+ if (workspaces.rows && workspaces.rows.length > 0) {
2831
+ text += `- **\u5DE5\u4F5C\u533A\u8BE6\u60C5 / Workspace Details**:
2832
+ `;
2833
+ workspaces.rows.slice(0, 3).forEach((ws) => {
2834
+ const projectCount = ws.project_details?.length || 0;
2835
+ text += ` - ${ws.workspaceName} (ID: ${ws.id}) - ${projectCount} projects
2836
+ `;
2837
+ });
2838
+ if (workspaces.total > 3) {
2839
+ text += ` - ... and ${workspaces.total - 3} more
2840
+ `;
2841
+ }
2842
+ }
2843
+ } else {
2844
+ text += `
2845
+ ### \u{1F4C1} \u5DE5\u4F5C\u533A\u4FE1\u606F / Workspace Information
2846
+ `;
2847
+ text += `- **\u72B6\u6001**: \u26A0\uFE0F \u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u533A\u4FE1\u606F
2848
+ `;
2849
+ text += `- **\u9519\u8BEF**: ${workspaceResult.msg}
2850
+ `;
2851
+ }
2852
+ } catch (error) {
2853
+ text += `
2854
+ ### \u{1F4C1} \u5DE5\u4F5C\u533A\u4FE1\u606F / Workspace Information
2855
+ `;
2856
+ text += `- **\u72B6\u6001**: \u274C \u65E0\u6CD5\u83B7\u53D6\u5DE5\u4F5C\u533A\u4FE1\u606F
2857
+ `;
2858
+ text += `- **\u9519\u8BEF**: ${error.message || "Unknown error"}
2859
+ `;
2860
+ }
2861
+ }
2862
+ if (includeBrowserCheck && healthStatus === "healthy") {
2863
+ try {
2864
+ const workspaceResult = await request("/browser/workspace?page_index=1&page_size=1", {
2865
+ method: "GET"
2866
+ });
2867
+ if (workspaceResult.code === 0 && workspaceResult.data.rows && workspaceResult.data.rows.length > 0) {
2868
+ const firstWorkspace = workspaceResult.data.rows[0];
2869
+ const browserResult = await request(`/browser/list_v3?workspaceId=${firstWorkspace.id}&page_index=1&page_size=5`, {
2870
+ method: "GET"
2871
+ });
2872
+ if (browserResult.code === 0) {
2873
+ const browsers = browserResult.data;
2874
+ text += `
2875
+ ### \u{1F310} \u6D4F\u89C8\u5668\u4FE1\u606F / Browser Information
2876
+ `;
2877
+ text += `- **\u5DE5\u4F5C\u533A / Workspace**: ${firstWorkspace.workspaceName} (ID: ${firstWorkspace.id})
2878
+ `;
2879
+ text += `- **\u6D4F\u89C8\u5668\u603B\u6570 / Total Browsers**: ${browsers.total}
2880
+ `;
2881
+ if (browsers.rows && browsers.rows.length > 0) {
2882
+ text += `- **\u6D4F\u89C8\u5668\u793A\u4F8B / Browser Examples**:
2883
+ `;
2884
+ browsers.rows.slice(0, 3).forEach((browser) => {
2885
+ text += ` - ${browser.windowName || "Unnamed"} (ID: ${browser.dirId}) - ${browser.status}
2886
+ `;
2887
+ });
2888
+ }
2889
+ }
2890
+ }
2891
+ } catch (error) {
2892
+ text += `
2893
+ ### \u{1F310} \u6D4F\u89C8\u5668\u4FE1\u606F / Browser Information
2894
+ `;
2895
+ text += `- **\u72B6\u6001**: \u26A0\uFE0F \u65E0\u6CD5\u83B7\u53D6\u6D4F\u89C8\u5668\u4FE1\u606F
2896
+ `;
2897
+ text += `- **\u9519\u8BEF**: ${error.message || "Unknown error"}
2898
+ `;
2899
+ }
2900
+ }
2901
+ if (verbose && healthStatus === "healthy") {
2902
+ text += `
2903
+ ### \u{1F4CA} \u8BE6\u7EC6\u4FE1\u606F / Detailed Information
2904
+ `;
2905
+ text += `- **\u5065\u5EB7\u68C0\u67E5\u65F6\u95F4 / Check Time**: ${(/* @__PURE__ */ new Date()).toISOString()}
2906
+ `;
2907
+ text += `- **\u68C0\u67E5\u6A21\u5F0F / Check Mode**: ${includeWorkspaceCheck ? "Workspace + " : ""}${includeBrowserCheck ? "Browser" : ""}
2908
+ `;
2909
+ }
2910
+ return {
2911
+ content: [
2912
+ {
2913
+ type: "text",
2914
+ text
2915
+ }
2916
+ ]
2917
+ };
2918
+ }
2919
+ };
2920
+ var listWorkspaces = new ListWorkspaces();
2921
+ var healthCheck = new HealthCheck();
2922
+
2923
+ // src/index.ts
2924
+ var TOOLS = [
2925
+ listBrowsers.schema,
2926
+ batchCreateBrowsers.schema,
2927
+ createBrowser.schema,
2928
+ openBrowser.schema,
2929
+ updateBrowser.schema,
2930
+ closeBrowsers.schema,
2931
+ deleteBrowsers.schema,
2932
+ getBrowserDetail.schema,
2933
+ clearLocalCache.schema,
2934
+ clearServerCache.schema,
2935
+ randomFingerprint.schema,
2936
+ listLabels.schema,
2937
+ getConnectionInfo.schema,
2938
+ proxyList.schema,
2939
+ proxyStore.schema,
2940
+ createProxy.schema,
2941
+ batchCreateProxies.schema,
2942
+ detectProxy.schema,
2943
+ modifyProxy.schema,
2944
+ deleteProxies.schema,
2945
+ // getDetectChannels.schema,
2946
+ listAccounts.schema,
2947
+ createAccount.schema,
2948
+ batchCreateAccounts.schema,
2949
+ modifyAccount.schema,
2950
+ deleteAccounts.schema,
2951
+ listWorkspaces.schema,
2952
+ healthCheck.schema
2953
+ ];
2954
+ var RoxyBrowserMCPServer = class {
2955
+ server;
2956
+ constructor() {
2957
+ this.server = new index_js.Server(
2958
+ {
2959
+ name: "roxybrowser-openapi-mcp",
2960
+ version: "1.0.0"
2961
+ },
2962
+ {
2963
+ capabilities: {
2964
+ tools: {}
2965
+ }
2966
+ }
2967
+ );
2968
+ this.setupHandlers();
2969
+ }
2970
+ setupHandlers() {
2971
+ this.server.setRequestHandler(types_js.ListToolsRequestSchema, async () => ({
2972
+ tools: TOOLS
2973
+ }));
2974
+ this.server.setRequestHandler(types_js.CallToolRequestSchema, async (request2) => {
2975
+ const { name, arguments: args } = request2.params;
2976
+ try {
2977
+ switch (name) {
2978
+ // 浏览器相关
2979
+ case listBrowsers.name:
2980
+ return await listBrowsers.handle(args);
2981
+ case createBrowser.name:
2982
+ return await createBrowser.handle(args);
2983
+ case openBrowser.name:
2984
+ return await openBrowser.handle(args);
2985
+ case updateBrowser.name:
2986
+ return await updateBrowser.handle(args);
2987
+ case closeBrowsers.name:
2988
+ return await closeBrowsers.handle(args);
2989
+ case deleteBrowsers.name:
2990
+ return await deleteBrowsers.handle(args);
2991
+ case batchCreateBrowsers.name:
2992
+ return await batchCreateBrowsers.handle(args);
2993
+ case listLabels.name:
2994
+ return await listLabels.handle(args);
2995
+ case getConnectionInfo.name:
2996
+ return await getConnectionInfo.handle(args);
2997
+ case randomFingerprint.name:
2998
+ return await randomFingerprint.handle(args);
2999
+ case clearLocalCache.name:
3000
+ return await clearLocalCache.handle(args);
3001
+ case clearServerCache.name:
3002
+ return await clearServerCache.handle(args);
3003
+ case getBrowserDetail.name:
3004
+ return await getBrowserDetail.handle(args);
3005
+ // 账号相关
3006
+ case listAccounts.name:
3007
+ return await listAccounts.handle(args);
3008
+ case createAccount.name:
3009
+ return await createAccount.handle(args);
3010
+ case batchCreateAccounts.name:
3011
+ return await batchCreateAccounts.handle(args);
3012
+ case modifyAccount.name:
3013
+ return await modifyAccount.handle(args);
3014
+ case deleteAccounts.name:
3015
+ return await deleteAccounts.handle(args);
3016
+ // 代理相关
3017
+ case proxyList.name:
3018
+ return await proxyList.handle(args);
3019
+ case proxyStore.name:
3020
+ return await proxyStore.handle(args);
3021
+ case createProxy.name:
3022
+ return await createProxy.handle(args);
3023
+ case batchCreateProxies.name:
3024
+ return await batchCreateProxies.handle(args);
3025
+ case detectProxy.name:
3026
+ return await detectProxy.handle(args);
3027
+ case modifyProxy.name:
3028
+ return await modifyProxy.handle(args);
3029
+ case deleteProxies.name:
3030
+ return await deleteProxies.handle(args);
3031
+ // 空间列表
3032
+ case listWorkspaces.name:
3033
+ return await listWorkspaces.handle(args);
3034
+ // 健康检查
3035
+ case healthCheck.name:
3036
+ return await healthCheck.handle(args);
3037
+ default:
3038
+ throw new Error(`Unknown tool: ${name}`);
3039
+ }
3040
+ } catch (error) {
3041
+ return {
3042
+ content: [
3043
+ {
3044
+ type: "text",
3045
+ text: error instanceof Error ? error.message : "Unknown error"
3046
+ }
3047
+ ]
3048
+ };
3049
+ }
3050
+ });
3051
+ }
3052
+ async run() {
3053
+ console.error("\u{1F680} Starting RoxyBrowser MCP Server...");
3054
+ const transport = new stdio_js.StdioServerTransport();
3055
+ await this.server.connect(transport);
3056
+ console.error("\u2705 RoxyBrowser MCP Server is running");
3057
+ }
3058
+ };
3059
+ async function runServer() {
3060
+ const server = new RoxyBrowserMCPServer();
3061
+ await server.run();
3062
+ }
3063
+
3064
+ // src/cli.ts
3065
+ var PKG_VERSION = "1.0.9";
3066
+ var program = new commander.Command();
3067
+ program.name("roxy-browser-mcp").description("RoxyBrowser MCP Server - Model Context Protocol server for RoxyBrowser automation").version(PKG_VERSION, "-V, --version", "Show version").option(
3068
+ "-H, --api-host <url>",
3069
+ "RoxyBrowser API base URL",
3070
+ process.env.ROXY_API_HOST ?? "http://127.0.0.1:50000"
3071
+ ).option(
3072
+ "-k, --api-key <key>",
3073
+ "API key (or set ROXY_API_KEY)",
3074
+ process.env.ROXY_API_KEY ?? ""
3075
+ ).option(
3076
+ "-t, --timeout <ms>",
3077
+ "Request timeout in milliseconds",
3078
+ (v) => v != null && v !== "" ? Number.parseInt(v, 10) : 3e4,
3079
+ process.env.ROXY_TIMEOUT != null ? Number(process.env.ROXY_TIMEOUT) : 3e4
3080
+ ).addHelpText(
3081
+ "after",
3082
+ `
3083
+ Environment (used when option not passed):
3084
+ ROXY_API_HOST API base URL (default: http://127.0.0.1:50000)
3085
+ ROXY_API_KEY API key (required)
3086
+ ROXY_TIMEOUT Timeout in ms (default: 30000)
3087
+
3088
+ Examples:
3089
+ roxy-browser-mcp --api-key "your-key"
3090
+ roxy-browser-mcp -k "your-key" -H http://127.0.0.1:50000
3091
+ ROXY_API_KEY=your-key roxy-browser-mcp
3092
+ `
3093
+ );
3094
+ async function main() {
3095
+ program.parse();
3096
+ const opts = program.opts();
3097
+ if (opts.apiHost != null && opts.apiHost !== "") process.env.ROXY_API_HOST = opts.apiHost;
3098
+ if (opts.apiKey != null && opts.apiKey !== "") process.env.ROXY_API_KEY = opts.apiKey;
3099
+ if (opts.timeout != null) process.env.ROXY_TIMEOUT = String(opts.timeout);
3100
+ try {
3101
+ await runServer();
3102
+ } catch (error) {
3103
+ if (error instanceof ConfigError) {
3104
+ console.error(`\u274C Configuration Error: ${error.message}`);
3105
+ process.exit(1);
3106
+ }
3107
+ console.error("\u274C Unexpected error:", error);
3108
+ process.exit(1);
3109
+ }
3110
+ }
3111
+ main();
3112
+ //# sourceMappingURL=cli.cjs.map
3113
+ //# sourceMappingURL=cli.cjs.map