@hubspot/cli 7.9.0 → 7.9.1-experimental.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 (214) hide show
  1. package/bin/cli.js +5 -4
  2. package/commands/__tests__/getStarted.test.js +10 -0
  3. package/commands/__tests__/project.test.js +2 -0
  4. package/commands/account/__tests__/rename.test.js +42 -0
  5. package/commands/account/auth.js +10 -14
  6. package/commands/account/clean.js +11 -19
  7. package/commands/account/createOverride.js +17 -23
  8. package/commands/account/info.js +8 -5
  9. package/commands/account/list.js +13 -18
  10. package/commands/account/remove.js +23 -22
  11. package/commands/account/removeOverride.js +8 -16
  12. package/commands/account/rename.d.ts +1 -1
  13. package/commands/account/rename.js +6 -3
  14. package/commands/account/use.js +19 -8
  15. package/commands/app/__tests__/migrate.test.js +8 -4
  16. package/commands/app/migrate.js +2 -2
  17. package/commands/auth.js +18 -14
  18. package/commands/cms/theme/preview.js +1 -4
  19. package/commands/config/migrate.js +5 -5
  20. package/commands/config/set.js +1 -2
  21. package/commands/customObject/createSchema.js +2 -3
  22. package/commands/customObject/updateSchema.js +2 -3
  23. package/commands/getStarted.js +15 -22
  24. package/commands/hubdb/__tests__/list.test.js +1 -0
  25. package/commands/hubdb/list.js +2 -2
  26. package/commands/hubdb.d.ts +1 -1
  27. package/commands/init.js +36 -32
  28. package/commands/project/__tests__/deploy.test.js +10 -5
  29. package/commands/project/__tests__/devUnifiedFlow.test.js +6 -4
  30. package/commands/project/__tests__/logs.test.js +4 -0
  31. package/commands/project/__tests__/updateDeps.test.js +142 -0
  32. package/commands/project/__tests__/validate.test.js +2 -2
  33. package/commands/project/cloneApp.js +2 -2
  34. package/commands/project/create.js +0 -1
  35. package/commands/project/deploy.js +2 -2
  36. package/commands/project/dev/deprecatedFlow.js +4 -5
  37. package/commands/project/dev/index.js +14 -4
  38. package/commands/project/dev/unifiedFlow.js +4 -5
  39. package/commands/project/listBuilds.js +7 -1
  40. package/commands/project/logs.js +2 -3
  41. package/commands/project/profile/add.js +6 -7
  42. package/commands/project/profile/delete.js +2 -2
  43. package/commands/project/updateDeps.d.ts +6 -0
  44. package/commands/project/updateDeps.js +80 -0
  45. package/commands/project/upload.js +9 -3
  46. package/commands/project/validate.js +9 -3
  47. package/commands/project/watch.js +7 -2
  48. package/commands/project.js +2 -0
  49. package/commands/sandbox/__tests__/create.test.js +14 -5
  50. package/commands/sandbox/create.js +4 -5
  51. package/commands/sandbox/delete.js +23 -20
  52. package/commands/testAccount/__tests__/create.test.js +68 -0
  53. package/commands/testAccount/create.d.ts +8 -0
  54. package/commands/testAccount/create.js +135 -45
  55. package/commands/testAccount/delete.js +9 -8
  56. package/commands/testAccount/importData.d.ts +1 -1
  57. package/lang/en.d.ts +3199 -3185
  58. package/lang/en.js +52 -14
  59. package/lib/__tests__/buildAccount.test.js +22 -30
  60. package/lib/__tests__/commonOpts.test.js +9 -13
  61. package/lib/__tests__/dependencyManagement.test.js +273 -1
  62. package/lib/__tests__/developerTestAccounts.test.js +29 -17
  63. package/lib/__tests__/importData.test.js +20 -10
  64. package/lib/__tests__/oauth.test.js +19 -8
  65. package/lib/__tests__/sandboxSync.test.js +33 -11
  66. package/lib/__tests__/sandboxes.test.js +30 -19
  67. package/lib/__tests__/usageTracking.test.js +10 -10
  68. package/lib/__tests__/validation.test.js +32 -32
  69. package/lib/accountTypes.d.ts +9 -9
  70. package/lib/accountTypes.js +2 -4
  71. package/lib/app/__tests__/migrate.test.js +15 -0
  72. package/lib/app/__tests__/migrate_legacy.test.js +9 -0
  73. package/lib/app/migrate_legacy.d.ts +2 -2
  74. package/lib/buildAccount.d.ts +4 -4
  75. package/lib/buildAccount.js +7 -14
  76. package/lib/commonOpts.js +5 -8
  77. package/lib/configMigrate.d.ts +2 -2
  78. package/lib/configMigrate.js +42 -18
  79. package/lib/configOptions.js +3 -2
  80. package/lib/constants.d.ts +1 -0
  81. package/lib/constants.js +6 -0
  82. package/lib/dependencyManagement.d.ts +8 -2
  83. package/lib/dependencyManagement.js +75 -12
  84. package/lib/developerTestAccounts.d.ts +3 -3
  85. package/lib/developerTestAccounts.js +4 -7
  86. package/lib/doctor/DiagnosticInfoBuilder.d.ts +1 -1
  87. package/lib/doctor/DiagnosticInfoBuilder.js +9 -6
  88. package/lib/doctor/Doctor.js +4 -3
  89. package/lib/doctor/__tests__/Diagnosis.test.js +4 -3
  90. package/lib/doctor/__tests__/DiagnosticInfoBuilder.test.js +17 -9
  91. package/lib/doctor/__tests__/Doctor.test.js +14 -0
  92. package/lib/importData.js +8 -7
  93. package/lib/links.js +5 -5
  94. package/lib/mcp/__tests__/setup.test.d.ts +1 -0
  95. package/lib/mcp/__tests__/setup.test.js +127 -0
  96. package/lib/mcp/setup.d.ts +4 -12
  97. package/lib/mcp/setup.js +34 -1
  98. package/lib/middleware/__test__/commandTargetingUtils.test.js +3 -3
  99. package/lib/middleware/__test__/configMiddleware.test.js +23 -22
  100. package/lib/middleware/__test__/gitMiddleware.test.js +9 -7
  101. package/lib/middleware/autoUpdateMiddleware.d.ts +3 -1
  102. package/lib/middleware/autoUpdateMiddleware.js +10 -2
  103. package/lib/middleware/commandTargetingUtils.js +2 -2
  104. package/lib/middleware/configMiddleware.d.ts +6 -1
  105. package/lib/middleware/configMiddleware.js +36 -15
  106. package/lib/middleware/gitMiddleware.js +8 -4
  107. package/lib/npm.d.ts +3 -0
  108. package/lib/npm.js +6 -0
  109. package/lib/oauth.d.ts +2 -2
  110. package/lib/oauth.js +8 -10
  111. package/lib/projects/__tests__/AppDevModeInterface.test.js +17 -6
  112. package/lib/projects/__tests__/DevServerManager.test.js +1 -0
  113. package/lib/projects/__tests__/LocalDevProcess.test.js +1 -0
  114. package/lib/projects/__tests__/components.test.js +148 -24
  115. package/lib/projects/__tests__/deploy.test.js +1 -0
  116. package/lib/projects/__tests__/platformVersion.test.js +5 -1
  117. package/lib/projects/__tests__/projects.test.js +13 -42
  118. package/lib/projects/components.js +76 -20
  119. package/lib/projects/config.js +5 -9
  120. package/lib/projects/create/__tests__/v2.test.js +11 -0
  121. package/lib/projects/localDev/AppDevModeInterface.js +2 -2
  122. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +2 -2
  123. package/lib/projects/localDev/LocalDevLogger.js +4 -4
  124. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +3 -3
  125. package/lib/projects/localDev/helpers/account.d.ts +10 -10
  126. package/lib/projects/localDev/helpers/account.js +6 -11
  127. package/lib/projects/platformVersion.js +1 -1
  128. package/lib/projects/urls.js +5 -6
  129. package/lib/prompts/__tests__/createDeveloperTestAccountConfigPrompt.test.d.ts +1 -0
  130. package/lib/prompts/__tests__/createDeveloperTestAccountConfigPrompt.test.js +153 -0
  131. package/lib/prompts/__tests__/downloadProjectPrompt.test.js +7 -5
  132. package/lib/prompts/accountNamePrompt.js +3 -3
  133. package/lib/prompts/accountsPrompt.d.ts +1 -1
  134. package/lib/prompts/accountsPrompt.js +6 -7
  135. package/lib/prompts/confirmImportDataPrompt.js +2 -2
  136. package/lib/prompts/createDeveloperTestAccountConfigPrompt.d.ts +5 -0
  137. package/lib/prompts/createDeveloperTestAccountConfigPrompt.js +76 -66
  138. package/lib/prompts/downloadProjectPrompt.d.ts +1 -0
  139. package/lib/prompts/downloadProjectPrompt.js +5 -2
  140. package/lib/prompts/importDataTestAccountSelectPrompt.js +4 -5
  141. package/lib/prompts/personalAccessKeyPrompt.js +2 -2
  142. package/lib/prompts/projectDevTargetAccountPrompt.d.ts +3 -3
  143. package/lib/prompts/projectDevTargetAccountPrompt.js +5 -7
  144. package/lib/prompts/sandboxesPrompt.js +7 -8
  145. package/lib/prompts/setAsDefaultAccountPrompt.js +7 -6
  146. package/lib/sandboxSync.d.ts +2 -2
  147. package/lib/sandboxSync.js +3 -9
  148. package/lib/sandboxes.d.ts +4 -4
  149. package/lib/sandboxes.js +6 -11
  150. package/lib/serverlessLogs.js +2 -2
  151. package/lib/theme/__tests__/migrate.test.js +15 -0
  152. package/lib/ui/index.js +6 -3
  153. package/lib/usageTracking.js +15 -8
  154. package/lib/validation.js +13 -11
  155. package/mcp-server/tools/cms/HsCreateFunctionTool.js +8 -2
  156. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +4 -4
  157. package/mcp-server/tools/cms/HsCreateModuleTool.js +8 -2
  158. package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -2
  159. package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +4 -4
  160. package/mcp-server/tools/cms/HsFunctionLogsTool.js +6 -2
  161. package/mcp-server/tools/cms/HsListFunctionsTool.js +5 -1
  162. package/mcp-server/tools/cms/HsListTool.js +5 -1
  163. package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -0
  164. package/mcp-server/tools/index.js +4 -0
  165. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +1 -1
  166. package/mcp-server/tools/project/AddFeatureToProjectTool.js +9 -3
  167. package/mcp-server/tools/project/CreateProjectTool.js +8 -2
  168. package/mcp-server/tools/project/CreateTestAccountTool.d.ts +41 -0
  169. package/mcp-server/tools/project/CreateTestAccountTool.js +150 -0
  170. package/mcp-server/tools/project/DeployProjectTool.d.ts +1 -1
  171. package/mcp-server/tools/project/DeployProjectTool.js +8 -2
  172. package/mcp-server/tools/project/DocFetchTool.d.ts +1 -1
  173. package/mcp-server/tools/project/DocFetchTool.js +9 -5
  174. package/mcp-server/tools/project/DocsSearchTool.d.ts +1 -1
  175. package/mcp-server/tools/project/DocsSearchTool.js +12 -8
  176. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +1 -1
  177. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +11 -7
  178. package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +1 -1
  179. package/mcp-server/tools/project/GetApplicationInfoTool.js +11 -7
  180. package/mcp-server/tools/project/GetBuildStatusTool.d.ts +26 -0
  181. package/mcp-server/tools/project/GetBuildStatusTool.js +164 -0
  182. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +1 -1
  183. package/mcp-server/tools/project/GetConfigValuesTool.js +11 -7
  184. package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +1 -1
  185. package/mcp-server/tools/project/GuidedWalkthroughTool.js +7 -3
  186. package/mcp-server/tools/project/UploadProjectTools.d.ts +9 -3
  187. package/mcp-server/tools/project/UploadProjectTools.js +51 -5
  188. package/mcp-server/tools/project/ValidateProjectTool.d.ts +1 -1
  189. package/mcp-server/tools/project/ValidateProjectTool.js +7 -3
  190. package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.d.ts +1 -0
  191. package/mcp-server/tools/project/__tests__/CreateTestAccountTool.test.js +454 -0
  192. package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +5 -1
  193. package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +25 -13
  194. package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +7 -5
  195. package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +7 -5
  196. package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.d.ts +1 -0
  197. package/mcp-server/tools/project/__tests__/GetBuildStatusTool.test.js +240 -0
  198. package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +8 -6
  199. package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +56 -4
  200. package/mcp-server/utils/__tests__/content.test.js +21 -20
  201. package/mcp-server/utils/__tests__/feedbackTracking.test.js +33 -28
  202. package/mcp-server/utils/content.d.ts +1 -1
  203. package/mcp-server/utils/content.js +2 -2
  204. package/mcp-server/utils/feedbackTracking.d.ts +1 -1
  205. package/mcp-server/utils/feedbackTracking.js +3 -3
  206. package/mcp-server/utils/toolUsageTracking.js +4 -3
  207. package/package.json +8 -7
  208. package/lang/en.lyaml +0 -1508
  209. package/lib/lang.d.ts +0 -8
  210. package/lib/lang.js +0 -72
  211. package/mcp-server/utils/__tests__/cliConfig.test.js +0 -110
  212. package/mcp-server/utils/cliConfig.d.ts +0 -1
  213. package/mcp-server/utils/cliConfig.js +0 -12
  214. /package/{mcp-server/utils/__tests__/cliConfig.test.d.ts → commands/project/__tests__/updateDeps.test.d.ts} +0 -0
