@darkiceinteractive/mcp-conductor 3.0.0-beta.2 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -286
- package/dist/bin/cli.d.ts +2 -2
- package/dist/bin/cli.js +37 -14
- package/dist/bin/cli.js.map +1 -1
- package/dist/bridge/http-server.d.ts.map +1 -1
- package/dist/bridge/http-server.js +11 -5
- package/dist/bridge/http-server.js.map +1 -1
- package/dist/cache/disk.d.ts.map +1 -1
- package/dist/cache/disk.js +36 -3
- package/dist/cache/disk.js.map +1 -1
- package/dist/cli/clients/adapter.d.ts +103 -0
- package/dist/cli/clients/adapter.d.ts.map +1 -0
- package/dist/cli/clients/adapter.js +24 -0
- package/dist/cli/clients/adapter.js.map +1 -0
- package/dist/cli/clients/claude-code.d.ts +15 -0
- package/dist/cli/clients/claude-code.d.ts.map +1 -0
- package/dist/cli/clients/claude-code.js +110 -0
- package/dist/cli/clients/claude-code.js.map +1 -0
- package/dist/cli/clients/claude-desktop.d.ts +26 -0
- package/dist/cli/clients/claude-desktop.d.ts.map +1 -0
- package/dist/cli/clients/claude-desktop.js +118 -0
- package/dist/cli/clients/claude-desktop.js.map +1 -0
- package/dist/cli/clients/cline.d.ts +40 -0
- package/dist/cli/clients/cline.d.ts.map +1 -0
- package/dist/cli/clients/cline.js +134 -0
- package/dist/cli/clients/cline.js.map +1 -0
- package/dist/cli/clients/codex.d.ts +30 -0
- package/dist/cli/clients/codex.d.ts.map +1 -0
- package/dist/cli/clients/codex.js +176 -0
- package/dist/cli/clients/codex.js.map +1 -0
- package/dist/cli/clients/continue.d.ts +41 -0
- package/dist/cli/clients/continue.d.ts.map +1 -0
- package/dist/cli/clients/continue.js +150 -0
- package/dist/cli/clients/continue.js.map +1 -0
- package/dist/cli/clients/cursor.d.ts +20 -0
- package/dist/cli/clients/cursor.d.ts.map +1 -0
- package/dist/cli/clients/cursor.js +110 -0
- package/dist/cli/clients/cursor.js.map +1 -0
- package/dist/cli/clients/gemini-cli.d.ts +42 -0
- package/dist/cli/clients/gemini-cli.d.ts.map +1 -0
- package/dist/cli/clients/gemini-cli.js +169 -0
- package/dist/cli/clients/gemini-cli.js.map +1 -0
- package/dist/cli/clients/index.d.ts +28 -0
- package/dist/cli/clients/index.d.ts.map +1 -0
- package/dist/cli/clients/index.js +44 -0
- package/dist/cli/clients/index.js.map +1 -0
- package/dist/cli/clients/kimi-code.d.ts +33 -0
- package/dist/cli/clients/kimi-code.d.ts.map +1 -0
- package/dist/cli/clients/kimi-code.js +177 -0
- package/dist/cli/clients/kimi-code.js.map +1 -0
- package/dist/cli/clients/opencode.d.ts +21 -0
- package/dist/cli/clients/opencode.d.ts.map +1 -0
- package/dist/cli/clients/opencode.js +150 -0
- package/dist/cli/clients/opencode.js.map +1 -0
- package/dist/cli/clients/registry.d.ts +51 -0
- package/dist/cli/clients/registry.d.ts.map +1 -0
- package/dist/cli/clients/registry.js +169 -0
- package/dist/cli/clients/registry.js.map +1 -0
- package/dist/cli/clients/zed.d.ts +41 -0
- package/dist/cli/clients/zed.d.ts.map +1 -0
- package/dist/cli/clients/zed.js +171 -0
- package/dist/cli/clients/zed.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +27 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -1
- package/dist/cli/commands/doctor.js +71 -0
- package/dist/cli/commands/doctor.js.map +1 -1
- package/dist/cli/commands/export-servers.d.ts +60 -0
- package/dist/cli/commands/export-servers.d.ts.map +1 -1
- package/dist/cli/commands/export-servers.js +85 -1
- package/dist/cli/commands/export-servers.js.map +1 -1
- package/dist/cli/commands/import-servers.d.ts +13 -2
- package/dist/cli/commands/import-servers.d.ts.map +1 -1
- package/dist/cli/commands/import-servers.js +42 -5
- package/dist/cli/commands/import-servers.js.map +1 -1
- package/dist/cli/wizard/setup.d.ts +29 -3
- package/dist/cli/wizard/setup.d.ts.map +1 -1
- package/dist/cli/wizard/setup.js +204 -7
- package/dist/cli/wizard/setup.js.map +1 -1
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +1 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/loader.d.ts +10 -1
- package/dist/config/loader.d.ts.map +1 -1
- package/dist/config/loader.js +14 -24
- package/dist/config/loader.js.map +1 -1
- package/dist/config/schema.d.ts +7 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/daemon/client.d.ts.map +1 -1
- package/dist/daemon/client.js +14 -6
- package/dist/daemon/client.js.map +1 -1
- package/dist/daemon/server.d.ts +9 -0
- package/dist/daemon/server.d.ts.map +1 -1
- package/dist/daemon/server.js +80 -9
- package/dist/daemon/server.js.map +1 -1
- package/dist/metrics/index.d.ts +1 -1
- package/dist/metrics/index.d.ts.map +1 -1
- package/dist/metrics/index.js +1 -1
- package/dist/metrics/index.js.map +1 -1
- package/dist/metrics/metrics-collector.d.ts +120 -0
- package/dist/metrics/metrics-collector.d.ts.map +1 -1
- package/dist/metrics/metrics-collector.js +136 -0
- package/dist/metrics/metrics-collector.js.map +1 -1
- package/dist/runtime/pool/recycle.d.ts +8 -2
- package/dist/runtime/pool/recycle.d.ts.map +1 -1
- package/dist/runtime/pool/recycle.js.map +1 -1
- package/dist/runtime/pool/worker-pool.d.ts.map +1 -1
- package/dist/runtime/pool/worker-pool.js +17 -10
- package/dist/runtime/pool/worker-pool.js.map +1 -1
- package/dist/runtime/pool/worker.d.ts +7 -1
- package/dist/runtime/pool/worker.d.ts.map +1 -1
- package/dist/runtime/pool/worker.js +9 -1
- package/dist/runtime/pool/worker.js.map +1 -1
- package/dist/server/mcp-server.d.ts +15 -3
- package/dist/server/mcp-server.d.ts.map +1 -1
- package/dist/server/mcp-server.js +81 -7
- package/dist/server/mcp-server.js.map +1 -1
- package/dist/utils/backup.d.ts +24 -0
- package/dist/utils/backup.d.ts.map +1 -0
- package/dist/utils/backup.js +40 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/tokenize.d.ts +8 -0
- package/dist/utils/tokenize.d.ts.map +1 -1
- package/dist/utils/tokenize.js +8 -0
- package/dist/utils/tokenize.js.map +1 -1
- package/dist/version.d.ts +3 -3
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +3 -3
- package/dist/version.js.map +1 -1
- package/package.json +23 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cli/clients/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAaxD,gFAAgF;AAChF,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAExC,8EAA8E;AAC9E,wBAAwB;AACxB,8EAA8E;AAC9E,uEAAuE;AACvE,yEAAyE;AACzE,wEAAwE;AACxE,8BAA8B;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,kBAAkB,CAAC;AAC1B,OAAO,qBAAqB,CAAC;AAC7B,OAAO,YAAY,CAAC;AACpB,OAAO,aAAa,CAAC;AACrB,OAAO,iBAAiB,CAAC;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAEnD,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;AACjC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAC3C,QAAQ,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;AACrC,QAAQ,CAAC,GAAG,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAC3C,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPClientAdapter for Kimi Code (Moonshot AI).
|
|
3
|
+
*
|
|
4
|
+
* Kimi Code stores MCP server definitions in a JSON file whose location varies
|
|
5
|
+
* by platform (see registry.ts). The config uses the Anthropic-compatible
|
|
6
|
+
* `mcpServers` shape, so entries are either stdio (`{command, args, env}`) or
|
|
7
|
+
* HTTP (`{url, headers}`).
|
|
8
|
+
*
|
|
9
|
+
* HTTP entries cannot be proxied through conductor's stdio process. They are
|
|
10
|
+
* skipped during normalisation and flagged with a logged warning so the caller
|
|
11
|
+
* can surface actionable guidance to the user.
|
|
12
|
+
*
|
|
13
|
+
* The CLI also accepts `--mcp-config-file <path>` so users may point it at an
|
|
14
|
+
* arbitrary Anthropic-format config (e.g. a symlink to a Claude config). This
|
|
15
|
+
* adapter works with any path that carries an `mcpServers` top-level key.
|
|
16
|
+
*
|
|
17
|
+
* 4-fact preamble:
|
|
18
|
+
* 1. Config format: JSON with top-level `mcpServers` key.
|
|
19
|
+
* 2. Stdio shape: `{ command, args?, env? }` — Anthropic-compatible.
|
|
20
|
+
* 3. HTTP shape: `{ url, headers? }` — skipped with warning; carried in `raw`.
|
|
21
|
+
* 4. Backup: `.bak.YYYYMMDDHHMMSS` written before every serialize() call.
|
|
22
|
+
*
|
|
23
|
+
* @module cli/clients/kimi-code
|
|
24
|
+
*/
|
|
25
|
+
import type { MCPClientAdapter } from './adapter.js';
|
|
26
|
+
/**
|
|
27
|
+
* MCPClientAdapter for Kimi Code.
|
|
28
|
+
*
|
|
29
|
+
* Exported as a named constant (singleton object literal) — stateless, so no
|
|
30
|
+
* class instance overhead is needed.
|
|
31
|
+
*/
|
|
32
|
+
export declare const KIMI_CODE_ADAPTER: MCPClientAdapter;
|
|
33
|
+
//# sourceMappingURL=kimi-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kimi-code.d.ts","sourceRoot":"","sources":["../../../src/cli/clients/kimi-code.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAIjB,MAAM,cAAc,CAAC;AA2DtB;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAkH/B,CAAC"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPClientAdapter for Kimi Code (Moonshot AI).
|
|
3
|
+
*
|
|
4
|
+
* Kimi Code stores MCP server definitions in a JSON file whose location varies
|
|
5
|
+
* by platform (see registry.ts). The config uses the Anthropic-compatible
|
|
6
|
+
* `mcpServers` shape, so entries are either stdio (`{command, args, env}`) or
|
|
7
|
+
* HTTP (`{url, headers}`).
|
|
8
|
+
*
|
|
9
|
+
* HTTP entries cannot be proxied through conductor's stdio process. They are
|
|
10
|
+
* skipped during normalisation and flagged with a logged warning so the caller
|
|
11
|
+
* can surface actionable guidance to the user.
|
|
12
|
+
*
|
|
13
|
+
* The CLI also accepts `--mcp-config-file <path>` so users may point it at an
|
|
14
|
+
* arbitrary Anthropic-format config (e.g. a symlink to a Claude config). This
|
|
15
|
+
* adapter works with any path that carries an `mcpServers` top-level key.
|
|
16
|
+
*
|
|
17
|
+
* 4-fact preamble:
|
|
18
|
+
* 1. Config format: JSON with top-level `mcpServers` key.
|
|
19
|
+
* 2. Stdio shape: `{ command, args?, env? }` — Anthropic-compatible.
|
|
20
|
+
* 3. HTTP shape: `{ url, headers? }` — skipped with warning; carried in `raw`.
|
|
21
|
+
* 4. Backup: `.bak.YYYYMMDDHHMMSS` written before every serialize() call.
|
|
22
|
+
*
|
|
23
|
+
* @module cli/clients/kimi-code
|
|
24
|
+
*/
|
|
25
|
+
import { existsSync, readFileSync, writeFileSync, copyFileSync } from 'node:fs';
|
|
26
|
+
import { logger } from '../../utils/logger.js';
|
|
27
|
+
// ---------------------------------------------------------------------------
|
|
28
|
+
// Type guards
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
function isHttpEntry(entry) {
|
|
31
|
+
return typeof entry.url === 'string';
|
|
32
|
+
}
|
|
33
|
+
function isStdioEntry(entry) {
|
|
34
|
+
return typeof entry.command === 'string';
|
|
35
|
+
}
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// Backup helper (mirrors writeBackup in import-servers.ts)
|
|
38
|
+
//
|
|
39
|
+
// Writes a `.bak.YYYYMMDDHHMMSS` file next to the original. A random 4-char
|
|
40
|
+
// hex suffix guards against sub-second collisions on repeat calls.
|
|
41
|
+
// ---------------------------------------------------------------------------
|
|
42
|
+
function writeBackup(filePath) {
|
|
43
|
+
const ts = new Date().toISOString().replace(/\D/g, '').slice(0, 14);
|
|
44
|
+
let backupPath = `${filePath}.bak.${ts}`;
|
|
45
|
+
if (existsSync(backupPath)) {
|
|
46
|
+
const salt = Math.floor(Math.random() * 0xffff).toString(16).padStart(4, '0');
|
|
47
|
+
backupPath = `${backupPath}.${salt}`;
|
|
48
|
+
}
|
|
49
|
+
copyFileSync(filePath, backupPath);
|
|
50
|
+
return backupPath;
|
|
51
|
+
}
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Adapter implementation
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
/**
|
|
56
|
+
* MCPClientAdapter for Kimi Code.
|
|
57
|
+
*
|
|
58
|
+
* Exported as a named constant (singleton object literal) — stateless, so no
|
|
59
|
+
* class instance overhead is needed.
|
|
60
|
+
*/
|
|
61
|
+
export const KIMI_CODE_ADAPTER = {
|
|
62
|
+
client: 'kimi-code',
|
|
63
|
+
/**
|
|
64
|
+
* Parse the Kimi Code config at `path`.
|
|
65
|
+
*
|
|
66
|
+
* - Returns `null` when the file does not exist, cannot be read, or contains
|
|
67
|
+
* no `mcpServers` key.
|
|
68
|
+
* - HTTP entries are warned about and excluded from `servers` but their raw
|
|
69
|
+
* data remains accessible via `config.raw` for diagnostics.
|
|
70
|
+
*/
|
|
71
|
+
parse(path) {
|
|
72
|
+
if (!existsSync(path)) {
|
|
73
|
+
logger.debug('kimi-code: config file not found', { path });
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
let raw;
|
|
77
|
+
try {
|
|
78
|
+
const text = readFileSync(path, 'utf-8');
|
|
79
|
+
raw = JSON.parse(text);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
logger.warn('kimi-code: failed to parse config file', {
|
|
83
|
+
path,
|
|
84
|
+
error: err instanceof Error ? err.message : String(err),
|
|
85
|
+
});
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
if (!raw.mcpServers || Object.keys(raw.mcpServers).length === 0) {
|
|
89
|
+
logger.debug('kimi-code: config contains no mcpServers', { path });
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const servers = {};
|
|
93
|
+
for (const [name, entry] of Object.entries(raw.mcpServers)) {
|
|
94
|
+
if (isHttpEntry(entry)) {
|
|
95
|
+
// HTTP entries cannot be proxied via conductor's stdio transport.
|
|
96
|
+
logger.warn('kimi-code: skipping HTTP entry — conductor cannot proxy HTTP MCP servers via stdio; ' +
|
|
97
|
+
'remove or migrate this entry to a stdio server', { server: name, url: entry.url });
|
|
98
|
+
// Entry stays in `raw` so serialize() preserves it for the user.
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (isStdioEntry(entry)) {
|
|
102
|
+
servers[name] = {
|
|
103
|
+
command: entry.command,
|
|
104
|
+
args: entry.args ?? [],
|
|
105
|
+
env: entry.env ?? {},
|
|
106
|
+
};
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
// Unknown shape — skip silently with a debug note.
|
|
110
|
+
logger.debug('kimi-code: unrecognised server entry shape, skipping', { server: name });
|
|
111
|
+
}
|
|
112
|
+
return { servers, raw };
|
|
113
|
+
},
|
|
114
|
+
/**
|
|
115
|
+
* Write the (possibly modified) config back to disk.
|
|
116
|
+
*
|
|
117
|
+
* Algorithm:
|
|
118
|
+
* 1. Write a `.bak.YYYYMMDDHHMMSS` backup if the file currently exists.
|
|
119
|
+
* 2. Start from `config.raw` to preserve all non-MCP top-level keys.
|
|
120
|
+
* 3. If `keepOnlyConductor` is set, replace `mcpServers` with only the
|
|
121
|
+
* conductor entry — all other server entries (including HTTP ones) are
|
|
122
|
+
* dropped.
|
|
123
|
+
* 4. Otherwise merge the normalised servers back in. HTTP entries that were
|
|
124
|
+
* in the original raw remain intact because they live in `raw.mcpServers`
|
|
125
|
+
* and are not deleted during normalisation.
|
|
126
|
+
* 5. Upsert `options.conductorEntry` under the `"mcp-conductor"` key.
|
|
127
|
+
*/
|
|
128
|
+
serialize(path, config, options) {
|
|
129
|
+
// Step 1: backup existing file before any mutation.
|
|
130
|
+
if (existsSync(path)) {
|
|
131
|
+
const backupPath = writeBackup(path);
|
|
132
|
+
logger.debug('kimi-code: backup written', { backup: backupPath });
|
|
133
|
+
}
|
|
134
|
+
// Step 2: clone raw to avoid mutating the caller's object.
|
|
135
|
+
const output = { ...config.raw };
|
|
136
|
+
if (options.keepOnlyConductor) {
|
|
137
|
+
// Step 3: replace mcpServers entirely — only the conductor entry survives.
|
|
138
|
+
output['mcpServers'] = {
|
|
139
|
+
'mcp-conductor': buildStdioEntry(options.conductorEntry),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
// Step 4: merge normalised servers into the existing raw mcpServers map.
|
|
144
|
+
// Raw already contains HTTP entries; we overwrite/add stdio entries from
|
|
145
|
+
// config.servers and then upsert the conductor entry.
|
|
146
|
+
const merged = {
|
|
147
|
+
...(config.raw.mcpServers ?? {}),
|
|
148
|
+
};
|
|
149
|
+
for (const [name, entry] of Object.entries(config.servers)) {
|
|
150
|
+
merged[name] = buildStdioEntry(entry);
|
|
151
|
+
}
|
|
152
|
+
// Step 5: upsert conductor entry.
|
|
153
|
+
merged['mcp-conductor'] = buildStdioEntry(options.conductorEntry);
|
|
154
|
+
output['mcpServers'] = merged;
|
|
155
|
+
}
|
|
156
|
+
writeFileSync(path, JSON.stringify(output, null, 2), 'utf-8');
|
|
157
|
+
logger.debug('kimi-code: config written', { path });
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
// ---------------------------------------------------------------------------
|
|
161
|
+
// Private helpers
|
|
162
|
+
// ---------------------------------------------------------------------------
|
|
163
|
+
/**
|
|
164
|
+
* Build a KimiStdioEntry from a NormalisedServerEntry, omitting optional
|
|
165
|
+
* fields when they are empty so the written JSON stays clean.
|
|
166
|
+
*/
|
|
167
|
+
function buildStdioEntry(entry) {
|
|
168
|
+
const result = { command: entry.command };
|
|
169
|
+
if (entry.args !== undefined && entry.args.length > 0) {
|
|
170
|
+
result.args = entry.args;
|
|
171
|
+
}
|
|
172
|
+
if (entry.env !== undefined && Object.keys(entry.env).length > 0) {
|
|
173
|
+
result.env = entry.env;
|
|
174
|
+
}
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=kimi-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kimi-code.js","sourceRoot":"","sources":["../../../src/cli/clients/kimi-code.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPClientAdapter implementation for OpenCode.
|
|
3
|
+
*
|
|
4
|
+
* Key divergences from the Claude-family adapters:
|
|
5
|
+
*
|
|
6
|
+
* 1. MCP key is `mcp` (NOT `mcpServers`).
|
|
7
|
+
* 2. Every server entry carries a required `type` field — either `"local"` or
|
|
8
|
+
* `"remote"`. Remote entries are not importable (skipped with a warning).
|
|
9
|
+
* 3. An optional `enabled` boolean may be present; disabled entries are still
|
|
10
|
+
* importable but the flag is preserved in `raw` so round-trip writes retain it.
|
|
11
|
+
*
|
|
12
|
+
* Config file locations (verified against OpenCode v0.1.x):
|
|
13
|
+
* - Global (macOS / Linux): `~/.config/opencode/opencode.json`
|
|
14
|
+
* - Global (Windows): `%APPDATA%\opencode\opencode.json`
|
|
15
|
+
* - Project-local: `./opencode.json`
|
|
16
|
+
*
|
|
17
|
+
* @module cli/clients/opencode
|
|
18
|
+
*/
|
|
19
|
+
import type { MCPClientAdapter } from './adapter.js';
|
|
20
|
+
export declare const OPENCODE_ADAPTER: MCPClientAdapter;
|
|
21
|
+
//# sourceMappingURL=opencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/cli/clients/opencode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAIjB,MAAM,cAAc,CAAC;AAmDtB,eAAO,MAAM,gBAAgB,EAAE,gBA4H9B,CAAC"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCPClientAdapter implementation for OpenCode.
|
|
3
|
+
*
|
|
4
|
+
* Key divergences from the Claude-family adapters:
|
|
5
|
+
*
|
|
6
|
+
* 1. MCP key is `mcp` (NOT `mcpServers`).
|
|
7
|
+
* 2. Every server entry carries a required `type` field — either `"local"` or
|
|
8
|
+
* `"remote"`. Remote entries are not importable (skipped with a warning).
|
|
9
|
+
* 3. An optional `enabled` boolean may be present; disabled entries are still
|
|
10
|
+
* importable but the flag is preserved in `raw` so round-trip writes retain it.
|
|
11
|
+
*
|
|
12
|
+
* Config file locations (verified against OpenCode v0.1.x):
|
|
13
|
+
* - Global (macOS / Linux): `~/.config/opencode/opencode.json`
|
|
14
|
+
* - Global (Windows): `%APPDATA%\opencode\opencode.json`
|
|
15
|
+
* - Project-local: `./opencode.json`
|
|
16
|
+
*
|
|
17
|
+
* @module cli/clients/opencode
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, readFileSync, writeFileSync, copyFileSync } from 'node:fs';
|
|
20
|
+
import { safeJsonParse } from '../../utils/index.js';
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
// Backup helper (mirrors writeBackup pattern from import-servers.ts)
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
/**
|
|
25
|
+
* Write a `.bak.YYYYMMDDHHMMSS` backup alongside `filePath`.
|
|
26
|
+
* A random 4-char hex suffix is appended on sub-second collision.
|
|
27
|
+
*/
|
|
28
|
+
function writeBackup(filePath) {
|
|
29
|
+
const ts = new Date().toISOString().replace(/\D/g, '').slice(0, 14);
|
|
30
|
+
let backupPath = `${filePath}.bak.${ts}`;
|
|
31
|
+
if (existsSync(backupPath)) {
|
|
32
|
+
const salt = Math.floor(Math.random() * 0xffff).toString(16).padStart(4, '0');
|
|
33
|
+
backupPath = `${backupPath}.${salt}`;
|
|
34
|
+
}
|
|
35
|
+
copyFileSync(filePath, backupPath);
|
|
36
|
+
return backupPath;
|
|
37
|
+
}
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Adapter implementation
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
export const OPENCODE_ADAPTER = {
|
|
42
|
+
client: 'opencode',
|
|
43
|
+
/**
|
|
44
|
+
* Parse an OpenCode config file into the normalised shape.
|
|
45
|
+
*
|
|
46
|
+
* - Iterates `mcp.*` (note: key is `mcp`, not `mcpServers`).
|
|
47
|
+
* - Skips `type: "remote"` entries with a console.warn (not importable).
|
|
48
|
+
* - `type: "local"` entries are normalised to `{command, args, env}`.
|
|
49
|
+
* - `enabled: false` is preserved in the underlying `raw` object so
|
|
50
|
+
* serialize() can round-trip it faithfully without touching NormalisedServerEntry.
|
|
51
|
+
*/
|
|
52
|
+
parse(path) {
|
|
53
|
+
if (!existsSync(path))
|
|
54
|
+
return null;
|
|
55
|
+
let content;
|
|
56
|
+
try {
|
|
57
|
+
content = readFileSync(path, 'utf-8');
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const raw = safeJsonParse(content, {});
|
|
63
|
+
const mcpMap = raw.mcp;
|
|
64
|
+
if (!mcpMap || typeof mcpMap !== 'object') {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const servers = {};
|
|
68
|
+
let localCount = 0;
|
|
69
|
+
for (const [name, entry] of Object.entries(mcpMap)) {
|
|
70
|
+
if (entry.type === 'remote') {
|
|
71
|
+
console.warn(`[opencode adapter] Skipping "${name}": type "remote" entries cannot be imported (only "local" is supported).`);
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (entry.type === 'local') {
|
|
75
|
+
localCount++;
|
|
76
|
+
servers[name] = {
|
|
77
|
+
command: entry.command,
|
|
78
|
+
...(entry.args !== undefined ? { args: entry.args } : {}),
|
|
79
|
+
...(entry.env !== undefined ? { env: entry.env } : {}),
|
|
80
|
+
};
|
|
81
|
+
// enabled flag stays in raw — not copied into NormalisedServerEntry to
|
|
82
|
+
// avoid changing the shared interface. serialize() reads it back from raw.
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Return null when there were no local entries at all (nothing importable).
|
|
86
|
+
if (localCount === 0) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return { servers, raw };
|
|
90
|
+
},
|
|
91
|
+
/**
|
|
92
|
+
* Write a (potentially modified) OpenCode config back to disk.
|
|
93
|
+
*
|
|
94
|
+
* Rules:
|
|
95
|
+
* 1. Always injects `type: "local"` on every serialised entry.
|
|
96
|
+
* 2. Ensures `mcp-conductor` is present with `conductorEntry`.
|
|
97
|
+
* 3. If `keepOnlyConductor` is true, replaces `mcp` with a single entry.
|
|
98
|
+
* 4. Preserves all other top-level OpenCode keys from `config.raw`.
|
|
99
|
+
* 5. Preserves `enabled: false` from the original raw entry on round-trip.
|
|
100
|
+
* 6. Writes a `.bak.YYYYMMDDHHMMSS` backup before overwriting.
|
|
101
|
+
*/
|
|
102
|
+
serialize(path, config, options) {
|
|
103
|
+
// Write backup first if file already exists.
|
|
104
|
+
if (existsSync(path)) {
|
|
105
|
+
writeBackup(path);
|
|
106
|
+
}
|
|
107
|
+
const existingRaw = config.raw ?? {};
|
|
108
|
+
// Build the mcp map to write.
|
|
109
|
+
let mcpToWrite;
|
|
110
|
+
if (options.keepOnlyConductor) {
|
|
111
|
+
mcpToWrite = {
|
|
112
|
+
'mcp-conductor': {
|
|
113
|
+
type: 'local',
|
|
114
|
+
command: options.conductorEntry.command,
|
|
115
|
+
...(options.conductorEntry.args !== undefined ? { args: options.conductorEntry.args } : {}),
|
|
116
|
+
...(options.conductorEntry.env !== undefined ? { env: options.conductorEntry.env } : {}),
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
mcpToWrite = {};
|
|
122
|
+
// Carry through existing normalised servers, injecting type: "local".
|
|
123
|
+
for (const [name, entry] of Object.entries(config.servers)) {
|
|
124
|
+
// Retrieve the enabled flag from raw if present so it survives round-trip.
|
|
125
|
+
const rawEntry = existingRaw.mcp?.[name];
|
|
126
|
+
mcpToWrite[name] = {
|
|
127
|
+
type: 'local',
|
|
128
|
+
command: entry.command,
|
|
129
|
+
...(entry.args !== undefined ? { args: entry.args } : {}),
|
|
130
|
+
...(entry.env !== undefined ? { env: entry.env } : {}),
|
|
131
|
+
...(rawEntry?.enabled === false ? { enabled: false } : {}),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// Ensure conductor entry is present / updated.
|
|
135
|
+
mcpToWrite['mcp-conductor'] = {
|
|
136
|
+
type: 'local',
|
|
137
|
+
command: options.conductorEntry.command,
|
|
138
|
+
...(options.conductorEntry.args !== undefined ? { args: options.conductorEntry.args } : {}),
|
|
139
|
+
...(options.conductorEntry.env !== undefined ? { env: options.conductorEntry.env } : {}),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// Merge into a copy of raw, preserving all non-mcp top-level keys.
|
|
143
|
+
const output = {
|
|
144
|
+
...existingRaw,
|
|
145
|
+
mcp: mcpToWrite,
|
|
146
|
+
};
|
|
147
|
+
writeFileSync(path, JSON.stringify(output, null, 2), 'utf-8');
|
|
148
|
+
},
|
|
149
|
+
};
|
|
150
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/cli/clients/opencode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-client MCP configuration discovery registry.
|
|
3
|
+
*
|
|
4
|
+
* Provides typed location records for every known MCP-capable client on the
|
|
5
|
+
* current machine. The list covers macOS, Linux, and Windows search paths
|
|
6
|
+
* from the v3.1.1 verified client table.
|
|
7
|
+
*
|
|
8
|
+
* @module cli/clients/registry
|
|
9
|
+
*/
|
|
10
|
+
export type MCPClientId = 'claude-code' | 'claude-desktop' | 'codex' | 'gemini-cli' | 'cursor' | 'cline' | 'zed' | 'continue' | 'opencode' | 'kimi-code';
|
|
11
|
+
export type ConfigFormat = 'json' | 'toml' | 'yaml';
|
|
12
|
+
export interface MCPClientConfigLocation {
|
|
13
|
+
/** Stable identifier for the client. */
|
|
14
|
+
client: MCPClientId;
|
|
15
|
+
/** Human-readable label shown in UI / logs. */
|
|
16
|
+
displayName: string;
|
|
17
|
+
/** Absolute path to the config file (may or may not exist). */
|
|
18
|
+
path: string;
|
|
19
|
+
/** Serialisation format of the config file. */
|
|
20
|
+
format: ConfigFormat;
|
|
21
|
+
/**
|
|
22
|
+
* Key (or key path) inside the config that holds the server map.
|
|
23
|
+
* - JSON clients: `"mcpServers"` | `"mcp"` | `"context_servers"`
|
|
24
|
+
* - TOML clients: `"[mcp_servers.*]"` (section prefix)
|
|
25
|
+
*/
|
|
26
|
+
mcpKey: string;
|
|
27
|
+
/** Whether the file exists on disk at discovery time. */
|
|
28
|
+
exists: boolean;
|
|
29
|
+
/** Whether this is a user-global config or a project-local config. */
|
|
30
|
+
scope: 'global' | 'project';
|
|
31
|
+
}
|
|
32
|
+
export interface GetMCPClientConfigPathsOptions {
|
|
33
|
+
/**
|
|
34
|
+
* When `true`, also include project-local config locations resolved from
|
|
35
|
+
* `process.cwd()`. Defaults to `false`.
|
|
36
|
+
*/
|
|
37
|
+
includeProject?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Discover every MCP client config location on this machine.
|
|
41
|
+
*
|
|
42
|
+
* Returns all known locations regardless of whether the file currently exists;
|
|
43
|
+
* callers should filter on `exists` when they only want present files.
|
|
44
|
+
*
|
|
45
|
+
* Platform coverage:
|
|
46
|
+
* - macOS (darwin)
|
|
47
|
+
* - Linux (via XDG / home-relative paths)
|
|
48
|
+
* - Windows (via APPDATA / LOCALAPPDATA)
|
|
49
|
+
*/
|
|
50
|
+
export declare function getMCPClientConfigPaths(opts?: GetMCPClientConfigPathsOptions): MCPClientConfigLocation[];
|
|
51
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/cli/clients/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,MAAM,MAAM,WAAW,GACnB,aAAa,GACb,gBAAgB,GAChB,OAAO,GACP,YAAY,GACZ,QAAQ,GACR,OAAO,GACP,KAAK,GACL,UAAU,GACV,UAAU,GACV,WAAW,CAAC;AAEhB,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,uBAAuB;IACtC,wCAAwC;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,YAAY,CAAC;IACrB;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,MAAM,EAAE,OAAO,CAAC;IAChB,sEAAsE;IACtE,KAAK,EAAE,QAAQ,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAwBD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,GAAE,8BAAmC,GACxC,uBAAuB,EAAE,CA2J3B"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-client MCP configuration discovery registry.
|
|
3
|
+
*
|
|
4
|
+
* Provides typed location records for every known MCP-capable client on the
|
|
5
|
+
* current machine. The list covers macOS, Linux, and Windows search paths
|
|
6
|
+
* from the v3.1.1 verified client table.
|
|
7
|
+
*
|
|
8
|
+
* @module cli/clients/registry
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync } from 'node:fs';
|
|
11
|
+
import { homedir } from 'node:os';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Internal helpers
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
/**
|
|
17
|
+
* Build a location record, resolving `exists` at call time.
|
|
18
|
+
*/
|
|
19
|
+
function loc(client, displayName, path, format, mcpKey, scope = 'global') {
|
|
20
|
+
return { client, displayName, path, format, mcpKey, exists: existsSync(path), scope };
|
|
21
|
+
}
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
// Discovery function
|
|
24
|
+
// ---------------------------------------------------------------------------
|
|
25
|
+
/**
|
|
26
|
+
* Discover every MCP client config location on this machine.
|
|
27
|
+
*
|
|
28
|
+
* Returns all known locations regardless of whether the file currently exists;
|
|
29
|
+
* callers should filter on `exists` when they only want present files.
|
|
30
|
+
*
|
|
31
|
+
* Platform coverage:
|
|
32
|
+
* - macOS (darwin)
|
|
33
|
+
* - Linux (via XDG / home-relative paths)
|
|
34
|
+
* - Windows (via APPDATA / LOCALAPPDATA)
|
|
35
|
+
*/
|
|
36
|
+
export function getMCPClientConfigPaths(opts = {}) {
|
|
37
|
+
const home = homedir();
|
|
38
|
+
const platform = process.platform;
|
|
39
|
+
const appData = process.env['APPDATA'] ?? '';
|
|
40
|
+
const localAppData = process.env['LOCALAPPDATA'] ?? '';
|
|
41
|
+
const isWin = platform === 'win32';
|
|
42
|
+
const isMac = platform === 'darwin';
|
|
43
|
+
const results = [];
|
|
44
|
+
// -------------------------------------------------------------------------
|
|
45
|
+
// Claude Code
|
|
46
|
+
// -------------------------------------------------------------------------
|
|
47
|
+
// macOS / Linux global
|
|
48
|
+
results.push(loc('claude-code', 'Claude Code', join(home, '.claude', 'settings.json'), 'json', 'mcpServers'));
|
|
49
|
+
results.push(loc('claude-code', 'Claude Code', join(home, '.claude.json'), 'json', 'mcpServers'));
|
|
50
|
+
// macOS application support
|
|
51
|
+
if (isMac) {
|
|
52
|
+
results.push(loc('claude-code', 'Claude Code', join(home, 'Library', 'Application Support', 'Claude Code', 'claude_code_config.json'), 'json', 'mcpServers'));
|
|
53
|
+
results.push(loc('claude-code', 'Claude Code', join(home, 'Library', 'Application Support', 'Claude', 'claude_code_config.json'), 'json', 'mcpServers'));
|
|
54
|
+
}
|
|
55
|
+
// Linux XDG
|
|
56
|
+
if (!isWin) {
|
|
57
|
+
results.push(loc('claude-code', 'Claude Code', join(home, '.config', 'Claude Code', 'claude_code_config.json'), 'json', 'mcpServers'));
|
|
58
|
+
}
|
|
59
|
+
// Windows
|
|
60
|
+
if (isWin && appData) {
|
|
61
|
+
results.push(loc('claude-code', 'Claude Code', join(appData, 'Claude Code', 'claude_code_config.json'), 'json', 'mcpServers'));
|
|
62
|
+
}
|
|
63
|
+
// -------------------------------------------------------------------------
|
|
64
|
+
// Claude Desktop
|
|
65
|
+
// -------------------------------------------------------------------------
|
|
66
|
+
if (isMac) {
|
|
67
|
+
results.push(loc('claude-desktop', 'Claude Desktop', join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'), 'json', 'mcpServers'));
|
|
68
|
+
}
|
|
69
|
+
// Linux
|
|
70
|
+
if (!isWin) {
|
|
71
|
+
results.push(loc('claude-desktop', 'Claude Desktop', join(home, '.config', 'claude', 'claude_desktop_config.json'), 'json', 'mcpServers'));
|
|
72
|
+
}
|
|
73
|
+
// Windows
|
|
74
|
+
if (isWin && appData) {
|
|
75
|
+
results.push(loc('claude-desktop', 'Claude Desktop', join(appData, 'Claude', 'claude_desktop_config.json'), 'json', 'mcpServers'));
|
|
76
|
+
}
|
|
77
|
+
// -------------------------------------------------------------------------
|
|
78
|
+
// OpenAI Codex CLI
|
|
79
|
+
// -------------------------------------------------------------------------
|
|
80
|
+
// ~/.codex/config.toml (all platforms — Codex uses TOML, not JSON)
|
|
81
|
+
results.push(loc('codex', 'Codex CLI', join(home, '.codex', 'config.toml'), 'toml', '[mcp_servers.*]'));
|
|
82
|
+
// -------------------------------------------------------------------------
|
|
83
|
+
// Gemini CLI
|
|
84
|
+
// -------------------------------------------------------------------------
|
|
85
|
+
// ~/.gemini/settings.json (all platforms)
|
|
86
|
+
results.push(loc('gemini-cli', 'Gemini CLI', join(home, '.gemini', 'settings.json'), 'json', 'mcpServers'));
|
|
87
|
+
// -------------------------------------------------------------------------
|
|
88
|
+
// Cursor
|
|
89
|
+
// -------------------------------------------------------------------------
|
|
90
|
+
if (isMac) {
|
|
91
|
+
results.push(loc('cursor', 'Cursor', join(home, 'Library', 'Application Support', 'Cursor', 'User', 'settings.json'), 'json', 'mcp'));
|
|
92
|
+
}
|
|
93
|
+
if (!isWin && !isMac) {
|
|
94
|
+
results.push(loc('cursor', 'Cursor', join(home, '.config', 'Cursor', 'User', 'settings.json'), 'json', 'mcp'));
|
|
95
|
+
}
|
|
96
|
+
if (isWin && appData) {
|
|
97
|
+
results.push(loc('cursor', 'Cursor', join(appData, 'Cursor', 'User', 'settings.json'), 'json', 'mcp'));
|
|
98
|
+
}
|
|
99
|
+
// Global cursor MCP config
|
|
100
|
+
results.push(loc('cursor', 'Cursor', join(home, '.cursor', 'mcp.json'), 'json', 'mcpServers'));
|
|
101
|
+
// -------------------------------------------------------------------------
|
|
102
|
+
// Cline (VS Code extension)
|
|
103
|
+
// -------------------------------------------------------------------------
|
|
104
|
+
// Cline stores its MCP config in the VS Code globalStorage area
|
|
105
|
+
if (isMac) {
|
|
106
|
+
results.push(loc('cline', 'Cline', join(home, 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'), 'json', 'mcpServers'));
|
|
107
|
+
}
|
|
108
|
+
if (!isWin && !isMac) {
|
|
109
|
+
results.push(loc('cline', 'Cline', join(home, '.config', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'), 'json', 'mcpServers'));
|
|
110
|
+
}
|
|
111
|
+
if (isWin && appData) {
|
|
112
|
+
results.push(loc('cline', 'Cline', join(appData, 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'), 'json', 'mcpServers'));
|
|
113
|
+
}
|
|
114
|
+
// -------------------------------------------------------------------------
|
|
115
|
+
// Zed
|
|
116
|
+
// -------------------------------------------------------------------------
|
|
117
|
+
if (isMac) {
|
|
118
|
+
results.push(loc('zed', 'Zed', join(home, 'Library', 'Application Support', 'Zed', 'settings.json'), 'json', 'context_servers'));
|
|
119
|
+
}
|
|
120
|
+
if (!isWin && !isMac) {
|
|
121
|
+
results.push(loc('zed', 'Zed', join(home, '.config', 'zed', 'settings.json'), 'json', 'context_servers'));
|
|
122
|
+
}
|
|
123
|
+
if (isWin && localAppData) {
|
|
124
|
+
results.push(loc('zed', 'Zed', join(localAppData, 'Zed', 'settings.json'), 'json', 'context_servers'));
|
|
125
|
+
}
|
|
126
|
+
// -------------------------------------------------------------------------
|
|
127
|
+
// Continue.dev (VS Code / JetBrains extension)
|
|
128
|
+
// -------------------------------------------------------------------------
|
|
129
|
+
results.push(loc('continue', 'Continue.dev', join(home, '.continue', 'config.yaml'), 'yaml', 'mcpServers'));
|
|
130
|
+
// -------------------------------------------------------------------------
|
|
131
|
+
// OpenCode (uses 'mcp' key not 'mcpServers'; file is opencode.json)
|
|
132
|
+
// -------------------------------------------------------------------------
|
|
133
|
+
results.push(loc('opencode', 'OpenCode', join(home, '.config', 'opencode', 'opencode.json'), 'json', 'mcp'));
|
|
134
|
+
if (isWin && appData) {
|
|
135
|
+
results.push(loc('opencode', 'OpenCode', join(appData, 'opencode', 'opencode.json'), 'json', 'mcp'));
|
|
136
|
+
}
|
|
137
|
+
// -------------------------------------------------------------------------
|
|
138
|
+
// Kimi Code (Moonshot AI)
|
|
139
|
+
// -------------------------------------------------------------------------
|
|
140
|
+
if (isMac) {
|
|
141
|
+
results.push(loc('kimi-code', 'Kimi Code', join(home, 'Library', 'Application Support', 'Kimi Code', 'mcp_settings.json'), 'json', 'mcpServers'));
|
|
142
|
+
}
|
|
143
|
+
if (!isWin && !isMac) {
|
|
144
|
+
results.push(loc('kimi-code', 'Kimi Code', join(home, '.config', 'kimi-code', 'mcp_settings.json'), 'json', 'mcpServers'));
|
|
145
|
+
}
|
|
146
|
+
if (isWin && appData) {
|
|
147
|
+
results.push(loc('kimi-code', 'Kimi Code', join(appData, 'Kimi Code', 'mcp_settings.json'), 'json', 'mcpServers'));
|
|
148
|
+
}
|
|
149
|
+
// -------------------------------------------------------------------------
|
|
150
|
+
// Project-local paths (opt-in)
|
|
151
|
+
// -------------------------------------------------------------------------
|
|
152
|
+
if (opts.includeProject) {
|
|
153
|
+
const cwd = process.cwd();
|
|
154
|
+
// Claude Code project-local
|
|
155
|
+
results.push(loc('claude-code', 'Claude Code', join(cwd, '.claude', 'settings.json'), 'json', 'mcpServers', 'project'));
|
|
156
|
+
results.push(loc('claude-code', 'Claude Code', join(cwd, 'claude_code_config.json'), 'json', 'mcpServers', 'project'));
|
|
157
|
+
results.push(loc('claude-code', 'Claude Code', join(cwd, '.mcp.json'), 'json', 'mcpServers', 'project'));
|
|
158
|
+
// Claude Desktop project-local
|
|
159
|
+
results.push(loc('claude-desktop', 'Claude Desktop', join(cwd, 'claude_desktop_config.json'), 'json', 'mcpServers', 'project'));
|
|
160
|
+
// Continue.dev project-local
|
|
161
|
+
results.push(loc('continue', 'Continue.dev', join(cwd, '.continue', 'config.json'), 'json', 'mcpServers', 'project'));
|
|
162
|
+
// OpenCode project-local
|
|
163
|
+
results.push(loc('opencode', 'OpenCode', join(cwd, 'opencode.json'), 'json', 'mcp', 'project'));
|
|
164
|
+
// Codex project-local
|
|
165
|
+
results.push(loc('codex', 'Codex CLI', join(cwd, '.codex', 'config.toml'), 'toml', '[mcp_servers.*]', 'project'));
|
|
166
|
+
}
|
|
167
|
+
return results;
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=registry.js.map
|