opalserve 3.1.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +33 -6
  2. package/dist/cli/commands/doctor.d.ts +2 -0
  3. package/dist/cli/commands/doctor.d.ts.map +1 -0
  4. package/dist/cli/commands/doctor.js +107 -0
  5. package/dist/cli/commands/doctor.js.map +1 -0
  6. package/dist/cli/commands/link.d.ts +11 -0
  7. package/dist/cli/commands/link.d.ts.map +1 -0
  8. package/dist/cli/commands/link.js +135 -0
  9. package/dist/cli/commands/link.js.map +1 -0
  10. package/dist/cli/commands/mcp.d.ts +7 -0
  11. package/dist/cli/commands/mcp.d.ts.map +1 -0
  12. package/dist/cli/commands/mcp.js +46 -0
  13. package/dist/cli/commands/mcp.js.map +1 -0
  14. package/dist/cli/commands/start.d.ts +1 -0
  15. package/dist/cli/commands/start.d.ts.map +1 -1
  16. package/dist/cli/commands/start.js +13 -0
  17. package/dist/cli/commands/start.js.map +1 -1
  18. package/dist/cli/editors/base.d.ts +23 -0
  19. package/dist/cli/editors/base.d.ts.map +1 -0
  20. package/dist/cli/editors/base.js +75 -0
  21. package/dist/cli/editors/base.js.map +1 -0
  22. package/dist/cli/editors/claude.d.ts +8 -0
  23. package/dist/cli/editors/claude.d.ts.map +1 -0
  24. package/dist/cli/editors/claude.js +31 -0
  25. package/dist/cli/editors/claude.js.map +1 -0
  26. package/dist/cli/editors/cline.d.ts +14 -0
  27. package/dist/cli/editors/cline.d.ts.map +1 -0
  28. package/dist/cli/editors/cline.js +32 -0
  29. package/dist/cli/editors/cline.js.map +1 -0
  30. package/dist/cli/editors/cursor.d.ts +8 -0
  31. package/dist/cli/editors/cursor.d.ts.map +1 -0
  32. package/dist/cli/editors/cursor.js +14 -0
  33. package/dist/cli/editors/cursor.js.map +1 -0
  34. package/dist/cli/editors/index.d.ts +14 -0
  35. package/dist/cli/editors/index.d.ts.map +1 -0
  36. package/dist/cli/editors/index.js +34 -0
  37. package/dist/cli/editors/index.js.map +1 -0
  38. package/dist/cli/editors/types.d.ts +33 -0
  39. package/dist/cli/editors/types.d.ts.map +1 -0
  40. package/dist/cli/editors/types.js +2 -0
  41. package/dist/cli/editors/types.js.map +1 -0
  42. package/dist/cli/index.js +26 -0
  43. package/dist/cli/index.js.map +1 -1
  44. package/dist/constants.d.ts +1 -1
  45. package/dist/constants.js +1 -1
  46. package/dist/utils/browser.d.ts +7 -0
  47. package/dist/utils/browser.d.ts.map +1 -0
  48. package/dist/utils/browser.js +34 -0
  49. package/dist/utils/browser.js.map +1 -0
  50. package/package.json +1 -1
package/README.md CHANGED
@@ -95,13 +95,33 @@ opalserve server add --name files --stdio "npx -y @modelcontextprotocol/server-f
95
95
 
96
96
  # 5. Discover available tools
97
97
  opalserve tools search "read file"
98
+
99
+ # 6. Wire OpalServe into your AI editor
100
+ opalserve link claude # or: cursor, cline
101
+ # (restart the editor; OpalServe shows up as the "opalserve" MCP server)
102
+ ```
103
+
104
+ > **Tip:** OpalServe runs on port **3456** by default. The dashboard ships inside the npm package, opens automatically on `start`, and is served from `http://localhost:3456/dashboard`.
105
+
106
+ ## Wire-Up — One Command
107
+
108
+ `opalserve link <editor>` writes the OpalServe MCP gateway into your editor's config so its AI assistant gets every tool you've registered. Supports **Claude Desktop**, **Cursor**, and **Cline (VS Code)**.
109
+
110
+ ```bash
111
+ opalserve link cursor # link a single editor
112
+ opalserve link --all # link every detected editor
113
+ opalserve link --status # see what's linked, no changes
114
+ opalserve unlink cursor # remove later
115
+ opalserve doctor # diagnose port, gateway, links, secrets
98
116
  ```
99
117
 
100
- > **Tip:** OpalServe runs on port **3456** by default. The dashboard ships inside the npm package and is served from `http://localhost:3456/dashboard` after starting.
118
+ Under the hood the editor spawns `npx -y opalserve mcp` as its MCP stdio process. Override with `OPALSERVE_LINK_COMMAND` env var if you want it to invoke a specific binary path instead.
119
+
120
+ ## Releases
101
121
 
102
- ## Trust Check
122
+ **3.2.0 Coherence (current)**: `opalserve link <editor>` wires OpalServe into Claude Desktop / Cursor / Cline with one command, plus `opalserve doctor` for self-serve diagnostics, the `opalserve mcp` stdio entry-point, and auto-open of the dashboard on `start`.
103
123
 
104
- OpalServe 3.1.1 — the **Trust Patch** hardens the auth and HTTP surface:
124
+ **3.1.1 — Trust Patch**: hardens the auth and HTTP surface.
105
125
 
106
126
  - **API keys** now use HMAC-SHA256 with a per-installation server secret (was unsalted SHA-256). Legacy keys are rehashed transparently on first use.
107
127
  - **Auth bypass** (env-var fallback that silently disabled auth in non-team mode) removed. The registry's mode is now the single source of truth.
@@ -113,11 +133,11 @@ Disclosure policy: see [SECURITY.md](SECURITY.md).
113
133
 
114
134
  ```bash
115
135
  opalserve --version
116
- # 3.1.0
136
+ # 3.2.0
117
137
 
118
138
  opalserve start
119
139
  # HTTP API http://127.0.0.1:3456
120
- # Dashboard http://127.0.0.1:3456/dashboard
140
+ # Dashboard http://127.0.0.1:3456/dashboard (opens in browser automatically)
121
141
  ```
122
142
 
123
143
  For source builds, the same release checks are used locally and in CI:
