@n8n/mcp-browser 0.1.0-rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +88 -0
- package/README.md +175 -0
- package/dist/adapters/playwright.d.ts +72 -0
- package/dist/adapters/playwright.js +684 -0
- package/dist/adapters/playwright.js.map +1 -0
- package/dist/browser-discovery.d.ts +12 -0
- package/dist/browser-discovery.js +219 -0
- package/dist/browser-discovery.js.map +1 -0
- package/dist/build.tsbuildinfo +1 -0
- package/dist/cdp-relay-protocol.d.ts +81 -0
- package/dist/cdp-relay-protocol.js +5 -0
- package/dist/cdp-relay-protocol.js.map +1 -0
- package/dist/cdp-relay.d.ts +52 -0
- package/dist/cdp-relay.js +508 -0
- package/dist/cdp-relay.js.map +1 -0
- package/dist/connection.d.ts +15 -0
- package/dist/connection.js +137 -0
- package/dist/connection.js.map +1 -0
- package/dist/errors.d.ts +40 -0
- package/dist/errors.js +83 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.js +88 -0
- package/dist/logger.js.map +1 -0
- package/dist/server-config.d.ts +7 -0
- package/dist/server-config.js +45 -0
- package/dist/server-config.js.map +1 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +93 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/helpers.d.ts +15 -0
- package/dist/tools/helpers.js +77 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +25 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/inspection.d.ts +3 -0
- package/dist/tools/inspection.js +205 -0
- package/dist/tools/inspection.js.map +1 -0
- package/dist/tools/interaction.d.ts +3 -0
- package/dist/tools/interaction.js +211 -0
- package/dist/tools/interaction.js.map +1 -0
- package/dist/tools/navigation.d.ts +3 -0
- package/dist/tools/navigation.js +75 -0
- package/dist/tools/navigation.js.map +1 -0
- package/dist/tools/response-envelope.d.ts +13 -0
- package/dist/tools/response-envelope.js +92 -0
- package/dist/tools/response-envelope.js.map +1 -0
- package/dist/tools/schemas.d.ts +236 -0
- package/dist/tools/schemas.js +46 -0
- package/dist/tools/schemas.js.map +1 -0
- package/dist/tools/session.d.ts +3 -0
- package/dist/tools/session.js +81 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/state.d.ts +3 -0
- package/dist/tools/state.js +108 -0
- package/dist/tools/state.js.map +1 -0
- package/dist/tools/tabs.d.ts +3 -0
- package/dist/tools/tabs.js +121 -0
- package/dist/tools/tabs.js.map +1 -0
- package/dist/tools/wait.d.ts +3 -0
- package/dist/tools/wait.js +39 -0
- package/dist/tools/wait.js.map +1 -0
- package/dist/types.d.ts +170 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +8 -0
- package/dist/utils.js +54 -0
- package/dist/utils.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.BrowserConnection = void 0;
|
|
37
|
+
const browser_discovery_1 = require("./browser-discovery");
|
|
38
|
+
const errors_1 = require("./errors");
|
|
39
|
+
const types_1 = require("./types");
|
|
40
|
+
class BrowserConnection {
|
|
41
|
+
constructor(userConfig) {
|
|
42
|
+
this.state = null;
|
|
43
|
+
const parsed = types_1.configSchema.parse(userConfig ?? {});
|
|
44
|
+
const discovery = (0, browser_discovery_1.getDefaultDiscovery)().discover();
|
|
45
|
+
const browsers = new Map();
|
|
46
|
+
for (const [name, info] of Object.entries(discovery)) {
|
|
47
|
+
if (info && typeof info === 'object' && 'executablePath' in info) {
|
|
48
|
+
const browserInfo = info;
|
|
49
|
+
browsers.set(name, { ...browserInfo, available: true });
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
for (const [name, override] of Object.entries(parsed.browsers)) {
|
|
53
|
+
const existing = browsers.get(name);
|
|
54
|
+
if (existing) {
|
|
55
|
+
if (override.executablePath)
|
|
56
|
+
existing.executablePath = override.executablePath;
|
|
57
|
+
if (override.profilePath)
|
|
58
|
+
existing.profilePath = override.profilePath;
|
|
59
|
+
}
|
|
60
|
+
else if (override.executablePath) {
|
|
61
|
+
browsers.set(name, {
|
|
62
|
+
executablePath: override.executablePath,
|
|
63
|
+
profilePath: override.profilePath,
|
|
64
|
+
available: true,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
this.config = {
|
|
69
|
+
defaultBrowser: parsed.defaultBrowser,
|
|
70
|
+
browsers,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
async connect(overrideBrowser) {
|
|
74
|
+
if (this.state) {
|
|
75
|
+
throw new errors_1.AlreadyConnectedError();
|
|
76
|
+
}
|
|
77
|
+
const browser = overrideBrowser ?? this.config.defaultBrowser;
|
|
78
|
+
this.requireBrowserAvailable(browser);
|
|
79
|
+
const connectConfig = {
|
|
80
|
+
browser,
|
|
81
|
+
};
|
|
82
|
+
const adapter = await this.createAdapter();
|
|
83
|
+
await adapter.launch(connectConfig);
|
|
84
|
+
const pages = await adapter.listTabs();
|
|
85
|
+
const pageMap = new Map(pages.map((p) => [p.id, p]));
|
|
86
|
+
this.state = {
|
|
87
|
+
adapter,
|
|
88
|
+
pages: pageMap,
|
|
89
|
+
activePageId: pages[0]?.id ?? '',
|
|
90
|
+
};
|
|
91
|
+
return { browser, pages };
|
|
92
|
+
}
|
|
93
|
+
async disconnect() {
|
|
94
|
+
if (!this.state)
|
|
95
|
+
return;
|
|
96
|
+
const { adapter } = this.state;
|
|
97
|
+
this.state = null;
|
|
98
|
+
try {
|
|
99
|
+
await adapter.close();
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
getConnection() {
|
|
105
|
+
if (!this.state)
|
|
106
|
+
throw new errors_1.NotConnectedError();
|
|
107
|
+
return this.state;
|
|
108
|
+
}
|
|
109
|
+
get isConnected() {
|
|
110
|
+
return this.state !== null;
|
|
111
|
+
}
|
|
112
|
+
async shutdown() {
|
|
113
|
+
await this.disconnect();
|
|
114
|
+
}
|
|
115
|
+
getResolvedConfig() {
|
|
116
|
+
return this.config;
|
|
117
|
+
}
|
|
118
|
+
getAvailableBrowsers() {
|
|
119
|
+
return [...this.config.browsers.entries()]
|
|
120
|
+
.filter(([_, v]) => v.available)
|
|
121
|
+
.map(([name]) => name);
|
|
122
|
+
}
|
|
123
|
+
requireBrowserAvailable(browser) {
|
|
124
|
+
const info = this.config.browsers.get(browser);
|
|
125
|
+
if (!info?.available) {
|
|
126
|
+
const available = this.getAvailableBrowsers();
|
|
127
|
+
const instructions = (0, browser_discovery_1.getInstallInstructions)(browser);
|
|
128
|
+
throw new errors_1.BrowserNotAvailableError(browser, available, instructions);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
async createAdapter() {
|
|
132
|
+
const { PlaywrightAdapter } = await Promise.resolve().then(() => __importStar(require('./adapters/playwright')));
|
|
133
|
+
return new PlaywrightAdapter(this.config);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.BrowserConnection = BrowserConnection;
|
|
137
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../src/connection.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare class McpBrowserError extends Error {
|
|
2
|
+
readonly hint?: string | undefined;
|
|
3
|
+
constructor(message: string, hint?: string | undefined);
|
|
4
|
+
}
|
|
5
|
+
export declare class NotConnectedError extends McpBrowserError {
|
|
6
|
+
constructor();
|
|
7
|
+
}
|
|
8
|
+
export declare class AlreadyConnectedError extends McpBrowserError {
|
|
9
|
+
constructor();
|
|
10
|
+
}
|
|
11
|
+
export declare class PageNotFoundError extends McpBrowserError {
|
|
12
|
+
readonly pageId: string;
|
|
13
|
+
constructor(pageId: string);
|
|
14
|
+
}
|
|
15
|
+
export declare class StaleRefError extends McpBrowserError {
|
|
16
|
+
readonly ref: string;
|
|
17
|
+
constructor(ref: string);
|
|
18
|
+
}
|
|
19
|
+
export declare class UnsupportedOperationError extends McpBrowserError {
|
|
20
|
+
readonly operation: string;
|
|
21
|
+
readonly adapterName: string;
|
|
22
|
+
constructor(operation: string, adapterName: string);
|
|
23
|
+
}
|
|
24
|
+
export declare class BrowserNotAvailableError extends McpBrowserError {
|
|
25
|
+
readonly browser: string;
|
|
26
|
+
readonly availableBrowsers: string[];
|
|
27
|
+
readonly installInstructions?: string | undefined;
|
|
28
|
+
constructor(browser: string, availableBrowsers?: string[], installInstructions?: string | undefined);
|
|
29
|
+
}
|
|
30
|
+
export declare class BrowserExecutableNotFoundError extends McpBrowserError {
|
|
31
|
+
readonly browser: string;
|
|
32
|
+
constructor(browser: string);
|
|
33
|
+
}
|
|
34
|
+
export type ExtensionNotConnectedPhase = 'browser_not_launched' | 'extension_missing' | 'unknown';
|
|
35
|
+
export declare class ExtensionNotConnectedError extends McpBrowserError {
|
|
36
|
+
readonly timeoutMs: number;
|
|
37
|
+
readonly phase: ExtensionNotConnectedPhase;
|
|
38
|
+
readonly extensionInstructions?: string | undefined;
|
|
39
|
+
constructor(timeoutMs: number, phase?: ExtensionNotConnectedPhase, extensionInstructions?: string | undefined);
|
|
40
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ExtensionNotConnectedError = exports.BrowserExecutableNotFoundError = exports.BrowserNotAvailableError = exports.UnsupportedOperationError = exports.StaleRefError = exports.PageNotFoundError = exports.AlreadyConnectedError = exports.NotConnectedError = exports.McpBrowserError = void 0;
|
|
4
|
+
class McpBrowserError extends Error {
|
|
5
|
+
constructor(message, hint) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.hint = hint;
|
|
8
|
+
this.name = this.constructor.name;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.McpBrowserError = McpBrowserError;
|
|
12
|
+
class NotConnectedError extends McpBrowserError {
|
|
13
|
+
constructor() {
|
|
14
|
+
super('Not connected to a browser', 'Call browser_connect first to connect to the browser.');
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.NotConnectedError = NotConnectedError;
|
|
18
|
+
class AlreadyConnectedError extends McpBrowserError {
|
|
19
|
+
constructor() {
|
|
20
|
+
super('Already connected to a browser', 'Disconnect first with browser_disconnect before connecting again.');
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.AlreadyConnectedError = AlreadyConnectedError;
|
|
24
|
+
class PageNotFoundError extends McpBrowserError {
|
|
25
|
+
constructor(pageId) {
|
|
26
|
+
super(`Page not found: ${pageId}`, 'The page may have been closed. List open pages with browser_tab_list.');
|
|
27
|
+
this.pageId = pageId;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
exports.PageNotFoundError = PageNotFoundError;
|
|
31
|
+
class StaleRefError extends McpBrowserError {
|
|
32
|
+
constructor(ref) {
|
|
33
|
+
super(`Stale element ref: ${ref}`, 'The ref is from a previous snapshot. Take a fresh snapshot with browser_snapshot and use the new refs.');
|
|
34
|
+
this.ref = ref;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.StaleRefError = StaleRefError;
|
|
38
|
+
class UnsupportedOperationError extends McpBrowserError {
|
|
39
|
+
constructor(operation, adapterName) {
|
|
40
|
+
super(`Operation not supported: ${operation}`, `This operation is not available for ${adapterName} sessions.`);
|
|
41
|
+
this.operation = operation;
|
|
42
|
+
this.adapterName = adapterName;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.UnsupportedOperationError = UnsupportedOperationError;
|
|
46
|
+
class BrowserNotAvailableError extends McpBrowserError {
|
|
47
|
+
constructor(browser, availableBrowsers = [], installInstructions) {
|
|
48
|
+
const alternatives = availableBrowsers.length > 0
|
|
49
|
+
? `Compatible Chromium-based browsers found: ${availableBrowsers.join(', ')}. ` +
|
|
50
|
+
`Call browser_connect with { "browser": "${availableBrowsers[0]}" } to use it instead.`
|
|
51
|
+
: 'No compatible Chromium-based browsers (Chrome, Brave, Edge, Chromium) were found on this system.';
|
|
52
|
+
const install = installInstructions ? `\n${installInstructions}` : '';
|
|
53
|
+
super(`Browser not available: ${browser}`, `${alternatives}${install}`);
|
|
54
|
+
this.browser = browser;
|
|
55
|
+
this.availableBrowsers = availableBrowsers;
|
|
56
|
+
this.installInstructions = installInstructions;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.BrowserNotAvailableError = BrowserNotAvailableError;
|
|
60
|
+
class BrowserExecutableNotFoundError extends McpBrowserError {
|
|
61
|
+
constructor(browser) {
|
|
62
|
+
super(`No executable path for ${browser}`, `The browser "${browser}" was detected but has no executable path configured. ` +
|
|
63
|
+
'Verify the browser is properly installed or provide an explicit executablePath in the config.');
|
|
64
|
+
this.browser = browser;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
exports.BrowserExecutableNotFoundError = BrowserExecutableNotFoundError;
|
|
68
|
+
class ExtensionNotConnectedError extends McpBrowserError {
|
|
69
|
+
constructor(timeoutMs, phase = 'unknown', extensionInstructions) {
|
|
70
|
+
const phaseHint = phase === 'browser_not_launched'
|
|
71
|
+
? 'The browser process may not have started.'
|
|
72
|
+
: phase === 'extension_missing'
|
|
73
|
+
? 'The browser opened but the n8n AI Browser Bridge extension did not connect.'
|
|
74
|
+
: 'The extension did not connect within the timeout period.';
|
|
75
|
+
const install = extensionInstructions ? `\n${extensionInstructions}` : '';
|
|
76
|
+
super(`Extension connection timed out after ${timeoutMs}ms`, `${phaseHint}${install}\nThen retry browser_connect.`);
|
|
77
|
+
this.timeoutMs = timeoutMs;
|
|
78
|
+
this.phase = phase;
|
|
79
|
+
this.extensionInstructions = extensionInstructions;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.ExtensionNotConnectedError = ExtensionNotConnectedError;
|
|
83
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":";;;AAAA,MAAa,eAAgB,SAAQ,KAAK;IACzC,YACC,OAAe,EACN,IAAa;QAEtB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,SAAI,GAAJ,IAAI,CAAS;QAGtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;IACnC,CAAC;CACD;AARD,0CAQC;AAED,MAAa,iBAAkB,SAAQ,eAAe;IACrD;QACC,KAAK,CAAC,4BAA4B,EAAE,uDAAuD,CAAC,CAAC;IAC9F,CAAC;CACD;AAJD,8CAIC;AAED,MAAa,qBAAsB,SAAQ,eAAe;IACzD;QACC,KAAK,CACJ,gCAAgC,EAChC,mEAAmE,CACnE,CAAC;IACH,CAAC;CACD;AAPD,sDAOC;AAED,MAAa,iBAAkB,SAAQ,eAAe;IACrD,YAAqB,MAAc;QAClC,KAAK,CACJ,mBAAmB,MAAM,EAAE,EAC3B,uEAAuE,CACvE,CAAC;QAJkB,WAAM,GAAN,MAAM,CAAQ;IAKnC,CAAC;CACD;AAPD,8CAOC;AAED,MAAa,aAAc,SAAQ,eAAe;IACjD,YAAqB,GAAW;QAC/B,KAAK,CACJ,sBAAsB,GAAG,EAAE,EAC3B,wGAAwG,CACxG,CAAC;QAJkB,QAAG,GAAH,GAAG,CAAQ;IAKhC,CAAC;CACD;AAPD,sCAOC;AAED,MAAa,yBAA0B,SAAQ,eAAe;IAC7D,YACU,SAAiB,EACjB,WAAmB;QAE5B,KAAK,CACJ,4BAA4B,SAAS,EAAE,EACvC,uCAAuC,WAAW,YAAY,CAC9D,CAAC;QANO,cAAS,GAAT,SAAS,CAAQ;QACjB,gBAAW,GAAX,WAAW,CAAQ;IAM7B,CAAC;CACD;AAVD,8DAUC;AAED,MAAa,wBAAyB,SAAQ,eAAe;IAC5D,YACU,OAAe,EACf,oBAA8B,EAAE,EAChC,mBAA4B;QAErC,MAAM,YAAY,GACjB,iBAAiB,CAAC,MAAM,GAAG,CAAC;YAC3B,CAAC,CAAC,6CAA6C,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;gBAC9E,2CAA2C,iBAAiB,CAAC,CAAC,CAAC,wBAAwB;YACxF,CAAC,CAAC,kGAAkG,CAAC;QACvG,MAAM,OAAO,GAAG,mBAAmB,CAAC,CAAC,CAAC,KAAK,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,KAAK,CAAC,0BAA0B,OAAO,EAAE,EAAE,GAAG,YAAY,GAAG,OAAO,EAAE,CAAC,CAAC;QAV/D,YAAO,GAAP,OAAO,CAAQ;QACf,sBAAiB,GAAjB,iBAAiB,CAAe;QAChC,wBAAmB,GAAnB,mBAAmB,CAAS;IAStC,CAAC;CACD;AAdD,4DAcC;AAED,MAAa,8BAA+B,SAAQ,eAAe;IAClE,YAAqB,OAAe;QACnC,KAAK,CACJ,0BAA0B,OAAO,EAAE,EACnC,gBAAgB,OAAO,wDAAwD;YAC9E,+FAA+F,CAChG,CAAC;QALkB,YAAO,GAAP,OAAO,CAAQ;IAMpC,CAAC;CACD;AARD,wEAQC;AAID,MAAa,0BAA2B,SAAQ,eAAe;IAC9D,YACU,SAAiB,EACjB,QAAoC,SAAS,EAC7C,qBAA8B;QAEvC,MAAM,SAAS,GACd,KAAK,KAAK,sBAAsB;YAC/B,CAAC,CAAC,2CAA2C;YAC7C,CAAC,CAAC,KAAK,KAAK,mBAAmB;gBAC9B,CAAC,CAAC,6EAA6E;gBAC/E,CAAC,CAAC,0DAA0D,CAAC;QAChE,MAAM,OAAO,GAAG,qBAAqB,CAAC,CAAC,CAAC,KAAK,qBAAqB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1E,KAAK,CACJ,wCAAwC,SAAS,IAAI,EACrD,GAAG,SAAS,GAAG,OAAO,+BAA+B,CACrD,CAAC;QAdO,cAAS,GAAT,SAAS,CAAQ;QACjB,UAAK,GAAL,KAAK,CAAwC;QAC7C,0BAAqB,GAArB,qBAAqB,CAAS;IAaxC,CAAC;CACD;AAlBD,gEAkBC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { BrowserConnection } from './connection';
|
|
2
|
+
export { createBrowserTools } from './tools/index';
|
|
3
|
+
export { configureLogger } from './logger';
|
|
4
|
+
export type { LogLevel } from './logger';
|
|
5
|
+
export { parseServerOptions } from './server-config';
|
|
6
|
+
export type { ServerOptions } from './server-config';
|
|
7
|
+
export type { BrowserName, BrowserToolkit, Config, ConnectConfig, ConnectResult, ConnectionState, Cookie, ElementTarget, PageInfo, ResolvedConfig, ToolContext, ToolDefinition, CallToolResult, } from './types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseServerOptions = exports.configureLogger = exports.createBrowserTools = exports.BrowserConnection = void 0;
|
|
4
|
+
var connection_1 = require("./connection");
|
|
5
|
+
Object.defineProperty(exports, "BrowserConnection", { enumerable: true, get: function () { return connection_1.BrowserConnection; } });
|
|
6
|
+
var index_1 = require("./tools/index");
|
|
7
|
+
Object.defineProperty(exports, "createBrowserTools", { enumerable: true, get: function () { return index_1.createBrowserTools; } });
|
|
8
|
+
var logger_1 = require("./logger");
|
|
9
|
+
Object.defineProperty(exports, "configureLogger", { enumerable: true, get: function () { return logger_1.configureLogger; } });
|
|
10
|
+
var server_config_1 = require("./server-config");
|
|
11
|
+
Object.defineProperty(exports, "parseServerOptions", { enumerable: true, get: function () { return server_config_1.parseServerOptions; } });
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,2CAAiD;AAAxC,+GAAA,iBAAiB,OAAA;AAC1B,uCAAmD;AAA1C,2GAAA,kBAAkB,OAAA;AAC3B,mCAA2C;AAAlC,yGAAA,eAAe,OAAA;AAExB,iDAAqD;AAA5C,mHAAA,kBAAkB,OAAA"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
|
|
2
|
+
export declare function configureLogger(options: {
|
|
3
|
+
level?: LogLevel;
|
|
4
|
+
}): void;
|
|
5
|
+
export declare function createLogger(tag: string): {
|
|
6
|
+
error: (...args: unknown[]) => void;
|
|
7
|
+
warn: (...args: unknown[]) => void;
|
|
8
|
+
info: (...args: unknown[]) => void;
|
|
9
|
+
debug: (...args: unknown[]) => void;
|
|
10
|
+
};
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.configureLogger = configureLogger;
|
|
7
|
+
exports.createLogger = createLogger;
|
|
8
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
9
|
+
const LEVEL_RANK = {
|
|
10
|
+
silent: 0,
|
|
11
|
+
error: 1,
|
|
12
|
+
warn: 2,
|
|
13
|
+
info: 3,
|
|
14
|
+
debug: 4,
|
|
15
|
+
};
|
|
16
|
+
let currentLevel = 'info';
|
|
17
|
+
function configureLogger(options) {
|
|
18
|
+
currentLevel = options.level ?? 'info';
|
|
19
|
+
}
|
|
20
|
+
function isEnabled(level) {
|
|
21
|
+
return LEVEL_RANK[level] <= LEVEL_RANK[currentLevel];
|
|
22
|
+
}
|
|
23
|
+
function devTimestamp() {
|
|
24
|
+
const now = new Date();
|
|
25
|
+
const pad = (num, digits = 2) => num.toString().padStart(digits, '0');
|
|
26
|
+
return `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}.${pad(now.getMilliseconds(), 3)}`;
|
|
27
|
+
}
|
|
28
|
+
function toPrintable(metadata) {
|
|
29
|
+
if (Object.keys(metadata).length === 0)
|
|
30
|
+
return '';
|
|
31
|
+
return JSON.stringify(metadata)
|
|
32
|
+
.replace(/{"/g, '{ "')
|
|
33
|
+
.replace(/,"/g, ', "')
|
|
34
|
+
.replace(/:/g, ': ')
|
|
35
|
+
.replace(/}/g, ' }');
|
|
36
|
+
}
|
|
37
|
+
const LEVEL_COLORS = {
|
|
38
|
+
error: picocolors_1.default.red,
|
|
39
|
+
warn: picocolors_1.default.yellow,
|
|
40
|
+
info: picocolors_1.default.green,
|
|
41
|
+
debug: picocolors_1.default.blue,
|
|
42
|
+
};
|
|
43
|
+
function colorFor(level) {
|
|
44
|
+
return LEVEL_COLORS[level] ?? ((s) => s);
|
|
45
|
+
}
|
|
46
|
+
function devDebugLine(level, message, meta) {
|
|
47
|
+
const separator = ' ';
|
|
48
|
+
const ts = devTimestamp();
|
|
49
|
+
const color = colorFor(level);
|
|
50
|
+
const lvl = color(level).padEnd(15);
|
|
51
|
+
const metaStr = toPrintable(meta);
|
|
52
|
+
const suffix = metaStr ? ' ' + picocolors_1.default.dim(metaStr) : '';
|
|
53
|
+
return [ts, lvl, color(message) + suffix].join(separator);
|
|
54
|
+
}
|
|
55
|
+
function parseArgs(args, tag) {
|
|
56
|
+
const meta = { scope: tag };
|
|
57
|
+
const messageParts = [];
|
|
58
|
+
for (const arg of args) {
|
|
59
|
+
if (typeof arg === 'object' && arg !== null && !Array.isArray(arg) && !(arg instanceof Error)) {
|
|
60
|
+
Object.assign(meta, arg);
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
messageParts.push(String(arg));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { message: messageParts.join(' '), meta };
|
|
67
|
+
}
|
|
68
|
+
function createLogger(tag) {
|
|
69
|
+
const prefix = `[mcp-browser:${tag}]`;
|
|
70
|
+
function log(level, consoleFn, args) {
|
|
71
|
+
if (!isEnabled(level))
|
|
72
|
+
return;
|
|
73
|
+
if (currentLevel === 'debug') {
|
|
74
|
+
const { message, meta } = parseArgs(args, tag);
|
|
75
|
+
consoleFn(devDebugLine(level, message, meta));
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
consoleFn(prefix, ...args);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
error: (...args) => log('error', console.error, args),
|
|
83
|
+
warn: (...args) => log('warn', console.warn, args),
|
|
84
|
+
info: (...args) => log('info', console.log, args),
|
|
85
|
+
debug: (...args) => log('debug', console.log, args),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";;;;;AAgBA,0CAEC;AA4DD,oCAmBC;AA/FD,4DAA4B;AAI5B,MAAM,UAAU,GAA6B;IAC5C,MAAM,EAAE,CAAC;IACT,KAAK,EAAE,CAAC;IACR,IAAI,EAAE,CAAC;IACP,IAAI,EAAE,CAAC;IACP,KAAK,EAAE,CAAC;CACR,CAAC;AAEF,IAAI,YAAY,GAAa,MAAM,CAAC;AAEpC,SAAgB,eAAe,CAAC,OAA6B;IAC5D,YAAY,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC;AACxC,CAAC;AAED,SAAS,SAAS,CAAC,KAAe;IACjC,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;AACtD,CAAC;AAID,SAAS,YAAY;IACpB,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;IACvB,MAAM,GAAG,GAAG,CAAC,GAAW,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9E,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC;AACpH,CAAC;AAED,SAAS,WAAW,CAAC,QAAiC;IACrD,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClD,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;SAC7B,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;SACnB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,YAAY,GAA0C;IAC3D,KAAK,EAAE,oBAAE,CAAC,GAAG;IACb,IAAI,EAAE,oBAAE,CAAC,MAAM;IACf,IAAI,EAAE,oBAAE,CAAC,KAAK;IACd,KAAK,EAAE,oBAAE,CAAC,IAAI;CACd,CAAC;AAEF,SAAS,QAAQ,CAAC,KAAa;IAC9B,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,YAAY,CAAC,KAAa,EAAE,OAAe,EAAE,IAA6B;IAClF,MAAM,SAAS,GAAG,KAAK,CAAC;IACxB,MAAM,EAAE,GAAG,YAAY,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,oBAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAC3D,CAAC;AAED,SAAS,SAAS,CACjB,IAAe,EACf,GAAW;IAEX,MAAM,IAAI,GAA4B,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC;IACrD,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC,EAAE,CAAC;YAC/F,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC1B,CAAC;aAAM,CAAC;YACP,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAChC,CAAC;IACF,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC;AAClD,CAAC;AAED,SAAgB,YAAY,CAAC,GAAW;IACvC,MAAM,MAAM,GAAG,gBAAgB,GAAG,GAAG,CAAC;IAEtC,SAAS,GAAG,CAAC,KAAe,EAAE,SAAuC,EAAE,IAAe;QACrF,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;YAAE,OAAO;QAC9B,IAAI,YAAY,KAAK,OAAO,EAAE,CAAC;YAC9B,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAC/C,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACP,SAAS,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;QAC5B,CAAC;IACF,CAAC;IAED,OAAO;QACN,KAAK,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC;QAChE,IAAI,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC;QAC7D,IAAI,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC;QAC5D,KAAK,EAAE,CAAC,GAAG,IAAe,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC;KAC9D,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseServerOptions = parseServerOptions;
|
|
7
|
+
const yargs_parser_1 = __importDefault(require("yargs-parser"));
|
|
8
|
+
const ENV_PREFIX = 'N8N_MCP_BROWSER_';
|
|
9
|
+
function envString(envKey) {
|
|
10
|
+
return process.env[`${ENV_PREFIX}${envKey}`];
|
|
11
|
+
}
|
|
12
|
+
function envNumber(envKey) {
|
|
13
|
+
const raw = envString(envKey);
|
|
14
|
+
if (raw === undefined)
|
|
15
|
+
return undefined;
|
|
16
|
+
const n = Number(raw);
|
|
17
|
+
return Number.isNaN(n) ? undefined : n;
|
|
18
|
+
}
|
|
19
|
+
function parseServerOptions(argv = process.argv.slice(2)) {
|
|
20
|
+
const args = (0, yargs_parser_1.default)(argv, {
|
|
21
|
+
string: ['browser', 'transport'],
|
|
22
|
+
number: ['port'],
|
|
23
|
+
alias: {
|
|
24
|
+
b: 'browser',
|
|
25
|
+
p: 'port',
|
|
26
|
+
t: 'transport',
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
const envConfig = {};
|
|
30
|
+
const envBrowser = envString('DEFAULT_BROWSER');
|
|
31
|
+
if (envBrowser)
|
|
32
|
+
envConfig.defaultBrowser = envBrowser;
|
|
33
|
+
const cliConfig = {};
|
|
34
|
+
if (args.browser)
|
|
35
|
+
cliConfig.defaultBrowser = args.browser;
|
|
36
|
+
const config = { ...envConfig, ...cliConfig };
|
|
37
|
+
const envTransport = envString('TRANSPORT');
|
|
38
|
+
const cliTransport = args.transport;
|
|
39
|
+
const transport = cliTransport ?? envTransport ?? 'http';
|
|
40
|
+
const envPort = envNumber('PORT');
|
|
41
|
+
const cliPort = args.port;
|
|
42
|
+
const port = cliPort ?? envPort ?? 3100;
|
|
43
|
+
return { config, transport, port };
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=server-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-config.js","sourceRoot":"","sources":["../src/server-config.ts"],"names":[],"mappings":";;;;;AAgCA,gDAqCC;AArED,gEAAuC;AAIvC,MAAM,UAAU,GAAG,kBAAkB,CAAC;AAQtC,SAAS,SAAS,CAAC,MAAc;IAChC,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,UAAU,GAAG,MAAM,EAAE,CAAC,CAAC;AAC9C,CAAC;AAED,SAAS,SAAS,CAAC,MAAc;IAChC,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAC9B,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACxC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,CAAC;AAWD,SAAgB,kBAAkB,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,IAAA,sBAAW,EAAC,IAAI,EAAE;QAE9B,MAAM,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC;QAEhC,MAAM,EAAE,CAAC,MAAM,CAAC;QAChB,KAAK,EAAE;YACN,CAAC,EAAE,SAAS;YACZ,CAAC,EAAE,MAAM;YACT,CAAC,EAAE,WAAW;SACd;KACD,CAAe,CAAC;IAGjB,MAAM,SAAS,GAAoB,EAAE,CAAC;IAEtC,MAAM,UAAU,GAAG,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAChD,IAAI,UAAU;QAAE,SAAS,CAAC,cAAc,GAAG,UAAsC,CAAC;IAGlF,MAAM,SAAS,GAAoB,EAAE,CAAC;IAEtC,IAAI,IAAI,CAAC,OAAO;QAAE,SAAS,CAAC,cAAc,GAAG,IAAI,CAAC,OAAmC,CAAC;IAGtF,MAAM,MAAM,GAAoB,EAAE,GAAG,SAAS,EAAE,GAAG,SAAS,EAAE,CAAC;IAG/D,MAAM,YAAY,GAAG,SAAS,CAAC,WAAW,CAAiC,CAAC;IAC5E,MAAM,YAAY,GAAG,IAAI,CAAC,SAAyC,CAAC;IACpE,MAAM,SAAS,GAAG,YAAY,IAAI,YAAY,IAAI,MAAM,CAAC;IAEzD,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;IAC1B,MAAM,IAAI,GAAG,OAAO,IAAI,OAAO,IAAI,IAAI,CAAC;IAExC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACpC,CAAC"}
|
package/dist/server.d.ts
ADDED
package/dist/server.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
5
|
+
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
|
+
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
|
|
7
|
+
const node_crypto_1 = require("node:crypto");
|
|
8
|
+
const node_http_1 = require("node:http");
|
|
9
|
+
const server_config_1 = require("./server-config");
|
|
10
|
+
const index_1 = require("./tools/index");
|
|
11
|
+
function registerTools(server, tools) {
|
|
12
|
+
for (const tool of tools) {
|
|
13
|
+
server.registerTool(tool.name, {
|
|
14
|
+
description: tool.description,
|
|
15
|
+
inputSchema: tool.inputSchema,
|
|
16
|
+
outputSchema: tool.outputSchema,
|
|
17
|
+
}, async (args) => {
|
|
18
|
+
const result = await tool.execute(args, { dir: '' });
|
|
19
|
+
return { ...result };
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
async function main() {
|
|
24
|
+
const { config, transport: transportType, port } = (0, server_config_1.parseServerOptions)();
|
|
25
|
+
const { tools, connection } = (0, index_1.createBrowserTools)(config);
|
|
26
|
+
if (transportType === 'http') {
|
|
27
|
+
const sessions = new Map();
|
|
28
|
+
const corsHeaders = {
|
|
29
|
+
'Access-Control-Allow-Origin': '*',
|
|
30
|
+
'Access-Control-Allow-Methods': 'GET, POST, DELETE, OPTIONS',
|
|
31
|
+
'Access-Control-Allow-Headers': 'Content-Type, Accept, Mcp-Session-Id, Mcp-Protocol-Version',
|
|
32
|
+
'Access-Control-Expose-Headers': 'Mcp-Session-Id',
|
|
33
|
+
};
|
|
34
|
+
const httpServer = (0, node_http_1.createServer)((req, res) => {
|
|
35
|
+
if (req.method === 'OPTIONS') {
|
|
36
|
+
res.writeHead(204, corsHeaders);
|
|
37
|
+
res.end();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
for (const [key, value] of Object.entries(corsHeaders)) {
|
|
41
|
+
res.setHeader(key, value);
|
|
42
|
+
}
|
|
43
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
44
|
+
const existingTransport = sessionId ? sessions.get(sessionId) : undefined;
|
|
45
|
+
if (existingTransport) {
|
|
46
|
+
void existingTransport.handleRequest(req, res);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (sessionId) {
|
|
50
|
+
res.writeHead(404, { 'Content-Type': 'application/json' });
|
|
51
|
+
res.end(JSON.stringify({
|
|
52
|
+
jsonrpc: '2.0',
|
|
53
|
+
error: { code: -32000, message: 'Session not found' },
|
|
54
|
+
id: null,
|
|
55
|
+
}));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
59
|
+
sessionIdGenerator: () => (0, node_crypto_1.randomUUID)(),
|
|
60
|
+
onsessioninitialized: (id) => {
|
|
61
|
+
sessions.set(id, transport);
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
transport.onclose = () => {
|
|
65
|
+
if (transport.sessionId) {
|
|
66
|
+
sessions.delete(transport.sessionId);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const mcpServer = new mcp_js_1.McpServer({ name: 'n8n-browser', version: '1.0.0' });
|
|
70
|
+
registerTools(mcpServer, tools);
|
|
71
|
+
void mcpServer.connect(transport).then(() => {
|
|
72
|
+
void transport.handleRequest(req, res);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
httpServer.listen(port, () => {
|
|
76
|
+
console.debug(`n8n-browser MCP server listening on http://localhost:${port}`);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
const server = new mcp_js_1.McpServer({ name: 'n8n-browser', version: '1.0.0' });
|
|
81
|
+
registerTools(server, tools);
|
|
82
|
+
const transport = new stdio_js_1.StdioServerTransport();
|
|
83
|
+
await server.connect(transport);
|
|
84
|
+
}
|
|
85
|
+
const shutdown = async () => {
|
|
86
|
+
await connection.shutdown();
|
|
87
|
+
process.exit(0);
|
|
88
|
+
};
|
|
89
|
+
process.on('SIGTERM', () => void shutdown());
|
|
90
|
+
process.on('SIGINT', () => void shutdown());
|
|
91
|
+
}
|
|
92
|
+
void main();
|
|
93
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { BrowserConnection } from '../connection';
|
|
3
|
+
import type { CallToolResult, ConnectionState, ToolDefinition } from '../types';
|
|
4
|
+
export { consoleSummarySchema, elementTargetSchema, modalStateSchema, pageIdField, withSnapshotEnvelope, } from './schemas';
|
|
5
|
+
export type { ElementTargetInput } from './schemas';
|
|
6
|
+
type ConnectedToolInput = {
|
|
7
|
+
pageId?: string;
|
|
8
|
+
};
|
|
9
|
+
export interface ConnectedToolOptions {
|
|
10
|
+
autoSnapshot?: boolean;
|
|
11
|
+
waitForCompletion?: boolean;
|
|
12
|
+
skipEnrichment?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function extractDomain(url: string): string;
|
|
15
|
+
export declare function createConnectedTool<TSchema extends z.ZodType<ConnectedToolInput & Record<string, unknown>>>(connection: BrowserConnection, name: string, description: string, inputSchema: TSchema, fn: (state: ConnectionState, input: z.infer<TSchema>, pageId: string) => Promise<CallToolResult>, outputSchema?: z.ZodObject<z.ZodRawShape>, options?: ConnectedToolOptions, getResourceFromArgs?: (args: z.infer<TSchema>) => string): ToolDefinition<TSchema>;
|