@jobshimo/browser-link 0.2.0 → 0.4.1
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/README.md +37 -0
- package/dist/bridge/client.d.ts +101 -0
- package/dist/bridge/client.js +435 -0
- package/dist/bridge/client.js.map +1 -0
- package/dist/bridge/dispatch.d.ts +29 -0
- package/dist/bridge/dispatch.js +39 -0
- package/dist/bridge/dispatch.js.map +1 -0
- package/dist/bridge/events.d.ts +39 -0
- package/dist/bridge/events.js +47 -0
- package/dist/bridge/events.js.map +1 -0
- package/dist/bridge/protocol.d.ts +80 -0
- package/dist/bridge/protocol.js +79 -0
- package/dist/bridge/protocol.js.map +1 -0
- package/dist/bridge/server.d.ts +42 -0
- package/dist/bridge/server.js +336 -0
- package/dist/bridge/server.js.map +1 -0
- package/dist/bridge/token.d.ts +17 -0
- package/dist/bridge/token.js +79 -0
- package/dist/bridge/token.js.map +1 -0
- package/dist/cli.js +106 -15
- package/dist/cli.js.map +1 -1
- package/dist/commands/doctor.d.ts +12 -1
- package/dist/commands/doctor.js +90 -20
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/extension.d.ts +3 -2
- package/dist/commands/extension.js +53 -28
- package/dist/commands/extension.js.map +1 -1
- package/dist/commands/free-port.d.ts +21 -0
- package/dist/commands/free-port.js +146 -0
- package/dist/commands/free-port.js.map +1 -0
- package/dist/commands/multi-agent.d.ts +7 -0
- package/dist/commands/multi-agent.js +109 -0
- package/dist/commands/multi-agent.js.map +1 -0
- package/dist/commands/tools.d.ts +11 -0
- package/dist/commands/tools.js +168 -0
- package/dist/commands/tools.js.map +1 -0
- package/dist/commands/updates.d.ts +2 -1
- package/dist/commands/updates.js +24 -7
- package/dist/commands/updates.js.map +1 -1
- package/dist/config.d.ts +25 -3
- package/dist/config.js +35 -2
- package/dist/config.js.map +1 -1
- package/dist/messages.d.ts +7 -0
- package/dist/permissions.d.ts +37 -0
- package/dist/permissions.js +156 -0
- package/dist/permissions.js.map +1 -0
- package/dist/server.d.ts +7 -3
- package/dist/server.js +196 -32
- package/dist/server.js.map +1 -1
- package/dist/tools/browser-definitions.js +18 -0
- package/dist/tools/browser-definitions.js.map +1 -1
- package/dist/tools/browser-dispatch.d.ts +7 -0
- package/dist/tools/browser-dispatch.js +11 -0
- package/dist/tools/browser-dispatch.js.map +1 -1
- package/dist/tools/server-instructions.d.ts +1 -1
- package/dist/tools/server-instructions.js +4 -0
- package/dist/tools/server-instructions.js.map +1 -1
- package/dist/ui/app.js +20 -1
- package/dist/ui/app.js.map +1 -1
- package/dist/ui/screens.d.ts +18 -1
- package/dist/ui/screens.js +395 -2
- package/dist/ui/screens.js.map +1 -1
- package/package.json +4 -3
package/dist/commands/updates.js
CHANGED
|
@@ -63,21 +63,38 @@ function isNewer(latest, current) {
|
|
|
63
63
|
}
|
|
64
64
|
return false;
|
|
65
65
|
}
|
|
66
|
+
const UPDATES_CLI_I18N = {
|
|
67
|
+
en: {
|
|
68
|
+
currentLabel: 'Current: ',
|
|
69
|
+
latestLabel: 'Latest: ',
|
|
70
|
+
cantReach: 'Could not check the registry',
|
|
71
|
+
upToDate: 'You are up to date.',
|
|
72
|
+
available: (cmd) => `Update available. Run: ${cmd}`,
|
|
73
|
+
},
|
|
74
|
+
es: {
|
|
75
|
+
currentLabel: 'Instalada: ',
|
|
76
|
+
latestLabel: 'Última: ',
|
|
77
|
+
cantReach: 'No se pudo consultar el registry',
|
|
78
|
+
upToDate: 'Estás en la última versión.',
|
|
79
|
+
available: (cmd) => `Hay una actualización disponible. Corré: ${cmd}`,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
66
82
|
/** Plain-text formatter for the non-interactive `browser-link updates`. */
|
|
67
|
-
export function formatUpdate(info) {
|
|
83
|
+
export function formatUpdate(info, language = 'en') {
|
|
84
|
+
const t = UPDATES_CLI_I18N[language];
|
|
68
85
|
if (info.error || info.latest === null) {
|
|
69
86
|
return [
|
|
70
|
-
|
|
71
|
-
|
|
87
|
+
`${t.currentLabel}${info.current}`,
|
|
88
|
+
`${t.cantReach}: ${info.error ?? 'unknown error'}`,
|
|
72
89
|
].join('\n');
|
|
73
90
|
}
|
|
74
91
|
if (info.newer) {
|
|
75
92
|
return [
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
`
|
|
93
|
+
`${t.currentLabel}${info.current}`,
|
|
94
|
+
`${t.latestLabel}${info.latest}`,
|
|
95
|
+
t.available(`npm install -g ${PACKAGE_NAME}@latest`),
|
|
79
96
|
].join('\n');
|
|
80
97
|
}
|
|
81
|
-
return [
|
|
98
|
+
return [`${t.currentLabel}${info.current}`, `${t.latestLabel}${info.latest}`, t.upToDate].join('\n');
|
|
82
99
|
}
|
|
83
100
|
//# sourceMappingURL=updates.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"updates.js","sourceRoot":"","sources":["../../src/commands/updates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"updates.js","sourceRoot":"","sources":["../../src/commands/updates.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,11 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Small per-user config persisted next to the map DB.
|
|
3
|
-
*
|
|
4
|
-
* No domain data ever lives here.
|
|
2
|
+
* Small per-user config persisted next to the map DB. UX preferences and
|
|
3
|
+
* the tool-access deny list — never any domain data.
|
|
5
4
|
*/
|
|
6
5
|
export interface BrowserLinkConfig {
|
|
7
6
|
skipWelcome?: boolean;
|
|
8
7
|
language?: 'en' | 'es';
|
|
8
|
+
/**
|
|
9
|
+
* Tool names the MCP server must not expose. Empty / undefined means
|
|
10
|
+
* "everything enabled" (default, backwards-compatible). Unknown names
|
|
11
|
+
* are dropped silently by sanitizeDisabledTools so old configs survive
|
|
12
|
+
* tool renames or removals.
|
|
13
|
+
*/
|
|
14
|
+
disabledTools?: string[];
|
|
15
|
+
/**
|
|
16
|
+
* Multi-agent mode. When false (default), only one MCP client can have
|
|
17
|
+
* browser-link active at a time; a second client trying to spawn the
|
|
18
|
+
* server crashes with EADDRINUSE. When true, the second instance becomes
|
|
19
|
+
* a proxy that forwards MCP requests to the first one over an internal
|
|
20
|
+
* IPC port (127.0.0.1:17530). All agents end up sharing the same Chrome
|
|
21
|
+
* tabs and the same persistent UI map.
|
|
22
|
+
*/
|
|
23
|
+
multiAgent?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Only honoured when multiAgent === true. When false (default), if the
|
|
26
|
+
* primary's MCP client closes, secondary clients lose the bridge and
|
|
27
|
+
* have to be relaunched manually. When true, one of the secondaries
|
|
28
|
+
* takes over the primary role automatically (race on bind(17529)).
|
|
29
|
+
*/
|
|
30
|
+
autoReelect?: boolean;
|
|
9
31
|
}
|
|
10
32
|
export declare function loadConfig(): BrowserLinkConfig;
|
|
11
33
|
export declare function saveConfig(patch: Partial<BrowserLinkConfig>): BrowserLinkConfig;
|
package/dist/config.js
CHANGED
|
@@ -1,9 +1,42 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { getDataDir } from './map/paths.js';
|
|
4
|
+
import { sanitizeDisabledTools } from './permissions.js';
|
|
4
5
|
function configFile() {
|
|
5
6
|
return join(getDataDir(), 'config.json');
|
|
6
7
|
}
|
|
8
|
+
function normalise(cfg) {
|
|
9
|
+
// Always run the disabled-tools list through the sanitizer — both on read
|
|
10
|
+
// and on write — so unknown names from a downgraded build, a typo, or a
|
|
11
|
+
// manual edit never reach the server filter.
|
|
12
|
+
const sanitized = sanitizeDisabledTools(cfg.disabledTools);
|
|
13
|
+
let next;
|
|
14
|
+
if (sanitized.length === 0) {
|
|
15
|
+
const { disabledTools: _omit, ...rest } = cfg;
|
|
16
|
+
next = rest;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
next = { ...cfg, disabledTools: sanitized };
|
|
20
|
+
}
|
|
21
|
+
// autoReelect only makes sense when multiAgent is on. Drop a stray
|
|
22
|
+
// autoReelect:true if multiAgent is off, so the config file never has
|
|
23
|
+
// an inert flag advertising a behaviour it does not produce.
|
|
24
|
+
if (next.autoReelect && !next.multiAgent) {
|
|
25
|
+
const { autoReelect: _omit2, ...rest2 } = next;
|
|
26
|
+
next = rest2;
|
|
27
|
+
}
|
|
28
|
+
// Drop explicit `false` for the two new flags too — the default is false,
|
|
29
|
+
// so storing it just adds noise.
|
|
30
|
+
if (next.multiAgent === false) {
|
|
31
|
+
const { multiAgent: _omit3, ...rest3 } = next;
|
|
32
|
+
next = rest3;
|
|
33
|
+
}
|
|
34
|
+
if (next.autoReelect === false) {
|
|
35
|
+
const { autoReelect: _omit4, ...rest4 } = next;
|
|
36
|
+
next = rest4;
|
|
37
|
+
}
|
|
38
|
+
return next;
|
|
39
|
+
}
|
|
7
40
|
export function loadConfig() {
|
|
8
41
|
const path = configFile();
|
|
9
42
|
if (!existsSync(path))
|
|
@@ -12,7 +45,7 @@ export function loadConfig() {
|
|
|
12
45
|
const raw = readFileSync(path, 'utf8');
|
|
13
46
|
const parsed = JSON.parse(raw);
|
|
14
47
|
if (parsed && typeof parsed === 'object')
|
|
15
|
-
return parsed;
|
|
48
|
+
return normalise(parsed);
|
|
16
49
|
return {};
|
|
17
50
|
}
|
|
18
51
|
catch (err) {
|
|
@@ -28,7 +61,7 @@ export function saveConfig(patch) {
|
|
|
28
61
|
const path = configFile();
|
|
29
62
|
mkdirSync(dirname(path), { recursive: true });
|
|
30
63
|
const current = loadConfig();
|
|
31
|
-
const next = { ...current, ...patch };
|
|
64
|
+
const next = normalise({ ...current, ...patch });
|
|
32
65
|
writeFileSync(path, JSON.stringify(next, null, 2) + '\n', 'utf8');
|
|
33
66
|
return next;
|
|
34
67
|
}
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/messages.d.ts
CHANGED
|
@@ -9,6 +9,13 @@ export type TabId = string;
|
|
|
9
9
|
export interface TabRegisterPayload {
|
|
10
10
|
url: string;
|
|
11
11
|
title: string;
|
|
12
|
+
/**
|
|
13
|
+
* Optional. The browser-link tab_id this Chrome tab last had, as
|
|
14
|
+
* remembered by the extension across primary swaps. The primary honours
|
|
15
|
+
* it if free; otherwise it assigns a new id and emits a `tab-renamed`
|
|
16
|
+
* event the agent can pick up via the `browser.events` tool.
|
|
17
|
+
*/
|
|
18
|
+
previousTabId?: TabId;
|
|
12
19
|
}
|
|
13
20
|
export interface TabRegisteredPayload {
|
|
14
21
|
tabId: TabId;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool access control — single source of truth for which MCP tools
|
|
3
|
+
* browser-link exposes and how the user can narrow that down.
|
|
4
|
+
*
|
|
5
|
+
* The runtime answer to "is this tool allowed?" is computed from the
|
|
6
|
+
* `disabledTools` list in `config.json` (default: empty = everything
|
|
7
|
+
* allowed). The catalogue below adds human-readable metadata used by
|
|
8
|
+
* the UI and the CLI subcommand — it never affects what the MCP server
|
|
9
|
+
* returns by itself.
|
|
10
|
+
*/
|
|
11
|
+
export type ToolFamily = 'bridge' | 'map';
|
|
12
|
+
/** Coarse-grained behaviour bucket — used by presets, not by the runtime
|
|
13
|
+
* filter. The runtime only cares about the exact tool name. */
|
|
14
|
+
export type ToolCategory = 'read' | 'action' | 'eval' | 'map-read' | 'map-write';
|
|
15
|
+
export interface ToolMeta {
|
|
16
|
+
name: string;
|
|
17
|
+
family: ToolFamily;
|
|
18
|
+
category: ToolCategory;
|
|
19
|
+
summary: string;
|
|
20
|
+
}
|
|
21
|
+
export declare const TOOL_CATALOGUE: readonly ToolMeta[];
|
|
22
|
+
export type PresetId = 'all' | 'readonly' | 'no-eval' | 'no-map';
|
|
23
|
+
export interface PresetDef {
|
|
24
|
+
id: PresetId;
|
|
25
|
+
label: string;
|
|
26
|
+
/** Which tool names this preset disables. */
|
|
27
|
+
disabled: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
export declare const PRESETS: readonly PresetDef[];
|
|
30
|
+
/** True when the tool should be exposed in tools/list and accepted in tools/call. */
|
|
31
|
+
export declare function isToolEnabled(name: string, disabled: readonly string[] | undefined): boolean;
|
|
32
|
+
/** Drop entries that don't match any current tool, dedupe, and sort. Used
|
|
33
|
+
* before writing the list to disk and after reading it back, so unknown
|
|
34
|
+
* names from older or newer versions never poison the runtime. */
|
|
35
|
+
export declare function sanitizeDisabledTools(input: readonly string[] | undefined): string[];
|
|
36
|
+
export declare function getPreset(id: PresetId): PresetDef;
|
|
37
|
+
export declare function isKnownTool(name: string): boolean;
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool access control — single source of truth for which MCP tools
|
|
3
|
+
* browser-link exposes and how the user can narrow that down.
|
|
4
|
+
*
|
|
5
|
+
* The runtime answer to "is this tool allowed?" is computed from the
|
|
6
|
+
* `disabledTools` list in `config.json` (default: empty = everything
|
|
7
|
+
* allowed). The catalogue below adds human-readable metadata used by
|
|
8
|
+
* the UI and the CLI subcommand — it never affects what the MCP server
|
|
9
|
+
* returns by itself.
|
|
10
|
+
*/
|
|
11
|
+
export const TOOL_CATALOGUE = [
|
|
12
|
+
// Browser bridge — read-only
|
|
13
|
+
{ name: 'browser.list_tabs', family: 'bridge', category: 'read', summary: 'List connected tabs' },
|
|
14
|
+
{
|
|
15
|
+
name: 'browser.ping',
|
|
16
|
+
family: 'bridge',
|
|
17
|
+
category: 'read',
|
|
18
|
+
summary: 'Verify the bridge to a tab',
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'browser.snapshot',
|
|
22
|
+
family: 'bridge',
|
|
23
|
+
category: 'read',
|
|
24
|
+
summary: 'Dump DOM, text and interactive elements',
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'browser.console',
|
|
28
|
+
family: 'bridge',
|
|
29
|
+
category: 'read',
|
|
30
|
+
summary: 'Read recent console messages',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'browser.network',
|
|
34
|
+
family: 'bridge',
|
|
35
|
+
category: 'read',
|
|
36
|
+
summary: 'Read recent network requests',
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
name: 'browser.network_body',
|
|
40
|
+
family: 'bridge',
|
|
41
|
+
category: 'read',
|
|
42
|
+
summary: 'Fetch the body of a specific request',
|
|
43
|
+
},
|
|
44
|
+
// Browser bridge — actions
|
|
45
|
+
{
|
|
46
|
+
name: 'browser.navigate',
|
|
47
|
+
family: 'bridge',
|
|
48
|
+
category: 'action',
|
|
49
|
+
summary: 'Navigate the tab to a URL',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'browser.click',
|
|
53
|
+
family: 'bridge',
|
|
54
|
+
category: 'action',
|
|
55
|
+
summary: 'Click an element by CSS selector',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
name: 'browser.type',
|
|
59
|
+
family: 'bridge',
|
|
60
|
+
category: 'action',
|
|
61
|
+
summary: 'Type text into an input',
|
|
62
|
+
},
|
|
63
|
+
// Browser bridge — arbitrary code
|
|
64
|
+
{
|
|
65
|
+
name: 'browser.evaluate',
|
|
66
|
+
family: 'bridge',
|
|
67
|
+
category: 'eval',
|
|
68
|
+
summary: 'Run arbitrary JavaScript in the page',
|
|
69
|
+
},
|
|
70
|
+
// Persistent map — reads
|
|
71
|
+
{
|
|
72
|
+
name: 'browser.map.recall',
|
|
73
|
+
family: 'map',
|
|
74
|
+
category: 'map-read',
|
|
75
|
+
summary: 'Recall selectors / flows / gotchas for an app',
|
|
76
|
+
},
|
|
77
|
+
{ name: 'browser.map.apps', family: 'map', category: 'map-read', summary: 'List known apps' },
|
|
78
|
+
// Persistent map — writes
|
|
79
|
+
{
|
|
80
|
+
name: 'browser.map.save',
|
|
81
|
+
family: 'map',
|
|
82
|
+
category: 'map-write',
|
|
83
|
+
summary: 'Persist a selector / flow / gotcha',
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'browser.map.record_use',
|
|
87
|
+
family: 'map',
|
|
88
|
+
category: 'map-write',
|
|
89
|
+
summary: 'Mark an entry verified or failed',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
name: 'browser.map.forget',
|
|
93
|
+
family: 'map',
|
|
94
|
+
category: 'map-write',
|
|
95
|
+
summary: 'Delete an entry or a whole app',
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'browser.map.rename_app',
|
|
99
|
+
family: 'map',
|
|
100
|
+
category: 'map-write',
|
|
101
|
+
summary: 'Rename an app_key',
|
|
102
|
+
},
|
|
103
|
+
];
|
|
104
|
+
function namesWhere(predicate) {
|
|
105
|
+
return TOOL_CATALOGUE.filter(predicate)
|
|
106
|
+
.map((m) => m.name)
|
|
107
|
+
.sort();
|
|
108
|
+
}
|
|
109
|
+
export const PRESETS = [
|
|
110
|
+
{ id: 'all', label: 'All enabled', disabled: [] },
|
|
111
|
+
{
|
|
112
|
+
id: 'readonly',
|
|
113
|
+
label: 'Read-only (no actions, no JS, no map writes)',
|
|
114
|
+
disabled: namesWhere((m) => m.category === 'action' || m.category === 'eval' || m.category === 'map-write'),
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'no-eval',
|
|
118
|
+
label: 'No evaluate (everything except arbitrary JS)',
|
|
119
|
+
disabled: ['browser.evaluate'],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'no-map',
|
|
123
|
+
label: 'No persistent map (all bridge tools on)',
|
|
124
|
+
disabled: namesWhere((m) => m.family === 'map'),
|
|
125
|
+
},
|
|
126
|
+
];
|
|
127
|
+
const KNOWN_NAMES = new Set(TOOL_CATALOGUE.map((m) => m.name));
|
|
128
|
+
/** True when the tool should be exposed in tools/list and accepted in tools/call. */
|
|
129
|
+
export function isToolEnabled(name, disabled) {
|
|
130
|
+
if (!disabled || disabled.length === 0)
|
|
131
|
+
return true;
|
|
132
|
+
return !disabled.includes(name);
|
|
133
|
+
}
|
|
134
|
+
/** Drop entries that don't match any current tool, dedupe, and sort. Used
|
|
135
|
+
* before writing the list to disk and after reading it back, so unknown
|
|
136
|
+
* names from older or newer versions never poison the runtime. */
|
|
137
|
+
export function sanitizeDisabledTools(input) {
|
|
138
|
+
if (!input || input.length === 0)
|
|
139
|
+
return [];
|
|
140
|
+
const out = new Set();
|
|
141
|
+
for (const name of input) {
|
|
142
|
+
if (typeof name === 'string' && KNOWN_NAMES.has(name))
|
|
143
|
+
out.add(name);
|
|
144
|
+
}
|
|
145
|
+
return [...out].sort();
|
|
146
|
+
}
|
|
147
|
+
export function getPreset(id) {
|
|
148
|
+
const found = PRESETS.find((p) => p.id === id);
|
|
149
|
+
if (!found)
|
|
150
|
+
throw new Error(`Unknown preset: ${id}`);
|
|
151
|
+
return found;
|
|
152
|
+
}
|
|
153
|
+
export function isKnownTool(name) {
|
|
154
|
+
return KNOWN_NAMES.has(name);
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../src/permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export declare const WS_HOST = "127.0.0.1";
|
|
2
2
|
export declare const WS_PORT = 17529;
|
|
3
|
-
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
/**
|
|
4
|
+
* Entry point used by the MCP client over stdio. Decides whether THIS
|
|
5
|
+
* process becomes the primary (binds 17529, runs the WS bridge + MCP
|
|
6
|
+
* server + optional IPC server) or — when multi-agent mode is enabled
|
|
7
|
+
* and another primary is already running — becomes a thin proxy that
|
|
8
|
+
* forwards MCP stdio frames to the primary over IPC.
|
|
9
|
+
*/
|
|
6
10
|
export declare function runServer(): Promise<void>;
|