@hailer/mcp 0.2.2 → 0.2.4

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.
@@ -52,10 +52,11 @@ function processHook(data) {
52
52
  process.exit(0);
53
53
  }
54
54
 
55
- const lowerPrompt = prompt.toLowerCase();
56
-
57
55
  // Detect task types that benefit from questions
56
+ // Order matters - more specific patterns first
58
57
  const taskPatterns = [
58
+ { pattern: /publish.*market|market.*publish|update.*market|market.*update|market.*icon|market.*listing/i, type: 'marketplace-publish', questions: ['New listing or update existing? (need productId for update)', 'Metadata only or new version with code?', 'Do you have an icon? (must upload with isPublic: true)'], skill: 'marketplace-publishing' },
59
+ { pattern: /publish|deploy|release|update.*app|app.*update|republish/i, type: 'app-publish', questions: ['Workspace only OR marketplace too?', 'Which app? (path or name)', 'Version bump needed?'], skill: 'publish-hailer-app' },
59
60
  { pattern: /build|create|make.*app/i, type: 'app', questions: ['What data to display?', 'What layout/components?', 'What user actions needed?'] },
60
61
  { pattern: /create|add.*insight|report/i, type: 'insight', questions: ['What metrics/aggregations?', 'Which workflows to query?', 'Any filters needed?'] },
61
62
  { pattern: /import|create.*activit|bulk/i, type: 'data', questions: ['Which workflow?', 'What field values?', 'How many records?'] },
@@ -66,6 +67,7 @@ function processHook(data) {
66
67
  const matched = taskPatterns.find(p => p.pattern.test(prompt));
67
68
 
68
69
  if (matched) {
70
+ const skillLine = matched.skill ? `\nLoad skill: ${matched.skill}` : '';
69
71
  const output = `
70
72
  <interactive-mode>
71
73
  BEFORE STARTING: Consider asking clarifying questions.
@@ -75,7 +77,7 @@ Suggested questions to ask user:
75
77
  ${matched.questions.map(q => `- ${q}`).join('\n')}
76
78
 
77
79
  Use AskUserQuestion tool if requirements are unclear.
78
- Gather specifics before spawning agents or making changes.
80
+ Gather specifics before spawning agents or making changes.${skillLine}
79
81
  </interactive-mode>
80
82
  `;
81
83
  console.log(output);
@@ -0,0 +1,155 @@
1
+ # Marketplace Publishing Skill
2
+
3
+ <when-to-use>
4
+ User wants to publish an app to marketplace, update marketplace listing, or change marketplace app icon/metadata.
5
+ </when-to-use>
6
+
7
+ <prerequisites>
8
+ - `productId` - Marketplace product ID (24-char hex)
9
+ - `appId` - The app being published (24-char hex)
10
+ - User must be Network Admin of the workspace
11
+ </prerequisites>
12
+
13
+ <option-a>
14
+ ## Update Metadata Only (No Version Change)
15
+
16
+ For updating icon, name, description without publishing new code:
17
+
18
+ <step-1>
19
+ **Upload icon as PUBLIC file**
20
+ ```javascript
21
+ upload_files({
22
+ files: [{ path: "/path/to/icon.png", isPublic: true }]
23
+ })
24
+ ```
25
+ </step-1>
26
+
27
+ <critical>
28
+ `isPublic: true` is REQUIRED for marketplace icons to display!
29
+ </critical>
30
+
31
+ <step-2>
32
+ **Update product metadata**
33
+ ```javascript
34
+ publish_app({
35
+ appId: "<appId>",
36
+ productId: "<productId>", // REQUIRED for update
37
+ title: "App Name",
38
+ description: "Description",
39
+ version: "1.0.0", // Current version (no bump needed)
40
+ versionDescription: "Release notes",
41
+ publisher: "Publisher Name",
42
+ iconFileId: "<public-file-id>"
43
+ })
44
+ ```
45
+ </step-2>
46
+ </option-a>
47
+
48
+ <option-b>
49
+ ## Publish New Version (Code Changes)
50
+
51
+ For publishing new app code with version bump:
52
+
53
+ <step-1>
54
+ **Upload icon as PUBLIC file (if changing)**
55
+ ```javascript
56
+ upload_files({
57
+ files: [{ path: "/path/to/icon.png", isPublic: true }]
58
+ })
59
+ ```
60
+ </step-1>
61
+
62
+ <step-2>
63
+ **Update manifest.json**
64
+ - Bump version (must be > current, e.g., "1.0.31" → "1.0.32")
65
+ - Update versionDescription
66
+ </step-2>
67
+
68
+ <step-3>
69
+ **Publish app bundle**
70
+ ```javascript
71
+ publish_hailer_app({
72
+ projectDirectory: "/path/to/app",
73
+ publishToMarket: true
74
+ })
75
+ ```
76
+ </step-3>
77
+
78
+ <step-4>
79
+ **Update product metadata**
80
+ ```javascript
81
+ publish_app({
82
+ appId: "<appId>",
83
+ productId: "<productId>",
84
+ title: "App Name",
85
+ description: "Description",
86
+ version: "1.0.32",
87
+ versionDescription: "What's new",
88
+ publisher: "Publisher Name",
89
+ iconFileId: "<public-file-id>"
90
+ })
91
+ ```
92
+ </step-4>
93
+ </option-b>
94
+
95
+ <option-c>
96
+ ## First-Time Marketplace Listing
97
+
98
+ For apps not yet in marketplace:
99
+
100
+ <step-1>
101
+ **Upload icon as PUBLIC**
102
+ ```javascript
103
+ upload_files({
104
+ files: [{ path: "/path/to/icon.png", isPublic: true }]
105
+ })
106
+ ```
107
+ </step-1>
108
+
109
+ <step-2>
110
+ **Publish app with marketplace flag**
111
+ ```javascript
112
+ publish_hailer_app({
113
+ projectDirectory: "/path/to/app",
114
+ publishToMarket: true
115
+ })
116
+ ```
117
+ Returns a `targetId`.
118
+ </step-2>
119
+
120
+ <step-3>
121
+ **Create marketplace listing**
122
+ ```javascript
123
+ publish_app({
124
+ appId: "<appId>",
125
+ versionId: "<targetId>", // From step 2
126
+ title: "App Name",
127
+ description: "Description",
128
+ version: "1.0.0",
129
+ versionDescription: "Initial release",
130
+ publisher: "Publisher Name",
131
+ iconFileId: "<public-file-id>"
132
+ })
133
+ ```
134
+ </step-3>
135
+
136
+ <note>
137
+ Creating new listings requires admin permissions.
138
+ </note>
139
+ </option-c>
140
+
141
+ <common-errors>
142
+ | Error | Cause | Fix |
143
+ |-------|-------|-----|
144
+ | Icon shows placeholder | File not public | Re-upload with `isPublic: true` |
145
+ | "You have to be a network admin" | Missing permissions | Get admin access |
146
+ | "Version not greater than previous" | Version too low | Bump version higher |
147
+ | POST /app/publish fails | Needs file upload | Use `publish_hailer_app` for code changes |
148
+ </common-errors>
149
+
150
+ <api-reference>
151
+ - `v3.product.update` - Updates metadata (name, description, icon, images)
152
+ - `v3.product.create` - Creates new listing (admin only)
153
+ - `POST /app/publish` - Uploads app bundle (requires .tgz file)
154
+ - `v3.app.product.install` - Installs/updates in workspace
155
+ </api-reference>
@@ -812,37 +812,15 @@ exports.publishAppTool = {
812
812
  };
813
813
  }
814
814
  let productId = args.productId;
815
- let targetId = args.versionId;
816
- // Step 1: If no versionId provided and not updating, create app version manifest
817
- if (!targetId && !productId) {
818
- const publishData = {
819
- appId: args.appId,
820
- workspaceId,
821
- version: args.version,
822
- versionDescription: args.versionDescription,
823
- title: args.title,
824
- description: args.description
815
+ const targetId = args.versionId;
816
+ // For new listings, we need both targetId (from publish_hailer_app) to create the product
817
+ if (!productId && !targetId) {
818
+ return {
819
+ content: [{
820
+ type: "text",
821
+ text: `❌ **Error**: Missing required IDs.\n\n**To create a new marketplace listing:**\n1. Run \`publish_hailer_app\` with \`publishToMarket: true\` to get a targetId\n2. Then run \`publish_app\` with the \`versionId\` (targetId)\n\n**To update existing listing metadata (icon, name, etc.):**\nInclude the \`productId\` parameter - no version bump needed.`,
822
+ }],
825
823
  };
826
- logger.debug('Calling v2.network.product.publishAppVersion', { publishData });
827
- try {
828
- const publishResult = await context.hailer.request('v2.network.product.publishAppVersion', [publishData]);
829
- logger.debug('publishAppVersion response', { result: JSON.stringify(publishResult) });
830
- targetId = publishResult?.productId || publishResult?._id || publishResult?.id;
831
- }
832
- catch (err) {
833
- logger.debug('v2.network.product.publishAppVersion failed', {
834
- error: err instanceof Error ? err.message : String(err)
835
- });
836
- // If publishAppVersion doesn't exist, the error will be caught below
837
- }
838
- if (!targetId) {
839
- return {
840
- content: [{
841
- type: "text",
842
- text: `❌ **Error**: Could not create app version for marketplace.\n\n**Note:** The app marketplace publishing API may not be available. Make sure the app has been published with \`publish_hailer_app\` first.\n\nYou can share the app directly with \`add_app_member\` instead.`,
843
- }],
844
- };
845
- }
846
824
  }
847
825
  // Step 2: Create or Update the product in marketplace
848
826
  let productData;
@@ -881,9 +859,9 @@ exports.publishAppTool = {
881
859
  apiMethod = 'v3.product.create';
882
860
  apiArgs = [productData];
883
861
  }
884
- logger.debug(`Calling ${apiMethod}`, { productId, workspaceId, appId: args.appId, targetId, iconFileId: args.iconFileId });
862
+ logger.info(`Calling ${apiMethod}`, { productId, workspaceId, appId: args.appId, targetId, productData });
885
863
  const apiResult = await context.hailer.request(apiMethod, apiArgs);
886
- logger.debug(`${apiMethod} response`, {
864
+ logger.info(`${apiMethod} response`, {
887
865
  result: JSON.stringify(apiResult)
888
866
  });
889
867
  // Get the final product ID from the v3 API response
@@ -507,11 +507,6 @@ exports.publishHailerAppTool = {
507
507
  async execute(args, context) {
508
508
  const path = await Promise.resolve().then(() => __importStar(require('path')));
509
509
  const fs = await Promise.resolve().then(() => __importStar(require('fs')));
510
- logger.debug('Step 0: Starting publishHailerApp execute function', {
511
- hasProjectDirectory: !!args.projectDirectory,
512
- hasAppId: !!args.appId,
513
- publishToMarket: args.publishToMarket
514
- });
515
510
  // Use provided credentials or fall back to session credentials
516
511
  const email = args.email || context.email;
517
512
  const password = args.password || context.password;
@@ -524,23 +519,14 @@ exports.publishHailerAppTool = {
524
519
  }],
525
520
  };
526
521
  }
527
- // Debug: log credential availability (not the actual values)
528
- logger.debug('Step 0.5: Credentials verified', {
529
- hasEmail: !!email,
530
- emailLength: email?.length,
531
- hasPassword: !!password,
532
- passwordLength: password?.length
533
- });
534
522
  try {
535
523
  const { execSync } = await Promise.resolve().then(() => __importStar(require('child_process')));
536
- // Step 1: Check if expect is installed
537
- logger.debug('Step 1: Checking if expect is installed...');
524
+ // Check if expect is installed
538
525
  try {
539
526
  execSync('which expect', { encoding: 'utf-8', stdio: 'pipe' });
540
- logger.debug('Step 1.5: expect command found');
541
527
  }
542
528
  catch {
543
- logger.error('Step 1 ERROR: expect command not found');
529
+ logger.error('expect command not found');
544
530
  return {
545
531
  content: [{
546
532
  type: "text",
@@ -548,14 +534,11 @@ exports.publishHailerAppTool = {
548
534
  }],
549
535
  };
550
536
  }
551
- // Step 2: Determine project directory
552
- logger.debug('Step 2: Checking project directory...');
537
+ // Determine project directory
553
538
  const projectDir = args.projectDirectory || config_1.environment.DEV_APPS_PATH || process.cwd();
554
- logger.debug('Step 2.5: Project directory resolved', { projectDir });
555
- // Step 3: Check if directory exists
556
- logger.debug('Step 3: Verifying project directory exists...');
539
+ // Check if directory exists
557
540
  if (!fs.existsSync(projectDir)) {
558
- logger.error('Step 3 ERROR: Project directory does not exist', { projectDir });
541
+ logger.error('Project directory does not exist', { projectDir });
559
542
  return {
560
543
  content: [{
561
544
  type: "text",
@@ -563,12 +546,10 @@ exports.publishHailerAppTool = {
563
546
  }],
564
547
  };
565
548
  }
566
- logger.debug('Step 3.5: Project directory exists');
567
- // Step 4: Check if package.json exists
568
- logger.debug('Step 4: Checking package.json...');
549
+ // Check if package.json exists
569
550
  const packageJsonPath = path.join(projectDir, 'package.json');
570
551
  if (!fs.existsSync(packageJsonPath)) {
571
- logger.error('Step 4 ERROR: package.json not found', { packageJsonPath });
552
+ logger.error('package.json not found', { packageJsonPath });
572
553
  return {
573
554
  content: [{
574
555
  type: "text",
@@ -576,32 +557,20 @@ exports.publishHailerAppTool = {
576
557
  }],
577
558
  };
578
559
  }
579
- logger.debug('Step 4.5: package.json found');
580
- // Step 5: Read manifest.json to get/verify appId
581
- logger.debug('Step 5: Reading manifest.json...');
560
+ // Read manifest.json to get/verify appId
582
561
  const manifestPath = path.join(projectDir, 'public', 'manifest.json');
583
562
  let appId = args.appId;
584
563
  let appName = 'Unknown';
585
564
  if (fs.existsSync(manifestPath)) {
586
- logger.debug('Step 5.5: manifest.json file found');
587
565
  try {
588
- logger.debug('Step 5.7: Reading manifest file content...');
589
566
  const manifestContent = fs.readFileSync(manifestPath, 'utf-8');
590
- logger.debug('Step 5.8: Parsing manifest JSON...');
591
567
  const manifest = JSON.parse(manifestContent);
592
- logger.debug('Step 5.9: Manifest parsed successfully', {
593
- hasAppId: !!manifest.appId,
594
- hasName: !!manifest.name,
595
- hasVersion: !!manifest.version,
596
- hasVersionDescription: !!manifest.versionDescription
597
- });
598
568
  if (!appId) {
599
569
  appId = manifest.appId;
600
570
  }
601
571
  appName = manifest.name || appName;
602
- logger.debug('Step 5.95: Manifest data extracted', { appId, appName });
603
572
  if (!appId) {
604
- logger.error('Step 5.97 ERROR: No appId found');
573
+ logger.error('No appId found');
605
574
  return {
606
575
  content: [{
607
576
  type: "text",
@@ -609,10 +578,9 @@ exports.publishHailerAppTool = {
609
578
  }],
610
579
  };
611
580
  }
612
- // Step 6: Validate version fields are present and not empty
613
- logger.debug('Step 6: Validating version fields...');
581
+ // Validate version fields are present and not empty
614
582
  if (!manifest.version || manifest.version.trim() === '') {
615
- logger.error('Step 6 ERROR: version field missing or empty');
583
+ logger.error('version field missing or empty');
616
584
  return {
617
585
  content: [{
618
586
  type: "text",
@@ -620,9 +588,8 @@ exports.publishHailerAppTool = {
620
588
  }],
621
589
  };
622
590
  }
623
- logger.debug('Step 6.5: version field OK', { version: manifest.version });
624
591
  if (!manifest.versionDescription || manifest.versionDescription.trim() === '') {
625
- logger.error('Step 6.7 ERROR: versionDescription field missing or empty');
592
+ logger.error('versionDescription field missing or empty');
626
593
  return {
627
594
  content: [{
628
595
  type: "text",
@@ -630,11 +597,10 @@ exports.publishHailerAppTool = {
630
597
  }],
631
598
  };
632
599
  }
633
- logger.debug('Step 6.9: versionDescription field OK', { versionDescription: manifest.versionDescription });
634
600
  }
635
601
  catch (error) {
636
602
  const errorMessage = (0, tool_helpers_1.extractErrorMessage)(error);
637
- logger.error('Step 5 ERROR: Failed to parse manifest.json', { error: errorMessage });
603
+ logger.error('Failed to parse manifest.json', { error: errorMessage });
638
604
  return {
639
605
  content: [{
640
606
  type: "text",
@@ -644,7 +610,7 @@ exports.publishHailerAppTool = {
644
610
  }
645
611
  }
646
612
  else if (!appId) {
647
- logger.error('Step 5.99 ERROR: Manifest not found and no appId provided');
613
+ logger.error('Manifest not found and no appId provided');
648
614
  return {
649
615
  content: [{
650
616
  type: "text",
@@ -652,14 +618,11 @@ exports.publishHailerAppTool = {
652
618
  }],
653
619
  };
654
620
  }
655
- // Step 7: Check if publish-production script exists
656
- logger.debug('Step 7: Checking publish-production script...');
621
+ // Check if publish-production script exists
657
622
  try {
658
- logger.debug('Step 7.3: Reading package.json for script...');
659
623
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
660
- logger.debug('Step 7.5: package.json parsed');
661
624
  if (!packageJson.scripts?.['publish-production']) {
662
- logger.error('Step 7 ERROR: publish-production script not found');
625
+ logger.error('publish-production script not found');
663
626
  return {
664
627
  content: [{
665
628
  type: "text",
@@ -667,11 +630,10 @@ exports.publishHailerAppTool = {
667
630
  }],
668
631
  };
669
632
  }
670
- logger.debug('Step 7.8: publish-production script found');
671
633
  }
672
634
  catch (error) {
673
635
  const errorMessage = (0, tool_helpers_1.extractErrorMessage)(error);
674
- logger.error('Step 7 ERROR: Failed to parse package.json for scripts', { error: errorMessage });
636
+ logger.error('Failed to parse package.json for scripts', { error: errorMessage });
675
637
  return {
676
638
  content: [{
677
639
  type: "text",
@@ -679,36 +641,28 @@ exports.publishHailerAppTool = {
679
641
  }],
680
642
  };
681
643
  }
682
- // Step 8: Prepare response and get ready to publish
683
- logger.debug('Step 8: Preparing to run publish script...');
644
+ // Log the start of publish
645
+ logger.info('Publishing app...', { appId, appName, workspace: context.workspaceCache.currentWorkspace.name });
684
646
  let responseText = `🚀 **Publishing Hailer App**\n\n`;
685
647
  responseText += `**App Name:** ${appName}\n`;
686
648
  responseText += `**App ID:** \`${appId}\`\n`;
687
649
  responseText += `**Project:** ${projectDir}\n`;
688
650
  responseText += `**Marketplace:** ${publishToMarket ? 'Yes (will get targetId)' : 'No'}\n\n`;
689
- logger.debug('Step 8.5: Response header prepared');
690
- // Step 9: Run the SDK publish script using `expect` for interactive automation
691
- // Write expect script to temp file to avoid shell escaping issues
692
- logger.debug('Step 9: Starting expect script execution process...');
651
+ // Run the SDK publish script using `expect` for interactive automation
693
652
  const os = await Promise.resolve().then(() => __importStar(require('os')));
694
653
  const result = await new Promise((resolve) => {
695
654
  // Create temp expect script file
696
- logger.debug('Step 9.1: Creating temp directory and script path...');
697
655
  const tmpDir = os.tmpdir();
698
656
  const expectScriptPath = path.join(tmpDir, `hailer-publish-${Date.now()}.exp`);
699
- logger.debug('Step 9.2: Expect script path resolved', { expectScriptPath });
700
657
  // For Tcl, use braces {} for literal strings (no escaping needed except for braces)
701
- // Escape only braces in the password
702
- logger.debug('Step 9.3: Escaping password for expect script...');
703
658
  const escapedPassword = password
704
659
  .replace(/\\/g, '\\\\')
705
660
  .replace(/\{/g, '\\{')
706
661
  .replace(/\}/g, '\\}');
707
- logger.debug('Step 9.4: Password escaped (length: ' + escapedPassword.length + ')');
708
662
  const expectScript = `#!/usr/bin/expect -f
709
663
  set timeout 45
710
664
  log_user 1
711
- exp_internal 1
665
+ exp_internal 0
712
666
  set password {${escapedPassword}}
713
667
  puts "\\n>>> SPAWNING npm run publish-production..."
714
668
  spawn npm run publish-production
@@ -762,11 +716,8 @@ expect {
762
716
  `;
763
717
  try {
764
718
  // Write expect script to temp file
765
- logger.debug('Step 9.5: Writing expect script to file...');
766
719
  fs.writeFileSync(expectScriptPath, expectScript, { mode: 0o755 });
767
- logger.debug('Step 9.6: Expect script written successfully', { fileSize: expectScript.length });
768
720
  // Build environment
769
- logger.debug('Step 9.7: Building environment variables...');
770
721
  const envVars = {
771
722
  ...process.env,
772
723
  EMAIL: email
@@ -774,8 +725,6 @@ expect {
774
725
  if (publishToMarket) {
775
726
  envVars.MARKET = 'true';
776
727
  }
777
- logger.debug('Step 9.8: Environment prepared', { hasEmail: !!email, publishToMarket });
778
- logger.debug('Step 9.9: Running expect script...', { projectDir, timeout: 60000 });
779
728
  const output = execSync(`expect "${expectScriptPath}"`, {
780
729
  cwd: projectDir,
781
730
  encoding: 'utf-8',
@@ -783,75 +732,58 @@ expect {
783
732
  maxBuffer: 10 * 1024 * 1024,
784
733
  env: envVars
785
734
  });
786
- logger.debug('Step 9.95: Expect script completed successfully', { outputLength: output.length });
787
735
  // Clean up temp file
788
- logger.debug('Step 9.97: Cleaning up expect script...');
789
736
  try {
790
737
  fs.unlinkSync(expectScriptPath);
791
738
  }
792
739
  catch { }
793
- logger.debug('Step 9.98: Temp file cleaned');
794
740
  // Check if manifest was updated with targetId
795
- logger.debug('Step 9.99: Checking for manifest update with targetId...');
796
741
  let targetId;
797
742
  try {
798
743
  const updatedManifest = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
799
744
  targetId = updatedManifest.targetId;
800
- logger.debug('Step 9.991: Manifest checked', { hasTargetId: !!targetId });
801
745
  }
802
746
  catch {
803
- logger.debug('Step 9.992: Could not read updated manifest');
804
747
  // Ignore
805
748
  }
806
749
  if (output.includes('Published successfully')) {
807
- logger.debug('Step 9.993: Success message found in output');
808
750
  resolve({ success: true, output, targetId });
809
751
  }
810
752
  else {
811
- logger.debug('Step 9.994: No success message in output');
812
753
  resolve({ success: false, output });
813
754
  }
814
755
  }
815
756
  catch (error) {
816
- logger.error('Step 9 ERROR: Expect script execution failed', {
757
+ logger.error('Expect script execution failed', {
817
758
  errorCode: error.code,
818
- signal: error.signal,
819
- hasStdout: !!error.stdout,
820
- hasStderr: !!error.stderr,
821
- errorMessage: error.message
759
+ signal: error.signal
822
760
  });
823
761
  // Clean up temp file
824
- logger.debug('Step 9.err.1: Cleaning up after error...');
825
762
  try {
826
763
  fs.unlinkSync(expectScriptPath);
827
764
  }
828
765
  catch { }
829
766
  const output = error.stdout || error.stderr || error.message || String(error);
830
- logger.debug('Step 9.err.2: Error output collected', { outputLength: output.length });
831
767
  // Check for specific error messages
832
768
  if (output.includes('not found') || output.includes('command not found')) {
833
- logger.debug('Step 9.err.3: expect command not found error detected');
834
769
  resolve({
835
770
  success: false,
836
771
  output: `ERROR: expect command not found. Try: apt-get install expect (Ubuntu) or brew install expect (macOS)\n\n${output}`
837
772
  });
838
773
  }
839
774
  else if (output.includes('TIMEOUT')) {
840
- logger.debug('Step 9.err.4: Timeout error detected');
841
775
  resolve({
842
776
  success: false,
843
777
  output: `ERROR: expect script timed out waiting for prompts. Check your internet connection and Hailer API status.\n\n${output}`
844
778
  });
845
779
  }
846
780
  else if (output.includes('INVALID PASSWORD')) {
847
- logger.debug('Step 9.err.5: Invalid password error detected');
848
781
  resolve({
849
782
  success: false,
850
783
  output: `ERROR: Invalid credentials provided. Check your email and password.\n\n${output}`
851
784
  });
852
785
  }
853
786
  else if (output.includes('Published successfully')) {
854
- logger.debug('Step 9.err.6: Success detected despite error code');
855
787
  // Even if exit code is non-zero, check if it actually succeeded
856
788
  let targetId;
857
789
  try {
@@ -864,14 +796,12 @@ expect {
864
796
  resolve({ success: true, output, targetId });
865
797
  }
866
798
  else {
867
- logger.debug('Step 9.err.7: Generic error');
868
799
  resolve({ success: false, output });
869
800
  }
870
801
  }
871
802
  });
872
- logger.debug('Step 10: Result received from promise', { success: result.success });
873
803
  if (!result.success) {
874
- logger.error('Step 10 ERROR: Publish failed', { outputLength: result.output.length });
804
+ logger.error('Publish failed');
875
805
  return {
876
806
  content: [{
877
807
  type: "text",
@@ -879,7 +809,8 @@ expect {
879
809
  }],
880
810
  };
881
811
  }
882
- logger.debug('Step 10.5: Publish succeeded, building response...');
812
+ // Log success
813
+ logger.info('App published successfully', { appId, appName });
883
814
  responseText += `✅ **App Published Successfully!**\n\n`;
884
815
  if (result.targetId) {
885
816
  responseText += `**Target ID:** \`${result.targetId}\`\n\n`;
@@ -913,7 +844,6 @@ expect {
913
844
  responseText += ` member: "network_<workspace-id>" // or team_*, user_*\n`;
914
845
  responseText += ` })\n`;
915
846
  responseText += ` \`\`\`\n`;
916
- logger.debug('Step 11: Publishing complete, returning success response');
917
847
  return {
918
848
  content: [{
919
849
  type: "text",
@@ -923,10 +853,7 @@ expect {
923
853
  }
924
854
  catch (error) {
925
855
  const errorMessage = (0, tool_helpers_1.extractErrorMessage)(error);
926
- logger.error('CRITICAL ERROR: Uncaught exception in publishHailerApp', {
927
- errorMessage,
928
- errorType: error instanceof Error ? error.constructor.name : typeof error
929
- });
856
+ logger.error('Error publishing Hailer app', { error: errorMessage });
930
857
  return {
931
858
  content: [{
932
859
  type: "text",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hailer/mcp",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "config": {
5
5
  "docker": {
6
6
  "registry": "registry.gitlab.com/hailer-repos/hailer-mcp"