@wuyax/mcps 0.1.0-beta.3 → 0.1.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/dist/cli.js CHANGED
@@ -1,24 +1,28 @@
1
1
  import {
2
- getMcpAgentTypes,
3
- installMcpServer,
4
- listInstalledMcpServers,
2
+ displayServerDetails,
5
3
  logCoHostedNotice,
6
4
  logger,
7
5
  mainMenu,
8
- mcpManageCommand,
9
- parseKeyValueList,
6
+ wizardAdd,
7
+ wizardManage,
8
+ wizardRemove
9
+ } from "./chunk-AWD3VQ3S.js";
10
+ import {
11
+ applyServerConfigDelta,
12
+ getMcpAgentTypes,
13
+ installMcpServer,
14
+ listInstalledMcpServers,
10
15
  parseMcpAgentList,
11
16
  parseMcpSource,
17
+ queryGroupedInstalledServers,
12
18
  removeMcpServer,
13
19
  resolveTargetAgents,
14
- resolveTransport,
15
20
  toErrorMessage,
16
- wizardAdd,
17
- wizardRemove
18
- } from "./chunk-BUKA3NPJ.js";
21
+ updateMcpServer
22
+ } from "./chunk-O3BRJFEC.js";
19
23
 
20
24
  // src/cli.ts
21
- import { Command as Command4 } from "commander";
25
+ import { Command as Command5 } from "commander";
22
26
 
23
27
  // src/cli/add.ts
24
28
  import { Command } from "commander";
@@ -27,6 +31,30 @@ import pc from "picocolors";
27
31
  // src/utils/format-agent-list.ts
28
32
  var formatAgentList = (agentList, emptyLabel = "(none)") => agentList.length === 0 ? emptyLabel : agentList.join(", ");
29
33
 
34
+ // src/utils/parse-key-value-list.ts
35
+ var parseKeyValueList = (entries, separator) => {
36
+ if (!entries || entries.length === 0) return {};
37
+ const result = {};
38
+ for (const entry of entries) {
39
+ const splitIndex = entry.indexOf(separator);
40
+ if (splitIndex === -1) {
41
+ throw new Error(`Invalid entry "${entry}": expected "${separator}" separator`);
42
+ }
43
+ const key = entry.slice(0, splitIndex).trim();
44
+ const value = entry.slice(splitIndex + separator.length).trim();
45
+ if (!key) throw new Error(`Invalid entry "${entry}": empty key`);
46
+ result[key] = value;
47
+ }
48
+ return result;
49
+ };
50
+
51
+ // src/utils/resolve-transport.ts
52
+ var resolveTransport = (input) => {
53
+ if (!input) return void 0;
54
+ if (input === "http" || input === "sse") return input;
55
+ throw new Error(`Unsupported transport "${input}" (expected: http, sse)`);
56
+ };
57
+
30
58
  // src/cli/add.ts
