@apify/mcpc 0.2.4 → 0.3.0-beta.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.
Files changed (123) hide show
  1. package/CHANGELOG.md +64 -1
  2. package/CONTRIBUTING.md +12 -0
  3. package/NOTICE +27 -0
  4. package/README.md +219 -226
  5. package/_config.yml +30 -0
  6. package/client-logo.svg +79 -0
  7. package/client-metadata.json +16 -0
  8. package/dist/bridge/index.js +51 -4
  9. package/dist/bridge/index.js.map +1 -1
  10. package/dist/cli/commands/auth.d.ts +2 -0
  11. package/dist/cli/commands/auth.d.ts.map +1 -1
  12. package/dist/cli/commands/auth.js +32 -10
  13. package/dist/cli/commands/auth.js.map +1 -1
  14. package/dist/cli/commands/clean.d.ts.map +1 -1
  15. package/dist/cli/commands/clean.js +13 -2
  16. package/dist/cli/commands/clean.js.map +1 -1
  17. package/dist/cli/commands/grep.d.ts.map +1 -1
  18. package/dist/cli/commands/grep.js +39 -8
  19. package/dist/cli/commands/grep.js.map +1 -1
  20. package/dist/cli/commands/prompts.d.ts.map +1 -1
  21. package/dist/cli/commands/prompts.js +7 -26
  22. package/dist/cli/commands/prompts.js.map +1 -1
  23. package/dist/cli/commands/resources.d.ts.map +1 -1
  24. package/dist/cli/commands/resources.js +9 -3
  25. package/dist/cli/commands/resources.js.map +1 -1
  26. package/dist/cli/commands/sessions.d.ts +45 -2
  27. package/dist/cli/commands/sessions.d.ts.map +1 -1
  28. package/dist/cli/commands/sessions.js +493 -27
  29. package/dist/cli/commands/sessions.js.map +1 -1
  30. package/dist/cli/commands/tasks.d.ts +1 -0
  31. package/dist/cli/commands/tasks.d.ts.map +1 -1
  32. package/dist/cli/commands/tasks.js +15 -1
  33. package/dist/cli/commands/tasks.js.map +1 -1
  34. package/dist/cli/commands/tools.d.ts +6 -1
  35. package/dist/cli/commands/tools.d.ts.map +1 -1
  36. package/dist/cli/commands/tools.js +66 -14
  37. package/dist/cli/commands/tools.js.map +1 -1
  38. package/dist/cli/commands/x402.d.ts.map +1 -1
  39. package/dist/cli/commands/x402.js +7 -7
  40. package/dist/cli/commands/x402.js.map +1 -1
  41. package/dist/cli/helpers.d.ts.map +1 -1
  42. package/dist/cli/helpers.js +3 -6
  43. package/dist/cli/helpers.js.map +1 -1
  44. package/dist/cli/index.js +370 -131
  45. package/dist/cli/index.js.map +1 -1
  46. package/dist/cli/output.d.ts +18 -5
  47. package/dist/cli/output.d.ts.map +1 -1
  48. package/dist/cli/output.js +275 -89
  49. package/dist/cli/output.js.map +1 -1
  50. package/dist/cli/parser.d.ts +4 -0
  51. package/dist/cli/parser.d.ts.map +1 -1
  52. package/dist/cli/parser.js +68 -24
  53. package/dist/cli/parser.js.map +1 -1
  54. package/dist/cli/shell.d.ts.map +1 -1
  55. package/dist/cli/shell.js +44 -21
  56. package/dist/cli/shell.js.map +1 -1
  57. package/dist/cli/tool-result.d.ts +1 -1
  58. package/dist/cli/tool-result.d.ts.map +1 -1
  59. package/dist/cli/tool-result.js +20 -15
  60. package/dist/cli/tool-result.js.map +1 -1
  61. package/dist/core/factory.d.ts +1 -0
  62. package/dist/core/factory.d.ts.map +1 -1
  63. package/dist/core/factory.js +3 -0
  64. package/dist/core/factory.js.map +1 -1
  65. package/dist/core/mcp-client.d.ts +1 -0
  66. package/dist/core/mcp-client.d.ts.map +1 -1
  67. package/dist/core/mcp-client.js +14 -0
  68. package/dist/core/mcp-client.js.map +1 -1
  69. package/dist/core/transports.d.ts +5 -1
  70. package/dist/core/transports.d.ts.map +1 -1
  71. package/dist/core/transports.js +26 -4
  72. package/dist/core/transports.js.map +1 -1
  73. package/dist/lib/auth/auth-page.d.ts +13 -0
  74. package/dist/lib/auth/auth-page.d.ts.map +1 -0
  75. package/dist/lib/auth/auth-page.js +129 -0
  76. package/dist/lib/auth/auth-page.js.map +1 -0
  77. package/dist/lib/auth/oauth-flow.d.ts +2 -1
  78. package/dist/lib/auth/oauth-flow.d.ts.map +1 -1
  79. package/dist/lib/auth/oauth-flow.js +65 -58
  80. package/dist/lib/auth/oauth-flow.js.map +1 -1
  81. package/dist/lib/auth/oauth-provider.d.ts +2 -0
  82. package/dist/lib/auth/oauth-provider.d.ts.map +1 -1
  83. package/dist/lib/auth/oauth-provider.js +6 -0
  84. package/dist/lib/auth/oauth-provider.js.map +1 -1
  85. package/dist/lib/auth/oauth-utils.d.ts +3 -0
  86. package/dist/lib/auth/oauth-utils.d.ts.map +1 -1
  87. package/dist/lib/auth/oauth-utils.js +32 -1
  88. package/dist/lib/auth/oauth-utils.js.map +1 -1
  89. package/dist/lib/auth/profiles.d.ts.map +1 -1
  90. package/dist/lib/auth/profiles.js +3 -3
  91. package/dist/lib/auth/profiles.js.map +1 -1
  92. package/dist/lib/bridge-manager.d.ts.map +1 -1
  93. package/dist/lib/bridge-manager.js +43 -28
  94. package/dist/lib/bridge-manager.js.map +1 -1
  95. package/dist/lib/cleanup.d.ts +5 -0
  96. package/dist/lib/cleanup.d.ts.map +1 -1
  97. package/dist/lib/cleanup.js +38 -1
  98. package/dist/lib/cleanup.js.map +1 -1
  99. package/dist/lib/config.d.ts +21 -0
  100. package/dist/lib/config.d.ts.map +1 -1
  101. package/dist/lib/config.js +99 -5
  102. package/dist/lib/config.js.map +1 -1
  103. package/dist/lib/errors.d.ts +1 -0
  104. package/dist/lib/errors.d.ts.map +1 -1
  105. package/dist/lib/errors.js +4 -1
  106. package/dist/lib/errors.js.map +1 -1
  107. package/dist/lib/session-client.d.ts +1 -0
  108. package/dist/lib/session-client.d.ts.map +1 -1
  109. package/dist/lib/session-client.js +7 -4
  110. package/dist/lib/session-client.js.map +1 -1
  111. package/dist/lib/sessions.d.ts.map +1 -1
  112. package/dist/lib/sessions.js +18 -9
  113. package/dist/lib/sessions.js.map +1 -1
  114. package/dist/lib/types.d.ts +2 -0
  115. package/dist/lib/types.d.ts.map +1 -1
  116. package/dist/lib/utils.d.ts +16 -2
  117. package/dist/lib/utils.d.ts.map +1 -1
  118. package/dist/lib/utils.js +112 -8
  119. package/dist/lib/utils.js.map +1 -1
  120. package/dist/lib/wallets.js +3 -3
  121. package/dist/lib/wallets.js.map +1 -1
  122. package/docs/TODOs.md +5 -0
  123. package/package.json +7 -6
