Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <command> --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 <command>`)
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(' ↳ <action>: mcpc <command>')` 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 <command>`)
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
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
17 changes: 13 additions & 4 deletions src/cli/commands/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`;
}

/**
Expand All @@ -683,7 +687,7 @@ export function formatTimeAgo(isoDate: string | undefined): string {
*/
export async function listSessionsAndAuthProfiles(options: {
outputMode: OutputMode;
}): Promise<void> {
}): Promise<{ hasSessions: boolean }> {
// Consolidate sessions first (cleans up crashed bridges, removes expired sessions)
const consolidateResult = await consolidateSessions(false);
const sessions = Object.values(consolidateResult.sessions);
Expand Down Expand Up @@ -772,6 +776,8 @@ export async function listSessionsAndAuthProfiles(options: {
}
}
}

return { hasSessions: sessions.length > 0 };
}

/**
Expand Down Expand Up @@ -1411,11 +1417,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'));
}
}
}

Expand Down
22 changes: 18 additions & 4 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,9 +234,16 @@ async function main(): Promise<void> {
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('To view server capabilities and tools, run: mcpc @session');
}
console.log('For usage information, run: mcpc --help');
console.log('');
}
await closeFileLogger();
return;
Expand Down Expand Up @@ -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('To view server capabilities and tools, run: mcpc @session');
}
console.log('For usage information, run: mcpc --help');
console.log('');
}
});

Expand Down
Loading