31
59
  var mcpAddCommand = new Command("add").description("Add an MCP server to coding agents").argument("[source]", "Remote URL, npm package, or command line").option("-a, --agent <agents...>", "Target specific agents (use '*' for all)").option("-g, --global", "Install to user-level config instead of project").option("-t, --transport <type>", "Transport type for remote servers (http or sse)").option("--header <header...>", "HTTP header (Key: Value), repeatable").option("--env <env...>", "Env var for stdio servers (KEY=VALUE), repeatable").option("--args <args...>", "CLI arguments for stdio/package servers").option("-n, --name <name>", "Server name override").option("-y, --yes", "Skip all prompts").option("--all", "Install to all supported agents").action(async (source, options) => {
32
60
  try {
@@ -144,10 +172,153 @@ var mcpListCommand = new Command2("list").alias("ls").description("List installe
144
172
  }
145
173
  });
146
174
 
147
- // src/cli/remove.ts
175
+ // src/cli/manage.ts
148
176
  import { Command as Command3 } from "commander";
149
177
  import pc3 from "picocolors";
150
- var mcpRemoveCommand = new Command3("remove").alias("rm").description("Remove an MCP server from agent configs").argument("[name]", "Server name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Filter by specific agents (use '*' for all)").option("-y, --yes", "Skip confirmation prompts").action(async (name, options) => {
178
+ var requireTargetServerGroup = (serverName, scope) => {
179
+ const grouped = queryGroupedInstalledServers(scope);
180
+ const targetGroup = grouped.get(serverName);
181
+ if (!targetGroup) {
182
+ logger.error(
183
+ `MCP server "${serverName}" is not configured in ${scope.global ? "global" : "project"} scope.`
184
+ );
185
+ process.exitCode = 1;
186
+ return void 0;
187
+ }
188
+ return targetGroup;
189
+ };
190
+ var mcpManageCommand = new Command3("manage").description("Inspect, modify, and sync installed MCP servers across coding agents").argument("[server-name]", "Optional server name to inspect or manage").option("-a, --agent <agents...>", "Target specific agents for update").option("-g, --global", "Manage global scope servers instead of project").option("-t, --transport <type>", "Transport type for remote servers (http or sse)").option("--header <header...>", "HTTP header (Header: Value), repeatable").option("--clear-headers", "Clear all HTTP headers for remote servers").option("--env <env...>", "Env var for stdio servers (KEY=VALUE), repeatable").option("--clear-env", "Clear all environment variables for stdio servers").option("--args <args...>", "CLI arguments for stdio/package servers").option("--clear-args", "Clear all arguments for stdio/package servers").option("--command <command>", "Executable command for stdio servers").option("--url <url>", "Remote endpoint URL").option("-y, --yes", "Skip interactive prompts").action(async (serverName, options) => {
191
+ try {
192
+ const cwd = process.cwd();
193
+ const isGlobal = Boolean(options.global);
194
+ const hasModifications = options.command !== void 0 || options.args !== void 0 || Boolean(options.clearArgs) || options.env !== void 0 || Boolean(options.clearEnv) || options.header !== void 0 || Boolean(options.clearHeaders) || options.url !== void 0 || options.transport !== void 0;
195
+ const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
196
+ if (hasModifications) {
197
+ if (!serverName) {
198
+ logger.error('Missing required argument: "server-name" when passing modification flags.');
199
+ process.exitCode = 1;
200
+ return;
201
+ }
202
+ const targetGroup = requireTargetServerGroup(serverName, { global: isGlobal, cwd });
203
+ if (!targetGroup) {
204
+ return;
205
+ }
206
+ const parsedEnv = options.env !== void 0 ? parseKeyValueList(options.env, "=") : void 0;
207
+ const parsedHeaders = options.header !== void 0 ? parseKeyValueList(options.header, ":") : void 0;
208
+ let deltaResult;
209
+ try {
210
+ deltaResult = applyServerConfigDelta(targetGroup.config, {
211
+ command: options.command,
212
+ args: options.args,
213
+ clearArgs: options.clearArgs,
214
+ env: parsedEnv,
215
+ clearEnv: options.clearEnv,
216
+ url: options.url,
217
+ transport: resolveTransport(options.transport),
218
+ headers: parsedHeaders,
219
+ clearHeaders: options.clearHeaders
220
+ });
221
+ } catch (error) {
222
+ logger.error(toErrorMessage(error));
223
+ process.exitCode = 1;
224
+ return;
225
+ }
226
+ if (deltaResult.ignoredFlags.length > 0) {
227
+ const isRemote = deltaResult.protocol === "remote";
228
+ const hint = isRemote ? options.url !== void 0 ? "When configuring a remote server, stdio flags are ignored." : "Use --command to switch to stdio mode." : options.command !== void 0 ? "When configuring a stdio server, remote flags are ignored." : "Use --url to switch to remote mode.";
229
+ logger.warn(
230
+ `Server "${serverName}" is a ${isRemote ? "remote" : "stdio"} server. The following ${isRemote ? "stdio" : "remote"} flags will be ignored: ${deltaResult.ignoredFlags.join(", ")}. ${hint}`
231
+ );
232
+ }
233
+ const incomingDelta = deltaResult.config;
234
+ let targetAgents = targetGroup.agents;
235
+ if (options.agent !== void 0) {
236
+ const parsed = parseMcpAgentList(options.agent);
237
+ if (!parsed || parsed.length === 0) {
238
+ logger.error(`No valid agents recognized from: "${options.agent.join(", ")}".`);
239
+ process.exitCode = 1;
240
+ return;
241
+ }
242
+ targetAgents = parsed;
243
+ }
244
+ const updateResult = updateMcpServer({
245
+ serverName,
246
+ config: incomingDelta,
247
+ previousConfig: targetGroup.config,
248
+ agents: targetAgents,
249
+ global: isGlobal,
250
+ cwd
251
+ });
252
+ for (const item of updateResult.incompatible) {
253
+ logger.warn(`Skipping ${pc3.cyan(item.agent)}: ${item.reason}`);
254
+ }
255
+ const attemptedResults = updateResult.results.filter(
256
+ (r) => !updateResult.incompatible.some((i) => i.agent === r.agent)
257
+ );
258
+ if (attemptedResults.length === 0) {
259
+ const requestedTransport = updateResult.config.url ? updateResult.config.type ?? "http" : "stdio";
260
+ logger.error(
261
+ `None of the target agents support ${requestedTransport} transport. Update aborted.`
262
+ );
263
+ process.exitCode = 1;
264
+ return;
265
+ }
266
+ logger.info(
267
+ `Updating ${pc3.bold(serverName)} across ${pc3.cyan(String(attemptedResults.length))} agent(s)...`
268
+ );
269
+ let allSuccess = true;
270
+ for (const res of attemptedResults) {
271
+ if (res.success) {
272
+ logger.success(`${pc3.cyan(res.agent)}: Successfully updated in ${pc3.dim(res.path)}`);
273
+ logCoHostedNotice("configured", res.coConfiguredAgents);
274
+ } else {
275
+ allSuccess = false;
276
+ logger.error(`${pc3.cyan(res.agent)}: Update failed - ${res.error}`);
277
+ }
278
+ }
279
+ if (!allSuccess) {
280
+ process.exitCode = 1;
281
+ }
282
+ return;
283
+ }
284
+ if (!isInteractive) {
285
+ if (!serverName) {
286
+ logger.error(
287
+ 'Missing required argument: "server-name" for non-interactive manage command. Specify a server name or use interactive terminal.'
288
+ );
289
+ process.exitCode = 1;
290
+ return;
291
+ }
292
+ const targetGroup = requireTargetServerGroup(serverName, { global: isGlobal, cwd });
293
+ if (!targetGroup) {
294
+ return;
295
+ }
296
+ displayServerDetails({
297
+ serverName,
298
+ config: targetGroup.config,
299
+ agents: targetGroup.agents,
300
+ global: isGlobal,
301
+ hasDivergence: targetGroup.hasDivergence
302
+ });
303
+ return;
304
+ }
305
+ await wizardManage({
306
+ global: options.global,
307
+ serverName
308
+ });
309
+ } catch (error) {
310
+ if (error && typeof error === "object" && "name" in error && error.name === "ExitPromptError") {
311
+ process.exit(0);
312
+ }
313
+ logger.error(toErrorMessage(error));
314
+ process.exitCode = 1;
315
+ }
316
+ });
317
+
318
+ // src/cli/remove.ts
319
+ import { Command as Command4 } from "commander";
320
+ import pc4 from "picocolors";
321
+ var mcpRemoveCommand = new Command4("remove").alias("rm").description("Remove an MCP server from agent configs").argument("[name]", "Server name").option("-g, --global", "Remove from global scope").option("-a, --agent <agents...>", "Filter by specific agents (use '*' for all)").option("-y, --yes", "Skip confirmation prompts").action(async (name, options) => {
151
322
  try {
152
323
  const isInteractive = Boolean(process.stdin.isTTY && !options.yes);
153
324
  if (!name) {
@@ -170,17 +341,17 @@ var mcpRemoveCommand = new Command3("remove").alias("rm").description("Remove an
170
341
  cwd: process.cwd()
171
342
  });
172
343
  if (results.length === 0) {
173
- logger.warn(`No agent config contained ${pc3.bold(name)}`);
344
+ logger.warn(`No agent config contained ${pc4.bold(name)}`);
174
345
  return;
175
346
  }
176
347
  for (const record of results) {
177
348
  if (record.removed) {
178
349
  logger.success(
179
- `${pc3.cyan(record.agent)} removed ${pc3.bold(name)} ${pc3.dim(record.path)}`
350
+ `${pc4.cyan(record.agent)} removed ${pc4.bold(name)} ${pc4.dim(record.path)}`
180
351
  );
181
352
  logCoHostedNotice("affected", record.coAffectedAgents);
182
353
  } else {
183
- logger.error(`${pc3.cyan(record.agent)}: ${record.error ?? "not found"}`);
354
+ logger.error(`${pc4.cyan(record.agent)}: ${record.error ?? "not found"}`);
184
355
  }
185
356
  }
186
357
  } catch (error) {
@@ -190,10 +361,10 @@ var mcpRemoveCommand = new Command3("remove").alias("rm").description("Remove an
190
361
  });
191
362
 
192
363
  // src/cli.ts
193
- var VERSION = "0.1.0-beta.3";
364
+ var VERSION = "0.1.0";
194
365
  process.on("SIGINT", () => process.exit(0));
195
366
  process.on("SIGTERM", () => process.exit(0));
196
- var program = new Command4().name("mcps").description("Install, list, and remove MCP servers across AI coding agents").version(VERSION, "-v, --version", "display the version number");
367
+ var program = new Command5().name("mcps").description("Install, list, and remove MCP servers across AI coding agents").version(VERSION, "-v, --version", "display the version number");
197
368
  program.addCommand(mcpAddCommand);
198
369
  program.addCommand(mcpListCommand);
199
370
  program.addCommand(mcpManageCommand);