@@ -1,8 +1,9 @@
1
1
  import chalk from 'chalk';
2
- import { extractSingleTextContent } from './tool-result.js';
3
- import { isValidSessionName } from '../lib/utils.js';
2
+ import { extractAllTextContent } from './tool-result.js';
3
+ import { join } from 'node:path';
4
+ import { getLogsDir } from '../lib/utils.js';
4
5
  import { getSession } from '../lib/sessions.js';
5
- export { extractSingleTextContent } from './tool-result.js';
6
+ export { extractAllTextContent } from './tool-result.js';
6
7
  function hslToHex(h, s, l) {
7
8
  s /= 100;
8
9
  l /= 100;
@@ -16,6 +17,19 @@ function hslToHex(h, s, l) {
16
17
  };
17
18
  return `#${f(0)}${f(8)}${f(4)}`;
18
19
  }
20
+ const RAINBOW_HUE_START = 12;
21
+ const RAINBOW_HUE_SPAN = 270;
22
+ const RAINBOW_SATURATION = 45;
23
+ const RAINBOW_LIGHTNESS = 62;
24
+ const themeHex = (hue) => hslToHex(hue, RAINBOW_SATURATION, RAINBOW_LIGHTNESS);
25
+ export const theme = {
26
+ red: chalk.hex(themeHex(12)),
27
+ yellow: chalk.hex(themeHex(60)),
28
+ green: chalk.hex(hslToHex(135, 65, 52)),
29
+ cyan: chalk.hex(themeHex(190)),
30
+ blue: chalk.hex(themeHex(230)),
31
+ magenta: chalk.hex(themeHex(282)),
32
+ };
19
33
  export function rainbow(text) {
20
34
  const len = text.length;
21
35
  if (len === 0)
@@ -23,9 +37,8 @@ export function rainbow(text) {
23
37
  return text
24
38
  .split('')
25
39
  .map((char, i) => {
26
- const hue = 12 + (i / (len - 1)) * 270;
27
- const hex = hslToHex(hue, 45, 62);
28
- return chalk.hex(hex)(char);
40
+ const hue = RAINBOW_HUE_START + (i / (len - 1)) * RAINBOW_HUE_SPAN;
41
+ return chalk.hex(themeHex(hue))(char);
29
42
  })
30
43
  .join('');
31
44
  }
@@ -33,9 +46,12 @@ export function formatOutput(data, mode = 'human', options) {
33
46
  if (mode === 'json') {
34
47
  return formatJson(data);
35
48
  }
36
- const output = formatHuman(data, options);
49
+ let output = formatHuman(data, options);
37
50
  if (!output.endsWith('````') && !output.endsWith('\n')) {
38
- return output + '\n';
51
+ output += '\n';
52
+ }
53
+ if (options?.maxChars) {
54
+ output = truncateOutput(output, options.maxChars);
39
55
  }
40
56
  return output;
41
57
  }
@@ -49,16 +65,16 @@ export function formatJson(data) {
49
65
  function highlightJson(json) {
50
66
  return json.replace(/("(?:\\.|[^"\\])*")\s*:|("(?:\\.|[^"\\])*")|(\b(?:true|false|null)\b)|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)/g, (match, key, str, bool, num) => {
51
67
  if (key) {
52
- return chalk.cyan(key) + ':';
68
+ return theme.cyan(key) + ':';
53
69
  }
54
70
  if (str) {
55
- return chalk.green(str);
71
+ return theme.green(str);
56
72
  }
57
73
  if (bool) {
58
- return chalk.magenta(bool);
74
+ return theme.magenta(bool);
59
75
  }
60
76
  if (num) {
61
- return chalk.yellow(num);
77
+ return theme.yellow(num);
62
78
  }
63
79
  return match;
64
80
  });
@@ -67,9 +83,9 @@ export function formatHuman(data, options) {
67
83
  if (data === null || data === undefined) {
68
84
  return chalk.gray('(no data)');
69
85
  }
70
- const singleText = extractSingleTextContent(data);
71
- if (singleText !== undefined) {
72
- return `${chalk.gray('````')}\n${singleText}\n${chalk.gray('````')}`;
86
+ const textContent = extractAllTextContent(data);
87
+ if (textContent !== undefined) {
88
+ return `${chalk.gray('````')}\n${textContent}\n${chalk.gray('````')}`;
73
89
  }
74
90
  if (Array.isArray(data)) {
75
91
  if (data.length === 0) {
@@ -111,7 +127,7 @@ export function formatToolAnnotations(annotations) {
111
127
  parts.push('read-only');
112
128
  }
113
129
  else if (annotations.destructiveHint === true) {
114
- parts.push(chalk.red('destructive'));
130
+ parts.push(theme.red('destructive'));
115
131
  }
116
132
  if (annotations.idempotentHint === true) {
117
133
  parts.push('idempotent');
@@ -121,6 +137,21 @@ export function formatToolAnnotations(annotations) {
121
137
  }
122
138
  return parts.length > 0 ? parts.join(', ') : null;
123
139
  }
140
+ export function getToolTaskSupport(tool) {
141
+ const toolAny = tool;
142
+ const execution = toolAny.execution;
143
+ return execution?.taskSupport;
144
+ }
145
+ export function formatToolHints(tool) {
146
+ const parts = [];
147
+ const annotationsStr = formatToolAnnotations(tool.annotations);
148
+ if (annotationsStr)
149
+ parts.push(annotationsStr);
150
+ const taskSupport = getToolTaskSupport(tool);
151
+ if (taskSupport && taskSupport !== 'forbidden')
152
+ parts.push(`task:${taskSupport}`);
153
+ return parts.length > 0 ? parts.join(', ') : null;
154
+ }
124
155
  export function formatSchemaType(schema) {
125
156
  if (!schema || typeof schema !== 'object') {
126
157
  return 'any';
@@ -161,7 +192,7 @@ export function grayBacktick() {
161
192
  return chalk.gray('`');
162
193
  }
163
194
  export function inBackticks(text) {
164
- return `${grayBacktick()}${chalk.cyan(text)}${grayBacktick()}`;
195
+ return `${grayBacktick()}${theme.cyan(text)}${grayBacktick()}`;
165
196
  }
166
197
  export function formatSimplifiedArgs(schema, indent = '') {
167
198
  const lines = [];
@@ -181,9 +212,9 @@ export function formatSimplifiedArgs(schema, indent = '') {
181
212
  const isRequired = required.includes(name);
182
213
  const description = propSchema.description;
183
214
  const defaultValue = propSchema.default;
184
- let line = `${indent}${bullet} ${inBackticks(name)}: ${chalk.yellow(typeStr)}`;
215
+ let line = `${indent}${bullet} ${inBackticks(name)}: ${theme.yellow(typeStr)}`;
185
216
  if (isRequired) {
186
- line += ` ${chalk.red('[required]')}`;
217
+ line += ` ${theme.red('[required]')}`;
187
218
  }
188
219
  if (defaultValue !== undefined) {
189
220
  line += chalk.dim(` (default: ${JSON.stringify(defaultValue)})`);
@@ -262,17 +293,9 @@ export function formatToolParamsInline(schema) {
262
293
  export function formatToolLine(tool) {
263
294
  const bullet = chalk.dim('*');
264
295
  const params = formatToolParamsInline(tool.inputSchema);
265
- const parts = [];
266
- const annotationsStr = formatToolAnnotations(tool.annotations);
267
- if (annotationsStr)
268
- parts.push(annotationsStr);
269
- const toolAny = tool;
270
- const execution = toolAny.execution;
271
- const taskSupport = execution?.taskSupport;
272
- if (taskSupport)
273
- parts.push(`task:${taskSupport}`);
274
- const suffix = parts.length > 0 ? ` ${chalk.gray(`[${parts.join(', ')}]`)}` : '';
275
- return `${bullet} ${grayBacktick()}${chalk.cyan(tool.name)} ${params}${grayBacktick()}${suffix}`;
296
+ const hintsStr = formatToolHints(tool);
297
+ const suffix = hintsStr ? ` ${chalk.gray(`[${hintsStr}]`)}` : '';
298
+ return `${bullet} ${grayBacktick()}${theme.cyan(tool.name)} ${params}${grayBacktick()}${suffix}`;
276
299
  }
277
300
  function formatToolsSummary(tools) {
278
301
  const lines = [];
@@ -304,9 +327,9 @@ export function formatToolDetail(tool) {
304
327
  if (title) {
305
328
  lines.push(chalk.bold(`# ${title}`));
306
329
  }
307
- const annotationsStr = formatToolAnnotations(tool.annotations);
308
- const annotationsSuffix = annotationsStr ? ` ${chalk.gray(`[${annotationsStr}]`)}` : '';
309
- lines.push(`${chalk.bold('Tool:')} ${inBackticks(tool.name)}${annotationsSuffix}`);
330
+ const hintsStr = formatToolHints(tool);
331
+ const hintsSuffix = hintsStr ? ` ${chalk.gray(`[${hintsStr}]`)}` : '';
332
+ lines.push(`${chalk.bold('Tool:')} ${inBackticks(tool.name)}${hintsSuffix}`);
310
333
  lines.push('');
311
334
  lines.push(chalk.bold('Input:'));
312
335
  const inputArgs = formatSimplifiedArgs(tool.inputSchema, '');
@@ -327,6 +350,69 @@ export function formatToolDetail(tool) {
327
350
  }
328
351
  return lines.join('\n');
329
352
  }
353
+ function exampleValue(propSchema) {
354
+ if (propSchema.default !== undefined) {
355
+ return JSON.stringify(propSchema.default);
356
+ }
357
+ if (propSchema.enum && Array.isArray(propSchema.enum) && propSchema.enum.length > 0) {
358
+ return JSON.stringify(propSchema.enum[0]);
359
+ }
360
+ const schemaType = propSchema.type;
361
+ if (schemaType === 'string')
362
+ return '"something"';
363
+ if (schemaType === 'number')
364
+ return '1';
365
+ if (schemaType === 'integer') {
366
+ const min = propSchema.minimum;
367
+ return String(min ?? 1);
368
+ }
369
+ if (schemaType === 'boolean')
370
+ return 'true';
371
+ if (Array.isArray(schemaType)) {
372
+ const nonNull = schemaType.filter((t) => t !== 'null');
373
+ if (nonNull.includes('string'))
374
+ return '"something"';
375
+ if (nonNull.includes('number') || nonNull.includes('integer'))
376
+ return '1';
377
+ if (nonNull.includes('boolean'))
378
+ return 'true';
379
+ }
380
+ return '"something"';
381
+ }
382
+ function shellSafeExampleValue(jsonValue) {
383
+ if (/^[a-zA-Z0-9_.+-]+$/.test(jsonValue)) {
384
+ return jsonValue;
385
+ }
386
+ return `'${jsonValue.replace(/'/g, `'\\''`)}'`;
387
+ }
388
+ export function formatToolCallExample(tool, sessionName) {
389
+ const schema = tool.inputSchema;
390
+ const properties = schema?.properties;
391
+ const session = sessionName || '<@session>';
392
+ const taskSupport = getToolTaskSupport(tool);
393
+ const taskFlag = taskSupport === 'required' ? ' --task' : taskSupport === 'optional' ? ' [--task]' : '';
394
+ const bullet = chalk.dim('*');
395
+ if (!properties || Object.keys(properties).length === 0) {
396
+ const cmd = `mcpc ${session} tools-call ${tool.name}${taskFlag}`;
397
+ return `${chalk.bold('Call example:')}\n${bullet} ${grayBacktick()}${theme.cyan(cmd)}${grayBacktick()}`;
398
+ }
399
+ const requiredNames = schema?.required || [];
400
+ const allNames = Object.keys(properties);
401
+ const requiredInOrder = allNames.filter((n) => requiredNames.includes(n));
402
+ const optionalInOrder = allNames.filter((n) => !requiredNames.includes(n));
403
+ const MAX_EXAMPLE_PARAMS = 3;
404
+ const params = [...requiredInOrder];
405
+ if (params.length < MAX_EXAMPLE_PARAMS) {
406
+ const remaining = MAX_EXAMPLE_PARAMS - params.length;
407
+ params.push(...optionalInOrder.slice(0, remaining));
408
+ }
409
+ const argParts = params.map((name) => {
410
+ const val = shellSafeExampleValue(exampleValue(properties[name] ?? {}));
411
+ return `${name}:=${val}`;
412
+ });
413
+ const cmd = `mcpc ${session} tools-call ${tool.name} ${argParts.join(' ')}${taskFlag}`;
414
+ return `${chalk.bold('Call example:')}\n${bullet} ${grayBacktick()}${theme.cyan(cmd)}${grayBacktick()}`;
415
+ }
330
416
  export function formatResources(resources) {
331
417
  const lines = [];
332
418
  lines.push(chalk.bold(`Resources (${resources.length}):`));
@@ -348,7 +434,7 @@ export function formatResourceDetail(resource) {
348
434
  lines.push(`${chalk.bold('Name:')} ${resource.name}`);
349
435
  }
350
436
  if (resource.mimeType) {
351
- lines.push(`${chalk.bold('MIME type:')} ${chalk.yellow(resource.mimeType)}`);
437
+ lines.push(`${chalk.bold('MIME type:')} ${theme.yellow(resource.mimeType)}`);
352
438
  }
353
439
  const description = (resource.description || '').trim();
354
440
  if (description) {
@@ -381,7 +467,7 @@ export function formatResourceTemplateDetail(template) {
381
467
  lines.push(`${chalk.bold('Name:')} ${template.name}`);
382
468
  }
383
469
  if (template.mimeType) {
384
- lines.push(`${chalk.bold('MIME type:')} ${chalk.yellow(template.mimeType)}`);
470
+ lines.push(`${chalk.bold('MIME type:')} ${theme.yellow(template.mimeType)}`);
385
471
  }
386
472
  const description = (template.description || '').trim();
387
473
  if (description) {
@@ -414,8 +500,8 @@ export function formatPromptDetail(prompt) {
414
500
  lines.push(chalk.bold('Arguments:'));
415
501
  if (prompt.arguments && prompt.arguments.length > 0) {
416
502
  for (const arg of prompt.arguments) {
417
- const typePart = chalk.yellow('string');
418
- const requiredPart = arg.required ? ` ${chalk.red('[required]')}` : '';
503
+ const typePart = theme.yellow('string');
504
+ const requiredPart = arg.required ? ` ${theme.red('[required]')}` : '';
419
505
  const description = arg.description ? ` ${chalk.dim('-')} ${arg.description}` : '';
420
506
  lines.push(` ${inBackticks(arg.name)}: ${typePart}${requiredPart}${description}`);
421
507
  }
@@ -457,7 +543,7 @@ function formatPromptResult(result) {
457
543
  lines.push(chalk.bold(`Messages (${result.messages.length}):`));
458
544
  for (const message of result.messages) {
459
545
  lines.push('');
460
- lines.push(`${chalk.bold('Role:')} ${chalk.cyan(message.role)}`);
546
+ lines.push(`${chalk.bold('Role:')} ${theme.cyan(message.role)}`);
461
547
  lines.push(formatPromptContent(message.content));
462
548
  }
463
549
  return lines.join('\n');
@@ -509,26 +595,27 @@ function formatPromptContent(content) {
509
595
  }
510
596
  return lines.join('\n');
511
597
  }
512
- function taskStatusIcon(status) {
598
+ function taskStatusLabel(status) {
599
+ const label = (icon) => `${icon} ${status}`;
513
600
  switch (status) {
514
601
  case 'working':
515
- return chalk.cyan('⟳');
602
+ return theme.cyan(label('⟳'));
516
603
  case 'input_required':
517
- return chalk.yellow('?');
604
+ return theme.yellow(label('?'));
518
605
  case 'completed':
519
- return chalk.green('✔');
606
+ return theme.green(label('✔'));
520
607
  case 'failed':
521
- return chalk.red('✖');
608
+ return theme.red(label('✖'));
522
609
  case 'cancelled':
523
- return chalk.gray('⊘');
610
+ return chalk.gray(label('⊘'));
524
611
  default:
525
- return chalk.gray('·');
612
+ return chalk.gray(label('·'));
526
613
  }
527
614
  }
528
615
  export function formatTask(task) {
529
616
  const lines = [];
530
- lines.push(`${chalk.bold('Task:')} ${inBackticks(task.taskId)}`);
531
- lines.push(`${chalk.bold('Status:')} ${taskStatusIcon(task.status)} ${task.status}`);
617
+ lines.push(`${chalk.bold('Task ID:')} ${inBackticks(task.taskId)}`);
618
+ lines.push(`${chalk.bold('Status:')} ${taskStatusLabel(task.status)}`);
532
619
  if (task.statusMessage) {
533
620
  lines.push(`${chalk.bold('Message:')} ${task.statusMessage}`);
534
621
  }
@@ -545,16 +632,115 @@ export function formatTasks(taskList) {
545
632
  lines.push(chalk.bold(`Tasks (${taskList.length}):`));
546
633
  const bullet = chalk.dim('*');
547
634
  for (const task of taskList) {
548
- const statusStr = `${taskStatusIcon(task.status)} ${task.status}`;
635
+ const statusStr = taskStatusLabel(task.status);
549
636
  const msgStr = task.statusMessage ? chalk.dim(` - ${task.statusMessage}`) : '';
550
637
  lines.push(`${bullet} ${inBackticks(task.taskId)} ${statusStr}${msgStr}`);
551
638
  }
552
639
  return lines.join('\n');
553
640
  }
641
+ function formatContentBlock(block, lines) {
642
+ const bullet = chalk.dim('*');
643
+ switch (block.type) {
644
+ case 'text':
645
+ lines.push(chalk.gray('````'));
646
+ lines.push(block.text);
647
+ lines.push(chalk.gray('````'));
648
+ break;
649
+ case 'resource_link':
650
+ lines.push(chalk.bold('Resource link'));
651
+ lines.push(`${bullet} URI: ${block.uri}`);
652
+ if (block.name)
653
+ lines.push(`${bullet} Name: ${block.name}`);
654
+ if (block.description) {
655
+ lines.push(`${bullet} Description: ${chalk.gray('````')}${block.description}${chalk.gray('````')}`);
656
+ }
657
+ if (block.mimeType)
658
+ lines.push(`${bullet} MIME type: ${block.mimeType}`);
659
+ break;
660
+ case 'image':
661
+ lines.push(`[Image: ${block.mimeType || 'unknown type'}${block.data ? `, ${block.data.length} chars base64` : ''}]`);
662
+ break;
663
+ case 'audio':
664
+ lines.push(`[Audio: ${block.mimeType || 'unknown type'}${block.data ? `, ${block.data.length} chars base64` : ''}]`);
665
+ break;
666
+ case 'resource':
667
+ lines.push(chalk.bold('Embedded resource'));
668
+ if (block.resource) {
669
+ lines.push(`${bullet} URI: ${block.resource.uri}`);
670
+ if (block.resource.mimeType)
671
+ lines.push(`${bullet} MIME type: ${block.resource.mimeType}`);
672
+ if ('text' in block.resource && block.resource.text) {
673
+ lines.push(chalk.gray('````'));
674
+ lines.push(block.resource.text);
675
+ lines.push(chalk.gray('````'));
676
+ }
677
+ }
678
+ break;
679
+ default:
680
+ lines.push(JSON.stringify(block, null, 2));
681
+ }
682
+ }
683
+ function findDuplicateTextBlocks(content, structuredContent) {
684
+ const dupes = new Set();
685
+ const canonical = JSON.stringify(structuredContent);
686
+ for (let i = 0; i < content.length; i++) {
687
+ const block = content[i];
688
+ if (!block || block.type !== 'text')
689
+ continue;
690
+ try {
691
+ const parsed = JSON.parse(block.text.trim());
692
+ if (JSON.stringify(parsed) === canonical)
693
+ dupes.add(i);
694
+ }
695
+ catch {
696
+ }
697
+ }
698
+ return dupes;
699
+ }
700
+ export function formatCallToolResultHuman(result) {
701
+ const lines = [];
702
+ const sc = result.structuredContent;
703
+ const hasStructuredContent = !!sc && Object.keys(sc).length > 0;
704
+ const content = result.content;
705
+ let skipIndices = new Set();
706
+ if (hasStructuredContent && content && sc) {
707
+ skipIndices = findDuplicateTextBlocks(content, sc);
708
+ }
709
+ if (content && content.length > 0) {
710
+ const visible = content.filter((_, i) => !skipIndices.has(i));
711
+ if (visible.length > 0) {
712
+ lines.push(chalk.bold('Content:'));
713
+ for (let i = 0; i < visible.length; i++) {
714
+ if (i > 0)
715
+ lines.push('');
716
+ formatContentBlock(visible[i], lines);
717
+ }
718
+ }
719
+ }
720
+ if (hasStructuredContent) {
721
+ if (lines.length > 0)
722
+ lines.push('');
723
+ lines.push(chalk.bold('Structured content:'));
724
+ const scJson = JSON.stringify(sc, null, 2);
725
+ lines.push(process.stdout.isTTY ? highlightJson(scJson) : scJson);
726
+ }
727
+ const meta = result._meta;
728
+ if (meta && typeof meta === 'object' && Object.keys(meta).length > 0) {
729
+ if (lines.length > 0)
730
+ lines.push('');
731
+ lines.push(chalk.bold('Metadata:'));
732
+ const metaJson = JSON.stringify(meta, null, 2);
733
+ lines.push(process.stdout.isTTY ? highlightJson(metaJson) : metaJson);
734
+ }
735
+ if (lines.length === 0) {
736
+ return chalk.gray('(no content)');
737
+ }
738
+ return lines.join('\n');
739
+ }
554
740
  export function formatObject(obj) {
555
741
  const lines = [];
556
742
  for (const [key, value] of Object.entries(obj)) {
557
- const formattedKey = chalk.cyan(`${key}:`);
743
+ const formattedKey = theme.cyan(`${key}:`);
558
744
  let formattedValue;
559
745
  if (value === null || value === undefined) {
560
746
  formattedValue = chalk.gray(String(value));
@@ -575,16 +761,35 @@ export function formatObject(obj) {
575
761
  return lines.join('\n');
576
762
  }
577
763
  export function formatSuccess(message) {
578
- return chalk.green(`✓ ${message}`);
764
+ return theme.green(`✓ ${message}`);
579
765
  }
580
766
  export function formatError(message) {
581
- return chalk.red(`✗ ${message}`);
767
+ return theme.red(`✗ ${message}`);
582
768
  }
583
769
  export function formatWarning(message) {
584
- return chalk.yellow(`⚠ ${message}`);
770
+ return theme.yellow(`⚠ ${message}`);
585
771
  }
586
772
  export function formatInfo(message) {
587
- return chalk.cyan(`ℹ ${message}`);
773
+ return theme.cyan(`ℹ ${message}`);
774
+ }
775
+ export function formatTaskCommandsHint(target, taskId, status) {
776
+ const id = taskId ?? '<taskId>';
777
+ const lines = [
778
+ '\nAvailable commands:',
779
+ ` mcpc ${target} tasks-get ${id}`,
780
+ ` mcpc ${target} tasks-result ${id}`,
781
+ ];
782
+ if (status === undefined || status === 'working' || status === 'input_required') {
783
+ lines.push(` mcpc ${target} tasks-cancel ${id}`);
784
+ }
785
+ return lines.join('\n');
786
+ }
787
+ export function truncateOutput(output, maxChars) {
788
+ if (output.length <= maxChars)
789
+ return output;
790
+ const truncated = output.substring(0, maxChars);
791
+ const totalSize = output.length >= 1024 ? `${(output.length / 1024).toFixed(1)}KB` : `${output.length} chars`;
792
+ return `${truncated}\n\n... output truncated (${totalSize} total, showing first ${maxChars} chars). Use --max-chars to adjust.`;
588
793
  }
589
794
  function truncateWithEllipsis(str, maxLen) {
590
795
  if (str.length <= maxLen + 3)
@@ -592,7 +797,7 @@ function truncateWithEllipsis(str, maxLen) {
592
797
  return str.substring(0, maxLen - 1) + '…';
593
798
  }
594
799
  export function formatSessionLine(session) {
595
- const nameStr = chalk.cyan(session.name);
800
+ const nameStr = theme.cyan(session.name);
596
801
  let target;
597
802
  if (session.server.url) {
598
803
  target = session.server.url;
@@ -604,54 +809,29 @@ export function formatSessionLine(session) {
604
809
  }
605
810
  }
606
811
  const targetStr = truncateWithEllipsis(target, 80);
607
- const parts = [];
608
- if (session.server.command) {
609
- parts.push('stdio');
812
+ let infoStr = '';
813
+ if (!session.server.command && session.profileName) {
814
+ infoStr = chalk.dim('(OAuth: ') + theme.magenta(session.profileName) + chalk.dim(')');
610
815
  }
611
- else {
612
- parts.push('HTTP');
613
- if (session.profileName) {
614
- parts.push('OAuth: ' + chalk.magenta(session.profileName) + chalk.dim(''));
615
- }
616
- }
617
- const infoStr = chalk.dim('(') + chalk.dim(parts.join(', ')) + chalk.dim(')');
618
816
  let proxyStr = '';
619
817
  if (session.proxy) {
620
818
  proxyStr =
621
819
  ' ' +
622
- chalk.green('[proxy: ') +
820
+ theme.green('[proxy: ') +
623
821
  chalk.greenBright(`${session.proxy.host}:${session.proxy.port}`) +
624
- chalk.green(']');
822
+ theme.green(']');
625
823
  }
626
- return `${nameStr} ${targetStr} ${infoStr}${proxyStr}`;
824
+ const suffix = [infoStr, proxyStr].filter(Boolean).join(' ');
825
+ return `${nameStr} → ${targetStr}${suffix ? ' ' + suffix : ''}`;
627
826
  }
628
827
  export async function logTarget(target, options) {
629
828
  if (options.outputMode !== 'human' || options.hide) {
630
829
  return;
631
830
  }
632
- if (isValidSessionName(target)) {
633
- const session = await getSession(target);
634
- if (session) {
635
- console.log(`[${formatSessionLine(session)}]\n`);
636
- }
637
- return;
638
- }
639
- const tc = options.serverConfig;
640
- if (tc?.command) {
641
- let targetStr = tc.command;
642
- if (tc.args && tc.args.length > 0) {
643
- targetStr += ' ' + tc.args.join(' ');
644
- }
645
- targetStr = truncateWithEllipsis(targetStr, 80);
646
- console.log(`[→ ${targetStr} ${chalk.dim('(stdio)')}]`);
647
- return;
648
- }
649
- const serverStr = tc?.url || target;
650
- const parts = ['HTTP'];
651
- if (options.profileName) {
652
- parts.push('OAuth: ' + chalk.magenta(options.profileName));
831
+ const session = await getSession(target);
832
+ if (session) {
833
+ console.log(`[${formatSessionLine(session)}]\n`);
653
834
  }
654
- console.log(`[→ ${serverStr} ${chalk.dim('(' + parts.join(', ') + ')')}]\n`);
655
835
  }
656
836
  export function formatJsonError(error, code) {
657
837
  return formatJson({
@@ -736,6 +916,7 @@ export function formatServerDetails(details, target, tools) {
736
916
  if (capabilities?.tasks) {
737
917
  commands.push(`${bullet} ${bt}mcpc ${target} tasks-list${bt}`);
738
918
  commands.push(`${bullet} ${bt}mcpc ${target} tasks-get <taskId>${bt}`);
919
+ commands.push(`${bullet} ${bt}mcpc ${target} tasks-result <taskId>${bt}`);
739
920
  commands.push(`${bullet} ${bt}mcpc ${target} tasks-cancel <taskId>${bt}`);
740
921
  }
741
922
  if (capabilities?.logging) {
@@ -744,6 +925,11 @@ export function formatServerDetails(details, target, tools) {
744
925
  commands.push(`${bullet} ${bt}mcpc ${target} shell${bt}`);
745
926
  lines.push(commands.join('\n'));
746
927
  lines.push('');
928
+ if (target.startsWith('@')) {
929
+ const logPath = join(getLogsDir(), `bridge-${target}.log`);
930
+ lines.push(chalk.dim(`Session log for debugging: ${logPath}`));
931
+ lines.push('');
932
+ }
747
933
  return lines.join('\n');
748
934
  }
749
935
  //# sourceMappingURL=output.js.map