botbrowser-mcp 0.1.5 → 0.1.7
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/dist/db/database.js +10 -16
- package/dist/db/database.js.map +1 -1
- package/dist/db/repositories/profile.d.ts +2 -2
- package/dist/db/repositories/profile.js +1 -1
- package/dist/db/repositories/profile.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +28 -9
- package/dist/index.js.map +1 -1
- package/dist/playwright/manager.d.ts +1 -1
- package/dist/playwright/manager.js +58 -28
- package/dist/playwright/manager.js.map +1 -1
- package/dist/tools/instance.d.ts +5 -0
- package/dist/tools/instance.js +12 -1
- package/dist/tools/instance.js.map +1 -1
- package/dist/tools/playwright-mcp-proxy.d.ts +63 -0
- package/dist/tools/playwright-mcp-proxy.js +229 -0
- package/dist/tools/playwright-mcp-proxy.js.map +1 -0
- package/dist/tools/profile.js +3 -3
- package/dist/tools/profile.js.map +1 -1
- package/package.json +5 -5
- package/readme.md +226 -12
- package/dist/cli.d.ts +0 -5
- package/dist/cli.js +0 -13
- package/dist/cli.js.map +0 -1
- package/dist/tools/browser.d.ts +0 -178
- package/dist/tools/browser.js +0 -211
- package/dist/tools/browser.js.map +0 -1
package/dist/db/database.js
CHANGED
|
@@ -20,8 +20,8 @@ export function initDatabase() {
|
|
|
20
20
|
CREATE TABLE IF NOT EXISTS browser_profiles (
|
|
21
21
|
alias TEXT PRIMARY KEY,
|
|
22
22
|
executable_path TEXT NOT NULL,
|
|
23
|
-
fingerprint_path TEXT
|
|
24
|
-
storage_state_path TEXT
|
|
23
|
+
fingerprint_path TEXT,
|
|
24
|
+
storage_state_path TEXT,
|
|
25
25
|
description TEXT,
|
|
26
26
|
proxy_server TEXT,
|
|
27
27
|
proxy_username TEXT,
|
|
@@ -36,33 +36,27 @@ export function initDatabase() {
|
|
|
36
36
|
CREATE TABLE IF NOT EXISTS accounts (
|
|
37
37
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
38
38
|
profile_alias TEXT NOT NULL,
|
|
39
|
-
platform TEXT NOT NULL,
|
|
40
|
-
identifier TEXT NOT NULL,
|
|
41
39
|
username TEXT NOT NULL,
|
|
42
40
|
metadata TEXT,
|
|
43
41
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
44
|
-
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
45
|
-
UNIQUE(platform, identifier),
|
|
46
42
|
FOREIGN KEY (profile_alias) REFERENCES browser_profiles(alias) ON DELETE CASCADE
|
|
47
43
|
)
|
|
48
44
|
`);
|
|
49
|
-
//
|
|
45
|
+
// 浏览器实例表
|
|
50
46
|
db.exec(`
|
|
51
47
|
CREATE TABLE IF NOT EXISTS browser_instances (
|
|
52
|
-
id
|
|
48
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
53
49
|
profile_alias TEXT NOT NULL,
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
FOREIGN KEY (profile_alias) REFERENCES browser_profiles(alias) ON DELETE CASCADE
|
|
50
|
+
account_id INTEGER,
|
|
51
|
+
is_active INTEGER DEFAULT 0,
|
|
52
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
53
|
+
last_active TEXT,
|
|
54
|
+
FOREIGN KEY (profile_alias) REFERENCES browser_profiles(alias) ON DELETE CASCADE,
|
|
55
|
+
FOREIGN KEY (account_id) REFERENCES accounts(id) ON DELETE SET NULL
|
|
61
56
|
)
|
|
62
57
|
`);
|
|
63
58
|
// 创建索引
|
|
64
59
|
db.exec(`
|
|
65
|
-
CREATE INDEX IF NOT EXISTS idx_accounts_platform_identifier ON accounts(platform, identifier);
|
|
66
60
|
CREATE INDEX IF NOT EXISTS idx_accounts_profile ON accounts(profile_alias);
|
|
67
61
|
CREATE INDEX IF NOT EXISTS idx_instances_profile ON browser_instances(profile_alias);
|
|
68
62
|
CREATE INDEX IF NOT EXISTS idx_instances_active ON browser_instances(is_active);
|
package/dist/db/database.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAEnD,SAAS;AACT,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;IAC3B,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,MAAM,EAAE,GAA2B,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;AAGhE,SAAS;AACT,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE/B,MAAM,UAAU,YAAY;IAC1B,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;GAcP,CAAC,CAAC;IAEH,MAAM;IACN,EAAE,CAAC,IAAI,CAAC
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AAEtC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AAEzB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAEnD,SAAS;AACT,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;IAC3B,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,MAAM,CAAC,MAAM,EAAE,GAA2B,IAAI,QAAQ,CAAC,OAAO,CAAC,CAAC;AAGhE,SAAS;AACT,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE/B,MAAM,UAAU,YAAY;IAC1B,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;GAcP,CAAC,CAAC;IAEH,MAAM;IACN,EAAE,CAAC,IAAI,CAAC;;;;;;;;;GASP,CAAC,CAAC;IAEH,SAAS;IACT,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;GAWP,CAAC,CAAC;IAEH,OAAO;IACP,EAAE,CAAC,IAAI,CAAC;;;;GAIP,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
export interface BrowserProfile {
|
|
2
2
|
alias: string;
|
|
3
3
|
executable_path: string;
|
|
4
|
-
fingerprint_path
|
|
5
|
-
storage_state_path
|
|
4
|
+
fingerprint_path?: string;
|
|
5
|
+
storage_state_path?: string;
|
|
6
6
|
description?: string;
|
|
7
7
|
proxy_server?: string;
|
|
8
8
|
proxy_username?: string;
|
|
@@ -16,7 +16,7 @@ export class ProfileRepository {
|
|
|
16
16
|
description, proxy_server, proxy_username, proxy_password, proxy_bypass
|
|
17
17
|
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
18
18
|
`);
|
|
19
|
-
stmt.run(profile.alias, profile.executable_path, profile.fingerprint_path, profile.storage_state_path, profile.description || null, profile.proxy_server || null, profile.proxy_username || null, profile.proxy_password || null, profile.proxy_bypass || null);
|
|
19
|
+
stmt.run(profile.alias, profile.executable_path, profile.fingerprint_path || null, profile.storage_state_path || null, profile.description || null, profile.proxy_server || null, profile.proxy_username || null, profile.proxy_password || null, profile.proxy_bypass || null);
|
|
20
20
|
}
|
|
21
21
|
update(alias, updates) {
|
|
22
22
|
const fields = [];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/db/repositories/profile.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAgBpC,MAAM,OAAO,iBAAiB;IAC5B,MAAM;QACJ,OAAO,EAAE,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC,GAAG,EAAsB,CAAC;IAChF,CAAC;IAED,UAAU,CAAC,KAAa;QACtB,OAAO,EAAE,CAAC,OAAO,CAAC,gDAAgD,CAAC,CAAC,GAAG,CAAC,KAAK,CAA+B,CAAC;IAC/G,CAAC;IAED,MAAM,CAAC,OAAyD;QAC9D,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;KAKvB,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CACN,OAAO,CAAC,KAAK,EACb,OAAO,CAAC,eAAe,EACvB,OAAO,CAAC,gBAAgB,
|
|
1
|
+
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../../../src/db/repositories/profile.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAgBpC,MAAM,OAAO,iBAAiB;IAC5B,MAAM;QACJ,OAAO,EAAE,CAAC,OAAO,CAAC,gCAAgC,CAAC,CAAC,GAAG,EAAsB,CAAC;IAChF,CAAC;IAED,UAAU,CAAC,KAAa;QACtB,OAAO,EAAE,CAAC,OAAO,CAAC,gDAAgD,CAAC,CAAC,GAAG,CAAC,KAAK,CAA+B,CAAC;IAC/G,CAAC;IAED,MAAM,CAAC,OAAyD;QAC9D,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,CAAC;;;;;KAKvB,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CACN,OAAO,CAAC,KAAK,EACb,OAAO,CAAC,eAAe,EACvB,OAAO,CAAC,gBAAgB,IAAI,IAAI,EAChC,OAAO,CAAC,kBAAkB,IAAI,IAAI,EAClC,OAAO,CAAC,WAAW,IAAI,IAAI,EAC3B,OAAO,CAAC,YAAY,IAAI,IAAI,EAC5B,OAAO,CAAC,cAAc,IAAI,IAAI,EAC9B,OAAO,CAAC,cAAc,IAAI,IAAI,EAC9B,OAAO,CAAC,YAAY,IAAI,IAAI,CAC7B,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,KAAa,EAAE,OAAgC;QACpD,MAAM,MAAM,GAAG,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,EAAE,CAAC;QAElB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YACnD,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,YAAY,EAAE,CAAC;gBAC5C,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,CAAC;gBAC1B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEhC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,EAAE,CAAC,OAAO,CAAC,+BAA+B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;IAChG,CAAC;IAED,MAAM,CAAC,KAAa;QAClB,EAAE,CAAC,OAAO,CAAC,8CAA8C,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACxE,CAAC;IAED,cAAc,CAAC,KAAa;QAC1B,EAAE,CAAC,OAAO,CAAC,yEAAyE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACnG,CAAC;CACF"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -10,20 +10,35 @@ import { PlaywrightManager } from './playwright/manager.js';
|
|
|
10
10
|
import { profileTools } from './tools/profile.js';
|
|
11
11
|
import { accountTools } from './tools/account.js';
|
|
12
12
|
import { instanceTools, setManager as setInstanceManager } from './tools/instance.js';
|
|
13
|
-
import {
|
|
13
|
+
import { PlaywrightMCPProxy } from './tools/playwright-mcp-proxy.js';
|
|
14
14
|
// 初始化数据库
|
|
15
15
|
initDatabase();
|
|
16
16
|
// 创建 Playwright 管理器
|
|
17
17
|
const manager = new PlaywrightManager();
|
|
18
18
|
setInstanceManager(manager);
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
19
|
+
// 创建 Playwright MCP 代理并导出为全局变量(供 switch_browser_instance 使用)
|
|
20
|
+
export const playwrightMCPProxy = new PlaywrightMCPProxy(async () => {
|
|
21
|
+
const context = manager.getActiveContext();
|
|
22
|
+
if (!context) {
|
|
23
|
+
throw new Error('没有活跃的浏览器实例,请先使用 launch_instance 启动');
|
|
24
|
+
}
|
|
25
|
+
return context;
|
|
26
|
+
});
|
|
27
|
+
// 初始化工具
|
|
28
|
+
let allTools = {};
|
|
29
|
+
async function initializeTools() {
|
|
30
|
+
// 初始化 Playwright MCP 代理
|
|
31
|
+
await playwrightMCPProxy.initialize();
|
|
32
|
+
// 获取 Playwright MCP 的所有工具
|
|
33
|
+
const playwrightTools = playwrightMCPProxy.getToolDefinitions();
|
|
34
|
+
// 合并所有工具
|
|
35
|
+
allTools = {
|
|
36
|
+
...profileTools,
|
|
37
|
+
...accountTools,
|
|
38
|
+
...instanceTools,
|
|
39
|
+
...playwrightTools, // 完整的 Playwright MCP 工具集
|
|
40
|
+
};
|
|
41
|
+
}
|
|
27
42
|
// 创建 MCP Server
|
|
28
43
|
const server = new Server({
|
|
29
44
|
name: 'botbrowser-mcp',
|
|
@@ -65,14 +80,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
65
80
|
});
|
|
66
81
|
// 启动服务器
|
|
67
82
|
async function main() {
|
|
83
|
+
// 初始化所有工具
|
|
84
|
+
await initializeTools();
|
|
68
85
|
const transport = new StdioServerTransport();
|
|
69
86
|
await server.connect(transport);
|
|
70
87
|
// 优雅退出
|
|
71
88
|
process.on('SIGINT', async () => {
|
|
89
|
+
await playwrightMCPProxy.close();
|
|
72
90
|
await manager.stopAll();
|
|
73
91
|
process.exit(0);
|
|
74
92
|
});
|
|
75
93
|
process.on('SIGTERM', async () => {
|
|
94
|
+
await playwrightMCPProxy.close();
|
|
76
95
|
await manager.stopAll();
|
|
77
96
|
process.exit(0);
|
|
78
97
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;GAEG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AACtF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAErE,SAAS;AACT,YAAY,EAAE,CAAC;AAEf,oBAAoB;AACpB,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;AACxC,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAE5B,6DAA6D;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,kBAAkB,CAAC,KAAK,IAAI,EAAE;IAClE,MAAM,OAAO,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAC3C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC,CAAC;AAEH,QAAQ;AACR,IAAI,QAAQ,GAAwB,EAAE,CAAC;AAEvC,KAAK,UAAU,eAAe;IAC5B,wBAAwB;IACxB,MAAM,kBAAkB,CAAC,UAAU,EAAE,CAAC;IAEtC,0BAA0B;IAC1B,MAAM,eAAe,GAAG,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;IAEhE,SAAS;IACT,QAAQ,GAAG;QACT,GAAG,YAAY;QACf,GAAG,YAAY;QACf,GAAG,aAAa;QAChB,GAAG,eAAe,EAAE,yBAAyB;KAC9C,CAAC;AACJ,CAAC;AAED,gBAAgB;AAChB,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB;IACE,IAAI,EAAE,gBAAgB;IACtB,OAAO,EAAE,OAAO;CACjB,EACD;IACE,YAAY,EAAE;QACZ,KAAK,EAAE,EAAE;KACV;CACF,CACF,CAAC;AAEF,WAAW;AACX,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;IAC1D,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;YACrD,IAAI;YACJ,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,WAAW;AACX,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC;IACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAiC,CAAC,CAAC;IAEzD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,SAAS,QAAQ,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;iBACtE,CAAC;YACF,OAAO,EAAE,IAAI;SACd,CAAC;IACJ,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,QAAQ;AACR,KAAK,UAAU,IAAI;IACjB,UAAU;IACV,MAAM,eAAe,EAAE,CAAC;IAExB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,OAAO;IACP,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,IAAI,EAAE;QAC9B,MAAM,kBAAkB,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,KAAK,IAAI,EAAE;QAC/B,MAAM,kBAAkB,CAAC,KAAK,EAAE,CAAC;QACjC,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -10,7 +10,7 @@ export declare class PlaywrightManager {
|
|
|
10
10
|
/**
|
|
11
11
|
* 启动浏览器实例
|
|
12
12
|
*/
|
|
13
|
-
launchInstance(profileAlias: string, accountId?: number): Promise<number>;
|
|
13
|
+
launchInstance(profileAlias: string, accountId?: number, launchOptions?: any): Promise<number>;
|
|
14
14
|
/**
|
|
15
15
|
* 切换活跃实例
|
|
16
16
|
*/
|
|
@@ -6,6 +6,8 @@ import { ProfileRepository } from '../db/repositories/profile.js';
|
|
|
6
6
|
import { InstanceRepository } from '../db/repositories/instance.js';
|
|
7
7
|
import { AccountRepository } from '../db/repositories/account.js';
|
|
8
8
|
import fs from 'fs/promises';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import os from 'os';
|
|
9
11
|
export class PlaywrightManager {
|
|
10
12
|
instances = new Map();
|
|
11
13
|
profileRepo = new ProfileRepository();
|
|
@@ -14,7 +16,7 @@ export class PlaywrightManager {
|
|
|
14
16
|
/**
|
|
15
17
|
* 启动浏览器实例
|
|
16
18
|
*/
|
|
17
|
-
async launchInstance(profileAlias, accountId) {
|
|
19
|
+
async launchInstance(profileAlias, accountId, launchOptions) {
|
|
18
20
|
const profile = this.profileRepo.getByAlias(profileAlias);
|
|
19
21
|
if (!profile) {
|
|
20
22
|
throw new Error(`浏览器配置不存在: ${profileAlias}`);
|
|
@@ -26,40 +28,60 @@ export class PlaywrightManager {
|
|
|
26
28
|
throw new Error(`账号 ${accountId} 不属于配置 ${profileAlias}`);
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
|
-
//
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
// 为每个实例创建独立的用户数据目录
|
|
32
|
+
const timestamp = Date.now();
|
|
33
|
+
const randomId = Math.random().toString(36).substring(7);
|
|
34
|
+
const userDataDir = path.join(os.tmpdir(), `botbrowser-${profileAlias}-${timestamp}-${randomId}`);
|
|
35
|
+
// 使用传入的 launchOptions,如果没有则使用默认值
|
|
36
|
+
const options = launchOptions || {};
|
|
37
|
+
// 确保有基本的 args 数组
|
|
38
|
+
if (!options.args) {
|
|
39
|
+
options.args = [];
|
|
40
|
+
}
|
|
41
|
+
// 添加基本参数(如果还没有的话)
|
|
42
|
+
if (!options.args.includes('--no-first-run')) {
|
|
43
|
+
options.args.push('--no-first-run', '--no-default-browser-check');
|
|
44
|
+
}
|
|
34
45
|
// 防指纹参数
|
|
35
46
|
if (profile.fingerprint_path) {
|
|
36
|
-
|
|
47
|
+
options.args.push(`--bot-profile=${profile.fingerprint_path}`);
|
|
37
48
|
}
|
|
38
|
-
//
|
|
49
|
+
// 代理配置(profile 中的代理优先级更高)
|
|
39
50
|
if (profile.proxy_server) {
|
|
40
|
-
|
|
51
|
+
options.proxy = {
|
|
41
52
|
server: profile.proxy_server,
|
|
42
53
|
};
|
|
43
54
|
if (profile.proxy_username) {
|
|
44
|
-
|
|
45
|
-
|
|
55
|
+
options.proxy.username = profile.proxy_username;
|
|
56
|
+
options.proxy.password = profile.proxy_password || '';
|
|
46
57
|
}
|
|
47
58
|
if (profile.proxy_bypass) {
|
|
48
|
-
|
|
59
|
+
options.proxy.bypass = profile.proxy_bypass;
|
|
49
60
|
}
|
|
50
61
|
}
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const contextOptions = {};
|
|
55
|
-
try {
|
|
56
|
-
await fs.access(profile.storage_state_path);
|
|
57
|
-
contextOptions.storageState = profile.storage_state_path;
|
|
62
|
+
// 设置默认 viewport(如果配置中没有指定)
|
|
63
|
+
if (!options.viewport) {
|
|
64
|
+
options.viewport = { width: 1280, height: 720 };
|
|
58
65
|
}
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
// 如果配置指定了 storage_state_path,尝试加载
|
|
67
|
+
if (profile.storage_state_path) {
|
|
68
|
+
try {
|
|
69
|
+
await fs.access(profile.storage_state_path);
|
|
70
|
+
options.storageState = profile.storage_state_path;
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// 文件不存在,使用默认空状态
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// 使用 launchPersistentContext 启动(支持 userDataDir)
|
|
77
|
+
const context = await chromium.launchPersistentContext(userDataDir, {
|
|
78
|
+
executablePath: profile.executable_path,
|
|
79
|
+
...options, // launchOptions 中可以包含 headless、channel 等配置
|
|
80
|
+
});
|
|
81
|
+
// 确保至少有一个页面存在
|
|
82
|
+
if (context.pages().length === 0) {
|
|
83
|
+
await context.newPage();
|
|
61
84
|
}
|
|
62
|
-
const context = await browser.newContext(contextOptions);
|
|
63
85
|
// 保存到数据库
|
|
64
86
|
const instanceId = this.instanceRepo.create({
|
|
65
87
|
profile_alias: profileAlias,
|
|
@@ -69,10 +91,10 @@ export class PlaywrightManager {
|
|
|
69
91
|
// 保存到内存
|
|
70
92
|
this.instances.set(instanceId, {
|
|
71
93
|
id: instanceId,
|
|
72
|
-
browser,
|
|
73
94
|
context,
|
|
74
95
|
profileAlias,
|
|
75
96
|
accountId,
|
|
97
|
+
userDataDir,
|
|
76
98
|
});
|
|
77
99
|
// 如果是第一个实例,设置为活跃
|
|
78
100
|
if (this.instances.size === 1) {
|
|
@@ -99,15 +121,21 @@ export class PlaywrightManager {
|
|
|
99
121
|
if (!instance) {
|
|
100
122
|
throw new Error(`实例 ${instanceId} 不存在`);
|
|
101
123
|
}
|
|
102
|
-
// 保存 storageState
|
|
124
|
+
// 保存 storageState(如果配置指定了路径)
|
|
103
125
|
const profile = this.profileRepo.getByAlias(instance.profileAlias);
|
|
104
|
-
if (profile) {
|
|
126
|
+
if (profile && profile.storage_state_path) {
|
|
105
127
|
const storageState = await instance.context.storageState();
|
|
106
128
|
await fs.writeFile(profile.storage_state_path, JSON.stringify(storageState, null, 2));
|
|
107
129
|
}
|
|
108
130
|
// 关闭浏览器
|
|
109
131
|
await instance.context.close();
|
|
110
|
-
|
|
132
|
+
// 清理用户数据目录
|
|
133
|
+
try {
|
|
134
|
+
await fs.rm(instance.userDataDir, { recursive: true, force: true });
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
console.error(`清理用户数据目录失败: ${instance.userDataDir}`, err);
|
|
138
|
+
}
|
|
111
139
|
// 从内存和数据库删除
|
|
112
140
|
this.instances.delete(instanceId);
|
|
113
141
|
this.instanceRepo.delete(instanceId);
|
|
@@ -134,11 +162,13 @@ export class PlaywrightManager {
|
|
|
134
162
|
*/
|
|
135
163
|
getActiveContext() {
|
|
136
164
|
const activeInstance = this.instanceRepo.getActive();
|
|
137
|
-
if (!activeInstance)
|
|
165
|
+
if (!activeInstance) {
|
|
138
166
|
return null;
|
|
167
|
+
}
|
|
139
168
|
const instance = this.instances.get(activeInstance.id);
|
|
140
|
-
if (!instance)
|
|
169
|
+
if (!instance) {
|
|
141
170
|
return null;
|
|
171
|
+
}
|
|
142
172
|
this.instanceRepo.updateLastActive(activeInstance.id);
|
|
143
173
|
return instance.context;
|
|
144
174
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/playwright/manager.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,QAAQ,EAA2B,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/playwright/manager.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/instance.d.ts
CHANGED
package/dist/tools/instance.js
CHANGED
|
@@ -10,11 +10,16 @@ export const instanceTools = {
|
|
|
10
10
|
properties: {
|
|
11
11
|
profile_alias: { type: 'string', description: '浏览器配置别名' },
|
|
12
12
|
account_id: { type: 'number', description: '使用的账号ID(可选)' },
|
|
13
|
+
launch_options: {
|
|
14
|
+
type: 'object',
|
|
15
|
+
description: 'Playwright LaunchOptions(可选,如 {"headless": false, "channel": "chrome", "viewport": {"width": 1920, "height": 1080}})',
|
|
16
|
+
additionalProperties: true,
|
|
17
|
+
},
|
|
13
18
|
},
|
|
14
19
|
required: ['profile_alias'],
|
|
15
20
|
},
|
|
16
21
|
handler: async (args) => {
|
|
17
|
-
const id = await manager.launchInstance(args.profile_alias, args.account_id);
|
|
22
|
+
const id = await manager.launchInstance(args.profile_alias, args.account_id, args.launch_options);
|
|
18
23
|
return {
|
|
19
24
|
content: [{
|
|
20
25
|
type: 'text',
|
|
@@ -50,6 +55,12 @@ export const instanceTools = {
|
|
|
50
55
|
},
|
|
51
56
|
handler: async (args) => {
|
|
52
57
|
await manager.switchActive(args.instance_id);
|
|
58
|
+
// CRITICAL: Reset Playwright MCP's context cache
|
|
59
|
+
// This forces it to fetch the new active context on the next tool call
|
|
60
|
+
const { playwrightMCPProxy } = await import('../index.js');
|
|
61
|
+
if (playwrightMCPProxy) {
|
|
62
|
+
await playwrightMCPProxy.resetContext();
|
|
63
|
+
}
|
|
53
64
|
return {
|
|
54
65
|
content: [{
|
|
55
66
|
type: 'text',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instance.js","sourceRoot":"","sources":["../../src/tools/instance.ts"],"names":[],"mappings":"AAKA,IAAI,OAA0B,CAAC;AAE/B,MAAM,UAAU,UAAU,CAAC,CAAoB;IAC7C,OAAO,GAAG,CAAC,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,cAAc,EAAE;QACd,WAAW,EAAE,SAAS;QACtB,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE;gBACzD,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;
|
|
1
|
+
{"version":3,"file":"instance.js","sourceRoot":"","sources":["../../src/tools/instance.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Playwright MCP Dynamic Multi-Instance Proxy
|
|
3
|
+
*
|
|
4
|
+
* This proxy wraps @playwright/mcp to support dynamic browser context switching.
|
|
5
|
+
*
|
|
6
|
+
* Key Architecture Change:
|
|
7
|
+
* - Standard @playwright/mcp caches the BrowserContext at initialization
|
|
8
|
+
* - This proxy ensures every tool call uses the CURRENT active context
|
|
9
|
+
* - Enables multiple browser instances with dynamic switching via switch_browser_instance
|
|
10
|
+
*/
|
|
11
|
+
import { BrowserContext } from 'playwright';
|
|
12
|
+
export declare class PlaywrightMCPProxy {
|
|
13
|
+
private mcpServer;
|
|
14
|
+
private backend;
|
|
15
|
+
private contextGetter;
|
|
16
|
+
private factory;
|
|
17
|
+
private tools;
|
|
18
|
+
constructor(contextGetter: () => Promise<BrowserContext>);
|
|
19
|
+
/**
|
|
20
|
+
* Initialize the MCP connection with our dynamic context factory
|
|
21
|
+
*
|
|
22
|
+
* We directly use Playwright MCP's internal modules to inject our
|
|
23
|
+
* custom factory, bypassing the createConnection() helper which
|
|
24
|
+
* doesn't support dynamic context switching.
|
|
25
|
+
*/
|
|
26
|
+
initialize(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Load all tool definitions from Playwright MCP
|
|
29
|
+
*/
|
|
30
|
+
private loadTools;
|
|
31
|
+
/**
|
|
32
|
+
* Get all tool definitions for MCP protocol
|
|
33
|
+
*/
|
|
34
|
+
getToolDefinitions(): Record<string, any>;
|
|
35
|
+
/**
|
|
36
|
+
* Call a Playwright MCP tool
|
|
37
|
+
*
|
|
38
|
+
* Each call will use the CURRENT active browser context thanks to our
|
|
39
|
+
* dynamic factory, enabling proper multi-instance support.
|
|
40
|
+
*/
|
|
41
|
+
callTool(name: string, args: any): Promise<any>;
|
|
42
|
+
/**
|
|
43
|
+
* Check if a tool exists
|
|
44
|
+
*/
|
|
45
|
+
hasTool(name: string): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Get list of all tool names
|
|
48
|
+
*/
|
|
49
|
+
getToolNames(): string[];
|
|
50
|
+
/**
|
|
51
|
+
* Reset the browser context cache
|
|
52
|
+
*
|
|
53
|
+
* This forces Playwright MCP's Context to clear its cached BrowserContext,
|
|
54
|
+
* so the next tool call will fetch the current active context from our factory.
|
|
55
|
+
*
|
|
56
|
+
* CRITICAL for multi-instance switching to work correctly.
|
|
57
|
+
*/
|
|
58
|
+
resetContext(): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Close/cleanup the proxy
|
|
61
|
+
*/
|
|
62
|
+
close(): Promise<void>;
|
|
63
|
+
}
|