@@ -255,8 +275,15 @@ http://localhost:3456/dashboard
255
275
  | Command | Description |
256
276
  |---|---|
257
277
  | `opalserve init` | Interactive setup wizard -- configures mode, port, and first server |
258
- | `opalserve start` | Start the registry server (HTTP API + MCP gateway) |
278
+ | `opalserve start` | Start the registry server (HTTP API + MCP gateway); opens dashboard in browser |
279
+ | `opalserve start --no-browser` | Start without auto-opening the dashboard |
259
280
  | `opalserve status` | Show server status, connected servers, and tool counts |
281
+ | `opalserve doctor` | Self-diagnose port, gateway, registered servers, editor links, secrets |
282
+ | `opalserve link <editor>` | Wire OpalServe into Claude Desktop, Cursor, or Cline |
283
+ | `opalserve link --all` | Link every detected AI editor in one shot |
284
+ | `opalserve link --status` | Show editor link status (no changes) |
285
+ | `opalserve unlink <editor>` | Remove OpalServe from an editor's MCP config |
286
+ | `opalserve mcp` | Run as a stdio MCP server (used internally by linked editors) |
260
287
  | `opalserve health` | Health check all registered servers |
261
288
  | `opalserve health --server <name>` | Health check a specific server |
262
289
  | `opalserve login` | Authenticate with a team server |
