Skip to content

Commit fffaed1

Browse files
committed
feat(cli): Merge new agents into existing user config
Previously, when saving a configuration with `--add` or `--wrap`, the command would fail if a `~/.mcpc/config.json` file already existed. This forced users to manually merge changes or delete their existing configuration, which was inconvenient and error-prone.
1 parent 3a219d7 commit fffaed1

File tree

2 files changed

+55
-48
lines changed

2 files changed

+55
-48
lines changed

packages/cli/deno.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@mcpc/cli",
3-
"version": "0.1.17",
3+
"version": "0.1.18",
44
"repository": {
55
"type": "git",
66
"url": "git+https://github.com/mcpc-tech/mcpc.git"

packages/cli/src/config/loader.ts

Lines changed: 54 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
*/
4646

4747
import type { ComposeDefinition } from "@mcpc/core";
48-
import { access, mkdir, readFile, writeFile } from "node:fs/promises";
48+
import { mkdir, readFile, writeFile } from "node:fs/promises";
4949
import { homedir } from "node:os";
5050
import { dirname, join, resolve } from "node:path";
5151
import process from "node:process";
@@ -116,57 +116,63 @@ function getUserConfigPath(): string {
116116

117117
/**
118118
* Save configuration to user's config file (~/.mcpc/config.json)
119+
* Merges new agent if name differs, warns if name conflicts
119120
*/
120-
async function saveUserConfig(config: MCPCConfig): Promise<void> {
121+
async function saveUserConfig(
122+
config: MCPCConfig,
123+
newAgentName: string,
124+
): Promise<void> {
121125
const configPath = getUserConfigPath();
122126
const configDir = dirname(configPath);
123127

124128
try {
125-
// Check if config file already exists
126-
let exists = false;
129+
// Try to load existing config
130+
let existingConfig: MCPCConfig | null = null;
127131
try {
128-
await access(configPath);
129-
exists = true;
132+
const content = await readFile(configPath, "utf-8");
133+
existingConfig = JSON.parse(content);
130134
} catch {
131-
// File doesn't exist, which is fine
135+
// File doesn't exist - will create new one
132136
}
133137

134-
if (exists) {
135-
console.error(`
136-
⚠ Configuration file already exists: ${configPath}
137-
138-
To avoid overwriting your customized settings:
139-
1. Use a different output path with --config-file
140-
2. Or manually merge the new servers into your existing config
141-
3. Or delete the file first: rm ${configPath}
138+
// Handle existing config
139+
if (existingConfig) {
140+
const hasConflict = existingConfig.agents.some(
141+
(agent) => agent.name === newAgentName,
142+
);
143+
144+
if (hasConflict) {
145+
console.error(
146+
`\n⚠ Agent "${newAgentName}" already exists in ${configPath}\n` +
147+
` Use --name to choose a different name, or delete the existing agent first.\n`,
148+
);
149+
return;
150+
}
142151

143-
Skipping save to preserve your existing configuration.
144-
`);
152+
// Merge new agent
153+
existingConfig.agents.push(...config.agents);
154+
await writeFile(
155+
configPath,
156+
JSON.stringify(existingConfig, null, 2),
157+
"utf-8",
158+
);
159+
console.error(
160+
`\n✓ Added agent "${newAgentName}" (total: ${existingConfig.agents.length})\n` +
161+
` Config: ${configPath}\n` +
162+
` Run: mcpc\n`,
163+
);
145164
return;
146165
}
147166

148-
// Create directory if it doesn't exist
167+
// Create new config
149168
await mkdir(configDir, { recursive: true });
150-
151-
// Write config file with pretty formatting
152169
await writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
153-
154-
console.error(`
155-
✓ Configuration saved to: ${configPath}
156-
157-
Next steps:
158-
1. (Optional) Edit the config to add headers, env vars, etc.
159-
Examples:
160-
- Add headers: "headers": {"Authorization": "Bearer \${YOUR_TOKEN}"}
161-
- Add env vars: "env": {"API_KEY": "\${API_KEY}"}
162-
163-
2. Run the server:
164-
mcpc
165-
166-
The config will be loaded automatically from ${configPath}
167-
`);
170+
console.error(
171+
`\n✓ Configuration saved to: ${configPath}\n` +
172+
` Run: mcpc\n`,
173+
);
168174
} catch (error) {
169-
console.error(`Warning: Failed to save config to ${configPath}:`, error);
175+
console.error(`Failed to save config to ${configPath}:`, error);
170176
}
171177
}
172178

@@ -181,12 +187,10 @@ async function createWrapConfig(args: {
181187
saveConfig?: boolean;
182188
}): Promise<MCPCConfig> {
183189
if (!args.mcpServers || args.mcpServers.length === 0) {
184-
console.error("Error: --wrap/--add requires at least one MCP server");
185190
console.error(
186-
"Example: mcpc --wrap --mcp-stdio 'npx -y @wonderwhy-er/desktop-commander'",
187-
);
188-
console.error(
189-
"Multiple: mcpc --add --mcp-stdio 'npx -y server1' --mcp-http 'https://api.example.com'",
191+
"Error: --wrap/--add requires at least one MCP server\n" +
192+
"Example: mcpc --wrap --mcp-stdio 'npx -y @wonderwhy-er/desktop-commander'\n" +
193+
"Multiple: mcpc --add --mcp-stdio 'npx -y server1' --mcp-http 'https://api.example.com'",
190194
);
191195
process.exit(1);
192196
}
@@ -208,9 +212,11 @@ async function createWrapConfig(args: {
208212
serverNames.push(serverName);
209213
refs.push(`<tool name="${serverName}.__ALL__"/>`);
210214

211-
console.error(`Added MCP server: ${serverName}
212-
Transport: ${spec.transportType}
213-
Command: ${spec.command} ${spec.args.join(" ")}`);
215+
console.error(
216+
`Added MCP server: ${serverName}\n` +
217+
` Transport: ${spec.transportType}\n` +
218+
` Command: ${spec.command} ${spec.args.join(" ")}`,
219+
);
214220
}
215221

216222
// Use custom name if provided, otherwise use merged server names
@@ -242,12 +248,13 @@ async function createWrapConfig(args: {
242248
};
243249

244250
const modeInfo = args.mode ? `\nMode: ${args.mode}` : "";
245-
console.error(`
246-
Created wrap configuration for ${serverNames.length} MCP server(s)${modeInfo}`);
251+
console.error(
252+
`\nCreated configuration for ${serverNames.length} MCP server(s)${modeInfo}`,
253+
);
247254

248255
// Save configuration to user's config file if requested
249256
if (args.saveConfig) {
250-
await saveUserConfig(config);
257+
await saveUserConfig(config, agentName);
251258
}
252259

253260
return config;

0 commit comments

Comments
 (0)