ai-agent-config 2.6.6 → 2.7.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 +8 -8
- package/package.json +1 -1
- package/scripts/installer.js +3 -3
- package/scripts/mcp-installer.js +130 -62
- package/scripts/platforms.js +9 -0
package/README.md
CHANGED
|
@@ -61,14 +61,14 @@ ai-agent update
|
|
|
61
61
|
|
|
62
62
|
## Supported Platforms
|
|
63
63
|
|
|
64
|
-
| Platform | Skills Path |
|
|
65
|
-
|
|
66
|
-
| Claude Code | `~/.claude/skills/` |
|
|
67
|
-
| Antigravity IDE | `~/.gemini/antigravity/skills/` |
|
|
68
|
-
| Cursor | `~/.cursor/skills/` |
|
|
69
|
-
| Windsurf | `~/.windsurf/skills/` |
|
|
70
|
-
| Codex CLI | `~/.codex/skills/` |
|
|
71
|
-
| GitHub Copilot | `~/.github/copilot-instructions.md` |
|
|
64
|
+
| Platform | Skills Path | MCP Support |
|
|
65
|
+
|----------|-------------|-------------|
|
|
66
|
+
| Claude Code | `~/.claude/skills/` | `claude_desktop_config.json` |
|
|
67
|
+
| Antigravity IDE | `~/.gemini/antigravity/skills/` | `mcp_config.json` |
|
|
68
|
+
| Cursor | `~/.cursor/skills/` | - |
|
|
69
|
+
| Windsurf | `~/.windsurf/skills/` | - |
|
|
70
|
+
| Codex CLI | `~/.codex/skills/` | - |
|
|
71
|
+
| GitHub Copilot | `~/.github/copilot-instructions.md` | - |
|
|
72
72
|
|
|
73
73
|
## Secret Management
|
|
74
74
|
|
package/package.json
CHANGED
package/scripts/installer.js
CHANGED
|
@@ -233,10 +233,10 @@ function installToPlatform(platform, options = {}) {
|
|
|
233
233
|
}
|
|
234
234
|
}
|
|
235
235
|
|
|
236
|
-
// Install MCP servers
|
|
237
|
-
if (platform.
|
|
236
|
+
// Install MCP servers to platforms with MCP support
|
|
237
|
+
if (platform.mcpConfigPath) {
|
|
238
238
|
try {
|
|
239
|
-
results.mcpServers = mcpInstaller.installMcpServers({ force });
|
|
239
|
+
results.mcpServers = mcpInstaller.installMcpServers({ force, platform });
|
|
240
240
|
} catch (error) {
|
|
241
241
|
console.warn(` ⚠️ MCP install failed: ${error.message}`);
|
|
242
242
|
}
|
package/scripts/mcp-installer.js
CHANGED
|
@@ -110,116 +110,141 @@ function collectBitwardenEnvs() {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
/**
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* @param {
|
|
116
|
-
* @
|
|
113
|
+
* Write MCP servers to a platform's config file
|
|
114
|
+
* @param {string} configPath - Path to platform's MCP config file
|
|
115
|
+
* @param {Array} servers - MCP server configs to install
|
|
116
|
+
* @param {Object} options - { force, platformName }
|
|
117
|
+
* @returns {{ added: number, skipped: number }}
|
|
117
118
|
*/
|
|
118
|
-
function
|
|
119
|
-
const { force = false } = options;
|
|
120
|
-
const antigravity = platforms.getByName("antigravity");
|
|
121
|
-
|
|
122
|
-
if (!antigravity || !antigravity.mcpConfigPath) {
|
|
123
|
-
return { added: 0, skipped: 0, servers: [] };
|
|
124
|
-
}
|
|
119
|
+
function writeMcpToPlatformConfig(configPath, servers, options = {}) {
|
|
120
|
+
const { force = false, platformName = "" } = options;
|
|
125
121
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Read existing mcp_config.json
|
|
132
|
-
let mcpConfig = { mcpServers: {} };
|
|
133
|
-
if (fs.existsSync(antigravity.mcpConfigPath)) {
|
|
122
|
+
// Read existing config — preserve ALL existing keys (e.g. Claude's "preferences")
|
|
123
|
+
let config = { mcpServers: {} };
|
|
124
|
+
if (fs.existsSync(configPath)) {
|
|
134
125
|
try {
|
|
135
|
-
|
|
136
|
-
if (!
|
|
126
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
127
|
+
if (!config.mcpServers) config.mcpServers = {};
|
|
137
128
|
} catch {
|
|
138
|
-
|
|
129
|
+
config = { mcpServers: {} };
|
|
139
130
|
}
|
|
140
131
|
}
|
|
141
132
|
|
|
142
133
|
let added = 0;
|
|
143
134
|
let skipped = 0;
|
|
144
|
-
const serverNames = [];
|
|
145
135
|
|
|
146
136
|
for (const server of servers) {
|
|
147
|
-
const existing =
|
|
137
|
+
const existing = config.mcpServers[server.name];
|
|
148
138
|
|
|
149
139
|
if (existing && !force) {
|
|
150
140
|
skipped++;
|
|
151
|
-
serverNames.push(server.name);
|
|
152
141
|
continue;
|
|
153
142
|
}
|
|
154
143
|
|
|
155
|
-
// Build server entry for Antigravity format
|
|
156
144
|
const entry = {
|
|
157
145
|
command: server.command,
|
|
158
146
|
args: server.args,
|
|
159
147
|
};
|
|
160
148
|
|
|
161
|
-
// Preserve existing env
|
|
149
|
+
// Preserve existing env
|
|
162
150
|
if (existing && existing.env) {
|
|
163
151
|
entry.env = existing.env;
|
|
164
152
|
}
|
|
165
153
|
|
|
166
|
-
|
|
154
|
+
// disabledTools: only add for platforms that support it (not Claude)
|
|
155
|
+
if (platformName !== "claude" && server.disabledTools && server.disabledTools.length > 0) {
|
|
167
156
|
entry.disabledTools = server.disabledTools;
|
|
168
157
|
}
|
|
169
158
|
|
|
170
|
-
|
|
159
|
+
config.mcpServers[server.name] = entry;
|
|
171
160
|
added++;
|
|
172
|
-
serverNames.push(server.name);
|
|
173
161
|
}
|
|
174
162
|
|
|
175
|
-
// Write back
|
|
163
|
+
// Write back (create directory if needed)
|
|
176
164
|
if (added > 0) {
|
|
177
|
-
const configDir = path.dirname(
|
|
165
|
+
const configDir = path.dirname(configPath);
|
|
178
166
|
if (!fs.existsSync(configDir)) {
|
|
179
167
|
fs.mkdirSync(configDir, { recursive: true });
|
|
180
168
|
}
|
|
181
|
-
fs.writeFileSync(
|
|
169
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
182
170
|
}
|
|
183
171
|
|
|
184
|
-
return { added, skipped
|
|
172
|
+
return { added, skipped };
|
|
185
173
|
}
|
|
186
174
|
|
|
187
175
|
/**
|
|
188
|
-
* Install MCP servers
|
|
189
|
-
* This is the "
|
|
190
|
-
* @param {Object}
|
|
191
|
-
* @returns {{
|
|
176
|
+
* Install MCP servers to platforms' config files
|
|
177
|
+
* This is the "pull" flow - installs structure without resolved secrets
|
|
178
|
+
* @param {Object} options - { force: boolean, platform: Object|null }
|
|
179
|
+
* @returns {{ added: number, skipped: number, servers: string[] }}
|
|
192
180
|
*/
|
|
193
|
-
function
|
|
194
|
-
const
|
|
181
|
+
function installMcpServers(options = {}) {
|
|
182
|
+
const { force = false, platform = null } = options;
|
|
195
183
|
|
|
196
|
-
|
|
197
|
-
|
|
184
|
+
const servers = getAvailableMcpServers().filter((s) => s.enabled !== false);
|
|
185
|
+
if (servers.length === 0) {
|
|
186
|
+
return { added: 0, skipped: 0, servers: [] };
|
|
198
187
|
}
|
|
199
188
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
189
|
+
// Determine target platforms
|
|
190
|
+
const targetPlatforms = [];
|
|
191
|
+
if (platform) {
|
|
192
|
+
// Single platform specified
|
|
193
|
+
if (platform.mcpConfigPath) targetPlatforms.push(platform);
|
|
194
|
+
} else {
|
|
195
|
+
// All detected platforms with MCP support
|
|
196
|
+
for (const p of platforms.detectAll()) {
|
|
197
|
+
const full = platforms.getByName(p.name);
|
|
198
|
+
if (full && full.mcpConfigPath) targetPlatforms.push(full);
|
|
199
|
+
}
|
|
203
200
|
}
|
|
204
201
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
202
|
+
if (targetPlatforms.length === 0) {
|
|
203
|
+
return { added: 0, skipped: 0, servers: [] };
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
let totalAdded = 0;
|
|
207
|
+
let totalSkipped = 0;
|
|
208
|
+
const serverNames = [...new Set(servers.map((s) => s.name))];
|
|
209
|
+
|
|
210
|
+
for (const p of targetPlatforms) {
|
|
211
|
+
const result = writeMcpToPlatformConfig(p.mcpConfigPath, servers, {
|
|
212
|
+
force,
|
|
213
|
+
platformName: p.name,
|
|
214
|
+
});
|
|
215
|
+
totalAdded += result.added;
|
|
216
|
+
totalSkipped += result.skipped;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return { added: totalAdded, skipped: totalSkipped, servers: serverNames };
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Write MCP servers with resolved secrets to a platform's config file
|
|
224
|
+
* @param {string} configPath - Path to platform's MCP config file
|
|
225
|
+
* @param {Array} servers - MCP server configs
|
|
226
|
+
* @param {Object} resolvedSecrets - Map of bitwardenItem → resolvedValue
|
|
227
|
+
* @param {string} platformName - Platform name for disabledTools handling
|
|
228
|
+
* @returns {{ installed: number, servers: Array<{ name: string, secretsCount: number }> }}
|
|
229
|
+
*/
|
|
230
|
+
function writeMcpWithSecretsToPlatformConfig(configPath, servers, resolvedSecrets, platformName) {
|
|
231
|
+
// Read existing config — preserve ALL existing keys
|
|
232
|
+
let config = { mcpServers: {} };
|
|
233
|
+
if (fs.existsSync(configPath)) {
|
|
208
234
|
try {
|
|
209
|
-
|
|
210
|
-
if (!
|
|
235
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
236
|
+
if (!config.mcpServers) config.mcpServers = {};
|
|
211
237
|
} catch {
|
|
212
|
-
|
|
238
|
+
config = { mcpServers: {} };
|
|
213
239
|
}
|
|
214
240
|
}
|
|
215
241
|
|
|
216
242
|
let installed = 0;
|
|
217
243
|
const serverResults = [];
|
|
218
244
|
|
|
219
|
-
for (const server of
|
|
220
|
-
const existing =
|
|
245
|
+
for (const server of servers) {
|
|
246
|
+
const existing = config.mcpServers[server.name] || {};
|
|
221
247
|
|
|
222
|
-
// Build entry: keep existing custom fields (disabledTools user may have customized)
|
|
223
248
|
const entry = {
|
|
224
249
|
command: server.command,
|
|
225
250
|
args: server.args,
|
|
@@ -246,29 +271,71 @@ function installMcpServersWithSecrets(resolvedSecrets) {
|
|
|
246
271
|
serverResults.push({ name: server.name, secretsCount: 0 });
|
|
247
272
|
}
|
|
248
273
|
|
|
249
|
-
//
|
|
250
|
-
if (
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
274
|
+
// disabledTools: only for platforms that support it (not Claude)
|
|
275
|
+
if (platformName !== "claude") {
|
|
276
|
+
if (existing.disabledTools) {
|
|
277
|
+
entry.disabledTools = existing.disabledTools;
|
|
278
|
+
} else if (server.disabledTools && server.disabledTools.length > 0) {
|
|
279
|
+
entry.disabledTools = server.disabledTools;
|
|
280
|
+
}
|
|
254
281
|
}
|
|
255
282
|
|
|
256
|
-
|
|
283
|
+
config.mcpServers[server.name] = entry;
|
|
257
284
|
installed++;
|
|
258
285
|
}
|
|
259
286
|
|
|
260
287
|
// Write back
|
|
261
288
|
if (installed > 0) {
|
|
262
|
-
const configDir = path.dirname(
|
|
289
|
+
const configDir = path.dirname(configPath);
|
|
263
290
|
if (!fs.existsSync(configDir)) {
|
|
264
291
|
fs.mkdirSync(configDir, { recursive: true });
|
|
265
292
|
}
|
|
266
|
-
fs.writeFileSync(
|
|
293
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
267
294
|
}
|
|
268
295
|
|
|
269
296
|
return { installed, servers: serverResults };
|
|
270
297
|
}
|
|
271
298
|
|
|
299
|
+
/**
|
|
300
|
+
* Install MCP servers with resolved secrets to all MCP-capable platforms
|
|
301
|
+
* This is the "secrets sync" flow - updates env with real values
|
|
302
|
+
* @param {Object} resolvedSecrets - Map of bitwardenItem → resolvedValue
|
|
303
|
+
* @returns {{ installed: number, servers: Array<{ name: string, secretsCount: number }> }}
|
|
304
|
+
*/
|
|
305
|
+
function installMcpServersWithSecrets(resolvedSecrets) {
|
|
306
|
+
const allServers = getAvailableMcpServers().filter((s) => s.enabled !== false);
|
|
307
|
+
if (allServers.length === 0) {
|
|
308
|
+
return { installed: 0, servers: [] };
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// All detected platforms with MCP support
|
|
312
|
+
const targetPlatforms = [];
|
|
313
|
+
for (const p of platforms.detectAll()) {
|
|
314
|
+
const full = platforms.getByName(p.name);
|
|
315
|
+
if (full && full.mcpConfigPath) targetPlatforms.push(full);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (targetPlatforms.length === 0) {
|
|
319
|
+
return { installed: 0, servers: [] };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
let totalInstalled = 0;
|
|
323
|
+
let aggregatedServers = [];
|
|
324
|
+
|
|
325
|
+
for (const p of targetPlatforms) {
|
|
326
|
+
const result = writeMcpWithSecretsToPlatformConfig(
|
|
327
|
+
p.mcpConfigPath, allServers, resolvedSecrets, p.name
|
|
328
|
+
);
|
|
329
|
+
totalInstalled += result.installed;
|
|
330
|
+
// Use server results from last platform (they're the same servers)
|
|
331
|
+
if (result.servers.length > 0) {
|
|
332
|
+
aggregatedServers = result.servers;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return { installed: totalInstalled, servers: aggregatedServers };
|
|
337
|
+
}
|
|
338
|
+
|
|
272
339
|
module.exports = {
|
|
273
340
|
getMcpServersDir,
|
|
274
341
|
validateMcpConfig,
|
|
@@ -276,5 +343,6 @@ module.exports = {
|
|
|
276
343
|
collectBitwardenEnvs,
|
|
277
344
|
installMcpServers,
|
|
278
345
|
installMcpServersWithSecrets,
|
|
346
|
+
writeMcpToPlatformConfig,
|
|
279
347
|
SKIP_FOLDERS,
|
|
280
348
|
};
|
package/scripts/platforms.js
CHANGED
|
@@ -32,6 +32,15 @@ const SUPPORTED = [
|
|
|
32
32
|
get commandsPath() {
|
|
33
33
|
return path.join(HOME, this.configDir, this.commandsDir);
|
|
34
34
|
},
|
|
35
|
+
get mcpConfigPath() {
|
|
36
|
+
if (process.platform === "darwin") {
|
|
37
|
+
return path.join(HOME, "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
38
|
+
} else if (process.platform === "win32") {
|
|
39
|
+
return path.join(process.env.APPDATA || "", "Claude", "claude_desktop_config.json");
|
|
40
|
+
} else {
|
|
41
|
+
return path.join(HOME, ".config", "Claude", "claude_desktop_config.json");
|
|
42
|
+
}
|
|
43
|
+
},
|
|
35
44
|
detect() {
|
|
36
45
|
return fs.existsSync(this.configPath);
|
|
37
46
|
},
|