@hailer/mcp 0.2.3 → 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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hailer/mcp",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "config": {
5
5
  "docker": {
6
6
  "registry": "registry.gitlab.com/hailer-repos/hailer-mcp"