@@ -0,0 +1,2 @@
1
+ export declare function doctorCommand(): Promise<void>;
2
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"AAwBA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA2FnD"}
@@ -0,0 +1,107 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { createConnection } from 'node:net';
3
+ import chalk from 'chalk';
4
+ import { OpalServeRegistry } from '../../core/registry.js';
5
+ import { getApiKeySecretPath, getDefaultDbPath } from '../../config/defaults.js';
6
+ import { SUPPORTED_EDITORS, OPALSERVE_ENTRY_NAME } from '../editors/index.js';
7
+ import { showMiniBanner, showSuccess, showError, showInfo, showWarning } from '../ui/banner.js';
8
+ function isPortFree(host, port, timeoutMs = 800) {
9
+ return new Promise(resolve => {
10
+ const socket = createConnection({ host, port });
11
+ const done = (free) => {
12
+ socket.removeAllListeners();
13
+ socket.destroy();
14
+ resolve(free);
15
+ };
16
+ const timer = setTimeout(() => done(true), timeoutMs);
17
+ socket.once('connect', () => { clearTimeout(timer); done(false); });
18
+ socket.once('error', () => { clearTimeout(timer); done(true); });
19
+ });
20
+ }
21
+ export async function doctorCommand() {
22
+ showMiniBanner();
23
+ console.log(chalk.bold(' Running diagnostics...\n'));
24
+ const checks = [];
25
+ try {
26
+ const registry = await OpalServeRegistry.create({ logging: { level: 'silent' } });
27
+ checks.push({
28
+ name: 'config',
29
+ ok: true,
30
+ level: 'info',
31
+ detail: `mode=${registry.config.mode}, port=${registry.config.gateway.port}`,
32
+ });
33
+ const dbPath = registry.config.storage.path || getDefaultDbPath();
34
+ checks.push({
35
+ name: 'database',
36
+ ok: existsSync(dbPath),
37
+ level: existsSync(dbPath) ? 'info' : 'warn',
38
+ detail: dbPath,
39
+ });
40
+ const secretPath = getApiKeySecretPath();
41
+ checks.push({
42
+ name: 'api-key secret',
43
+ ok: existsSync(secretPath) || !!process.env.OPALSERVE_API_KEY_SECRET,
44
+ level: 'info',
45
+ detail: process.env.OPALSERVE_API_KEY_SECRET ? '(from env)' : secretPath,
46
+ });
47
+ const port = registry.config.gateway.port;
48
+ const host = registry.config.gateway.host;
49
+ const portFree = await isPortFree(host, port);
50
+ checks.push({
51
+ name: `port ${port}`,
52
+ ok: true,
53
+ level: portFree ? 'info' : 'warn',
54
+ detail: portFree ? 'available' : 'in use (server may already be running)',
55
+ });
56
+ const servers = registry.listServers();
57
+ checks.push({
58
+ name: 'registered servers',
59
+ ok: servers.length > 0,
60
+ level: servers.length > 0 ? 'info' : 'warn',
61
+ detail: servers.length === 0
62
+ ? 'none registered yet — try `opalserve add` or `opalserve init`'
63
+ : `${servers.length} (${servers.filter(s => s.status === 'connected').length} connected)`,
64
+ });
65
+ for (const editor of SUPPORTED_EDITORS) {
66
+ const status = editor.status(OPALSERVE_ENTRY_NAME);
67
+ checks.push({
68
+ name: `editor: ${editor.displayName}`,
69
+ ok: status.linked,
70
+ level: status.installed ? (status.linked ? 'info' : 'warn') : 'info',
71
+ detail: !status.installed
72
+ ? 'not installed on this machine'
73
+ : status.linked
74
+ ? `linked → ${status.configPath}`
75
+ : `installed but not linked — run \`opalserve link ${editor.id}\``,
76
+ });
77
+ }
78
+ await registry.stop();
79
+ }
80
+ catch (err) {
81
+ checks.push({
82
+ name: 'registry',
83
+ ok: false,
84
+ level: 'error',
85
+ detail: err instanceof Error ? err.message : String(err),
86
+ });
87
+ }
88
+ for (const c of checks) {
89
+ if (c.level === 'error')
90
+ showError(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
91
+ else if (c.level === 'warn')
92
+ showWarning(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
93
+ else if (c.ok)
94
+ showSuccess(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
95
+ else
96
+ showInfo(`${c.name.padEnd(28)} ${c.detail ? chalk.dim(c.detail) : ''}`);
97
+ }
98
+ const errors = checks.filter(c => c.level === 'error').length;
99
+ console.log('');
100
+ if (errors > 0) {
101
+ showError(`${errors} error(s) found.`);
102
+ process.exit(1);
103
+ }
104
+ showSuccess('All checks passed.');
105
+ console.log('');
106
+ }
107
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../src/cli/commands/doctor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ interface LinkOptions {
2
+ all?: boolean;
3
+ status?: boolean;
4
+ }
5
+ interface UnlinkOptions {
6
+ all?: boolean;
7
+ }
8
+ export declare function linkCommand(editorId: string | undefined, options: LinkOptions): Promise<void>;
9
+ export declare function unlinkCommand(editorId: string | undefined, options: UnlinkOptions): Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/link.ts"],"names":[],"mappings":"AAUA,UAAU,WAAW;IACnB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,aAAa;IACrB,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AA0CD,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CA0DnG;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAsCvG"}
@@ -0,0 +1,135 @@
1
+ import chalk from 'chalk';
2
+ import { SUPPORTED_EDITORS, OPALSERVE_ENTRY_NAME, buildOpalserveEntry, getEditor, } from '../editors/index.js';
3
+ import { showMiniBanner, showSuccess, showError, showInfo, showWarning, showBox } from '../ui/banner.js';
4
+ function formatStatusLine(adapter) {
5
+ const status = adapter.status(OPALSERVE_ENTRY_NAME);
6
+ const presence = status.installed
7
+ ? chalk.green('detected')
8
+ : chalk.dim('not detected');
9
+ const linked = status.linked
10
+ ? chalk.cyan('linked')
11
+ : chalk.gray('not linked');
12
+ return ` ${chalk.bold(adapter.displayName.padEnd(20))} ${presence} · ${linked}\n ${chalk.dim(status.configPath)}`;
13
+ }
14
+ function showStatusTable() {
15
+ console.log('');
16
+ console.log(chalk.bold(' AI editor status:'));
17
+ console.log('');
18
+ for (const editor of SUPPORTED_EDITORS) {
19
+ console.log(formatStatusLine(editor));
20
+ }
21
+ console.log('');
22
+ }
23
+ function linkOne(adapter) {
24
+ try {
25
+ const entry = buildOpalserveEntry();
26
+ const prior = adapter.link(OPALSERVE_ENTRY_NAME, entry);
27
+ return { ok: true, replaced: prior !== null };
28
+ }
29
+ catch (err) {
30
+ return { ok: false, replaced: false, error: err instanceof Error ? err.message : String(err) };
31
+ }
32
+ }
33
+ function unlinkOne(adapter) {
34
+ try {
35
+ const removed = adapter.unlink(OPALSERVE_ENTRY_NAME);
36
+ return { ok: true, removed };
37
+ }
38
+ catch (err) {
39
+ return { ok: false, removed: false, error: err instanceof Error ? err.message : String(err) };
40
+ }
41
+ }
42
+ export async function linkCommand(editorId, options) {
43
+ showMiniBanner();
44
+ if (options.status) {
45
+ showStatusTable();
46
+ return;
47
+ }
48
+ let targets = [];
49
+ if (editorId) {
50
+ const adapter = getEditor(editorId);
51
+ if (!adapter) {
52
+ showError(`Unknown editor "${editorId}". Supported: ${SUPPORTED_EDITORS.map(e => e.id).join(', ')}`);
53
+ process.exit(1);
54
+ }
55
+ targets = [adapter];
56
+ }
57
+ else if (options.all) {
58
+ targets = SUPPORTED_EDITORS.filter(e => e.detect());
59
+ if (targets.length === 0) {
60
+ showWarning('No supported AI editors detected on this machine.');
61
+ showStatusTable();
62
+ return;
63
+ }
64
+ }
65
+ else {
66
+ showStatusTable();
67
+ showInfo('Run `opalserve link <editor>` to link a specific editor, or `opalserve link --all` for every detected one.');
68
+ return;
69
+ }
70
+ console.log('');
71
+ for (const adapter of targets) {
72
+ if (!adapter.detect()) {
73
+ showWarning(`${adapter.displayName} not detected — linking anyway (config will be created at ${adapter.getConfigPath()}).`);
74
+ }
75
+ const result = linkOne(adapter);
76
+ if (result.ok) {
77
+ const verb = result.replaced ? 'updated' : 'wired up';
78
+ showSuccess(`${adapter.displayName} ${verb}: ${chalk.dim(adapter.getConfigPath())}`);
79
+ if (result.replaced) {
80
+ showInfo(` Prior \`${OPALSERVE_ENTRY_NAME}\` entry overwritten.`);
81
+ }
82
+ }
83
+ else {
84
+ showError(`${adapter.displayName}: ${result.error}`);
85
+ }
86
+ }
87
+ console.log('');
88
+ showBox([
89
+ `OpalServe is now reachable to ${targets.length === 1 ? 'this editor' : 'these editors'} as the MCP server "${chalk.cyan(OPALSERVE_ENTRY_NAME)}".`,
90
+ '',
91
+ chalk.bold('Next:'),
92
+ ` 1. ${chalk.dim('Restart the editor for it to pick up the new MCP server.')}`,
93
+ ` 2. ${chalk.dim('Try asking your AI: "what tools are available via opalserve?"')}`,
94
+ ].join('\n'), 'Linked');
95
+ }
96
+ export async function unlinkCommand(editorId, options) {
97
+ showMiniBanner();
98
+ let targets = [];
99
+ if (editorId) {
100
+ const adapter = getEditor(editorId);
101
+ if (!adapter) {
102
+ showError(`Unknown editor "${editorId}". Supported: ${SUPPORTED_EDITORS.map(e => e.id).join(', ')}`);
103
+ process.exit(1);
104
+ }
105
+ targets = [adapter];
106
+ }
107
+ else if (options.all) {
108
+ targets = SUPPORTED_EDITORS.filter(e => e.isLinked(OPALSERVE_ENTRY_NAME));
109
+ if (targets.length === 0) {
110
+ showInfo('No editors currently linked.');
111
+ return;
112
+ }
113
+ }
114
+ else {
115
+ showStatusTable();
116
+ showInfo('Run `opalserve unlink <editor>` to unlink, or `opalserve unlink --all` to unlink everywhere.');
117
+ return;
118
+ }
119
+ console.log('');
120
+ for (const adapter of targets) {
121
+ const result = unlinkOne(adapter);
122
+ if (!result.ok) {
123
+ showError(`${adapter.displayName}: ${result.error}`);
124
+ continue;
125
+ }
126
+ if (result.removed) {
127
+ showSuccess(`${adapter.displayName} unlinked`);
128
+ }
129
+ else {
130
+ showInfo(`${adapter.displayName} was not linked — nothing to remove.`);
131
+ }
132
+ }
133
+ console.log('');
134
+ }
135
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../../src/cli/commands/link.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Run OpalServe as a stdio MCP server. This is what AI editors spawn after
3
+ * `opalserve link`. Stdout is reserved for the JSON-RPC protocol stream;
4
+ * everything else must go to stderr or be silenced.
5
+ */
6
+ export declare function mcpCommand(): Promise<void>;
7
+ //# sourceMappingURL=mcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/mcp.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAqChD"}
@@ -0,0 +1,46 @@
1
+ import { OpalServeRegistry } from '../../core/registry.js';
2
+ import { McpGateway } from '../../server/mcp-gateway.js';
3
+ import { setLogLevel } from '../../utils/logger.js';
4
+ /**
5
+ * Run OpalServe as a stdio MCP server. This is what AI editors spawn after
6
+ * `opalserve link`. Stdout is reserved for the JSON-RPC protocol stream;
7
+ * everything else must go to stderr or be silenced.
8
+ */
9
+ export async function mcpCommand() {
10
+ setLogLevel('silent');
11
+ const safeWrite = (...args) => process.stderr.write(args.map(a => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ') + '\n');
12
+ console.log = safeWrite;
13
+ console.warn = safeWrite;
14
+ console.info = safeWrite;
15
+ let registry;
16
+ try {
17
+ registry = await OpalServeRegistry.create({ logging: { level: 'silent' } });
18
+ setLogLevel('silent');
19
+ for (const server of registry.config.servers.filter(s => s.enabled)) {
20
+ try {
21
+ await registry.addServer(server);
22
+ }
23
+ catch (err) {
24
+ process.stderr.write(`opalserve: failed to connect ${server.name}: ${err instanceof Error ? err.message : String(err)}\n`);
25
+ }
26
+ }
27
+ const gateway = new McpGateway(registry);
28
+ await gateway.connectStdio();
29
+ const shutdown = async () => {
30
+ try {
31
+ await registry.stop();
32
+ }
33
+ catch { /* swallow */ }
34
+ process.exit(0);
35
+ };
36
+ process.on('SIGINT', shutdown);
37
+ process.on('SIGTERM', shutdown);
38
+ process.stdin.on('end', shutdown);
39
+ process.stdin.on('close', shutdown);
40
+ }
41
+ catch (err) {
42
+ process.stderr.write(`opalserve: fatal: ${err instanceof Error ? err.message : String(err)}\n`);
43
+ process.exit(1);
44
+ }
45
+ }
46
+ //# sourceMappingURL=mcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../../../src/cli/commands/mcp.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,WAAW,CAAC,QAAQ,CAAC,CAAC;IAEtB,MAAM,SAAS,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,CACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACxG,OAAO,CAAC,GAAG,GAAG,SAAS,CAAC;IACxB,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IACzB,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC;IAEzB,IAAI,QAA2B,CAAC;IAChC,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC5E,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEtB,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YACpE,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACnC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,MAAM,CAAC,IAAI,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC7H,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAC;QAE7B,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,IAAI,CAAC;gBAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC;YACtD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -2,5 +2,6 @@ export declare function startCommand(options: {
2
2
  port?: string;
3
3
  host?: string;
4
4
  config?: string;
5
+ browser?: boolean;
5
6
  }): Promise<void>;
6
7
  //# sourceMappingURL=start.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAMA,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgE5G"}
1
+ {"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAOA,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA2E/H"}
@@ -2,6 +2,7 @@ import chalk from 'chalk';
2
2
  import ora from 'ora';
3
3
  import { OpalServeRegistry } from '../../core/registry.js';
4
4
  import { startServer } from '../../server/app.js';
5
+ import { openInBrowser } from '../../utils/browser.js';
5
6
  import { showMiniBanner, showSuccess, showError, showInfo } from '../ui/banner.js';
6
7
  export async function startCommand(options) {
7
8
  showMiniBanner();
@@ -41,6 +42,18 @@ export async function startCommand(options) {
41
42
  const toolCount = registry.listTools().length;
42
43
  const serverCount = registry.listServers().filter(s => s.status === 'connected').length;
43
44
  showInfo(`${chalk.bold(String(toolCount))} tools available across ${chalk.bold(String(serverCount))} server(s)`);
45
+ const dashboardUrl = `http://${address.address === '0.0.0.0' ? '127.0.0.1' : address.address}:${address.port}/dashboard`;
46
+ if (options.browser !== false) {
47
+ if (openInBrowser(dashboardUrl)) {
48
+ showInfo(`Dashboard opening at ${chalk.cyan(dashboardUrl)}`);
49
+ }
50
+ else {
51
+ showInfo(`Dashboard at ${chalk.cyan(dashboardUrl)}`);
52
+ }
53
+ }
54
+ else {
55
+ showInfo(`Dashboard at ${chalk.cyan(dashboardUrl)}`);
56
+ }
44
57
  console.log(` ${chalk.dim('Press Ctrl+C to stop')}\n`);
45
58
  // Graceful shutdown
46
59
  const shutdown = async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEnF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA0D;IAC3F,cAAc,EAAE,CAAC;IAEjB,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAEnF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,CAAC;QAClD,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAExC,kBAAkB;QAClB,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC/D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,QAAQ,CAAC,iBAAiB,OAAO,CAAC,MAAM,eAAe,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAEhB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,aAAa,GAAG,GAAG,CAAC;oBACxB,IAAI,EAAE,KAAK,MAAM,CAAC,IAAI,EAAE;oBACxB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,CAAC;iBACV,CAAC,CAAC,KAAK,EAAE,CAAC;gBAEX,IAAI,CAAC;oBACH,MAAM,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;oBACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;oBACxE,aAAa,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,EAAE,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBAC3G,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACnE,aAAa,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;QAEnC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,WAAW,CAAC,yBAAyB,KAAK,CAAC,IAAI,CAAC,UAAU,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAEhG,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC;QAC9C,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;QACxF,QAAQ,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC;QACjH,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAExD,oBAAoB;QACpB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,MAAM,WAAW,GAAG,GAAG,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,CAAC;YACpD,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtB,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAChC,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"start.js","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEnF,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA6E;IAC9G,cAAc,EAAE,CAAC;IAEjB,MAAM,OAAO,GAAG,GAAG,CAAC,EAAE,IAAI,EAAE,0BAA0B,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;IAEnF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,CAAC;QAClD,OAAO,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;QAExC,kBAAkB;QAClB,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC/D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,QAAQ,CAAC,iBAAiB,OAAO,CAAC,MAAM,eAAe,CAAC,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAEhB,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,MAAM,aAAa,GAAG,GAAG,CAAC;oBACxB,IAAI,EAAE,KAAK,MAAM,CAAC,IAAI,EAAE;oBACxB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,CAAC;iBACV,CAAC,CAAC,KAAK,EAAE,CAAC;gBAEX,IAAI,CAAC;oBACH,MAAM,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;oBACjC,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;oBACxE,aAAa,CAAC,OAAO,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,MAAM,EAAE,SAAS,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBAC3G,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACnE,aAAa,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACxE,CAAC;YACH,CAAC;QACH,CAAC;QAED,iBAAiB;QACjB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,MAAM,GAAG,GAAG,MAAM,WAAW,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QACtE,MAAM,OAAO,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;QAEnC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,WAAW,CAAC,yBAAyB,KAAK,CAAC,IAAI,CAAC,UAAU,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAEhG,MAAM,SAAS,GAAG,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC;QAC9C,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM,CAAC;QACxF,QAAQ,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC;QAEjH,MAAM,YAAY,GAAG,UAAU,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,YAAY,CAAC;QACzH,IAAI,OAAO,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;YAC9B,IAAI,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC;gBAChC,QAAQ,CAAC,wBAAwB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YAC/D,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,gBAAgB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,gBAAgB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAExD,oBAAoB;QACpB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;YAC1B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,MAAM,WAAW,GAAG,GAAG,CAAC,kBAAkB,CAAC,CAAC,KAAK,EAAE,CAAC;YACpD,MAAM,GAAG,CAAC,KAAK,EAAE,CAAC;YAClB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACtB,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC,CAAC;QAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAChC,SAAS,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ import type { EditorAdapter, EditorStatus, McpServerEntry } from './types.js';
2
+ /**
3
+ * Common adapter for editors whose MCP config follows the
4
+ * `{ mcpServers: { <name>: { command, args, env } } }` shape used by Claude
5
+ * Desktop, Cursor, and Cline. Subclasses provide id, displayName, configPath,
6
+ * and a presence-detection signal.
7
+ */
8
+ export declare abstract class JsonMcpServersAdapter implements EditorAdapter {
9
+ abstract readonly id: string;
10
+ abstract readonly displayName: string;
11
+ abstract getConfigPath(): string;
12
+ /** Path that, if present, indicates the editor is installed. */
13
+ protected abstract getInstallSignalPath(): string;
14
+ detect(): boolean;
15
+ readConfig(): Record<string, unknown>;
16
+ writeConfig(config: Record<string, unknown>): void;
17
+ private getServers;
18
+ isLinked(entryName: string): boolean;
19
+ link(entryName: string, entry: McpServerEntry): McpServerEntry | null;
20
+ unlink(entryName: string): boolean;
21
+ status(entryName: string): EditorStatus;
22
+ }
23
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/cli/editors/base.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE9E;;;;;GAKG;AACH,8BAAsB,qBAAsB,YAAW,aAAa;IAClE,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAEtC,QAAQ,CAAC,aAAa,IAAI,MAAM;IAChC,gEAAgE;IAChE,SAAS,CAAC,QAAQ,CAAC,oBAAoB,IAAI,MAAM;IAEjD,MAAM,IAAI,OAAO;IAIjB,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAcrC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAMlD,OAAO,CAAC,UAAU;IAQlB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAMpC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,cAAc,GAAG,IAAI;IASrE,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO;IAUlC,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY;CASxC"}
@@ -0,0 +1,75 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
+ import { dirname } from 'node:path';
3
+ /**
4
+ * Common adapter for editors whose MCP config follows the
5
+ * `{ mcpServers: { <name>: { command, args, env } } }` shape used by Claude
6
+ * Desktop, Cursor, and Cline. Subclasses provide id, displayName, configPath,
7
+ * and a presence-detection signal.
8
+ */
9
+ export class JsonMcpServersAdapter {
10
+ detect() {
11
+ return existsSync(this.getInstallSignalPath());
12
+ }
13
+ readConfig() {
14
+ const path = this.getConfigPath();
15
+ if (!existsSync(path))
16
+ return {};
17
+ try {
18
+ const raw = readFileSync(path, 'utf8');
19
+ const parsed = raw.trim() ? JSON.parse(raw) : {};
20
+ return (parsed && typeof parsed === 'object' && !Array.isArray(parsed))
21
+ ? parsed
22
+ : {};
23
+ }
24
+ catch (err) {
25
+ throw new Error(`Failed to parse ${this.displayName} config at ${path}: ${err instanceof Error ? err.message : String(err)}`);
26
+ }
27
+ }
28
+ writeConfig(config) {
29
+ const path = this.getConfigPath();
30
+ mkdirSync(dirname(path), { recursive: true });
31
+ writeFileSync(path, JSON.stringify(config, null, 2) + '\n', 'utf8');
32
+ }
33
+ getServers(config) {
34
+ const existing = config.mcpServers;
35
+ if (existing && typeof existing === 'object' && !Array.isArray(existing)) {
36
+ return existing;
37
+ }
38
+ return {};
39
+ }
40
+ isLinked(entryName) {
41
+ if (!existsSync(this.getConfigPath()))
42
+ return false;
43
+ const config = this.readConfig();
44
+ return entryName in this.getServers(config);
45
+ }
46
+ link(entryName, entry) {
47
+ const config = this.readConfig();
48
+ const servers = { ...this.getServers(config) };
49
+ const prior = servers[entryName] ?? null;
50
+ servers[entryName] = entry;
51
+ this.writeConfig({ ...config, mcpServers: servers });
52
+ return prior;
53
+ }
54
+ unlink(entryName) {
55
+ if (!existsSync(this.getConfigPath()))
56
+ return false;
57
+ const config = this.readConfig();
58
+ const servers = { ...this.getServers(config) };
59
+ if (!(entryName in servers))
60
+ return false;
61
+ delete servers[entryName];
62
+ this.writeConfig({ ...config, mcpServers: servers });
63
+ return true;
64
+ }
65
+ status(entryName) {
66
+ return {
67
+ id: this.id,
68
+ displayName: this.displayName,
69
+ configPath: this.getConfigPath(),
70
+ installed: this.detect(),
71
+ linked: this.isLinked(entryName),
72
+ };
73
+ }
74
+ }
75
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/cli/editors/base.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import { JsonMcpServersAdapter } from './base.js';
2
+ export declare class ClaudeDesktopAdapter extends JsonMcpServersAdapter {
3
+ readonly id = "claude";
4
+ readonly displayName = "Claude Desktop";
5
+ getConfigPath(): string;
6
+ protected getInstallSignalPath(): string;
7
+ }
8
+ //# sourceMappingURL=claude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/cli/editors/claude.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,qBAAa,oBAAqB,SAAQ,qBAAqB;IAC7D,QAAQ,CAAC,EAAE,YAAY;IACvB,QAAQ,CAAC,WAAW,oBAAoB;IAExC,aAAa,IAAI,MAAM;IAavB,SAAS,CAAC,oBAAoB,IAAI,MAAM;CAUzC"}
@@ -0,0 +1,31 @@
1
+ import { homedir, platform } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { JsonMcpServersAdapter } from './base.js';
4
+ export class ClaudeDesktopAdapter extends JsonMcpServersAdapter {
5
+ id = 'claude';
6
+ displayName = 'Claude Desktop';
7
+ getConfigPath() {
8
+ const home = homedir();
9
+ const plat = platform();
10
+ if (plat === 'darwin') {
11
+ return join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
12
+ }
13
+ if (plat === 'win32') {
14
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
15
+ return join(appdata, 'Claude', 'claude_desktop_config.json');
16
+ }
17
+ return join(home, '.config', 'Claude', 'claude_desktop_config.json');
18
+ }
19
+ getInstallSignalPath() {
20
+ const home = homedir();
21
+ const plat = platform();
22
+ if (plat === 'darwin')
23
+ return join(home, 'Library', 'Application Support', 'Claude');
24
+ if (plat === 'win32') {
25
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
26
+ return join(appdata, 'Claude');
27
+ }
28
+ return join(home, '.config', 'Claude');
29
+ }
30
+ }
31
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/cli/editors/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,OAAO,oBAAqB,SAAQ,qBAAqB;IACpD,EAAE,GAAG,QAAQ,CAAC;IACd,WAAW,GAAG,gBAAgB,CAAC;IAExC,aAAa;QACX,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;QAC9F,CAAC;QACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YACxE,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;QAC/D,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,4BAA4B,CAAC,CAAC;IACvE,CAAC;IAES,oBAAoB;QAC5B,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,QAAQ,CAAC,CAAC;QACrF,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YACxE,OAAO,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;IACzC,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import { JsonMcpServersAdapter } from './base.js';
2
+ /**
3
+ * Cline (formerly Claude Dev) stores its MCP servers under the VS Code
4
+ * extension's globalStorage. Path differs per OS but the extension id is
5
+ * stable.
6
+ */
7
+ export declare class ClineAdapter extends JsonMcpServersAdapter {
8
+ readonly id = "cline";
9
+ readonly displayName = "Cline (VS Code)";
10
+ getConfigPath(): string;
11
+ protected getInstallSignalPath(): string;
12
+ private globalStorageDir;
13
+ }
14
+ //# sourceMappingURL=cline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cline.d.ts","sourceRoot":"","sources":["../../../src/cli/editors/cline.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAIlD;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,qBAAqB;IACrD,QAAQ,CAAC,EAAE,WAAW;IACtB,QAAQ,CAAC,WAAW,qBAAqB;IAEzC,aAAa,IAAI,MAAM;IAIvB,SAAS,CAAC,oBAAoB,IAAI,MAAM;IAIxC,OAAO,CAAC,gBAAgB;CAYzB"}
@@ -0,0 +1,32 @@
1
+ import { homedir, platform } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { JsonMcpServersAdapter } from './base.js';
4
+ const EXTENSION_ID = 'saoudrizwan.claude-dev';
5
+ /**
6
+ * Cline (formerly Claude Dev) stores its MCP servers under the VS Code
7
+ * extension's globalStorage. Path differs per OS but the extension id is
8
+ * stable.
9
+ */
10
+ export class ClineAdapter extends JsonMcpServersAdapter {
11
+ id = 'cline';
12
+ displayName = 'Cline (VS Code)';
13
+ getConfigPath() {
14
+ return join(this.globalStorageDir(), 'settings', 'cline_mcp_settings.json');
15
+ }
16
+ getInstallSignalPath() {
17
+ return this.globalStorageDir();
18
+ }
19
+ globalStorageDir() {
20
+ const home = homedir();
21
+ const plat = platform();
22
+ if (plat === 'darwin') {
23
+ return join(home, 'Library', 'Application Support', 'Code', 'User', 'globalStorage', EXTENSION_ID);
24
+ }
25
+ if (plat === 'win32') {
26
+ const appdata = process.env.APPDATA ?? join(home, 'AppData', 'Roaming');
27
+ return join(appdata, 'Code', 'User', 'globalStorage', EXTENSION_ID);
28
+ }
29
+ return join(home, '.config', 'Code', 'User', 'globalStorage', EXTENSION_ID);
30
+ }
31
+ }
32
+ //# sourceMappingURL=cline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cline.js","sourceRoot":"","sources":["../../../src/cli/editors/cline.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,YAAY,GAAG,wBAAwB,CAAC;AAE9C;;;;GAIG;AACH,MAAM,OAAO,YAAa,SAAQ,qBAAqB;IAC5C,EAAE,GAAG,OAAO,CAAC;IACb,WAAW,GAAG,iBAAiB,CAAC;IAEzC,aAAa;QACX,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,UAAU,EAAE,yBAAyB,CAAC,CAAC;IAC9E,CAAC;IAES,oBAAoB;QAC5B,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;IACjC,CAAC;IAEO,gBAAgB;QACtB,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;QACrG,CAAC;QACD,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YACxE,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC;IAC9E,CAAC;CACF"}
@@ -0,0 +1,8 @@
1
+ import { JsonMcpServersAdapter } from './base.js';
2
+ export declare class CursorAdapter extends JsonMcpServersAdapter {
3
+ readonly id = "cursor";
4
+ readonly displayName = "Cursor";
5
+ getConfigPath(): string;
6
+ protected getInstallSignalPath(): string;
7
+ }
8
+ //# sourceMappingURL=cursor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.d.ts","sourceRoot":"","sources":["../../../src/cli/editors/cursor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,qBAAa,aAAc,SAAQ,qBAAqB;IACtD,QAAQ,CAAC,EAAE,YAAY;IACvB,QAAQ,CAAC,WAAW,YAAY;IAEhC,aAAa,IAAI,MAAM;IAIvB,SAAS,CAAC,oBAAoB,IAAI,MAAM;CAGzC"}
@@ -0,0 +1,14 @@
1
+ import { homedir } from 'node:os';
2
+ import { join } from 'node:path';
3
+ import { JsonMcpServersAdapter } from './base.js';
4
+ export class CursorAdapter extends JsonMcpServersAdapter {
5
+ id = 'cursor';
6
+ displayName = 'Cursor';
7
+ getConfigPath() {
8
+ return join(homedir(), '.cursor', 'mcp.json');
9
+ }
10
+ getInstallSignalPath() {
11
+ return join(homedir(), '.cursor');
12
+ }
13
+ }
14
+ //# sourceMappingURL=cursor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cursor.js","sourceRoot":"","sources":["../../../src/cli/editors/cursor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,WAAW,CAAC;AAElD,MAAM,OAAO,aAAc,SAAQ,qBAAqB;IAC7C,EAAE,GAAG,QAAQ,CAAC;IACd,WAAW,GAAG,QAAQ,CAAC;IAEhC,aAAa;QACX,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAChD,CAAC;IAES,oBAAoB;QAC5B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACpC,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { EditorAdapter, McpServerEntry } from './types.js';
2
+ export declare const SUPPORTED_EDITORS: ReadonlyArray<EditorAdapter>;
3
+ export declare const OPALSERVE_ENTRY_NAME = "opalserve";
4
+ export declare function getEditor(id: string): EditorAdapter | null;
5
+ export declare function listInstalledEditors(): EditorAdapter[];
6
+ /**
7
+ * Build the mcpServers entry that points at this OpalServe installation.
8
+ * Defaults to `npx -y opalserve mcp` so end users don't have to install
9
+ * globally; an override via OPALSERVE_LINK_COMMAND lets advanced users pin
10
+ * to a specific path.
11
+ */
12
+ export declare function buildOpalserveEntry(): McpServerEntry;
13
+ export type { EditorAdapter, EditorStatus, McpServerEntry } from './types.js';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/editors/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAKhE,eAAO,MAAM,iBAAiB,EAAE,aAAa,CAAC,aAAa,CAI1D,CAAC;AAEF,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAEhD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAE1D;AAED,wBAAgB,oBAAoB,IAAI,aAAa,EAAE,CAEtD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,cAAc,CAUpD;AAED,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { ClaudeDesktopAdapter } from './claude.js';
2
+ import { CursorAdapter } from './cursor.js';
3
+ import { ClineAdapter } from './cline.js';
4
+ export const SUPPORTED_EDITORS = [
5
+ new ClaudeDesktopAdapter(),
6
+ new CursorAdapter(),
7
+ new ClineAdapter(),
8
+ ];
9
+ export const OPALSERVE_ENTRY_NAME = 'opalserve';
10
+ export function getEditor(id) {
11
+ return SUPPORTED_EDITORS.find(e => e.id === id) ?? null;
12
+ }
13
+ export function listInstalledEditors() {
14
+ return SUPPORTED_EDITORS.filter(e => e.detect());
15
+ }
16
+ /**
17
+ * Build the mcpServers entry that points at this OpalServe installation.
18
+ * Defaults to `npx -y opalserve mcp` so end users don't have to install
19
+ * globally; an override via OPALSERVE_LINK_COMMAND lets advanced users pin
20
+ * to a specific path.
21
+ */
22
+ export function buildOpalserveEntry() {
23
+ const override = process.env.OPALSERVE_LINK_COMMAND;
24
+ if (override) {
25
+ const [command, ...args] = override.split(/\s+/).filter(Boolean);
26
+ if (command)
27
+ return { command, args };
28
+ }
29
+ return {
30
+ command: 'npx',
31
+ args: ['-y', 'opalserve', 'mcp'],
32
+ };
33
+ }
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/editors/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,CAAC,MAAM,iBAAiB,GAAiC;IAC7D,IAAI,oBAAoB,EAAE;IAC1B,IAAI,aAAa,EAAE;IACnB,IAAI,YAAY,EAAE;CACnB,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAEhD,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,IAAI,IAAI,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACpD,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACjE,IAAI,OAAO;YAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACxC,CAAC;IACD,OAAO;QACL,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC;KACjC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,33 @@
1
+ export interface McpServerEntry {
2
+ command: string;
3
+ args?: string[];
4
+ env?: Record<string, string>;
5
+ }
6
+ export interface EditorStatus {
7
+ id: string;
8
+ displayName: string;
9
+ configPath: string;
10
+ installed: boolean;
11
+ linked: boolean;
12
+ }
13
+ export interface EditorAdapter {
14
+ id: string;
15
+ displayName: string;
16
+ /** OS-resolved config file path (may not exist yet). */
17
+ getConfigPath(): string;
18
+ /** True if a sign of the editor's presence is on disk. */
19
+ detect(): boolean;
20
+ /** Read or initialise the config file, returning the parsed JSON object. */
21
+ readConfig(): Record<string, unknown>;
22
+ /** Write a config object back to disk, creating parent dirs if needed. */
23
+ writeConfig(config: Record<string, unknown>): void;
24
+ /** Returns true if the entry name exists in the editor's mcpServers section. */
25
+ isLinked(entryName: string): boolean;
26
+ /** Add or replace an mcpServers entry under entryName. Returns prior value if any. */
27
+ link(entryName: string, entry: McpServerEntry): McpServerEntry | null;
28
+ /** Remove an mcpServers entry. Returns true if removed. */
29
+ unlink(entryName: string): boolean;
30
+ /** Build a status snapshot for diagnostics. */
31
+ status(entryName: string): EditorStatus;
32
+ }
33
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/cli/editors/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,wDAAwD;IACxD,aAAa,IAAI,MAAM,CAAC;IACxB,0DAA0D;IAC1D,MAAM,IAAI,OAAO,CAAC;IAClB,4EAA4E;IAC5E,UAAU,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,0EAA0E;IAC1E,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACnD,gFAAgF;IAChF,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACrC,sFAAsF;IACtF,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,cAAc,GAAG,cAAc,GAAG,IAAI,CAAC;IACtE,2DAA2D;IAC3D,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,+CAA+C;IAC/C,MAAM,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY,CAAC;CACzC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/cli/editors/types.ts"],"names":[],"mappings":""}
package/dist/cli/index.js CHANGED
@@ -11,6 +11,9 @@ import { loginCommand, logoutCommand, whoamiCommand } from './commands/auth.js';
11
11
  import { syncCommand } from './commands/sync.js';
12
12
  import { contextAddCommand, contextListCommand, contextSearchCommand, contextRemoveCommand } from './commands/context.js';
13
13
  import { adminInitCommand, adminStatsCommand, adminUsersCommand, adminInviteCommand, adminLimitsCommand, adminPermissionsCommand } from './commands/admin.js';
14
+ import { mcpCommand } from './commands/mcp.js';
15
+ import { linkCommand, unlinkCommand } from './commands/link.js';
16
+ import { doctorCommand } from './commands/doctor.js';
14
17
  import { VERSION } from '../constants.js';
15
18
  const program = new Command()
16
19
  .name('opalserve')
@@ -34,6 +37,7 @@ program
34
37
  .option('-p, --port <port>', 'HTTP API port')
35
38
  .option('-h, --host <host>', 'HTTP API host')
36
39
  .option('-c, --config <path>', 'Config file path')
40
+ .option('--no-browser', 'Do not open the dashboard in the default browser')
37
41
  .action(startCommand);
38
42
  // --- Status ---
39
43
  program
@@ -152,6 +156,28 @@ program
152
156
  .description('Health check all servers')
153
157
  .option('-s, --server <name>', 'Check specific server')
154
158
  .action(healthCommand);
159
+ // --- Doctor ---
160
+ program
161
+ .command('doctor')
162
+ .description('Diagnose configuration, port, server, and editor link state')
163
+ .action(doctorCommand);
164
+ // --- MCP stdio entry-point (used by AI editors via `opalserve link`) ---
165
+ program
166
+ .command('mcp')
167
+ .description('Run as a stdio MCP server (used by linked AI editors)')
168
+ .action(mcpCommand);
169
+ // --- Link / Unlink ---
170
+ program
171
+ .command('link [editor]')
172
+ .description('Wire OpalServe into an AI editor (claude, cursor, cline)')
173
+ .option('--all', 'Link every detected editor')
174
+ .option('--status', 'Show editor link status without making changes')
175
+ .action(linkCommand);
176
+ program
177
+ .command('unlink [editor]')
178
+ .description('Remove OpalServe from an AI editor')
179
+ .option('--all', 'Unlink from every editor where present')
180
+ .action(unlinkCommand);
155
181
  // Show banner on bare `opalserve` with no args
156
182
  if (process.argv.length <= 2) {
157
183
  showBanner();
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- export declare const VERSION = "3.1.1";
1
+ export declare const VERSION = "3.2.0";
2
2
  export declare const APP_NAME = "opalserve";
3
3
  export declare const DEFAULT_PORT = 3456;
4
4
  export declare const DEFAULT_HOST = "127.0.0.1";
package/dist/constants.js CHANGED
@@ -1,4 +1,4 @@
1
- export const VERSION = '3.1.1';
1
+ export const VERSION = '3.2.0';
2
2
  export const APP_NAME = 'opalserve';
3
3
  export const DEFAULT_PORT = 3456;
4
4
  export const DEFAULT_HOST = '127.0.0.1';
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Open a URL in the user's default browser. Returns true if a child was
3
+ * spawned, false if we deliberately skipped (CI, non-interactive, opt-out).
4
+ * Failures are swallowed — opening a browser is best-effort UX, not critical.
5
+ */
6
+ export declare function openInBrowser(url: string): boolean;
7
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAmBlD"}
@@ -0,0 +1,34 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { platform } from 'node:os';
3
+ /**
4
+ * Open a URL in the user's default browser. Returns true if a child was
5
+ * spawned, false if we deliberately skipped (CI, non-interactive, opt-out).
6
+ * Failures are swallowed — opening a browser is best-effort UX, not critical.
7
+ */
8
+ export function openInBrowser(url) {
9
+ if (process.env.OPALSERVE_NO_BROWSER === '1')
10
+ return false;
11
+ if (process.env.CI)
12
+ return false;
13
+ if (process.env.NODE_ENV === 'test')
14
+ return false;
15
+ if (!process.stdout.isTTY)
16
+ return false;
17
+ try {
18
+ const plat = platform();
19
+ if (plat === 'darwin') {
20
+ spawn('open', [url], { detached: true, stdio: 'ignore' }).unref();
21
+ }
22
+ else if (plat === 'win32') {
23
+ spawn('cmd', ['/c', 'start', '""', url], { detached: true, stdio: 'ignore' }).unref();
24
+ }
25
+ else {
26
+ spawn('xdg-open', [url], { detached: true, stdio: 'ignore' }).unref();
27
+ }
28
+ return true;
29
+ }
30
+ catch {
31
+ return false;
32
+ }
33
+ }
34
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/utils/browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,GAAG;QAAE,OAAO,KAAK,CAAC;IAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IACjC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IAClD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAExC,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACpE,CAAC;aAAM,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YAC5B,KAAK,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACxF,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;QACxE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opalserve",
3
- "version": "3.1.1",
3
+ "version": "3.2.0",
4
4
  "description": "The control plane for your team's AI tools — share MCP servers, knowledge bases, and usage analytics across your engineering team",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",