@hubspot/cli 8.0.8-experimental.4 → 8.0.8-experimental.6

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 (53) hide show
  1. package/commands/mcp/__tests__/start.test.js +1 -8
  2. package/commands/mcp/start.js +1 -0
  3. package/lang/en.d.ts +0 -2
  4. package/lang/en.js +0 -2
  5. package/lib/__tests__/commandSuggestion.test.js +2 -0
  6. package/lib/commandSuggestion.js +1 -7
  7. package/lib/mcp/__tests__/setup.test.js +0 -15
  8. package/lib/mcp/setup.d.ts +0 -1
  9. package/lib/mcp/setup.js +36 -91
  10. package/mcp-server/tools/cms/HsCreateFunctionTool.js +1 -1
  11. package/mcp-server/tools/cms/HsCreateModuleTool.js +1 -1
  12. package/mcp-server/tools/cms/HsCreateTemplateTool.js +1 -1
  13. package/mcp-server/tools/cms/HsFunctionLogsTool.js +1 -1
  14. package/mcp-server/tools/cms/HsListFunctionsTool.js +1 -1
  15. package/mcp-server/tools/cms/HsListTool.js +1 -1
  16. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +2 -1
  17. package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +2 -2
  18. package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +2 -2
  19. package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +2 -2
  20. package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +2 -2
  21. package/mcp-server/tools/cms/__tests__/HsListTool.test.js +2 -2
  22. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +20 -3
  23. package/mcp-server/tools/project/AddFeatureToProjectTool.js +7 -11
  24. package/mcp-server/tools/project/CreateProjectTool.d.ts +24 -4
  25. package/mcp-server/tools/project/CreateProjectTool.js +6 -11
  26. package/mcp-server/tools/project/CreateTestAccountTool.js +1 -1
  27. package/mcp-server/tools/project/DeployProjectTool.js +1 -1
  28. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +5 -8
  29. package/mcp-server/tools/project/GetBuildLogsTool.d.ts +2 -2
  30. package/mcp-server/tools/project/GetBuildLogsTool.js +6 -7
  31. package/mcp-server/tools/project/GetBuildStatusTool.d.ts +1 -1
  32. package/mcp-server/tools/project/GetBuildStatusTool.js +3 -4
  33. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +6 -1
  34. package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -6
  35. package/mcp-server/tools/project/UploadProjectTools.js +1 -1
  36. package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
  37. package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +2 -2
  38. package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +2 -2
  39. package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +2 -2
  40. package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +2 -2
  41. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +0 -32
  42. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +2 -10
  43. package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +2 -2
  44. package/mcp-server/tools/project/constants.d.ts +12 -1
  45. package/mcp-server/tools/project/constants.js +12 -16
  46. package/mcp-server/utils/__tests__/command.test.js +3 -233
  47. package/mcp-server/utils/__tests__/project.test.d.ts +1 -0
  48. package/mcp-server/utils/__tests__/project.test.js +140 -0
  49. package/mcp-server/utils/command.d.ts +0 -5
  50. package/mcp-server/utils/command.js +0 -24
  51. package/mcp-server/utils/project.d.ts +5 -0
  52. package/mcp-server/utils/project.js +18 -0
  53. package/package.json +2 -2
@@ -7,20 +7,14 @@ import * as errorHandlers from '../../../lib/errorHandlers/index.js';
7
7
  import * as usageTrackingLib from '../../../lib/usageTracking.js';
8
8
  import * as processLib from '../../../lib/process.js';
9
9
  import { EXIT_CODES } from '../../../lib/enums/exitCodes.js';
10
- // Create a mock execAsync function before importing the module
11
- const execAsyncMock = vi.fn();
10
+ import startCommand from '../start.js';
12
11
  vi.mock('yargs');
13
12
  vi.mock('../../../lib/commonOpts');
14
13
  vi.mock('node:child_process');
15
- vi.mock('node:util', () => ({
16
- promisify: vi.fn(() => execAsyncMock),
17
- }));
18
14
  vi.mock('fs');
19
15
  vi.mock('@hubspot/local-dev-lib/config');
20
16
  vi.mock('../../../lib/errorHandlers/index.js');
21
17
  vi.mock('../../../lib/process.js');
22
- // Import after mocks are set up
23
- const startCommand = await import('../start.js').then(m => m.default);
24
18
  const spawnSpy = vi.mocked(spawn);
