@apify/mcpc 0.2.4 → 0.2.6
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/CHANGELOG.md +34 -1
- package/README.md +65 -26
- package/dist/bridge/index.js +26 -4
- package/dist/bridge/index.js.map +1 -1
- package/dist/cli/commands/auth.d.ts +1 -0
- package/dist/cli/commands/auth.d.ts.map +1 -1
- package/dist/cli/commands/auth.js +7 -0
- package/dist/cli/commands/auth.js.map +1 -1
- package/dist/cli/commands/clean.d.ts.map +1 -1
- package/dist/cli/commands/clean.js +13 -2
- package/dist/cli/commands/clean.js.map +1 -1
- package/dist/cli/commands/grep.d.ts.map +1 -1
- package/dist/cli/commands/grep.js +35 -4
- package/dist/cli/commands/grep.js.map +1 -1
- package/dist/cli/commands/prompts.d.ts.map +1 -1
- package/dist/cli/commands/prompts.js +7 -26
- package/dist/cli/commands/prompts.js.map +1 -1
- package/dist/cli/commands/resources.d.ts.map +1 -1
- package/dist/cli/commands/resources.js +9 -3
- package/dist/cli/commands/resources.js.map +1 -1
- package/dist/cli/commands/sessions.d.ts +25 -1
- package/dist/cli/commands/sessions.d.ts.map +1 -1
- package/dist/cli/commands/sessions.js +177 -11
- package/dist/cli/commands/sessions.js.map +1 -1
- package/dist/cli/commands/tasks.d.ts +1 -0
- package/dist/cli/commands/tasks.d.ts.map +1 -1
- package/dist/cli/commands/tasks.js +11 -0
- package/dist/cli/commands/tasks.js.map +1 -1
- package/dist/cli/commands/tools.d.ts +6 -1
- package/dist/cli/commands/tools.d.ts.map +1 -1
- package/dist/cli/commands/tools.js +39 -11
- package/dist/cli/commands/tools.js.map +1 -1
- package/dist/cli/commands/x402.js +1 -1
- package/dist/cli/commands/x402.js.map +1 -1
- package/dist/cli/index.js +290 -88
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/output.d.ts +5 -0
- package/dist/cli/output.d.ts.map +1 -1
- package/dist/cli/output.js +103 -16
- package/dist/cli/output.js.map +1 -1
- package/dist/cli/parser.d.ts +4 -0
- package/dist/cli/parser.d.ts.map +1 -1
- package/dist/cli/parser.js +50 -16
- package/dist/cli/parser.js.map +1 -1
- package/dist/cli/shell.d.ts.map +1 -1
- package/dist/cli/shell.js +26 -3
- package/dist/cli/shell.js.map +1 -1
- package/dist/core/mcp-client.d.ts +1 -0
- package/dist/core/mcp-client.d.ts.map +1 -1
- package/dist/core/mcp-client.js +14 -0
- package/dist/core/mcp-client.js.map +1 -1
- package/dist/lib/auth/oauth-flow.d.ts +1 -0
- package/dist/lib/auth/oauth-flow.d.ts.map +1 -1
- package/dist/lib/auth/oauth-flow.js +33 -9
- package/dist/lib/auth/oauth-flow.js.map +1 -1
- package/dist/lib/auth/oauth-provider.d.ts +2 -0
- package/dist/lib/auth/oauth-provider.d.ts.map +1 -1
- package/dist/lib/auth/oauth-provider.js +4 -0
- package/dist/lib/auth/oauth-provider.js.map +1 -1
- package/dist/lib/bridge-manager.d.ts.map +1 -1
- package/dist/lib/bridge-manager.js +22 -19
- package/dist/lib/bridge-manager.js.map +1 -1
- package/dist/lib/cleanup.d.ts +5 -0
- package/dist/lib/cleanup.d.ts.map +1 -1
- package/dist/lib/cleanup.js +38 -1
- package/dist/lib/cleanup.js.map +1 -1
- package/dist/lib/config.d.ts.map +1 -1
- package/dist/lib/config.js +5 -1
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +1 -1
- package/dist/lib/errors.js.map +1 -1
- package/dist/lib/session-client.d.ts +1 -0
- package/dist/lib/session-client.d.ts.map +1 -1
- package/dist/lib/session-client.js +7 -4
- package/dist/lib/session-client.js.map +1 -1
- package/dist/lib/sessions.d.ts.map +1 -1
- package/dist/lib/sessions.js +13 -5
- package/dist/lib/sessions.js.map +1 -1
- package/dist/lib/types.d.ts +2 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/utils.d.ts +15 -2
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +91 -7
- package/dist/lib/utils.js.map +1 -1
- package/docs/TODOs.md +5 -0
- package/package.json +6 -6
package/dist/cli/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { initProxy } from '../lib/proxy.js';
|
|
3
|
-
import { Command, Help } from 'commander';
|
|
3
|
+
import { Command, CommanderError, Help } from 'commander';
|
|
4
4
|
import { setVerbose, setJsonMode, closeFileLogger } from '../lib/index.js';
|
|
5
5
|
import { isMcpError, formatHumanError, ClientError } from '../lib/index.js';
|
|
6
6
|
import chalk from 'chalk';
|
|
@@ -16,7 +16,7 @@ import * as tasks from './commands/tasks.js';
|
|
|
16
16
|
import * as grepCmd from './commands/grep.js';
|
|
17
17
|
import { handleX402Command } from './commands/x402.js';
|
|
18
18
|
import { clean } from './commands/clean.js';
|
|
19
|
-
import { extractOptions, getVerboseFromEnv, getJsonFromEnv, validateOptions, validateArgValues, parseServerArg, hasSubcommand, optionTakesValue, KNOWN_COMMANDS, KNOWN_SESSION_COMMANDS, } from './parser.js';
|
|
19
|
+
import { extractOptions, getVerboseFromEnv, getJsonFromEnv, validateOptions, validateArgValues, parseServerArg, hasSubcommand, optionTakesValue, suggestCommand, KNOWN_COMMANDS, KNOWN_SESSION_COMMANDS, } from './parser.js';
|
|
20
20
|
import { createRequire } from 'module';
|
|
21
21
|
const { version: mcpcVersion } = createRequire(import.meta.url)('../../package.json');
|
|
22
22
|
{
|
|
@@ -64,8 +64,21 @@ function getOptionsFromCommand(command) {
|
|
|
64
64
|
}
|
|
65
65
|
if (opts.full)
|
|
66
66
|
options.full = opts.full;
|
|
67
|
+
if (opts.maxChars) {
|
|
68
|
+
const maxChars = parseInt(opts.maxChars, 10);
|
|
69
|
+
if (isNaN(maxChars) || maxChars <= 0) {
|
|
70
|
+
throw new Error(`Invalid --max-chars value: "${opts.maxChars}". Must be a positive number (characters).`);
|
|
71
|
+
}
|
|
72
|
+
options.maxChars = maxChars;
|
|
73
|
+
}
|
|
67
74
|
return options;
|
|
68
75
|
}
|
|
76
|
+
function jsonHelp(description, shape, schemaUrl) {
|
|
77
|
+
const line = shape ? ` ${description}:\n ${shape}` : ` ${description}`;
|
|
78
|
+
const link = schemaUrl ? `\n Schema: ${schemaUrl}` : '';
|
|
79
|
+
return `\n${chalk.bold('JSON output (--json):')}\n${line}${link}\n`;
|
|
80
|
+
}
|
|
81
|
+
const SCHEMA_BASE = 'https://modelcontextprotocol.io/specification/2025-11-25/schema';
|
|
69
82
|
async function main() {
|
|
70
83
|
const args = process.argv.slice(2);
|
|
71
84
|
const handleExit = () => {
|
|
@@ -90,16 +103,26 @@ async function main() {
|
|
|
90
103
|
return;
|
|
91
104
|
}
|
|
92
105
|
if (args.includes('--help') || args.includes('-h')) {
|
|
93
|
-
|
|
106
|
+
const hasSessionArg = args.some((a) => a.startsWith('@') && !a.startsWith('--'));
|
|
107
|
+
if (hasSessionArg) {
|
|
108
|
+
}
|
|
109
|
+
else if (args.includes('x402')) {
|
|
94
110
|
const x402Index = args.indexOf('x402');
|
|
95
111
|
const x402Args = args.slice(x402Index + 1);
|
|
96
112
|
await handleX402Command(x402Args);
|
|
97
113
|
await closeFileLogger();
|
|
98
114
|
return;
|
|
99
115
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
116
|
+
else {
|
|
117
|
+
const helpTarget = args.find((a) => a !== '--help' && a !== '-h' && !a.startsWith('-') && !a.startsWith('@'));
|
|
118
|
+
if (helpTarget && KNOWN_SESSION_COMMANDS.includes(helpTarget)) {
|
|
119
|
+
showSessionCommandHelp(helpTarget);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const program = createTopLevelProgram();
|
|
123
|
+
await program.parseAsync(process.argv);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
103
126
|
}
|
|
104
127
|
try {
|
|
105
128
|
validateOptions(args);
|
|
@@ -210,11 +233,20 @@ async function main() {
|
|
|
210
233
|
}
|
|
211
234
|
}
|
|
212
235
|
else {
|
|
236
|
+
const suggestion = suggestCommand(firstNonOption, allCommands);
|
|
213
237
|
if (outputMode === 'json') {
|
|
214
238
|
console.error(formatJsonError(new Error(`Unknown command: ${firstNonOption}`), 1));
|
|
215
239
|
}
|
|
216
240
|
else {
|
|
217
241
|
console.error(`Error: Unknown command: ${firstNonOption}`);
|
|
242
|
+
if (suggestion) {
|
|
243
|
+
if (KNOWN_SESSION_COMMANDS.includes(suggestion)) {
|
|
244
|
+
console.error(`\nDid you mean: mcpc <@session> ${suggestion}`);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
console.error(`\nDid you mean: mcpc ${suggestion}`);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
218
250
|
console.error(`Run "mcpc --help" for usage information.\n`);
|
|
219
251
|
}
|
|
220
252
|
}
|
|
@@ -255,18 +287,17 @@ function createTopLevelProgram() {
|
|
|
255
287
|
.name('mcpc')
|
|
256
288
|
.description(`${rainbow('Universal')} command-line client for the Model Context Protocol (MCP).`)
|
|
257
289
|
.usage('[<@session>] [<command>] [options]')
|
|
258
|
-
.option('
|
|
290
|
+
.option('--json', 'Output in JSON format for scripting')
|
|
259
291
|
.option('--verbose', 'Enable debug logging')
|
|
260
292
|
.option('--profile <name>', 'OAuth profile for the server ("default" if not provided)')
|
|
261
|
-
.option('--schema <file>', 'Validate tool/prompt schema against expected schema')
|
|
262
|
-
.option('--schema-mode <mode>', 'Schema validation mode: strict, compatible (default), ignore')
|
|
263
293
|
.option('--timeout <seconds>', 'Request timeout in seconds (default: 300)')
|
|
294
|
+
.option('--max-chars <n>', 'Truncate output to n characters (ignored in --json mode)')
|
|
264
295
|
.option('--insecure', 'Skip TLS certificate verification (for self-signed certs)')
|
|
265
296
|
.version(mcpcVersion, '-v, --version', 'Output the version number')
|
|
266
297
|
.helpOption('-h, --help', 'Display help');
|
|
267
298
|
program.addHelpText('after', `
|
|
268
299
|
${chalk.bold('MCP session commands (after connecting):')}
|
|
269
|
-
<@session> Show MCP server info, capabilities, and tools
|
|
300
|
+
<@session> Show MCP server info, capabilities, and tools overview
|
|
270
301
|
<@session> ${chalk.cyan('grep')} <pattern> Search tools and instructions
|
|
271
302
|
<@session> ${chalk.cyan('tools-list')} List all server tools
|
|
272
303
|
<@session> ${chalk.cyan('tools-get')} <name> Get tool details and schema
|
|
@@ -280,6 +311,7 @@ ${chalk.bold('MCP session commands (after connecting):')}
|
|
|
280
311
|
<@session> ${chalk.cyan('resources-templates-list')}
|
|
281
312
|
<@session> ${chalk.cyan('tasks-list')}
|
|
282
313
|
<@session> ${chalk.cyan('tasks-get')} <taskId>
|
|
314
|
+
<@session> ${chalk.cyan('tasks-result')} <taskId>
|
|
283
315
|
<@session> ${chalk.cyan('tasks-cancel')} <taskId>
|
|
284
316
|
<@session> ${chalk.cyan('logging-set-level')} <level>
|
|
285
317
|
<@session> ${chalk.cyan('ping')}
|
|
@@ -289,8 +321,8 @@ Run "mcpc" without arguments to show active sessions and OAuth profiles.
|
|
|
289
321
|
Full docs: ${docsUrl}`);
|
|
290
322
|
program
|
|
291
323
|
.command('connect [server] [@session]')
|
|
292
|
-
.usage('<server>
|
|
293
|
-
.description('Connect to an MCP server and start a
|
|
324
|
+
.usage('<server> [@session]')
|
|
325
|
+
.description('Connect to an MCP server and start a named @session')
|
|
294
326
|
.option('-H, --header <header>', 'HTTP header (can be repeated)')
|
|
295
327
|
.option('--profile <name>', 'OAuth profile to use ("default" if skipped)')
|
|
296
328
|
.option('--no-profile', 'Skip OAuth profile (connect anonymously)')
|
|
@@ -301,14 +333,20 @@ Full docs: ${docsUrl}`);
|
|
|
301
333
|
${chalk.bold('Server formats:')}
|
|
302
334
|
mcp.apify.com Remote HTTP server (https:// added automatically)
|
|
303
335
|
~/.vscode/mcp.json:puppeteer Config file entry (file:entry)
|
|
304
|
-
|
|
336
|
+
~/.vscode/mcp.json Config file — connect all servers in the file
|
|
337
|
+
|
|
338
|
+
${chalk.bold('Session name:')}
|
|
339
|
+
If @session is omitted, a name is auto-generated from the server hostname
|
|
340
|
+
(e.g. mcp.apify.com → @apify) or config entry name. If a matching session
|
|
341
|
+
already exists (same server URL, OAuth profile, and HTTP header names), it
|
|
342
|
+
is reused (restarted if not live). Header values are not compared — they
|
|
343
|
+
are stored securely in OS keychain.
|
|
344
|
+
When connecting all servers from a config file, @session cannot be specified.
|
|
345
|
+
${jsonHelp('`InitializeResult` object extended with `toolNames` and `_mcpc` metadata', '`{ protocolVersion, capabilities, serverInfo, instructions?, toolNames?, _mcpc }`', `${SCHEMA_BASE}#initializeresult`)}`)
|
|
305
346
|
.action(async (server, sessionName, opts, command) => {
|
|
306
347
|
if (!server) {
|
|
307
348
|
throw new ClientError('Missing required argument: server\n\nExample: mcpc connect mcp.apify.com @myapp');
|
|
308
349
|
}
|
|
309
|
-
if (!sessionName) {
|
|
310
|
-
throw new ClientError('Missing required argument: @session\n\nExample: mcpc connect mcp.apify.com @myapp');
|
|
311
|
-
}
|
|
312
350
|
const globalOpts = getOptionsFromCommand(command);
|
|
313
351
|
const parsed = parseServerArg(server);
|
|
314
352
|
const headers = opts.header
|
|
@@ -320,6 +358,29 @@ ${chalk.bold('Server formats:')}
|
|
|
320
358
|
throw new ClientError(`Invalid server: "${server}"\n\n` +
|
|
321
359
|
`Expected a URL (e.g. mcp.apify.com) or a config file entry (e.g. ~/.vscode/mcp.json:filesystem)`);
|
|
322
360
|
}
|
|
361
|
+
if (parsed.type === 'config-file') {
|
|
362
|
+
if (sessionName) {
|
|
363
|
+
throw new ClientError(`Cannot specify @session name when connecting all servers from a config file.\n` +
|
|
364
|
+
`To connect a specific entry, use: mcpc connect ${server}:<entry> ${sessionName}`);
|
|
365
|
+
}
|
|
366
|
+
await sessions.connectAllFromConfig(parsed.file, {
|
|
367
|
+
...globalOpts,
|
|
368
|
+
...(headers && { headers }),
|
|
369
|
+
...(opts.proxy && { proxy: opts.proxy }),
|
|
370
|
+
...(opts.proxyBearerToken && { proxyBearerToken: opts.proxyBearerToken }),
|
|
371
|
+
...(opts.x402 && { x402: opts.x402 }),
|
|
372
|
+
...(globalOpts.insecure && { insecure: true }),
|
|
373
|
+
});
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
if (!sessionName) {
|
|
377
|
+
sessionName = await sessions.resolveSessionName(parsed, {
|
|
378
|
+
outputMode: globalOpts.outputMode,
|
|
379
|
+
...(globalOpts.profile && { profile: globalOpts.profile }),
|
|
380
|
+
...(headers && { headers }),
|
|
381
|
+
...(globalOpts.noProfile && { noProfile: globalOpts.noProfile }),
|
|
382
|
+
});
|
|
383
|
+
}
|
|
323
384
|
if (parsed.type === 'config') {
|
|
324
385
|
await sessions.connectSession(parsed.entry, sessionName, {
|
|
325
386
|
...globalOpts,
|
|
@@ -346,6 +407,7 @@ ${chalk.bold('Server formats:')}
|
|
|
346
407
|
.command('close [@session]')
|
|
347
408
|
.usage('<@session>')
|
|
348
409
|
.description('Close a session')
|
|
410
|
+
.addHelpText('after', jsonHelp('`{ sessionName, closed: true }`'))
|
|
349
411
|
.action(async (sessionName, _opts, command) => {
|
|
350
412
|
if (!sessionName) {
|
|
351
413
|
throw new ClientError('Missing required argument: @session\n\nExample: mcpc close @myapp');
|
|
@@ -377,9 +439,24 @@ ${chalk.bold('Server formats:')}
|
|
|
377
439
|
.usage('<server>')
|
|
378
440
|
.description('Interactively login to a server using OAuth and save profile')
|
|
379
441
|
.option('--profile <name>', 'Profile name (default: "default")')
|
|
380
|
-
.option('--scope <scopes>', 'OAuth scopes to request
|
|
381
|
-
.option('--client-id <id>', 'OAuth client ID (
|
|
382
|
-
.option('--client-secret <secret>', 'OAuth client secret (
|
|
442
|
+
.option('--scope <scopes>', 'OAuth scopes to request (e.g. --scope "read write")')
|
|
443
|
+
.option('--client-id <id>', 'Pre-registered OAuth client ID (skips CIMD and DCR)')
|
|
444
|
+
.option('--client-secret <secret>', 'Pre-registered OAuth client secret (requires --client-id)')
|
|
445
|
+
.option('--client-metadata-url <url>', 'HTTPS URL of an OAuth CIMD to use as the Client ID')
|
|
446
|
+
.addHelpText('after', `
|
|
447
|
+
${chalk.bold('OAuth client registration approaches:')}
|
|
448
|
+
|
|
449
|
+
1. Pre-registration: --client-id (and optionally --client-secret).
|
|
450
|
+
2. Client ID Metadata Documents (CIMD): --client-metadata-url <https-url>.
|
|
451
|
+
Used when the authorization server advertises
|
|
452
|
+
"client_id_metadata_document_supported: true".
|
|
453
|
+
3. Dynamic Client Registration (DCR): default fallback when the server
|
|
454
|
+
exposes a "registration_endpoint". No flags required.
|
|
455
|
+
|
|
456
|
+
See https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
|
|
457
|
+
|
|
458
|
+
${jsonHelp('Interactive prompts are written to stderr, stdout contains a clean JSON object', '`{ profile, serverUrl, scopes }`')}
|
|
459
|
+
`)
|
|
383
460
|
.action(async (server, opts, command) => {
|
|
384
461
|
if (!server) {
|
|
385
462
|
throw new ClientError('Missing required argument: server\n\nExample: mcpc login mcp.apify.com');
|
|
@@ -389,6 +466,7 @@ ${chalk.bold('Server formats:')}
|
|
|
389
466
|
scope: opts.scope,
|
|
390
467
|
clientId: opts.clientId,
|
|
391
468
|
clientSecret: opts.clientSecret,
|
|
469
|
+
clientMetadataUrl: opts.clientMetadataUrl,
|
|
392
470
|
...getOptionsFromCommand(command),
|
|
393
471
|
});
|
|
394
472
|
});
|
|
@@ -397,6 +475,7 @@ ${chalk.bold('Server formats:')}
|
|
|
397
475
|
.usage('<server>')
|
|
398
476
|
.description('Delete an OAuth profile for a server')
|
|
399
477
|
.option('--profile <name>', 'Profile name (default: "default")')
|
|
478
|
+
.addHelpText('after', jsonHelp('`{ profile, serverUrl, deleted: true, affectedSessions }`'))
|
|
400
479
|
.action(async (server, opts, command) => {
|
|
401
480
|
if (!server) {
|
|
402
481
|
throw new ClientError('Missing required argument: server\n\nExample: mcpc logout mcp.apify.com');
|
|
@@ -417,7 +496,7 @@ ${chalk.bold('Resources:')}
|
|
|
417
496
|
all Remove all of the above
|
|
418
497
|
|
|
419
498
|
Without arguments, performs safe cleanup of stale data only.
|
|
420
|
-
`)
|
|
499
|
+
${jsonHelp('`{ crashedBridges, expiredSessions, orphanedBridgeLogs, sessions, profiles, logs }`')}`)
|
|
421
500
|
.action(async (resources, _opts, command) => {
|
|
422
501
|
const globalOpts = getOptionsFromCommand(command);
|
|
423
502
|
const VALID_CLEAN_TYPES = ['sessions', 'profiles', 'logs', 'all'];
|
|
@@ -458,7 +537,7 @@ ${chalk.bold('Examples:')}
|
|
|
458
537
|
mcpc @apify grep "actor" Search within a single session
|
|
459
538
|
mcpc grep "file" --json JSON output for scripting
|
|
460
539
|
mcpc grep "actor" -m 5 Show at most 5 results
|
|
461
|
-
`)
|
|
540
|
+
${jsonHelp('`[{ sessionName, tools?: Tool[], resources?: Resource[], prompts?: Prompt[], instructions?: string[] }]`')}`)
|
|
462
541
|
.action(async (pattern, opts, command) => {
|
|
463
542
|
if (!pattern) {
|
|
464
543
|
throw new ClientError('Missing required argument: pattern\n\nUsage: mcpc grep <pattern>\n\nExample: mcpc grep "search"');
|
|
@@ -496,17 +575,12 @@ ${chalk.bold('Examples:')}
|
|
|
496
575
|
}
|
|
497
576
|
const topLevelCmd = program.commands.find((c) => c.name() === cmdName || c.aliases().includes(cmdName));
|
|
498
577
|
if (topLevelCmd) {
|
|
578
|
+
tuneCommandHelp(topLevelCmd);
|
|
499
579
|
topLevelCmd.outputHelp();
|
|
500
580
|
return;
|
|
501
581
|
}
|
|
502
|
-
|
|
503
|
-
dummyProgram.name('mcpc <@session>');
|
|
504
|
-
registerSessionCommands(dummyProgram, '@dummy');
|
|
505
|
-
const sessionCmd = dummyProgram.commands.find((c) => c.name() === cmdName || c.aliases().includes(cmdName));
|
|
506
|
-
if (sessionCmd) {
|
|
507
|
-
sessionCmd.outputHelp();
|
|
582
|
+
if (showSessionCommandHelp(cmdName))
|
|
508
583
|
return;
|
|
509
|
-
}
|
|
510
584
|
console.error(`Unknown command: ${cmdName}`);
|
|
511
585
|
console.error(`Run "mcpc --help" for usage information.`);
|
|
512
586
|
process.exit(1);
|
|
@@ -523,57 +597,150 @@ ${chalk.bold('Examples:')}
|
|
|
523
597
|
});
|
|
524
598
|
return program;
|
|
525
599
|
}
|
|
600
|
+
const NO_JSON_COMMANDS = new Set(['shell']);
|
|
601
|
+
function tuneCommandHelp(cmd) {
|
|
602
|
+
if (!NO_JSON_COMMANDS.has(cmd.name()) && !cmd.options.some((o) => o.long === '--json')) {
|
|
603
|
+
cmd.option('--json', 'Output in JSON format');
|
|
604
|
+
}
|
|
605
|
+
cmd.helpOption('-h, --help', 'Display help');
|
|
606
|
+
const helpOpt = cmd._getHelpOption?.();
|
|
607
|
+
if (helpOpt)
|
|
608
|
+
helpOpt.hidden = true;
|
|
609
|
+
}
|
|
610
|
+
function showSessionCommandHelp(cmdName) {
|
|
611
|
+
const dummyProgram = createSessionProgram();
|
|
612
|
+
registerSessionCommands(dummyProgram, '<@session>');
|
|
613
|
+
for (const cmd of dummyProgram.commands) {
|
|
614
|
+
tuneCommandHelp(cmd);
|
|
615
|
+
}
|
|
616
|
+
const sessionCmd = dummyProgram.commands.find((c) => c.name() === cmdName || c.aliases().includes(cmdName));
|
|
617
|
+
if (sessionCmd) {
|
|
618
|
+
sessionCmd.outputHelp();
|
|
619
|
+
return true;
|
|
620
|
+
}
|
|
621
|
+
return false;
|
|
622
|
+
}
|
|
526
623
|
function registerSessionCommands(program, session) {
|
|
527
624
|
program
|
|
528
|
-
.command('help')
|
|
529
|
-
.description('Show
|
|
530
|
-
.action(
|
|
531
|
-
|
|
625
|
+
.command('help', { hidden: true })
|
|
626
|
+
.description('Show available commands and options.')
|
|
627
|
+
.action((_options, command) => {
|
|
628
|
+
command.parent.outputHelp();
|
|
532
629
|
});
|
|
533
630
|
program
|
|
534
631
|
.command('shell')
|
|
535
|
-
.description('
|
|
632
|
+
.description('Launch interactive MCP shell.')
|
|
536
633
|
.action(async () => {
|
|
537
634
|
await sessions.openShell(session);
|
|
538
635
|
});
|
|
539
636
|
program
|
|
540
|
-
.command('close'
|
|
541
|
-
.description('Close
|
|
637
|
+
.command('close')
|
|
638
|
+
.description('Close MCP session.')
|
|
542
639
|
.action(async (_options, command) => {
|
|
543
640
|
await sessions.closeSession(session, getOptionsFromCommand(command));
|
|
544
641
|
});
|
|
545
642
|
program
|
|
546
643
|
.command('restart')
|
|
547
|
-
.description('Restart
|
|
644
|
+
.description('Restart MCP session (losing all state).')
|
|
548
645
|
.action(async (_options, command) => {
|
|
549
646
|
await sessions.restartSession(session, getOptionsFromCommand(command));
|
|
550
647
|
});
|
|
648
|
+
program
|
|
649
|
+
.command('grep <pattern>')
|
|
650
|
+
.usage('<pattern> [options]')
|
|
651
|
+
.description('Search MCP session objects.')
|
|
652
|
+
.option('--tools', 'Search tools')
|
|
653
|
+
.option('--resources', 'Search resources')
|
|
654
|
+
.option('--prompts', 'Search prompts')
|
|
655
|
+
.option('--instructions', 'Search server instructions')
|
|
656
|
+
.option('-E, --regex', 'Treat pattern as a regular expression')
|
|
657
|
+
.option('-s, --case-sensitive', 'Case-sensitive matching')
|
|
658
|
+
.option('-m, --max-results <n>', 'Limit the number of results')
|
|
659
|
+
.addHelpText('after', `
|
|
660
|
+
${chalk.bold('Type filters:')}
|
|
661
|
+
By default, tools and instructions are searched. Use --resources or --prompts
|
|
662
|
+
to search those instead. Combine flags to search multiple types.
|
|
663
|
+
|
|
664
|
+
${chalk.bold('Examples:')}
|
|
665
|
+
mcpc ${session} grep "search" Search tools and instructions
|
|
666
|
+
mcpc ${session} grep "search" --resources Search resources only
|
|
667
|
+
mcpc ${session} grep "search|find" -E Regex search
|
|
668
|
+
${jsonHelp('`{ tools?: Tool[], resources?: Resource[], prompts?: Prompt[], instructions?: string[] }`')}`)
|
|
669
|
+
.action(async (pattern, opts, command) => {
|
|
670
|
+
const globalOpts = getOptionsFromCommand(command);
|
|
671
|
+
const maxResults = opts.maxResults ? parseInt(opts.maxResults, 10) : undefined;
|
|
672
|
+
const exitCode = await grepCmd.grepSession(session, pattern, {
|
|
673
|
+
tools: opts.tools,
|
|
674
|
+
resources: opts.resources,
|
|
675
|
+
prompts: opts.prompts,
|
|
676
|
+
instructions: opts.instructions,
|
|
677
|
+
regex: opts.regex,
|
|
678
|
+
caseSensitive: opts.caseSensitive,
|
|
679
|
+
maxResults,
|
|
680
|
+
...globalOpts,
|
|
681
|
+
});
|
|
682
|
+
process.exit(exitCode);
|
|
683
|
+
});
|
|
551
684
|
program
|
|
552
685
|
.command('tools')
|
|
553
|
-
.description('List
|
|
554
|
-
.option('--full', 'Show full tool details including
|
|
686
|
+
.description('List MCP tools (shorthand for tools-list).')
|
|
687
|
+
.option('--full', 'Show full tool details including schema')
|
|
688
|
+
.addHelpText('after', jsonHelp('Array of `Tool` objects', '`[{ name, description?, inputSchema, annotations? }, ...]`', `${SCHEMA_BASE}#tool`))
|
|
555
689
|
.action(async (_options, command) => {
|
|
556
690
|
await tools.listTools(session, getOptionsFromCommand(command));
|
|
557
691
|
});
|
|
558
692
|
program
|
|
559
693
|
.command('tools-list')
|
|
560
|
-
.description('List
|
|
561
|
-
.option('--full', 'Show full tool details including
|
|
694
|
+
.description('List all MCP tools.')
|
|
695
|
+
.option('--full', 'Show full tool details including schema')
|
|
696
|
+
.addHelpText('after', jsonHelp('Array of `Tool` objects', '`[{ name, description?, inputSchema, annotations? }, ...]`', `${SCHEMA_BASE}#tool`))
|
|
562
697
|
.action(async (_options, command) => {
|
|
563
698
|
await tools.listTools(session, getOptionsFromCommand(command));
|
|
564
699
|
});
|
|
565
700
|
program
|
|
566
701
|
.command('tools-get <name>')
|
|
567
|
-
.description('Get
|
|
702
|
+
.description('Get details and schema for an MCP tool.')
|
|
703
|
+
.option('--schema <file>', 'Validate tool schema against expected schema')
|
|
704
|
+
.option('--schema-mode <mode>', 'Schema validation mode: strict, compatible (default), ignore')
|
|
705
|
+
.addHelpText('after', `
|
|
706
|
+
${chalk.bold('Schema validation:')}
|
|
707
|
+
--schema <file> Validate against expected schema (save with tools-get --json)
|
|
708
|
+
--schema-mode <mode> strict | compatible (default) | ignore
|
|
709
|
+
${jsonHelp('`Tool` object', '`{ name, description?, inputSchema, annotations? }`', `${SCHEMA_BASE}#tool`)}`)
|
|
568
710
|
.action(async (name, _options, command) => {
|
|
569
711
|
await tools.getTool(session, name, getOptionsFromCommand(command));
|
|
570
712
|
});
|
|
713
|
+
const toolsCallJsonHelp = jsonHelp('`CallToolResult` object', '`{ content: [{ type, text?, ... }], isError?, structuredContent?: { ... } }`', `${SCHEMA_BASE}#calltoolresult`);
|
|
571
714
|
program
|
|
572
715
|
.command('tools-call <name> [args...]')
|
|
573
|
-
.description('Call
|
|
574
|
-
.
|
|
716
|
+
.description('Call an MCP tool with arguments.')
|
|
717
|
+
.helpOption(false)
|
|
718
|
+
.option('--task', 'Use async task execution (experimental)')
|
|
575
719
|
.option('--detach', 'Start task and return immediately with task ID (implies --task)')
|
|
720
|
+
.option('--schema <file>', 'Validate tool schema against expected schema before calling')
|
|
721
|
+
.option('--schema-mode <mode>', 'Schema validation mode: strict, compatible (default), ignore')
|
|
722
|
+
.addHelpText('after', `
|
|
723
|
+
${chalk.bold('Arguments:')}
|
|
724
|
+
key:=value pairs mcpc ${session} tools-call search query:=hello limit:=10
|
|
725
|
+
Inline JSON mcpc ${session} tools-call search '{"query":"hello"}'
|
|
726
|
+
Stdin pipe echo '{"query":"hello"}' | mcpc ${session} tools-call search
|
|
727
|
+
|
|
728
|
+
Values are auto-parsed: strings, numbers, booleans, JSON objects/arrays.
|
|
729
|
+
To force a string, wrap in quotes: id:='"123"'
|
|
730
|
+
|
|
731
|
+
${chalk.bold('Schema validation:')}
|
|
732
|
+
--schema <file> Validate tool schema before calling (save with tools-get --json)
|
|
733
|
+
--schema-mode <mode> strict | compatible (default) | ignore
|
|
734
|
+
${toolsCallJsonHelp}`)
|
|
576
735
|
.action(async (name, args, options, command) => {
|
|
736
|
+
if (name === '--help' || name === '-h') {
|
|
737
|
+
command.help();
|
|
738
|
+
return;
|
|
739
|
+
}
|
|
740
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
741
|
+
await tools.getTool(session, name, getOptionsFromCommand(command));
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
577
744
|
await tools.callTool(session, name, {
|
|
578
745
|
args,
|
|
579
746
|
task: options.task,
|
|
@@ -583,39 +750,52 @@ function registerSessionCommands(program, session) {
|
|
|
583
750
|
});
|
|
584
751
|
program
|
|
585
752
|
.command('tasks-list')
|
|
586
|
-
.description('List
|
|
753
|
+
.description('List all MCP tasks.')
|
|
754
|
+
.addHelpText('after', jsonHelp('`{ tasks: Task[] }`', '`{ tasks: [{ taskId, status, ttl, createdAt, lastUpdatedAt, statusMessage?, pollInterval? }] }`', `${SCHEMA_BASE}#task`))
|
|
587
755
|
.action(async (_options, command) => {
|
|
588
756
|
await tasks.listTasks(session, getOptionsFromCommand(command));
|
|
589
757
|
});
|
|
590
758
|
program
|
|
591
759
|
.command('tasks-get <taskId>')
|
|
592
|
-
.description('Get
|
|
760
|
+
.description('Get MCP task status.')
|
|
761
|
+
.addHelpText('after', jsonHelp('`Task` object', '`{ taskId, status, ttl, createdAt, lastUpdatedAt, statusMessage?, pollInterval? }`', `${SCHEMA_BASE}#task`))
|
|
593
762
|
.action(async (taskId, _options, command) => {
|
|
594
763
|
await tasks.getTask(session, taskId, getOptionsFromCommand(command));
|
|
595
764
|
});
|
|
765
|
+
program
|
|
766
|
+
.command('tasks-result <taskId>')
|
|
767
|
+
.description('Get MCP task final result (blocks until task reaches a terminal state).')
|
|
768
|
+
.addHelpText('after', toolsCallJsonHelp)
|
|
769
|
+
.action(async (taskId, _options, command) => {
|
|
770
|
+
await tasks.getTaskResult(session, taskId, getOptionsFromCommand(command));
|
|
771
|
+
});
|
|
596
772
|
program
|
|
597
773
|
.command('tasks-cancel <taskId>')
|
|
598
|
-
.description('Cancel
|
|
774
|
+
.description('Cancel an MCP task.')
|
|
775
|
+
.addHelpText('after', jsonHelp('`Task` object', '`{ taskId, status, ttl, createdAt, lastUpdatedAt, statusMessage?, pollInterval? }`', `${SCHEMA_BASE}#task`))
|
|
599
776
|
.action(async (taskId, _options, command) => {
|
|
600
777
|
await tasks.cancelTask(session, taskId, getOptionsFromCommand(command));
|
|
601
778
|
});
|
|
602
779
|
program
|
|
603
780
|
.command('resources')
|
|
604
|
-
.description('List
|
|
781
|
+
.description('List MCP resources (shorthand for resources-list).')
|
|
782
|
+
.addHelpText('after', jsonHelp('Array of `Resource` objects', '`[{ uri, name?, description?, mimeType? }, ...]`', `${SCHEMA_BASE}#resource`))
|
|
605
783
|
.action(async (_options, command) => {
|
|
606
784
|
await resources.listResources(session, getOptionsFromCommand(command));
|
|
607
785
|
});
|
|
608
786
|
program
|
|
609
787
|
.command('resources-list')
|
|
610
|
-
.description('List
|
|
788
|
+
.description('List all MCP resources.')
|
|
789
|
+
.addHelpText('after', jsonHelp('Array of `Resource` objects', '`[{ uri, name?, description?, mimeType? }, ...]`', `${SCHEMA_BASE}#resource`))
|
|
611
790
|
.action(async (_options, command) => {
|
|
612
791
|
await resources.listResources(session, getOptionsFromCommand(command));
|
|
613
792
|
});
|
|
614
793
|
program
|
|
615
794
|
.command('resources-read <uri>')
|
|
616
|
-
.description('
|
|
795
|
+
.description('Read an MCP resource by URI.')
|
|
617
796
|
.option('-o, --output <file>', 'Write resource to file')
|
|
618
797
|
.option('--max-size <bytes>', 'Maximum resource size in bytes')
|
|
798
|
+
.addHelpText('after', jsonHelp('`ReadResourceResult` object', '`{ contents: [{ uri, mimeType?, text? | blob? }] }`', `${SCHEMA_BASE}#readresourceresult`))
|
|
619
799
|
.action(async (uri, options, command) => {
|
|
620
800
|
await resources.getResource(session, uri, {
|
|
621
801
|
output: options.output,
|
|
@@ -625,37 +805,51 @@ function registerSessionCommands(program, session) {
|
|
|
625
805
|
});
|
|
626
806
|
program
|
|
627
807
|
.command('resources-subscribe <uri>')
|
|
628
|
-
.description('Subscribe to resource updates')
|
|
808
|
+
.description('Subscribe to MCP resource updates.')
|
|
809
|
+
.addHelpText('after', jsonHelp('`{ subscribed: true, uri: string }`'))
|
|
629
810
|
.action(async (uri, _options, command) => {
|
|
630
811
|
await resources.subscribeResource(session, uri, getOptionsFromCommand(command));
|
|
631
812
|
});
|
|
632
813
|
program
|
|
633
814
|
.command('resources-unsubscribe <uri>')
|
|
634
|
-
.description('Unsubscribe from resource updates')
|
|
815
|
+
.description('Unsubscribe from MCP resource updates.')
|
|
816
|
+
.addHelpText('after', jsonHelp('`{ unsubscribed: true, uri: string }`'))
|
|
635
817
|
.action(async (uri, _options, command) => {
|
|
636
818
|
await resources.unsubscribeResource(session, uri, getOptionsFromCommand(command));
|
|
637
819
|
});
|
|
638
820
|
program
|
|
639
821
|
.command('resources-templates-list')
|
|
640
|
-
.description('List
|
|
822
|
+
.description('List MCP resource templates.')
|
|
823
|
+
.addHelpText('after', jsonHelp('Array of `ResourceTemplate` objects', '`[{ uriTemplate, name?, description?, mimeType? }, ...]`', `${SCHEMA_BASE}#resourcetemplate`))
|
|
641
824
|
.action(async (_options, command) => {
|
|
642
825
|
await resources.listResourceTemplates(session, getOptionsFromCommand(command));
|
|
643
826
|
});
|
|
644
827
|
program
|
|
645
828
|
.command('prompts')
|
|
646
|
-
.description('List
|
|
829
|
+
.description('List MCP prompts (shorthand for prompts-list).')
|
|
830
|
+
.addHelpText('after', jsonHelp('Array of `Prompt` objects', '`[{ name, description?, arguments?: [{ name, required? }] }, ...]`', `${SCHEMA_BASE}#prompt`))
|
|
647
831
|
.action(async (_options, command) => {
|
|
648
832
|
await prompts.listPrompts(session, getOptionsFromCommand(command));
|
|
649
833
|
});
|
|
650
834
|
program
|
|
651
835
|
.command('prompts-list')
|
|
652
|
-
.description('List
|
|
836
|
+
.description('List all MCP prompts.')
|
|
837
|
+
.addHelpText('after', jsonHelp('Array of `Prompt` objects', '`[{ name, description?, arguments?: [{ name, required? }] }, ...]`', `${SCHEMA_BASE}#prompt`))
|
|
653
838
|
.action(async (_options, command) => {
|
|
654
839
|
await prompts.listPrompts(session, getOptionsFromCommand(command));
|
|
655
840
|
});
|
|
656
841
|
program
|
|
657
842
|
.command('prompts-get <name> [args...]')
|
|
658
|
-
.description('Get
|
|
843
|
+
.description('Get an MCP prompt with arguments.')
|
|
844
|
+
.addHelpText('after', `
|
|
845
|
+
${chalk.bold('Arguments:')}
|
|
846
|
+
key:=value pairs mcpc ${session} prompts-get summarize style:=brief lang:=en
|
|
847
|
+
Inline JSON mcpc ${session} prompts-get summarize '{"style":"brief"}'
|
|
848
|
+
Stdin pipe echo '{"style":"brief"}' | mcpc ${session} prompts-get summarize
|
|
849
|
+
|
|
850
|
+
Values are auto-parsed: strings, numbers, booleans, JSON objects/arrays.
|
|
851
|
+
To force a string, wrap in quotes: id:='"123"'
|
|
852
|
+
${jsonHelp('`GetPromptResult` object', '`{ description?, messages: [{ role, content: { type, text?, ... } }] }`', `${SCHEMA_BASE}#getpromptresult`)}`)
|
|
659
853
|
.action(async (name, args, _options, command) => {
|
|
660
854
|
await prompts.getPrompt(session, name, {
|
|
661
855
|
args,
|
|
@@ -664,63 +858,47 @@ function registerSessionCommands(program, session) {
|
|
|
664
858
|
});
|
|
665
859
|
program
|
|
666
860
|
.command('logging-set-level <level>')
|
|
667
|
-
.description('Set server logging level
|
|
861
|
+
.description('Set MCP server logging level.')
|
|
862
|
+
.addHelpText('after', jsonHelp('`{ level: string }`'))
|
|
668
863
|
.action(async (level, _options, command) => {
|
|
669
864
|
await logging.setLogLevel(session, level, getOptionsFromCommand(command));
|
|
670
865
|
});
|
|
671
866
|
program
|
|
672
867
|
.command('ping')
|
|
673
|
-
.description('Ping the MCP server
|
|
868
|
+
.description('Ping the MCP server.')
|
|
869
|
+
.addHelpText('after', jsonHelp('`{ success: true, durationMs: number }`'))
|
|
674
870
|
.action(async (_options, command) => {
|
|
675
871
|
await utilities.ping(session, getOptionsFromCommand(command));
|
|
676
872
|
});
|
|
677
|
-
program
|
|
678
|
-
.command('grep <pattern>')
|
|
679
|
-
.description('Search tools and instructions')
|
|
680
|
-
.option('--tools', 'Search tools')
|
|
681
|
-
.option('--resources', 'Search resources')
|
|
682
|
-
.option('--prompts', 'Search prompts')
|
|
683
|
-
.option('--instructions', 'Search server instructions')
|
|
684
|
-
.option('-E, --regex', 'Treat pattern as a regular expression')
|
|
685
|
-
.option('-s, --case-sensitive', 'Case-sensitive matching')
|
|
686
|
-
.option('-m, --max-results <n>', 'Limit the number of results')
|
|
687
|
-
.action(async (pattern, opts, command) => {
|
|
688
|
-
const globalOpts = getOptionsFromCommand(command);
|
|
689
|
-
const maxResults = opts.maxResults ? parseInt(opts.maxResults, 10) : undefined;
|
|
690
|
-
const exitCode = await grepCmd.grepSession(session, pattern, {
|
|
691
|
-
tools: opts.tools,
|
|
692
|
-
resources: opts.resources,
|
|
693
|
-
prompts: opts.prompts,
|
|
694
|
-
instructions: opts.instructions,
|
|
695
|
-
regex: opts.regex,
|
|
696
|
-
caseSensitive: opts.caseSensitive,
|
|
697
|
-
maxResults,
|
|
698
|
-
...globalOpts,
|
|
699
|
-
});
|
|
700
|
-
process.exit(exitCode);
|
|
701
|
-
});
|
|
702
873
|
}
|
|
703
874
|
function createSessionProgram() {
|
|
704
875
|
const program = new Command();
|
|
705
876
|
program.configureOutput({
|
|
706
|
-
outputError: (
|
|
877
|
+
outputError: () => { },
|
|
707
878
|
getOutHelpWidth: () => 100,
|
|
708
879
|
getErrHelpWidth: () => 100,
|
|
709
880
|
});
|
|
881
|
+
program.configureHelp({
|
|
882
|
+
subcommandTerm: (cmd) => `${cmd.name()} ${cmd.usage()}`.replace(/^\[options\]\s*|\s*\[options\]/g, '').trim(),
|
|
883
|
+
styleTitle: (str) => chalk.bold(str),
|
|
884
|
+
styleSubcommandText: (str) => chalk.cyan(str),
|
|
885
|
+
});
|
|
710
886
|
program
|
|
711
887
|
.name('mcpc <@session>')
|
|
888
|
+
.description('Execute MCP commands on a connected session.')
|
|
712
889
|
.helpOption('-h, --help', 'Display help')
|
|
713
|
-
.option('
|
|
890
|
+
.option('--json', 'Output in JSON format for scripting and code mode')
|
|
714
891
|
.option('--verbose', 'Enable debug logging')
|
|
715
892
|
.option('--profile <name>', 'OAuth profile override')
|
|
716
|
-
.option('--schema <file>', 'Validate tool/prompt schema against expected schema')
|
|
717
|
-
.option('--schema-mode <mode>', 'Schema validation mode: strict, compatible (default), ignore')
|
|
718
893
|
.option('--timeout <seconds>', 'Request timeout in seconds (default: 300)')
|
|
719
|
-
.option('--
|
|
894
|
+
.option('--max-chars <n>', 'Truncate output to n characters (ignored in --json mode)')
|
|
895
|
+
.option('--insecure', 'Skip TLS certificate verification (for self-signed certs)')
|
|
896
|
+
.addHelpText('after', `\nWhen no command is given, shows server info, capabilities, and tools.\n`);
|
|
720
897
|
return program;
|
|
721
898
|
}
|
|
722
899
|
async function handleSessionCommands(session, args) {
|
|
723
|
-
|
|
900
|
+
const argsSlice = args.slice(2);
|
|
901
|
+
if (!hasSubcommand(args) && !argsSlice.includes('--help') && !argsSlice.includes('-h')) {
|
|
724
902
|
const options = extractOptions(args);
|
|
725
903
|
if (options.verbose)
|
|
726
904
|
setVerbose(true);
|
|
@@ -734,13 +912,37 @@ async function handleSessionCommands(session, args) {
|
|
|
734
912
|
return;
|
|
735
913
|
}
|
|
736
914
|
const program = createSessionProgram();
|
|
915
|
+
program.exitOverride();
|
|
737
916
|
registerSessionCommands(program, session);
|
|
917
|
+
for (const cmd of program.commands) {
|
|
918
|
+
tuneCommandHelp(cmd);
|
|
919
|
+
}
|
|
738
920
|
try {
|
|
739
921
|
await program.parseAsync(args);
|
|
740
922
|
}
|
|
741
923
|
catch (error) {
|
|
742
924
|
const opts = program.opts();
|
|
743
925
|
const outputMode = opts.json ? 'json' : 'human';
|
|
926
|
+
if (error instanceof CommanderError && error.code === 'commander.unknownCommand') {
|
|
927
|
+
const unknownCmd = args.find((a, i) => i >= 2 && !a.startsWith('-') && !KNOWN_SESSION_COMMANDS.includes(a));
|
|
928
|
+
if (unknownCmd) {
|
|
929
|
+
const suggestion = suggestCommand(unknownCmd, KNOWN_SESSION_COMMANDS);
|
|
930
|
+
if (outputMode === 'json') {
|
|
931
|
+
console.error(formatJsonError(new Error(`Unknown command: ${unknownCmd}`), 1));
|
|
932
|
+
}
|
|
933
|
+
else {
|
|
934
|
+
console.error(`Error: Unknown command: ${unknownCmd}`);
|
|
935
|
+
if (suggestion) {
|
|
936
|
+
console.error(`\nDid you mean: mcpc ${session} ${suggestion}`);
|
|
937
|
+
}
|
|
938
|
+
console.error(`Run "mcpc ${session} --help" for available commands.\n`);
|
|
939
|
+
}
|
|
940
|
+
process.exit(1);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
if (error instanceof CommanderError && error.code === 'commander.helpDisplayed') {
|
|
944
|
+
process.exit(0);
|
|
945
|
+
}
|
|
744
946
|
if (isMcpError(error)) {
|
|
745
947
|
if (outputMode === 'json') {
|
|
746
948
|
console.error(formatJsonError(error, error.code));
|