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.
- package/README.md +33 -6
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +107 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/link.d.ts +11 -0
- package/dist/cli/commands/link.d.ts.map +1 -0
- package/dist/cli/commands/link.js +135 -0
- package/dist/cli/commands/link.js.map +1 -0
- package/dist/cli/commands/mcp.d.ts +7 -0
- package/dist/cli/commands/mcp.d.ts.map +1 -0
- package/dist/cli/commands/mcp.js +46 -0
- package/dist/cli/commands/mcp.js.map +1 -0
- package/dist/cli/commands/start.d.ts +1 -0
- package/dist/cli/commands/start.d.ts.map +1 -1
- package/dist/cli/commands/start.js +13 -0
- package/dist/cli/commands/start.js.map +1 -1
- package/dist/cli/editors/base.d.ts +23 -0
- package/dist/cli/editors/base.d.ts.map +1 -0
- package/dist/cli/editors/base.js +75 -0
- package/dist/cli/editors/base.js.map +1 -0
- package/dist/cli/editors/claude.d.ts +8 -0
- package/dist/cli/editors/claude.d.ts.map +1 -0
- package/dist/cli/editors/claude.js +31 -0
- package/dist/cli/editors/claude.js.map +1 -0
- package/dist/cli/editors/cline.d.ts +14 -0
- package/dist/cli/editors/cline.d.ts.map +1 -0
- package/dist/cli/editors/cline.js +32 -0
- package/dist/cli/editors/cline.js.map +1 -0
- package/dist/cli/editors/cursor.d.ts +8 -0
- package/dist/cli/editors/cursor.d.ts.map +1 -0
- package/dist/cli/editors/cursor.js +14 -0
- package/dist/cli/editors/cursor.js.map +1 -0
- package/dist/cli/editors/index.d.ts +14 -0
- package/dist/cli/editors/index.d.ts.map +1 -0
- package/dist/cli/editors/index.js +34 -0
- package/dist/cli/editors/index.js.map +1 -0
- package/dist/cli/editors/types.d.ts +33 -0
- package/dist/cli/editors/types.d.ts.map +1 -0
- package/dist/cli/editors/types.js +2 -0
- package/dist/cli/editors/types.js.map +1 -0
- package/dist/cli/index.js +26 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/utils/browser.d.ts +7 -0
- package/dist/utils/browser.d.ts.map +1 -0
- package/dist/utils/browser.js +34 -0
- package/dist/utils/browser.js.map +1 -0
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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 @@
|
|
|
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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/start.ts"],"names":[],"mappings":"
|
|
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,
|
|
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 @@
|
|
|
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();
|
package/dist/cli/index.js.map
CHANGED
|
@@ -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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"}
|
package/dist/constants.d.ts
CHANGED
package/dist/constants.js
CHANGED
|
@@ -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