From e7df1b84c902897a002036041f3d490d9a323cc5 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 20 May 2026 20:16:06 +0000 Subject: [PATCH 1/6] Show next-step hints after `mcpc` and `mcpc connect` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `↳ view a session: mcpc @sessionname` hint after listing sessions in `mcpc` (no args), so users and agents see what to do next. - Move `pass --stdio to include` out of the `mcpc connect` summary line into a dedicated `↳ run: mcpc connect --stdio` hint, matching the unauthorized/expired-session hint style. - Document the convention as a new "Next-step hints" principle in CLAUDE.md. --- CLAUDE.md | 23 ++++++++++++----------- src/cli/commands/sessions.ts | 6 +++++- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 71df4c3..9bd69af 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -612,17 +612,18 @@ When opening a pull request, always reference the originating issue or PR in the When implementing features: 1. **Self-documenting CLI** - All features, options, and usage patterns must be documented in command `--help` output (Commander.js `.description()` and `.addHelpText()`), not just in the README. AI agents discover how to use mcpc purely by running `mcpc --help` and `mcpc --help`, so help text is the primary documentation surface. Include examples in help text for non-obvious commands. The README can provide additional context but must not be the only place a feature is documented. -2. **Keep core runtime-agnostic** - Use native APIs, avoid runtime-specific dependencies -3. **Error handling** - Provide clear, actionable error messages; use appropriate exit codes -4. **Retry logic** - Use exponential backoff for network operations (3 attempts for requests, 1s→30s for streams) -5. **Concurrent safety** - Use file locking for shared state (`sessions.json`) -6. **Security** - Never log credentials (log `present`/`MISSING` instead); use OS keychain; enforce HTTPS; use `execFile()` not `exec()`; escape HTML output; validate Host headers on local servers; send secrets via IPC not CLI args; see "Security Considerations" section for full guidelines -7. **Output formatting** - Support both human-readable (default) and JSON (`--json`) modes -8. **Protocol compliance** - Follow MCP specification strictly; handle all notification types -9. **Session management** - Always clean up resources; handle orphaned processes; provide reconnection -10. **Hyphenated commands** - All MCP commands use hyphens: `tools-list`, `resources-read`, `prompts-list` -11. **Command-first syntax** - Top-level commands come first (`connect`, `login`, `clean`); MCP operations always go through a named session (`mcpc @session `) -12. **JSON field naming** - Use consistent field names in JSON output: +2. **Next-step hints** - Every command's human-mode output should make it clear what the user or agent might want to do next. After listing items or finishing an action, print a dim hint suggesting the next likely command using the format `chalk.dim(' ↳ : mcpc ')` with the `↳` arrow prefix. Examples: after `mcpc` lists sessions, hint how to view details (`↳ view a session: mcpc @sessionname`); after `mcpc connect` skips stdio servers, hint how to include them (`↳ run: mcpc connect --stdio`); after recoverable session states, hint the recovery command (`↳ run: mcpc @sessionname restart`). The goal is that any user or agent can chain commands without consulting `--help`. Do not emit hints in `--json` mode — JSON output stays strictly machine-readable. +3. **Keep core runtime-agnostic** - Use native APIs, avoid runtime-specific dependencies +4. **Error handling** - Provide clear, actionable error messages; use appropriate exit codes +5. **Retry logic** - Use exponential backoff for network operations (3 attempts for requests, 1s→30s for streams) +6. **Concurrent safety** - Use file locking for shared state (`sessions.json`) +7. **Security** - Never log credentials (log `present`/`MISSING` instead); use OS keychain; enforce HTTPS; use `execFile()` not `exec()`; escape HTML output; validate Host headers on local servers; send secrets via IPC not CLI args; see "Security Considerations" section for full guidelines +8. **Output formatting** - Support both human-readable (default) and JSON (`--json`) modes +9. **Protocol compliance** - Follow MCP specification strictly; handle all notification types +10. **Session management** - Always clean up resources; handle orphaned processes; provide reconnection +11. **Hyphenated commands** - All MCP commands use hyphens: `tools-list`, `resources-read`, `prompts-list` +12. **Command-first syntax** - Top-level commands come first (`connect`, `login`, `clean`); MCP operations always go through a named session (`mcpc @session `) +13. **JSON field naming** - Use consistent field names in JSON output: - `sessionName` (not `name`) for session identifiers - `server` (not `target`) for server URLs/addresses - No `success` wrapper - indicate errors via exit codes diff --git a/src/cli/commands/sessions.ts b/src/cli/commands/sessions.ts index 58f25af..9bab926 100644 --- a/src/cli/commands/sessions.ts +++ b/src/cli/commands/sessions.ts @@ -744,6 +744,7 @@ export async function listSessionsAndAuthProfiles(options: { console.log(chalk.dim(` ↳ run: mcpc ${session.name} restart`)); } } + console.log(chalk.dim(' ↳ view a session: mcpc @sessionname')); } // Display auth profiles @@ -1411,11 +1412,14 @@ export async function connectAllFromStandardConfigs(options: BulkConnectOptions) } if (skippedStdio.length > 0) { parts.push( - `skipped ${skippedStdio.length} stdio server${skippedStdio.length === 1 ? '' : 's'}, pass --stdio to include` + `skipped ${skippedStdio.length} stdio server${skippedStdio.length === 1 ? '' : 's'}` ); } if (parts.length > 0) { console.log(theme.cyan(`\n${parts.join('. ')}.`)); + if (skippedStdio.length > 0) { + console.log(chalk.dim(' ↳ run: mcpc connect --stdio')); + } } } From 4b93489205e5018a0221a24e87940f1002f1115a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 20 May 2026 20:29:42 +0000 Subject: [PATCH 2/6] Link Node.js / Bun install pages in README Adds a one-liner before the install snippet pointing newbies to nodejs.org and bun.sh so they don't have to figure out where to get the runtime first. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 843eb40..cef6b21 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,8 @@ many AI agents on the same machine. Authenticate once, reuse everywhere. ## Install +Requires a JavaScript runtime — install [Node.js](https://nodejs.org/en/download) (≥ 18) or [Bun](https://bun.sh) (≥ 1) if you don't have one yet. + ```bash npm install -g @apify/mcpc From bd09fadd0e340e73be87c4ef53e35f01ca7ad276 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 09:28:02 +0000 Subject: [PATCH 3/6] Move `view a session` hint next to the `mcpc --help` line MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously the hint was placed directly after the sessions list, where its 2-space indent collided visually with the 4-space recovery hints under each session (e.g. `↳ run: mcpc @test restart`), making it look like a per-session hint rather than a global one. Now `listSessionsAndAuthProfiles` returns `hasSessions`, and the caller prints the view-session hint immediately above the existing `Run "mcpc --help"...` line — visually grouped with the global footer instead of nested inside the session list. --- src/cli/commands/sessions.ts | 5 +++-- src/cli/index.ts | 22 ++++++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/cli/commands/sessions.ts b/src/cli/commands/sessions.ts index 18cfb82..9ab8b03 100644 --- a/src/cli/commands/sessions.ts +++ b/src/cli/commands/sessions.ts @@ -683,7 +683,7 @@ export function formatTimeAgo(isoDate: string | undefined): string { */ export async function listSessionsAndAuthProfiles(options: { outputMode: OutputMode; -}): Promise { +}): Promise<{ hasSessions: boolean }> { // Consolidate sessions first (cleans up crashed bridges, removes expired sessions) const consolidateResult = await consolidateSessions(false); const sessions = Object.values(consolidateResult.sessions); @@ -744,7 +744,6 @@ export async function listSessionsAndAuthProfiles(options: { console.log(chalk.dim(` ↳ run: mcpc ${session.name} restart`)); } } - console.log(chalk.dim(' ↳ view a session: mcpc @sessionname')); } // Display auth profiles @@ -773,6 +772,8 @@ export async function listSessionsAndAuthProfiles(options: { } } } + + return { hasSessions: sessions.length > 0 }; } /** diff --git a/src/cli/index.ts b/src/cli/index.ts index 72efb0a..e866eb1 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -234,9 +234,16 @@ async function main(): Promise { if (!firstNonOption) { const { json } = extractOptions(args); if (json) setJsonMode(true); - await sessions.listSessionsAndAuthProfiles({ outputMode: json ? 'json' : 'human' }); + const { hasSessions } = await sessions.listSessionsAndAuthProfiles({ + outputMode: json ? 'json' : 'human', + }); if (!json) { - console.log('\nRun "mcpc --help" for usage information.\n'); + console.log(''); + if (hasSessions) { + console.log(chalk.dim(' ↳ view a session: mcpc @sessionname')); + } + console.log('Run "mcpc --help" for usage information.'); + console.log(''); } await closeFileLogger(); return; @@ -824,9 +831,16 @@ ${jsonHelp('`[{ sessionName, tools?: Tool[], resources?: Resource[], prompts?: P const opts = program.opts(); const json = opts.json || getJsonFromEnv(); if (json) setJsonMode(true); - await sessions.listSessionsAndAuthProfiles({ outputMode: json ? 'json' : 'human' }); + const { hasSessions } = await sessions.listSessionsAndAuthProfiles({ + outputMode: json ? 'json' : 'human', + }); if (!json) { - console.log('\nRun "mcpc --help" for usage information.\n'); + console.log(''); + if (hasSessions) { + console.log(chalk.dim(' ↳ view a session: mcpc @sessionname')); + } + console.log('Run "mcpc --help" for usage information.'); + console.log(''); } }); From 31f9346c0b85eeead164ab274dc6aba056af48c9 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 11:15:35 +0000 Subject: [PATCH 4/6] Improve `mcpc` footer hints and fix `1 weeks ago` plural - Rephrase the view-session hint to match the existing `Run "..."` footer line: `Run "mcpc @sessionname" to view session details.` sits naturally next to `Run "mcpc --help" for usage information.` - Fix `formatTimeAgo` to use singular form when the count is 1: `1 week ago` / `1 month ago` instead of `1 weeks ago` / `1 months ago`. --- src/cli/commands/sessions.ts | 8 ++++++-- src/cli/index.ts | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/cli/commands/sessions.ts b/src/cli/commands/sessions.ts index 9ab8b03..c80c610 100644 --- a/src/cli/commands/sessions.ts +++ b/src/cli/commands/sessions.ts @@ -673,8 +673,12 @@ export function formatTimeAgo(isoDate: string | undefined): string { if (diffHours < 24) return `${diffHours}h ago`; if (diffDays === 1) return 'yesterday'; if (diffDays < 7) return `${diffDays} days ago`; - if (diffDays < 30) return `${Math.floor(diffDays / 7)} weeks ago`; - return `${Math.floor(diffDays / 30)} months ago`; + if (diffDays < 30) { + const weeks = Math.floor(diffDays / 7); + return `${weeks} ${weeks === 1 ? 'week' : 'weeks'} ago`; + } + const months = Math.floor(diffDays / 30); + return `${months} ${months === 1 ? 'month' : 'months'} ago`; } /** diff --git a/src/cli/index.ts b/src/cli/index.ts index e866eb1..2c82d6c 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -240,7 +240,7 @@ async function main(): Promise { if (!json) { console.log(''); if (hasSessions) { - console.log(chalk.dim(' ↳ view a session: mcpc @sessionname')); + console.log('Run "mcpc @sessionname" to view session details.'); } console.log('Run "mcpc --help" for usage information.'); console.log(''); @@ -837,7 +837,7 @@ ${jsonHelp('`[{ sessionName, tools?: Tool[], resources?: Resource[], prompts?: P if (!json) { console.log(''); if (hasSessions) { - console.log(chalk.dim(' ↳ view a session: mcpc @sessionname')); + console.log('Run "mcpc @sessionname" to view session details.'); } console.log('Run "mcpc --help" for usage information.'); console.log(''); From 4b6f1ebd98e0c3c4083738c770404d2356d49329 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 11:19:29 +0000 Subject: [PATCH 5/6] Rephrase `mcpc` footer hints to match `To X, run: ...` style Aligns the two footer lines with the existing `To X, run: ...` / `For X, run: ...` pattern used in tasks.ts, helpers.ts, bridge-manager.ts, and errors.ts: To view server info and capabilities, run: mcpc @session For usage information, run: mcpc --help --- src/cli/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cli/index.ts b/src/cli/index.ts index 2c82d6c..69c2b9b 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -240,9 +240,9 @@ async function main(): Promise { if (!json) { console.log(''); if (hasSessions) { - console.log('Run "mcpc @sessionname" to view session details.'); + console.log('To view server info and capabilities, run: mcpc @session'); } - console.log('Run "mcpc --help" for usage information.'); + console.log('For usage information, run: mcpc --help'); console.log(''); } await closeFileLogger(); @@ -837,9 +837,9 @@ ${jsonHelp('`[{ sessionName, tools?: Tool[], resources?: Resource[], prompts?: P if (!json) { console.log(''); if (hasSessions) { - console.log('Run "mcpc @sessionname" to view session details.'); + console.log('To view server info and capabilities, run: mcpc @session'); } - console.log('Run "mcpc --help" for usage information.'); + console.log('For usage information, run: mcpc --help'); console.log(''); } }); From 15f33c9ddaefdf88d4db0acad759e53ab9c2a014 Mon Sep 17 00:00:00 2001 From: Jan Curn Date: Thu, 21 May 2026 13:21:40 +0200 Subject: [PATCH 6/6] Better copy --- src/cli/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/index.ts b/src/cli/index.ts index 69c2b9b..c844163 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -240,7 +240,7 @@ async function main(): Promise { if (!json) { console.log(''); if (hasSessions) { - console.log('To view server info and capabilities, run: mcpc @session'); + console.log('To view server capabilities and tools, run: mcpc @session'); } console.log('For usage information, run: mcpc --help'); console.log(''); @@ -837,7 +837,7 @@ ${jsonHelp('`[{ sessionName, tools?: Tool[], resources?: Resource[], prompts?: P if (!json) { console.log(''); if (hasSessions) { - console.log('To view server info and capabilities, run: mcpc @session'); + console.log('To view server capabilities and tools, run: mcpc @session'); } console.log('For usage information, run: mcpc --help'); console.log('');