@@ -1,4 +1,5 @@
1
1
  import { getProjectThemeDetails, migrateThemes, } from '@hubspot/project-parsing-lib';
2
+ import { getConfigAccountById } from '@hubspot/local-dev-lib/config';
2
3
  import { confirmPrompt } from '../../prompts/promptUtils.js';
3
4
  import { writeProjectConfig, } from '../../projects/config.js';
4
5
  import { ensureProjectExists } from '../../projects/ensureProjectExists.js';
@@ -13,6 +14,7 @@ vi.mock('../../projects/config');
13
14
  vi.mock('../../projects/ensureProjectExists');
14
15
  vi.mock('../../projects/platformVersion');
15
16
  vi.mock('../../app/migrate');
17
+ vi.mock('@hubspot/local-dev-lib/config');
16
18
  const mockedGetProjectThemeDetails = getProjectThemeDetails;
17
19
  const mockedMigrateThemes = migrateThemes;
18
20
  const mockedConfirmPrompt = confirmPrompt;
@@ -20,6 +22,7 @@ const mockedWriteProjectConfig = writeProjectConfig;
20
22
  const mockedEnsureProjectExists = ensureProjectExists;
21
23
  const mockedUseV2Api = isV2Project;
22
24
  const mockedFetchMigrationApps = fetchMigrationApps;