25
19
  const existsSyncSpy = vi.spyOn(fs, 'existsSync');
26
20
  const trackCommandUsageSpy = vi.spyOn(usageTrackingLib, 'trackCommandUsage');
@@ -42,7 +36,6 @@ describe('commands/mcp/start', () => {
42
36
  processExitSpy.mockImplementation(() => { });
43
37
  // Mock config to prevent reading actual config file in CI
44
38
  getConfigAccountIfExistsSpy.mockReturnValue(undefined);
45
- execAsyncMock.mockClear();
46
39
  });
47
40
  describe('command', () => {
48
41
  it('should have the correct command structure', () => {
@@ -28,6 +28,7 @@ async function startMcpServer(aiAgent) {
28
28
  uiLogger.debug(commands.mcp.start.startingServer);
29
29
  uiLogger.debug(commands.mcp.start.stopInstructions);
30
30
  const args = [serverPath];
31
+ // Start the server using ts-node
31
32
  const child = spawn(`node`, args, {
32
33
  stdio: 'inherit',
33
34
  env: {
package/lang/en.d.ts CHANGED
@@ -1295,8 +1295,6 @@ export declare const commands: {
1295
1295
  prompts: {
1296
1296
  targets: string;
1297
1297
  targetsRequired: string;
1298
- standaloneMode: string;
1299
- cliVersion: string;
1300
1298
  };
1301
1299
  };
1302
1300
  start: {
package/lang/en.js CHANGED
@@ -1311,8 +1311,6 @@ export const commands = {
1311
1311
  prompts: {
1312
1312
  targets: '[--client] Which tools would you like to add the HubSpot CLI MCP server to?',
1313
1313
  targetsRequired: 'Must choose at least one app to configure.',
1314
- standaloneMode: 'Do you want to run in standalone mode? (This will use npx @hubspot/cli instead of the installed hs command)',
1315
- cliVersion: 'Specify a CLI version to pin (leave blank for latest):',
1316
1314
  },
1317
1315
  },
1318
1316
  start: {
@@ -71,6 +71,8 @@ describe('lib/commandSuggestion', () => {
71
71
  // Create a mock yargs builder with strict method
72
72
  const mockYargsBuilder = {
73
73
  strict: vi.fn().mockReturnThis(),
74
+ help: vi.fn().mockReturnThis(),
75
+ version: vi.fn().mockReturnThis(),
74
76
  };
75
77
  await commandModule.builder(mockYargsBuilder);
76
78
  expect(mockYargsBuilder.strict).toHaveBeenCalledWith(false);
@@ -18,12 +18,6 @@ export const commandSuggestionMappings = {
18
18
  'theme generate-selectors': 'hs cms theme generate-selectors',
19
19
  'theme marketplace-validate': 'hs cms theme marketplace-validate',
20
20
  'theme preview': 'hs cms theme preview',
21
- 'custom-object schema create': 'hs custom-object create-schema',
22
- 'custom-object schema delete': 'hs custom-object delete-schema',
23
- 'custom-object schema fetch-all': 'hs custom-object fetch-all-schemas',
24
- 'custom-object schema fetch': 'hs custom-object fetch-schema',
25
- 'custom-object schema list': 'hs custom-object list-schemas',
26
- 'custom-object schema update': 'hs custom-object update-schema',
27
21
  };
28
22
  function createCommandSuggestionHandler(newCommand) {
29
23
  return () => {
@@ -35,7 +29,7 @@ function createCommandSuggestion(oldCommand, newCommand) {
35
29
  return {
36
30
  command: oldCommand,
37
31
  builder: async (yargs) => {
38
- return yargs.strict(false);
32
+ return yargs.strict(false).help(false).version(false);
39
33
  },
40
34
  handler: createCommandSuggestionHandler(newCommand),
41
35
  };
@@ -132,21 +132,6 @@ describe('lib/mcp/setup', () => {
132
132
  });
133
133
  expect(mockedLogError).toHaveBeenCalledWith(error);
134
134
  });
135
- it('should pass through environment variables in command', async () => {
136
- const mockMcpCommandWithEnv = {
137
- command: 'test-command',
138
- args: ['--arg1'],
139
- env: { HUBSPOT_MCP_STANDALONE: 'true' },
140
- };
141
- mockedExecAsync.mockResolvedValueOnce({
142
- stdout: 'codex version 1.0.0',
143
- stderr: '',
144
- });
145
- mockedExecAsync.mockResolvedValueOnce({ stdout: '', stderr: '' });
146
- const result = await setupCodex(mockMcpCommandWithEnv);
147
- expect(result).toBe(true);
148
- expect(mockedExecAsync).toHaveBeenCalledWith('codex mcp add "HubSpotDev" --env HUBSPOT_MCP_STANDALONE=true -- test-command --arg1 --ai-agent codex');
149
- });
150
135
  });
151
136
  describe('setupGemini', () => {
152
137
  const mockMcpCommand = {
@@ -5,7 +5,6 @@ export declare const supportedTools: {
5
5
  interface McpCommand {
6
6
  command: string;
7
7
  args: string[];
8
- env?: Record<string, string>;
9
8
  }
10
9
  export declare function addMcpServerToConfig(targets: string[] | undefined): Promise<string[]>;
11
10
  export declare function setupVsCode(mcpCommand?: McpCommand): Promise<boolean>;
package/lib/mcp/setup.js CHANGED
@@ -47,56 +47,23 @@ export async function addMcpServerToConfig(targets) {
47
47
  else {
48
48
  derivedTargets = targets;
49
49
  }
50
- // Prompt for standalone mode
51
- const { useStandaloneMode } = await promptUser({
52
- name: 'useStandaloneMode',
53
- type: 'confirm',
54
- message: commands.mcp.setup.prompts.standaloneMode,
55
- default: false,
56
- });
57
- const { cliVersion } = useStandaloneMode
58
- ? await promptUser({
59
- name: 'cliVersion',
60
- type: 'input',
61
- message: commands.mcp.setup.prompts.cliVersion,
62
- validate: (v) => !v || /^[\d]+\.[\d]+\.[\d]+([-+][\w.]+)?$/.test(v.trim())
63
- ? true
64
- : 'Please enter a valid semver version (e.g. 8.0.1) or leave blank for latest.',
65
- })
66
- : { cliVersion: '' };
67
- const cliPackage = cliVersion
68
- ? `@hubspot/cli@${cliVersion}`
69
- : '@hubspot/cli';
70
- const standaloneEnv = {
71
- HUBSPOT_MCP_STANDALONE: 'true',
72
- };
73
- if (cliVersion) {
74
- standaloneEnv.HUBSPOT_CLI_VERSION = cliVersion;
75
- }
76
- const mcpCommand = useStandaloneMode
77
- ? {
78
- command: 'npx',
79
- args: ['-y', '-p', cliPackage, 'hs', 'mcp', 'start'],
80
- env: standaloneEnv,
81
- }
82
- : defaultMcpCommand;
83
50
  if (derivedTargets.includes(claudeCode)) {
84
- await runSetupFunction(() => setupClaudeCode(mcpCommand));
51
+ await runSetupFunction(setupClaudeCode);
85
52
  }
86
53
  if (derivedTargets.includes(cursor)) {
87
- await runSetupFunction(() => setupCursor(mcpCommand));
54
+ await runSetupFunction(setupCursor);
88
55
  }
89
56
  if (derivedTargets.includes(windsurf)) {
90
- await runSetupFunction(() => setupWindsurf(mcpCommand));
57
+ await runSetupFunction(setupWindsurf);
91
58
  }
92
59
  if (derivedTargets.includes(vscode)) {
93
- await runSetupFunction(() => setupVsCode(mcpCommand));
60
+ await runSetupFunction(setupVsCode);
94
61
  }
95
62
  if (derivedTargets.includes(codex)) {
96
- await runSetupFunction(() => setupCodex(mcpCommand));
63
+ await runSetupFunction(setupCodex);
97
64
  }
98
65
  if (derivedTargets.includes(gemini)) {
99
- await runSetupFunction(() => setupGemini(mcpCommand));
66
+ await runSetupFunction(setupGemini);
100
67
  }
101
68
  uiLogger.info(commands.mcp.setup.success(derivedTargets));
102
69
  return derivedTargets;
@@ -154,7 +121,10 @@ function setupMcpConfigFile(config) {
154
121
  if (!mcpConfig.mcpServers) {
155
122
  mcpConfig.mcpServers = {};
156
123
  }
157
- mcpConfig.mcpServers[mcpServerName] = config.mcpCommand;
124
+ // Add or update HubSpot CLI MCP server
125
+ mcpConfig.mcpServers[mcpServerName] = {
126
+ ...config.mcpCommand,
127
+ };
158
128
  // Write the updated config
159
129
  fs.writeFileSync(config.configPath, JSON.stringify(mcpConfig, null, 2));
160
130
  SpinniesManager.succeed('spinner', {
@@ -175,12 +145,10 @@ export async function setupVsCode(mcpCommand = defaultMcpCommand) {
175
145
  SpinniesManager.add('vsCode', {
176
146
  text: commands.mcp.setup.spinners.configuringVsCode,
177
147
  });
178
- const commandWithAgent = buildCommandWithAgentString(mcpCommand, vscode);
179
- const configObject = {
148
+ const mcpConfig = JSON.stringify({
180
149
  name: mcpServerName,
181
- ...commandWithAgent,
182
- };
183
- const mcpConfig = JSON.stringify(configObject);
150
+ ...buildCommandWithAgentString(mcpCommand, vscode),
151
+ });
184
152
  await execAsync(`code --add-mcp ${JSON.stringify(mcpConfig)}`);
185
153
  SpinniesManager.succeed('vsCode', {
186
154
  text: commands.mcp.setup.spinners.configuredVsCode,
@@ -211,40 +179,30 @@ export async function setupClaudeCode(mcpCommand = defaultMcpCommand) {
211
179
  try {
212
180
  // Check if claude command is available
213
181
  await execAsync('claude --version');
214
- // Run claude mcp add command
215
- const commandWithAgent = buildCommandWithAgentString(mcpCommand, claudeCode);
216
- const configObject = {
217
- type: 'stdio',
218
- ...commandWithAgent,
219
- };
220
- const mcpConfig = JSON.stringify(configObject);
221
- const { stdout } = await execAsync('claude mcp list');
222
- if (stdout.includes(mcpServerName)) {
223
- SpinniesManager.update('claudeCode', {
224
- text: commands.mcp.setup.spinners.alreadyInstalled,
225
- });
226
- await execAsync(`claude mcp remove "${mcpServerName}" --scope user`);
227
- }
228
- await execAsync(`claude mcp add-json "${mcpServerName}" ${JSON.stringify(mcpConfig)} --scope user`);
229
- SpinniesManager.succeed('claudeCode', {
230
- text: commands.mcp.setup.spinners.configuredClaudeCode,
231
- });
232
- return true;
233
182
  }
234
- catch (error) {
235
- if (error instanceof Error && error.message.includes('claude')) {
236
- SpinniesManager.fail('claudeCode', {
237
- text: commands.mcp.setup.spinners.claudeCodeNotFound,
238
- });
239
- }
240
- else {
241
- SpinniesManager.fail('claudeCode', {
242
- text: commands.mcp.setup.spinners.claudeCodeInstallFailed,
243
- });
244
- logError(error);
245
- }
183
+ catch (e) {
184
+ SpinniesManager.fail('claudeCode', {
185
+ text: commands.mcp.setup.spinners.claudeCodeNotFound,
186
+ });
246
187
  return false;
247
188
  }
189
+ // Run claude mcp add command
190
+ const mcpConfig = JSON.stringify({
191
+ type: 'stdio',
192
+ ...buildCommandWithAgentString(mcpCommand, claudeCode),
193
+ });
194
+ const { stdout } = await execAsync('claude mcp list');
195
+ if (stdout.includes(mcpServerName)) {
196
+ SpinniesManager.update('claudeCode', {
197
+ text: commands.mcp.setup.spinners.alreadyInstalled,
198
+ });
199
+ await execAsync(`claude mcp remove "${mcpServerName}" --scope user`);
200
+ }
201
+ await execAsync(`claude mcp add-json "${mcpServerName}" ${JSON.stringify(mcpConfig)} --scope user`);
202
+ SpinniesManager.succeed('claudeCode', {
203
+ text: commands.mcp.setup.spinners.configuredClaudeCode,
204
+ });
205
+ return true;
248
206
  }
249
207
  catch (error) {
250
208
  SpinniesManager.fail('claudeCode', {
@@ -290,7 +248,7 @@ export async function setupCodex(mcpCommand = defaultMcpCommand) {
290
248
  return false;
291
249
  }
292
250
  const mcpCommandWithAgent = buildCommandWithAgentString(mcpCommand, codex);
293
- await execAsync(`codex mcp add "${mcpServerName}"${buildEnvFlagString(mcpCommand)} -- ${mcpCommandWithAgent.command} ${mcpCommandWithAgent.args.join(' ')}`);
251
+ await execAsync(`codex mcp add "${mcpServerName}" -- ${mcpCommandWithAgent.command} ${mcpCommandWithAgent.args.join(' ')}`);
294
252
  SpinniesManager.succeed('codexSpinner', {
295
253
  text: commands.mcp.setup.spinners.configuredCodex,
296
254
  });
@@ -319,7 +277,7 @@ export async function setupGemini(mcpCommand = defaultMcpCommand) {
319
277
  return false;
320
278
  }
321
279
  const mcpCommandWithAgent = buildCommandWithAgentString(mcpCommand, gemini);
322
- await execAsync(`gemini mcp add -s user${buildEnvFlagString(mcpCommand)} "${mcpServerName}" ${mcpCommandWithAgent.command} ${mcpCommandWithAgent.args.join(' ')}`);
280
+ await execAsync(`gemini mcp add -s user "${mcpServerName}" ${mcpCommandWithAgent.command} ${mcpCommandWithAgent.args.join(' ')}`);
323
281
  SpinniesManager.succeed('geminiSpinner', {
324
282
  text: commands.mcp.setup.spinners.configuredGemini,
325
283
  });
@@ -338,16 +296,3 @@ function buildCommandWithAgentString(mcpCommand, agent) {
338
296
  mcpCommandCopy.args.push('--ai-agent', agent);
339
297
  return mcpCommandCopy;
340
298
  }
341
- function buildEnvFlagString(mcpCommand) {
342
- const envFlags = [];
343
- if (mcpCommand.env) {
344
- const env = Object.entries(mcpCommand.env);
345
- env.forEach(([key, value]) => {
346
- envFlags.push(`--env ${key}=${value}`);
347
- });
348
- }
349
- if (envFlags.length === 0) {
350
- return '';
351
- }
352
- return ` ${envFlags.join(' ')}`;
353
- }
@@ -1,7 +1,7 @@
1
1
  import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
4
- import { runCommandInDir } from '../../utils/command.js';
4
+ import { runCommandInDir } from '../../utils/project.js';
5
5
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
6
6
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
7
7
  import { addFlag } from '../../utils/command.js';
@@ -1,7 +1,7 @@
1
1
  import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
4
- import { runCommandInDir } from '../../utils/command.js';
4
+ import { runCommandInDir } from '../../utils/project.js';
5
5
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
6
6
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
7
7
  import { addFlag } from '../../utils/command.js';
@@ -1,7 +1,7 @@
1
1
  import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
4
- import { runCommandInDir } from '../../utils/command.js';
4
+ import { runCommandInDir } from '../../utils/project.js';
5
5
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
6
6
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
7
7
  import { addFlag } from '../../utils/command.js';
@@ -2,7 +2,7 @@ import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { addFlag } from '../../utils/command.js';
4
4
  import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
5
- import { runCommandInDir } from '../../utils/command.js';
5
+ import { runCommandInDir } from '../../utils/project.js';
6
6
  import { formatTextContents } from '../../utils/content.js';
7
7
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
8
8
  import { setupHubSpotConfig } from '../../utils/config.js';
@@ -2,7 +2,7 @@ import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { addFlag } from '../../utils/command.js';
4
4
  import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
5
- import { runCommandInDir } from '../../utils/command.js';
5
+ import { runCommandInDir } from '../../utils/project.js';
6
6
  import { formatTextContents } from '../../utils/content.js';
7
7
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
8
8
  import { setupHubSpotConfig } from '../../utils/config.js';
@@ -2,7 +2,7 @@ import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { addFlag } from '../../utils/command.js';
4
4
  import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
5
- import { runCommandInDir } from '../../utils/command.js';
5
+ import { runCommandInDir } from '../../utils/project.js';
6
6
  import { formatTextContents } from '../../utils/content.js';
7
7
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
8
8
  import { setupHubSpotConfig } from '../../utils/config.js';
@@ -1,10 +1,11 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { HsCreateFunctionTool } from '../HsCreateFunctionTool.js';
3
- import { runCommandInDir } from '../../../utils/command.js';
3
+ import { runCommandInDir } from '../../../utils/project.js';
4
4
  import { addFlag } from '../../../utils/command.js';
5
5
  import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
6
6
  import { trackToolUsage } from '../../../utils/toolUsageTracking.js';
7
7
  vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
8
+ vi.mock('../../../utils/project');
8
9
  vi.mock('../../../utils/command');
9
10
  vi.mock('../../../utils/toolUsageTracking');
10
11
  vi.mock('../../../utils/feedbackTracking');
@@ -1,11 +1,11 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { HsCreateModuleTool } from '../HsCreateModuleTool.js';
3
- import { runCommandInDir } from '../../../utils/command.js';
3
+ import { runCommandInDir } from '../../../utils/project.js';
4
4
  import { addFlag } from '../../../utils/command.js';
5
5
  import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
6
6
  import { trackToolUsage } from '../../../utils/toolUsageTracking.js';
7
7
  vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
8
- vi.mock('../../../utils/command');
8
+ vi.mock('../../../utils/project');
9
9
  vi.mock('../../../utils/command');
10
10
  vi.mock('../../../utils/toolUsageTracking');
11
11
  vi.mock('../../../utils/feedbackTracking');
@@ -1,11 +1,11 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { HsCreateTemplateTool } from '../HsCreateTemplateTool.js';
3
- import { runCommandInDir } from '../../../utils/command.js';
3
+ import { runCommandInDir } from '../../../utils/project.js';
4
4
  import { addFlag } from '../../../utils/command.js';
5
5
  import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
6
6
  import { trackToolUsage } from '../../../utils/toolUsageTracking.js';
7
7
  vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
8
- vi.mock('../../../utils/command');
8
+ vi.mock('../../../utils/project');
9
9
  vi.mock('../../../utils/command');
10
10
  vi.mock('../../../utils/toolUsageTracking');
11
11
  vi.mock('../../../utils/feedbackTracking');
@@ -1,11 +1,11 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { HsFunctionLogsTool } from '../HsFunctionLogsTool.js';
3
- import { runCommandInDir } from '../../../utils/command.js';
3
+ import { runCommandInDir } from '../../../utils/project.js';
4
4
  import { addFlag } from '../../../utils/command.js';
5
5
  import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
6
6
  import { trackToolUsage } from '../../../utils/toolUsageTracking.js';
7
7
  vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
8
- vi.mock('../../../utils/command');
8
+ vi.mock('../../../utils/project');
9
9
  vi.mock('../../../utils/command');
10
10
  vi.mock('../../../utils/toolUsageTracking');
11
11
  vi.mock('../../../utils/feedbackTracking');
@@ -1,11 +1,11 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { HsListFunctionsTool } from '../HsListFunctionsTool.js';
3
- import { runCommandInDir } from '../../../utils/command.js';
3
+ import { runCommandInDir } from '../../../utils/project.js';
4
4
  import { addFlag } from '../../../utils/command.js';
5
5
  import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
6
6
  import { trackToolUsage } from '../../../utils/toolUsageTracking.js';
7
7
  vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
8
- vi.mock('../../../utils/command');
8
+ vi.mock('../../../utils/project');
9
9
  vi.mock('../../../utils/command');
10
10
  vi.mock('../../../utils/toolUsageTracking');
11
11
  vi.mock('../../../utils/feedbackTracking');
@@ -1,11 +1,11 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
2
  import { HsListTool } from '../HsListTool.js';
3
- import { runCommandInDir } from '../../../utils/command.js';
3
+ import { runCommandInDir } from '../../../utils/project.js';
4
4
  import { addFlag } from '../../../utils/command.js';
5
5
  import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
6
6
  import { trackToolUsage } from '../../../utils/toolUsageTracking.js';
7
7
  vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
8
- vi.mock('../../../utils/command');
8
+ vi.mock('../../../utils/project');
9
9
  vi.mock('../../../utils/command');
10
10
  vi.mock('../../../utils/toolUsageTracking');
11
11
  vi.mock('../../../utils/feedbackTracking');
@@ -5,9 +5,26 @@ declare const inputSchemaZodObject: z.ZodObject<{
5
5
  absoluteProjectPath: z.ZodString;
6
6
  absoluteCurrentWorkingDirectory: z.ZodString;
7
7
  addApp: z.ZodBoolean;
8
- distribution: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"marketplace">, z.ZodLiteral<"private">]>>;
9
- auth: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"static">, z.ZodLiteral<"oauth">]>>;
10
- features: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">, z.ZodLiteral<"workflow-action">, z.ZodLiteral<"workflow-action-tool">, z.ZodLiteral<"app-object">, z.ZodLiteral<"app-event">, z.ZodLiteral<"scim">, z.ZodLiteral<"page">]>>>;
8
+ distribution: z.ZodOptional<z.ZodEnum<{
9
+ marketplace: "marketplace";
10
+ private: "private";
11
+ }>>;
12
+ auth: z.ZodOptional<z.ZodEnum<{
13
+ oauth: "oauth";
14
+ static: "static";
15
+ }>>;
16
+ features: z.ZodOptional<z.ZodArray<z.ZodEnum<{
17
+ card: "card";
18
+ settings: "settings";
19
+ "app-event": "app-event";
20
+ "workflow-action-tool": "workflow-action-tool";
21
+ page: "page";
22
+ webhooks: "webhooks";
23
+ "workflow-action": "workflow-action";
24
+ "app-function": "app-function";
25
+ "app-object": "app-object";
26
+ scim: "scim";
27
+ }>>>;
11
28
  }, z.core.$strip>;
12
29
  export type AddFeatureInputSchema = z.infer<typeof inputSchemaZodObject>;
13
30
  export declare class AddFeatureToProjectTool extends Tool<AddFeatureInputSchema> {
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  import { APP_AUTH_TYPES, APP_DISTRIBUTION_TYPES, } from '../../../lib/constants.js';
4
4
  import { addFlag } from '../../utils/command.js';
5
5
  import { absoluteCurrentWorkingDirectory, absoluteProjectPath, features, } from './constants.js';
6
- import { runCommandInDir } from '../../utils/command.js';
6
+ import { runCommandInDir } from '../../utils/project.js';
7
7
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
8
8
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
9
9
  import { setupHubSpotConfig } from '../../utils/config.js';
@@ -15,17 +15,13 @@ const inputSchema = {
15
15
  .boolean()
16
16
  .describe('Should an app be added? If there is no app in the project, an app must be added to add a feature'),
17
17
  distribution: z
18
- .optional(z.union([
19
- z.literal(APP_DISTRIBUTION_TYPES.MARKETPLACE),
20
- z.literal(APP_DISTRIBUTION_TYPES.PRIVATE),
21
- ]))
22
- .describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Private is used if you do not wish to distribute your app on the HubSpot marketplace. '),
18
+ .enum([APP_DISTRIBUTION_TYPES.MARKETPLACE, APP_DISTRIBUTION_TYPES.PRIVATE])
19
+ .describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Private is used if you do not wish to distribute your app on the HubSpot marketplace. ')
20
+ .optional(),
23
21
  auth: z
24
- .optional(z.union([
25
- z.literal(APP_AUTH_TYPES.STATIC),
26
- z.literal(APP_AUTH_TYPES.OAUTH),
27
- ]))
28
- .describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Static uses a static non changing authentication token, and is only available for private distribution. '),
22
+ .enum([APP_AUTH_TYPES.STATIC, APP_AUTH_TYPES.OAUTH])
23
+ .describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Static uses a static non changing authentication token, and is only available for private distribution. ')
24
+ .optional(),
29
25
  features,
30
26
  };
31
27
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -5,10 +5,30 @@ declare const inputSchemaZodObject: z.ZodObject<{
5
5
  absoluteCurrentWorkingDirectory: z.ZodString;
6
6
  name: z.ZodOptional<z.ZodString>;
7
7
  destination: z.ZodString;
8
- projectBase: z.ZodUnion<readonly [z.ZodLiteral<"empty">, z.ZodLiteral<"app">]>;
9
- distribution: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"marketplace">, z.ZodLiteral<"private">]>>;
10
- auth: z.ZodOptional<z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<"static">, z.ZodLiteral<"oauth">]>>>;
11
- features: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">, z.ZodLiteral<"workflow-action">, z.ZodLiteral<"workflow-action-tool">, z.ZodLiteral<"app-object">, z.ZodLiteral<"app-event">, z.ZodLiteral<"scim">, z.ZodLiteral<"page">]>>>;
8
+ projectBase: z.ZodEnum<{
9
+ app: "app";
10
+ empty: "empty";
11
+ }>;
12
+ distribution: z.ZodOptional<z.ZodEnum<{
13
+ marketplace: "marketplace";
14
+ private: "private";
15
+ }>>;
16
+ auth: z.ZodOptional<z.ZodEnum<{
17
+ oauth: "oauth";
18
+ static: "static";
19
+ }>>;
20
+ features: z.ZodOptional<z.ZodArray<z.ZodEnum<{
21
+ card: "card";
22
+ settings: "settings";
23
+ "app-event": "app-event";
24
+ "workflow-action-tool": "workflow-action-tool";
25
+ page: "page";
26
+ webhooks: "webhooks";
27
+ "workflow-action": "workflow-action";
28
+ "app-function": "app-function";
29
+ "app-object": "app-object";
30
+ scim: "scim";
31
+ }>>>;
12
32
  }, z.core.$strip>;
13
33
  export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
14
34
  export declare class CreateProjectTool extends Tool<CreateProjectInputSchema> {
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  import { APP_AUTH_TYPES, APP_DISTRIBUTION_TYPES, EMPTY_PROJECT, PROJECT_WITH_APP, } from '../../../lib/constants.js';
4
4
  import { addFlag } from '../../utils/command.js';
5
5
  import { absoluteCurrentWorkingDirectory, features } from './constants.js';
6
- import { runCommandInDir } from '../../utils/command.js';
6
+ import { runCommandInDir } from '../../utils/project.js';
7
7
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
8
8
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
9
9
  import { setupHubSpotConfig } from '../../utils/config.js';
@@ -18,19 +18,14 @@ const inputSchema = {
18
18
  .string()
19
19
  .describe('DO NOT use the current directory unless the user has explicitly stated to do so. Relative path to the directory the project will be created in.'),
20
20
  projectBase: z
21
- .union([z.literal(EMPTY_PROJECT), z.literal(PROJECT_WITH_APP)])
21
+ .enum([EMPTY_PROJECT, PROJECT_WITH_APP])
22
22
  .describe('Empty will create an empty project, and app will create a project with an app inside of it.'),
23
23
  distribution: z
24
- .optional(z.union([
25
- z.literal(APP_DISTRIBUTION_TYPES.MARKETPLACE),
26
- z.literal(APP_DISTRIBUTION_TYPES.PRIVATE),
27
- ]))
28
- .describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Private is used if you do not wish to distribute your app on the HubSpot marketplace. '),
24
+ .enum([APP_DISTRIBUTION_TYPES.MARKETPLACE, APP_DISTRIBUTION_TYPES.PRIVATE])
25
+ .describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Private is used if you do not wish to distribute your app on the HubSpot marketplace. ')
26
+ .optional(),
29
27
  auth: z
30
- .optional(z.union([
31
- z.literal(APP_AUTH_TYPES.STATIC),
32
- z.literal(APP_AUTH_TYPES.OAUTH),
33
- ]))
28
+ .enum([APP_AUTH_TYPES.STATIC, APP_AUTH_TYPES.OAUTH])
34
29
  .describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Static uses a static non changing authentication token, and is only available for private distribution. ')
35
30
  .optional(),
36
31
  features,
@@ -3,7 +3,7 @@ import fs from 'fs';
3
3
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
4
4
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
5
5
  import { addFlag } from '../../utils/command.js';
6
- import { runCommandInDir } from '../../utils/command.js';
6
+ import { runCommandInDir } from '../../utils/project.js';
7
7
  import { ACCOUNT_LEVELS, ACCOUNT_LEVEL_CHOICES, } from '../../../lib/constants.js';
8
8
  import { Tool } from '../../types.js';
9
9
  import { absoluteCurrentWorkingDirectory } from './constants.js';
@@ -2,7 +2,7 @@ import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { addFlag } from '../../utils/command.js';
4
4
  import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
5
- import { runCommandInDir } from '../../utils/command.js';
5
+ import { runCommandInDir } from '../../utils/project.js';
6
6
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
7
7
  import { trackToolUsage } from '../../utils/toolUsageTracking.js';
8
8
  import { setupHubSpotConfig } from '../../utils/config.js';