25
+ const mockedGetConfigAccountById = getConfigAccountById;
23
26
  const ACCOUNT_ID = 123;
24
27
  const PROJECT_NAME = 'Test Project';
25
28
  const PLATFORM_VERSION = '2025.2';
@@ -31,6 +34,18 @@ const createLoadedProjectConfig = (name) => ({
31
34
  describe('lib/theme/migrate', () => {
32
35
  beforeEach(() => {
33
36
  mockedUseV2Api.mockReturnValue(false);
37
+ // Mock account config for the test account ID
38
+ mockedGetConfigAccountById.mockReturnValue({
39
+ accountId: ACCOUNT_ID,
40
+ name: 'Test Account',
41
+ authType: 'personalaccesskey',
42
+ auth: {
43
+ tokenInfo: {
44
+ accessToken: 'test-token',
45
+ },
46
+ },
47
+ env: 'prod',
48
+ });
34
49
  });
35
50
  describe('getHasMigratableThemes', () => {
36
51
  it('should return false when no projectConfig is provided', async () => {
package/lib/ui/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import chalk from 'chalk';
2
- import { getAccountConfig, configFileExists, } from '@hubspot/local-dev-lib/config';
2
+ import { getConfigAccountIfExists, globalConfigFileExists, } from '@hubspot/local-dev-lib/config';
3
3
  import { uiLogger } from './logger.js';
4
4
  import { supportsHyperlinkModule } from './supportHyperlinks.js';
5
5
  import { supportsColor } from './supportsColor.js';
@@ -38,7 +38,7 @@ export function uiLink(linkText, url) {
38
38
  : `${linkText}: ${encodedUrl}`;
39
39
  }
40
40
  export function uiAccountDescription(accountId, bold = true) {
41
- const account = getAccountConfig(accountId || undefined);
41
+ const account = accountId ? getConfigAccountIfExists(accountId) : undefined;
42
42
  let message;
43
43
  if (account && account.accountType) {
44
44
  message = `${account.name ? `${account.name} ` : ''}[${HUBSPOT_ACCOUNT_TYPE_STRINGS[account.accountType]}] (${accountId})`;
@@ -46,6 +46,9 @@ export function uiAccountDescription(accountId, bold = true) {
46
46
  else {
47
47
  message = accountId ? accountId.toString() : '';
48
48
  }
49
+ if (message.trim().length === 0) {
50
+ return 'unknown account';
51
+ }
49
52
  return bold ? chalk.bold(message) : message;
50
53
  }
51
54
  export function uiInfoSection(title, logContent) {
@@ -64,7 +67,7 @@ export function uiCommandReference(command, withQuotes = true) {
64
67
  : commandReference);
65
68
  }
66
69
  export function uiAuthCommandReference({ accountId, qa, } = {}) {
67
- const userIsUsingGlobalConfig = configFileExists(true);
70
+ const userIsUsingGlobalConfig = globalConfigFileExists();
68
71
  let command = 'hs auth';
69
72
  if (userIsUsingGlobalConfig) {
70
73
  command = 'hs account auth';
@@ -1,5 +1,5 @@
1
1
  import { trackUsage } from '@hubspot/local-dev-lib/trackUsage';
2
- import { isTrackingAllowed, getAccountConfig, } from '@hubspot/local-dev-lib/config';
2
+ import { getConfigAccountById, getConfig } from '@hubspot/local-dev-lib/config';
3
3
  import { API_KEY_AUTH_METHOD } from '@hubspot/local-dev-lib/constants/auth';
4
4
  import { uiLogger } from './ui/logger.js';
5
5
  import { pkg } from './jsonLoader.js';
@@ -28,13 +28,17 @@ export function getPlatform() {
28
28
  }
29
29
  }
30
30
  export async function trackCommandUsage(command, meta = {}, accountId) {
31
- if (!isTrackingAllowed()) {
32
- return;
31
+ try {
32
+ const config = getConfig();
33
+ if (config?.allowUsageTracking === false) {
34
+ return;
35
+ }
33
36
  }
37
+ catch (e) { }
34
38
  uiLogger.debug(`Attempting to track usage of "${command}" command`);
35
39
  let authType = 'unknown';
36
40
  if (accountId) {
37
- const accountConfig = getAccountConfig(accountId);
41
+ const accountConfig = getConfigAccountById(accountId);
38
42
  authType =
39
43
  accountConfig && accountConfig.authType
40
44
  ? accountConfig.authType
@@ -49,7 +53,8 @@ export async function trackCommandUsage(command, meta = {}, accountId) {
49
53
  });
50
54
  }
51
55
  export async function trackHelpUsage(command) {
52
- if (!isTrackingAllowed()) {
56
+ const config = getConfig();
57
+ if (config?.allowUsageTracking === false) {
53
58
  return;
54
59
  }
55
60
  if (command) {
@@ -81,13 +86,14 @@ export async function trackAuthAction(command, authType, step, accountId) {
81
86
  });
82
87
  }
83
88
  export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
84
- if (!isTrackingAllowed()) {
89
+ const config = getConfig();
90
+ if (config?.allowUsageTracking === false) {
85
91
  return;
86
92
  }
87
93
  uiLogger.debug(`Attempting to track metadata usage of "${command}" command`);
88
94
  let authType = 'unknown';
89
95
  if (accountId) {
90
- const accountConfig = getAccountConfig(accountId);
96
+ const accountConfig = getConfigAccountById(accountId);
91
97
  authType =
92
98
  accountConfig && accountConfig.authType
93
99
  ? accountConfig.authType
@@ -103,7 +109,8 @@ export async function trackCommandMetadataUsage(command, meta = {}, accountId) {
103
109
  }
104
110
  async function trackCliInteraction({ action, accountId, command, authType, meta = {}, }) {
105
111
  try {
106
- if (!isTrackingAllowed()) {
112
+ const config = getConfig();
113
+ if (config?.allowUsageTracking === false) {
107
114
  return;
108
115
  }
109
116
  const usageTrackingEvent = {
package/lib/validation.js CHANGED
@@ -4,16 +4,17 @@ import { uiLogger } from '../lib/ui/logger.js';
4
4
  import { CMS_PUBLISH_MODE } from '@hubspot/local-dev-lib/constants/files';
5
5
  import { API_KEY_AUTH_METHOD, OAUTH_AUTH_METHOD, PERSONAL_ACCESS_KEY_AUTH_METHOD, } from '@hubspot/local-dev-lib/constants/auth';
6
6
  import { commaSeparatedValues } from '@hubspot/local-dev-lib/text';
7
- import { getConfigPath, getAccountConfig, getAccountId, loadConfigFromEnvironment, } from '@hubspot/local-dev-lib/config';
7
+ import { getConfigFilePath, getConfigAccountById, } from '@hubspot/local-dev-lib/config';
8
8
  import { getOauthManager } from '@hubspot/local-dev-lib/oauth';
9
9
  import { accessTokenForPersonalAccessKey } from '@hubspot/local-dev-lib/personalAccessKey';
10
10
  import { getAbsoluteFilePath, getCwd, getExt, } from '@hubspot/local-dev-lib/path';
11
+ import { ENVIRONMENT_VARIABLES } from '@hubspot/local-dev-lib/constants/config';
11
12
  import { getCmsPublishMode } from './commonOpts.js';
12
13
  import { logError } from './errorHandlers/index.js';
13
14
  import { lib } from '../lang/en.js';
14
15
  export async function validateAccount(options) {
15
16
  const { derivedAccountId, userProvidedAccount } = options;
16
- const accountId = getAccountId(derivedAccountId);
17
+ const accountId = derivedAccountId;
17
18
  if (!accountId) {
18
19
  if (userProvidedAccount) {
19
20
  uiLogger.error(lib.validation.accountNotFoundInConfig(userProvidedAccount));
@@ -23,33 +24,34 @@ export async function validateAccount(options) {
23
24
  }
24
25
  return false;
25
26
  }
26
- if (userProvidedAccount && loadConfigFromEnvironment()) {
27
+ if (userProvidedAccount &&
28
+ process.env[ENVIRONMENT_VARIABLES.USE_ENVIRONMENT_HUBSPOT_CONFIG]) {
27
29
  throw new Error(lib.validation.userProvidedAccount);
28
30
  }
29
- const accountConfig = getAccountConfig(accountId);
31
+ const accountConfig = getConfigAccountById(accountId);
30
32
  if (!accountConfig) {
31
33
  uiLogger.error(lib.validation.accountNotConfigured(accountId));
32
34
  return false;
33
35
  }
34
- const { authType, auth, apiKey, personalAccessKey } = accountConfig;
36
+ const { authType } = accountConfig;
35
37
  if (typeof authType === 'string' && authType !== authType.toLowerCase()) {
36
- uiLogger.error(lib.validation.invalidAuthType(authType, accountId, getConfigPath() || '', commaSeparatedValues([
38
+ uiLogger.error(lib.validation.invalidAuthType(authType, accountId, getConfigFilePath(), commaSeparatedValues([
37
39
  PERSONAL_ACCESS_KEY_AUTH_METHOD,
38
40
  OAUTH_AUTH_METHOD,
39
41
  API_KEY_AUTH_METHOD,
40
42
  ].map(method => method.value))));
41
43
  }
42
44
  if (authType === 'oauth2') {
43
- if (typeof auth !== 'object') {
45
+ if (typeof accountConfig.auth !== 'object') {
44
46
  uiLogger.error(lib.validation.oauth2ConfigMissing(accountId));
45
47
  return false;
46
48
  }
47
- const { clientId, clientSecret, tokenInfo } = auth;
49
+ const { clientId, clientSecret, tokenInfo } = accountConfig.auth;
48
50
  if (!clientId || !clientSecret || !tokenInfo || !tokenInfo.refreshToken) {
49
51
  uiLogger.error(lib.validation.oauth2ConfigIncorrect(accountId));
50
52
  return false;
51
53
  }
52
- const oauth = getOauthManager(accountId, accountConfig);
54
+ const oauth = getOauthManager(accountConfig);
53
55
  try {
54
56
  let accessToken;
55
57
  if (oauth) {
@@ -66,7 +68,7 @@ export async function validateAccount(options) {
66
68
  }
67
69
  }
68
70
  else if (authType === 'personalaccesskey') {
69
- if (!personalAccessKey) {
71
+ if (!accountConfig.personalAccessKey) {
70
72
  uiLogger.error(lib.validation.personalAccessKeyMissing(accountId));
71
73
  return false;
72
74
  }
@@ -82,7 +84,7 @@ export async function validateAccount(options) {
82
84
  return false;
83
85
  }
84
86
  }
85
- else if (!apiKey) {
87
+ else if (!accountConfig.apiKey) {
86
88
  uiLogger.error(lib.validation.authConfigurationMissing(accountId));
87
89
  return false;
88
90
  }
@@ -80,10 +80,10 @@ export class HsCreateFunctionTool extends Tool {
80
80
  }
81
81
  try {
82
82
  const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
83
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
83
+ return formatTextContents(stdout, stderr);
84
84
  }
85
85
  catch (error) {
86
- return formatTextContents(absoluteCurrentWorkingDirectory, error instanceof Error ? error.message : `${error}`);
86
+ return formatTextContents(error instanceof Error ? error.message : `${error}`);
87
87
  }
88
88
  }
89
89
  register() {
@@ -91,6 +91,12 @@ export class HsCreateFunctionTool extends Tool {
91
91
  title: 'Create HubSpot CMS Serverless Function',
92
92
  description: `Creates a new HubSpot CMS serverless function using the hs create function command. Functions can be created non-interactively by specifying functionsFolder, filename, and endpointPath. Supports all HTTP methods (${HTTP_METHODS.join(', ')}).`,
93
93
  inputSchema,
94
+ annotations: {
95
+ readOnlyHint: false,
96
+ destructiveHint: false,
97
+ idempotentHint: false,
98
+ openWorldHint: false,
99
+ },
94
100
  }, this.handler);
95
101
  }
96
102
  }
@@ -13,20 +13,20 @@ declare const inputSchemaZodObject: z.ZodObject<{
13
13
  }, "strip", z.ZodTypeAny, {
14
14
  absoluteCurrentWorkingDirectory: string;
15
15
  dest?: string | undefined;
16
+ global?: boolean | undefined;
16
17
  moduleLabel?: string | undefined;
17
18
  reactType?: boolean | undefined;
18
- global?: boolean | undefined;
19
- availableForNewContent?: boolean | undefined;
20
19
  contentTypes?: string | undefined;
20
+ availableForNewContent?: boolean | undefined;
21
21
  userSuppliedName?: string | undefined;
22
22
  }, {
23
23
  absoluteCurrentWorkingDirectory: string;
24
24
  dest?: string | undefined;
25
+ global?: boolean | undefined;
25
26
  moduleLabel?: string | undefined;
26
27
  reactType?: boolean | undefined;
27
- global?: boolean | undefined;
28
- availableForNewContent?: boolean | undefined;
29
28
  contentTypes?: string | undefined;
29
+ availableForNewContent?: boolean | undefined;
30
30
  userSuppliedName?: string | undefined;
31
31
  }>;
32
32
  export type HsCreateModuleInputSchema = z.infer<typeof inputSchemaZodObject>;
@@ -102,10 +102,10 @@ export class HsCreateModuleTool extends Tool {
102
102
  }
103
103
  try {
104
104
  const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
105
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
105
+ return formatTextContents(stdout, stderr);
106
106
  }
107
107
  catch (error) {
108
- return formatTextContents(absoluteCurrentWorkingDirectory, error instanceof Error ? error.message : `${error}`);
108
+ return formatTextContents(error instanceof Error ? error.message : `${error}`);
109
109
  }
110
110
  }
111
111
  register() {
@@ -113,6 +113,12 @@ export class HsCreateModuleTool extends Tool {
113
113
  title: 'Create HubSpot CMS Module',
114
114
  description: 'Creates a new HubSpot CMS module using the hs create module command. Modules can be created non-interactively by specifying moduleLabel and other module options. You can create either HubL or React modules by setting the reactType parameter.',
115
115
  inputSchema,
116
+ annotations: {
117
+ readOnlyHint: false,
118
+ destructiveHint: false,
119
+ idempotentHint: false,
120
+ openWorldHint: false,
121
+ },
116
122
  }, this.handler);
117
123
  }
118
124
  }
@@ -59,10 +59,10 @@ export class HsCreateTemplateTool extends Tool {
59
59
  }
60
60
  try {
61
61
  const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
62
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
62
+ return formatTextContents(stdout, stderr);
63
63
  }
64
64
  catch (error) {
65
- return formatTextContents(absoluteCurrentWorkingDirectory, error instanceof Error ? error.message : `${error}`);
65
+ return formatTextContents(error instanceof Error ? error.message : `${error}`);
66
66
  }
67
67
  }
68
68
  register() {
@@ -70,6 +70,12 @@ export class HsCreateTemplateTool extends Tool {
70
70
  title: 'Create HubSpot CMS Template',
71
71
  description: `Creates a new HubSpot CMS template using the hs create template command. Templates can be created non-interactively by specifying templateType. Supports all template types including: ${TEMPLATE_TYPES.join(', ')}.`,
72
72
  inputSchema,
73
+ annotations: {
74
+ readOnlyHint: false,
75
+ destructiveHint: false,
76
+ idempotentHint: false,
77
+ openWorldHint: false,
78
+ },
73
79
  }, this.handler);
74
80
  }
75
81
  }
@@ -12,16 +12,16 @@ declare const inputSchemaZodObject: z.ZodObject<{
12
12
  endpoint: string;
13
13
  absoluteCurrentWorkingDirectory: string;
14
14
  account?: string | undefined;
15
- limit?: number | undefined;
16
- compact?: boolean | undefined;
17
15
  latest?: boolean | undefined;
16
+ compact?: boolean | undefined;
17
+ limit?: number | undefined;
18
18
  }, {
19
19
  endpoint: string;
20
20
  absoluteCurrentWorkingDirectory: string;
21
21
  account?: string | undefined;
22
- limit?: number | undefined;
23
- compact?: boolean | undefined;
24
22
  latest?: boolean | undefined;
23
+ compact?: boolean | undefined;
24
+ limit?: number | undefined;
25
25
  }>;
26
26
  export type HsFunctionLogsInputSchema = z.infer<typeof inputSchemaZodObject>;
27
27
  export declare class HsFunctionLogsTool extends Tool<HsFunctionLogsInputSchema> {
@@ -52,11 +52,11 @@ export class HsFunctionLogsTool extends Tool {
52
52
  }
53
53
  try {
54
54
  const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
55
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
55
+ return formatTextContents(stdout, stderr);
56
56
  }
57
57
  catch (error) {
58
58
  const errorMessage = error instanceof Error ? error.message : String(error);
59
- return formatTextContents(absoluteCurrentWorkingDirectory, `Error executing hs logs command: ${errorMessage}`);
59
+ return formatTextContents(`Error executing hs logs command: ${errorMessage}`);
60
60
  }
61
61
  }
62
62
  register() {
@@ -64,6 +64,10 @@ export class HsFunctionLogsTool extends Tool {
64
64
  title: 'Get HubSpot CMS serverless function logs for an endpoint',
65
65
  description: 'Retrieve logs for HubSpot CMS serverless functions. Use this tool to help debug issues with serverless functions by reading the production logs. Supports various options like latest, compact, and limiting results. Use after listing functions with list-cms-serverless-functions to get the endpoint path.',
66
66
  inputSchema,
67
+ annotations: {
68
+ readOnlyHint: true,
69
+ openWorldHint: true,
70
+ },
67
71
  }, this.handler);
68
72
  }
69
73
  }
@@ -34,7 +34,7 @@ export class HsListFunctionsTool extends Tool {
34
34
  }
35
35
  try {
36
36
  const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
37
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
37
+ return formatTextContents(stdout, stderr);
38
38
  }
39
39
  catch (error) {
40
40
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -53,6 +53,10 @@ export class HsListFunctionsTool extends Tool {
53
53
  title: 'List HubSpot CMS Serverless Functions',
54
54
  description: 'Get a list of all serverless functions deployed in a HubSpot portal/account. Shows function routes, HTTP methods, secrets, and timestamps.',
55
55
  inputSchema,
56
+ annotations: {
57
+ readOnlyHint: true,
58
+ openWorldHint: true,
59
+ },
56
60
  }, this.handler);
57
61
  }
58
62
  }
@@ -34,7 +34,7 @@ export class HsListTool extends Tool {
34
34
  }
35
35
  try {
36
36
  const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
37
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
37
+ return formatTextContents(stdout, stderr);
38
38
  }
39
39
  catch (error) {
40
40
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -53,6 +53,10 @@ export class HsListTool extends Tool {
53
53
  title: 'List HubSpot CMS Directory Contents',
54
54
  description: 'List remote contents of a HubSpot CMS directory.',
55
55
  inputSchema,
56
+ annotations: {
57
+ readOnlyHint: true,
58
+ openWorldHint: true,
59
+ },
56
60
  }, this.handler);
57
61
  }
58
62
  }
@@ -10,6 +10,7 @@ vi.mock('../../../utils/toolUsageTracking', () => ({
10
10
  trackToolUsage: vi.fn(),
11
11
  }));
12
12
  vi.mock('../../../utils/feedbackTracking');
13
+ vi.mock('@hubspot/local-dev-lib/config');
13
14
  const mockMcpFeedbackRequest = mcpFeedbackRequest;
14
15
  const mockRunCommandInDir = runCommandInDir;
15
16
  const mockAddFlag = addFlag;
@@ -9,17 +9,20 @@ import { DocsSearchTool } from './project/DocsSearchTool.js';
9
9
  import { DocFetchTool } from './project/DocFetchTool.js';
10
10
  import { GetApiUsagePatternsByAppIdTool } from './project/GetApiUsagePatternsByAppIdTool.js';
11
11
  import { GetApplicationInfoTool } from './project/GetApplicationInfoTool.js';
12
+ import { GetBuildStatusTool } from './project/GetBuildStatusTool.js';
12
13
  import { HsListTool } from './cms/HsListTool.js';
13
14
  import { HsCreateModuleTool } from './cms/HsCreateModuleTool.js';
14
15
  import { HsCreateTemplateTool } from './cms/HsCreateTemplateTool.js';
15
16
  import { HsCreateFunctionTool } from './cms/HsCreateFunctionTool.js';
16
17
  import { HsListFunctionsTool } from './cms/HsListFunctionsTool.js';
17
18
  import { HsFunctionLogsTool } from './cms/HsFunctionLogsTool.js';
19
+ import { CreateTestAccountTool } from './project/CreateTestAccountTool.js';
18
20
  export function registerProjectTools(mcpServer) {
19
21
  return [
20
22
  new UploadProjectTools(mcpServer).register(),
21
23
  new CreateProjectTool(mcpServer).register(),
22
24
  new GuidedWalkthroughTool(mcpServer).register(),
25
+ new CreateTestAccountTool(mcpServer).register(),
23
26
  new DeployProjectTool(mcpServer).register(),
24
27
  new AddFeatureToProjectTool(mcpServer).register(),
25
28
  new ValidateProjectTool(mcpServer).register(),
@@ -28,6 +31,7 @@ export function registerProjectTools(mcpServer) {
28
31
  new DocFetchTool(mcpServer).register(),
29
32
  new GetApiUsagePatternsByAppIdTool(mcpServer).register(),
30
33
  new GetApplicationInfoTool(mcpServer).register(),
34
+ new GetBuildStatusTool(mcpServer).register(),
31
35
  ];
32
36
  }
33
37
  export function registerCmsTools(mcpServer) {
@@ -26,7 +26,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
26
26
  export type AddFeatureInputSchema = z.infer<typeof inputSchemaZodObject>;
27
27
  export declare class AddFeatureToProjectTool extends Tool<AddFeatureInputSchema> {
28
28
  constructor(mcpServer: McpServer);
29
- handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, distribution, auth, features, addApp, }: AddFeatureInputSchema): Promise<TextContentResponse>;
29
+ handler({ absoluteProjectPath, distribution, auth, features, addApp, }: AddFeatureInputSchema): Promise<TextContentResponse>;
30
30
  register(): RegisteredTool;
31
31
  }
32
32
  export {};
@@ -35,7 +35,7 @@ export class AddFeatureToProjectTool extends Tool {
35
35
  constructor(mcpServer) {
36
36
  super(mcpServer);
37
37
  }
38
- async handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, distribution, auth, features, addApp, }) {
38
+ async handler({ absoluteProjectPath, distribution, auth, features, addApp, }) {
39
39
  try {
40
40
  await trackToolUsage(toolName);
41
41
  let command = `hs project add`;
@@ -60,10 +60,10 @@ export class AddFeatureToProjectTool extends Tool {
60
60
  // If features isn't provided, pass an empty array to bypass the prompt
61
61
  command = addFlag(command, 'features', features || []);
62
62
  const { stdout, stderr } = await runCommandInDir(absoluteProjectPath, command);
63
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
63
+ return formatTextContents(stdout, stderr);
64
64
  }
65
65
  catch (error) {
66
- return formatTextContents(absoluteCurrentWorkingDirectory, error instanceof Error ? error.message : `${error}`);
66
+ return formatTextContents(error instanceof Error ? error.message : `${error}`);
67
67
  }
68
68
  }
69
69
  register() {
@@ -72,6 +72,12 @@ export class AddFeatureToProjectTool extends Tool {
72
72
  description: `Adds a feature to an existing HubSpot project.
73
73
  Only works for projects with platformVersion '2025.2' and beyond`,
74
74
  inputSchema,
75
+ annotations: {
76
+ readOnlyHint: false,
77
+ destructiveHint: false,
78
+ idempotentHint: false,
79
+ openWorldHint: false,
80
+ },
75
81
  }, this.handler);
76
82
  }
77
83
  }
@@ -77,10 +77,10 @@ export class CreateProjectTool extends Tool {
77
77
  command = addFlag(command, 'features', features || []);
78
78
  try {
79
79
  const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
80
- return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
80
+ return formatTextContents(stdout, stderr);
81
81
  }
82
82
  catch (error) {
83
- return formatTextContents(absoluteCurrentWorkingDirectory, error instanceof Error ? error.message : `${error}`);
83
+ return formatTextContents(error instanceof Error ? error.message : `${error}`);
84
84
  }
85
85
  }
86
86
  register() {
@@ -88,6 +88,12 @@ export class CreateProjectTool extends Tool {
88
88
  title: 'Create HubSpot Project',
89
89
  description: 'Creates a HubSpot project with the provided name and outputs it in the provided destination',
90
90
  inputSchema,
91
+ annotations: {
92
+ readOnlyHint: false,
93
+ destructiveHint: false,
94
+ idempotentHint: false,
95
+ openWorldHint: false,
96
+ },
91
97
  }, this.handler);
92
98
  }
93
99
  }
@@ -0,0 +1,41 @@
1
+ import { TextContentResponse, Tool } from '../../types.js';
2
+ import { z } from 'zod';
3
+ import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ declare const createTestAccountInputSchema: z.ZodObject<{
5
+ absoluteCurrentWorkingDirectory: z.ZodString;
6
+ configPath: z.ZodOptional<z.ZodString>;
7
+ name: z.ZodOptional<z.ZodString>;
8
+ description: z.ZodOptional<z.ZodString>;
9
+ marketingLevel: z.ZodOptional<z.ZodEnum<["FREE", "STARTER", "PROFESSIONAL", "ENTERPRISE"]>>;
10
+ opsLevel: z.ZodOptional<z.ZodEnum<["FREE", "STARTER", "PROFESSIONAL", "ENTERPRISE"]>>;
11
+ serviceLevel: z.ZodOptional<z.ZodEnum<["FREE", "STARTER", "PROFESSIONAL", "ENTERPRISE"]>>;
12
+ salesLevel: z.ZodOptional<z.ZodEnum<["FREE", "STARTER", "PROFESSIONAL", "ENTERPRISE"]>>;
13
+ contentLevel: z.ZodOptional<z.ZodEnum<["FREE", "STARTER", "PROFESSIONAL", "ENTERPRISE"]>>;
14
+ }, "strip", z.ZodTypeAny, {
15
+ absoluteCurrentWorkingDirectory: string;
16
+ name?: string | undefined;
17
+ description?: string | undefined;
18
+ marketingLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
19
+ opsLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
20
+ serviceLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
21
+ salesLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
22
+ contentLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
23
+ configPath?: string | undefined;
24
+ }, {
25
+ absoluteCurrentWorkingDirectory: string;
26
+ name?: string | undefined;
27
+ description?: string | undefined;
28
+ marketingLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
29
+ opsLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
30
+ serviceLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
31
+ salesLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
32
+ contentLevel?: "FREE" | "STARTER" | "PROFESSIONAL" | "ENTERPRISE" | undefined;
33
+ configPath?: string | undefined;
34
+ }>;
35
+ export type CreateTestAccountInputSchema = z.infer<typeof createTestAccountInputSchema>;
36
+ export declare class CreateTestAccountTool extends Tool<CreateTestAccountInputSchema> {
37
+ constructor(mcpServer: McpServer);
38
+ handler({ absoluteCurrentWorkingDirectory, name, description, marketingLevel, opsLevel, serviceLevel, salesLevel, contentLevel, configPath, }: CreateTestAccountInputSchema): Promise<TextContentResponse>;
39
+ register(): RegisteredTool;
40
+ }
41
+ export {};