@hubspot/cli 8.2.0-experimental.2 → 8.2.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 (147) hide show
  1. package/commands/account/clean.js +1 -1
  2. package/commands/account/list.js +1 -1
  3. package/commands/account/remove.js +1 -1
  4. package/commands/account/rename.js +1 -1
  5. package/commands/account/use.js +1 -1
  6. package/commands/api.d.ts +4 -1
  7. package/commands/api.js +11 -14
  8. package/commands/config/set.js +24 -5
  9. package/commands/customObject/createSchema.js +2 -3
  10. package/commands/customObject/updateSchema.js +2 -3
  11. package/commands/getStarted.js +1 -0
  12. package/commands/hubdb/list.d.ts +1 -1
  13. package/commands/hubdb/list.js +7 -8
  14. package/commands/mcp/setup.d.ts +2 -0
  15. package/commands/mcp/setup.js +29 -1
  16. package/commands/project/appInstallStatus.d.ts +2 -1
  17. package/commands/project/appInstallStatus.js +21 -19
  18. package/commands/project/create.js +0 -1
  19. package/commands/project/deploy.d.ts +2 -1
  20. package/commands/project/deploy.js +31 -14
  21. package/commands/project/dev/index.js +18 -64
  22. package/commands/project/dev/unifiedFlow.js +3 -1
  23. package/commands/project/info.d.ts +2 -1
  24. package/commands/project/info.js +8 -6
  25. package/commands/project/installApp.d.ts +2 -1
  26. package/commands/project/installApp.js +26 -27
  27. package/commands/project/list.js +1 -1
  28. package/commands/project/listBuilds.d.ts +1 -1
  29. package/commands/project/listBuilds.js +8 -6
  30. package/commands/project/logs.js +2 -4
  31. package/commands/project/profile/add.d.ts +2 -1
  32. package/commands/project/profile/add.js +22 -1
  33. package/commands/project/profile/delete.d.ts +1 -1
  34. package/commands/project/release/create.d.ts +2 -1
  35. package/commands/project/release/create.js +68 -69
  36. package/commands/project/release/info.d.ts +2 -1
  37. package/commands/project/release/info.js +7 -6
  38. package/commands/project/release/list.d.ts +2 -1
  39. package/commands/project/release/list.js +15 -7
  40. package/commands/project/upload.d.ts +4 -1
  41. package/commands/project/upload.js +48 -21
  42. package/commands/project/validate.d.ts +1 -1
  43. package/commands/project/watch.js +3 -2
  44. package/commands/project.js +2 -2
  45. package/commands/sandbox/delete.js +2 -3
  46. package/commands/testAccount/create.d.ts +2 -1
  47. package/commands/testAccount/create.js +7 -7
  48. package/commands/testAccount/importData.d.ts +1 -1
  49. package/lang/en.d.ts +61 -33
  50. package/lang/en.js +77 -48
  51. package/lib/app/urls.js +2 -3
  52. package/lib/commonOpts.js +6 -1
  53. package/lib/configOptions.d.ts +10 -10
  54. package/lib/configOptions.js +10 -11
  55. package/lib/constants.d.ts +2 -0
  56. package/lib/constants.js +2 -0
  57. package/lib/dependencyManagement.js +7 -7
  58. package/lib/getStartedV2Actions.js +2 -1
  59. package/lib/importData.js +3 -4
  60. package/lib/jsonOutput.d.ts +109 -0
  61. package/lib/jsonOutput.js +94 -0
  62. package/lib/links.js +6 -5
  63. package/lib/mcp/clients.d.ts +1 -1
  64. package/lib/mcp/clients.js +8 -1
  65. package/lib/mcp/setup.d.ts +9 -4
  66. package/lib/mcp/setup.js +115 -35
  67. package/lib/npm/npmCli.d.ts +1 -0
  68. package/lib/npm/npmCli.js +13 -0
  69. package/lib/projects/builds.d.ts +2 -0
  70. package/lib/projects/builds.js +22 -0
  71. package/lib/projects/create/v2.js +1 -0
  72. package/lib/projects/installApp.d.ts +1 -1
  73. package/lib/projects/installApp.js +8 -3
  74. package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
  75. package/lib/projects/localDev/DevSessionManager.js +4 -30
  76. package/lib/projects/localDev/LocalDevProcess.js +7 -5
  77. package/lib/projects/localDev/helpers/account.d.ts +0 -7
  78. package/lib/projects/localDev/helpers/account.js +1 -80
  79. package/lib/projects/localDev/helpers/project.js +3 -2
  80. package/lib/projects/release.d.ts +4 -0
  81. package/lib/projects/release.js +90 -0
  82. package/lib/projects/ui.d.ts +1 -0
  83. package/lib/projects/ui.js +14 -0
  84. package/lib/projects/upload.d.ts +10 -2
  85. package/lib/projects/upload.js +14 -7
  86. package/lib/projects/urls.d.ts +0 -1
  87. package/lib/projects/urls.js +6 -13
  88. package/lib/yargs/makeWrappedYargsHandler.d.ts +5 -1
  89. package/lib/yargs/makeWrappedYargsHandler.js +123 -65
  90. package/mcp-server/Tool.d.ts +8 -3
  91. package/mcp-server/Tool.js +58 -32
  92. package/mcp-server/server.js +10 -6
  93. package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +2 -2
  94. package/mcp-server/tools/cms/HsCreateFunctionTool.js +10 -17
  95. package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
  96. package/mcp-server/tools/cms/HsCreateModuleTool.js +12 -18
  97. package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +2 -2
  98. package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -10
  99. package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +2 -2
  100. package/mcp-server/tools/cms/HsFunctionLogsTool.js +9 -9
  101. package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +2 -2
  102. package/mcp-server/tools/cms/HsListFunctionsTool.js +7 -7
  103. package/mcp-server/tools/cms/HsListTool.d.ts +2 -2
  104. package/mcp-server/tools/cms/HsListTool.js +6 -10
  105. package/mcp-server/tools/index.js +2 -0
  106. package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -2
  107. package/mcp-server/tools/project/AddFeatureToProjectTool.js +8 -9
  108. package/mcp-server/tools/project/AuthAccountTool.d.ts +18 -0
  109. package/mcp-server/tools/project/AuthAccountTool.js +78 -0
  110. package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -2
  111. package/mcp-server/tools/project/CreateProjectTool.js +13 -12
  112. package/mcp-server/tools/project/CreateTestAccountTool.d.ts +2 -2
  113. package/mcp-server/tools/project/CreateTestAccountTool.js +14 -15
  114. package/mcp-server/tools/project/DeployProjectTool.d.ts +2 -2
  115. package/mcp-server/tools/project/DeployProjectTool.js +10 -10
  116. package/mcp-server/tools/project/DocFetchTool.js +1 -1
  117. package/mcp-server/tools/project/DocsSearchTool.js +8 -7
  118. package/mcp-server/tools/project/FindProjectsTool.js +1 -1
  119. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +2 -1
  120. package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -8
  121. package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +2 -1
  122. package/mcp-server/tools/project/GetApplicationInfoTool.js +12 -9
  123. package/mcp-server/tools/project/GetBuildLogsTool.js +11 -7
  124. package/mcp-server/tools/project/GetBuildStatusTool.js +11 -7
  125. package/mcp-server/tools/project/GetConfigValuesTool.d.ts +2 -1
  126. package/mcp-server/tools/project/GetConfigValuesTool.js +9 -7
  127. package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
  128. package/mcp-server/tools/project/UploadProjectTools.d.ts +2 -2
  129. package/mcp-server/tools/project/UploadProjectTools.js +9 -8
  130. package/mcp-server/tools/project/ValidateProjectTool.d.ts +2 -2
  131. package/mcp-server/tools/project/ValidateProjectTool.js +5 -4
  132. package/mcp-server/tools/project/constants.d.ts +1 -0
  133. package/mcp-server/tools/project/constants.js +2 -1
  134. package/mcp-server/utils/command.d.ts +25 -2
  135. package/mcp-server/utils/command.js +67 -17
  136. package/mcp-server/utils/config.js +5 -0
  137. package/mcp-server/utils/logger.d.ts +3 -0
  138. package/mcp-server/utils/logger.js +30 -0
  139. package/mcp-server/utils/toolUsageTracking.js +18 -3
  140. package/package.json +11 -9
  141. package/types/Yargs.d.ts +3 -1
  142. package/commands/project/dev/deprecatedFlow.d.ts +0 -11
  143. package/commands/project/dev/deprecatedFlow.js +0 -180
  144. package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +0 -43
  145. package/lib/projects/localDev/DevServerManager_DEPRECATED.js +0 -128
  146. package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +0 -64
  147. package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +0 -394
@@ -0,0 +1,78 @@
1
+ import { z } from 'zod';
2
+ import { Tool } from '../../Tool.js';
3
+ import { formatTextContents } from '../../utils/content.js';
4
+ import { HubSpotCommand } from '../../utils/command.js';
5
+ import { setupHubSpotConfig } from '../../utils/config.js';
6
+ import { absoluteCurrentWorkingDirectory } from './constants.js';
7
+ import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
8
+ const inputSchema = {
9
+ absoluteCurrentWorkingDirectory,
10
+ accountId: z
11
+ .number()
12
+ .optional()
13
+ .describe('The HubSpot portal ID to authenticate.'),
14
+ name: z
15
+ .string()
16
+ .optional()
17
+ .describe('A name to assign to this account in the HubSpot CLI config. Defaults to the portal name if not provided.'),
18
+ setAsDefault: z
19
+ .boolean()
20
+ .optional()
21
+ .describe('Set this account as the default for CLI operations. Defaults to true when not specified.'),
22
+ };
23
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
24
+ const inputSchemaZodObject = z.object({ ...inputSchema });
25
+ const toolName = 'auth-account';
26
+ export class AuthAccountTool extends Tool {
27
+ constructor(mcpServer, logger) {
28
+ super(mcpServer, logger, toolName);
29
+ }
30
+ async handler({ absoluteCurrentWorkingDirectory, accountId, name, setAsDefault, }, extra) {
31
+ setupHubSpotConfig(absoluteCurrentWorkingDirectory);
32
+ const command = new HubSpotCommand('account auth');
33
+ if (name) {
34
+ command.addFlag('name', name);
35
+ }
36
+ else {
37
+ command.addFlag('use-default-name', 'true');
38
+ }
39
+ if (accountId !== undefined) {
40
+ command.addFlag('account', accountId);
41
+ }
42
+ command.addFlag('default', setAsDefault === false ? 'false' : 'true');
43
+ try {
44
+ const { stdout, stderr } = await this.runCommand(absoluteCurrentWorkingDirectory, command, extra);
45
+ return formatTextContents(stdout, stderr);
46
+ }
47
+ catch (error) {
48
+ this.logger.debug(toolName, {
49
+ message: 'Handler caught error running hs account auth',
50
+ error: error instanceof Error ? error.message : String(error),
51
+ });
52
+ return formatTextContents(getErrorMessage(error));
53
+ }
54
+ }
55
+ register() {
56
+ return this.mcpServer.registerTool(toolName, {
57
+ title: 'Authenticate a HubSpot Account',
58
+ description: 'Authenticates a HubSpot account with the CLI using `hs account auth`.\n\n' +
59
+ 'WHEN TO USE:\n' +
60
+ '- The user wants to add or authenticate a HubSpot account\n' +
61
+ '- Any other tool reports that no account is configured\n' +
62
+ '- The user asks how to connect their HubSpot account to the CLI\n\n' +
63
+ 'WORKFLOW:\n' +
64
+ '1. Call this tool — it opens a browser tab for the user to authorize\n' +
65
+ '2. The user clicks "Connect to CLI" in the browser\n' +
66
+ '3. Auth completes automatically via WebSocket\n' +
67
+ '4. Retry any operation that was blocked by missing auth\n\n' +
68
+ 'setAsDefault defaults to true. Pass setAsDefault: false to keep an existing default account.',
69
+ inputSchema,
70
+ annotations: {
71
+ readOnlyHint: false,
72
+ destructiveHint: false,
73
+ idempotentHint: false,
74
+ openWorldHint: true,
75
+ },
76
+ }, (input, extra) => this.wrappedHandler(input, extra));
77
+ }
78
+ }
@@ -1,5 +1,5 @@
1
1
  import { TextContentResponse } from '../../types.js';
2
- import { Tool } from '../../Tool.js';
2
+ import { Tool, ToolExtra } from '../../Tool.js';
3
3
  import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
4
4
  import { McpLogger } from '../../utils/logger.js';
5
5
  import { z } from 'zod';
@@ -24,6 +24,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
24
24
  settings: "settings";
25
25
  "app-event": "app-event";
26
26
  "workflow-action-tool": "workflow-action-tool";
27
+ "crm-bulk-action": "crm-bulk-action";
27
28
  page: "page";
28
29
  webhooks: "webhooks";
29
30
  "app-function": "app-function";
@@ -36,7 +37,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
36
37
  export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
37
38
  export declare class CreateProjectTool extends Tool<CreateProjectInputSchema> {
38
39
  constructor(mcpServer: McpServer, logger: McpLogger);
39
- handler({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }: CreateProjectInputSchema): Promise<TextContentResponse>;
40
+ handler({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }: CreateProjectInputSchema, extra?: ToolExtra): Promise<TextContentResponse>;
40
41
  register(): RegisteredTool;
41
42
  }
42
43
  export {};
@@ -1,9 +1,8 @@
1
1
  import { Tool } from '../../Tool.js';
2
2
  import { z } from 'zod';
3
3
  import { APP_AUTH_TYPES, APP_DISTRIBUTION_TYPES, EMPTY_PROJECT, PROJECT_WITH_APP, } from '../../../lib/constants.js';
4
- import { addFlag } from '../../utils/command.js';
4
+ import { HubSpotCommand } from '../../utils/command.js';
5
5
  import { absoluteCurrentWorkingDirectory, features } from './constants.js';
6
- import { runCommandInDir } from '../../utils/command.js';
7
6
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
8
7
  import { setupHubSpotConfig } from '../../utils/config.js';
9
8
  import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
@@ -37,30 +36,32 @@ export class CreateProjectTool extends Tool {
37
36
  constructor(mcpServer, logger) {
38
37
  super(mcpServer, logger, toolName);
39
38
  }
40
- async handler({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }) {
39
+ async handler({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }, extra) {
41
40
  setupHubSpotConfig(absoluteCurrentWorkingDirectory);
42
- let command = addFlag('hs project create', 'platform-version', PLATFORM_VERSIONS.v2026_03);
41
+ const command = new HubSpotCommand('project create', [
42
+ { name: 'platform-version', value: PLATFORM_VERSIONS.v2026_03 },
43
+ ]);
43
44
  const content = [];
44
45
  if (name) {
45
- command = addFlag(command, 'name', name);
46
+ command.addFlag('name', name);
46
47
  }
47
48
  else {
48
49
  content.push(formatTextContent(`Ask the user what they would like to name the project.`));
49
50
  }
50
51
  if (destination) {
51
- command = addFlag(command, 'dest', destination);
52
+ command.addFlag('dest', destination);
52
53
  }
53
54
  if (projectBase) {
54
- command = addFlag(command, 'project-base', projectBase);
55
+ command.addFlag('project-base', projectBase);
55
56
  }
56
57
  if (distribution) {
57
- command = addFlag(command, 'distribution', distribution);
58
+ command.addFlag('distribution', distribution);
58
59
  }
59
60
  else if (projectBase === PROJECT_WITH_APP) {
60
61
  content.push(formatTextContent(`Ask the user how they would you like to distribute the app? Options are ${APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${APP_DISTRIBUTION_TYPES.PRIVATE}`));
61
62
  }
62
63
  if (auth) {
63
- command = addFlag(command, 'auth', auth);
64
+ command.addFlag('auth', auth);
64
65
  }
65
66
  else if (projectBase === PROJECT_WITH_APP) {
66
67
  content.push(formatTextContent(`Ask the user which auth type they would like to use? Options are ${APP_AUTH_TYPES.STATIC} and ${APP_AUTH_TYPES.OAUTH}`));
@@ -71,9 +72,9 @@ export class CreateProjectTool extends Tool {
71
72
  };
72
73
  }
73
74
  // Always pass features, even if it is an empty array to bypass the prompts
74
- command = addFlag(command, 'features', features || []);
75
+ command.addFlag('features', features || []);
75
76
  try {
76
- const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
77
+ const { stdout, stderr } = await this.runCommand(absoluteCurrentWorkingDirectory, command, extra);
77
78
  return formatTextContents(stdout, stderr);
78
79
  }
79
80
  catch (error) {
@@ -95,6 +96,6 @@ export class CreateProjectTool extends Tool {
95
96
  idempotentHint: false,
96
97
  openWorldHint: false,
97
98
  },
98
- }, input => this.wrappedHandler(input));
99
+ }, (input, extra) => this.wrappedHandler(input, extra));
99
100
  }
100
101
  }
@@ -2,7 +2,7 @@ import { z } from 'zod';
2
2
  import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { McpLogger } from '../../utils/logger.js';
4
4
  import { TextContentResponse } from '../../types.js';
5
- import { Tool } from '../../Tool.js';
5
+ import { Tool, ToolExtra } from '../../Tool.js';
6
6
  declare const createTestAccountInputSchema: z.ZodObject<{
7
7
  absoluteCurrentWorkingDirectory: z.ZodString;
8
8
  configPath: z.ZodOptional<z.ZodString>;
@@ -47,7 +47,7 @@ declare const createTestAccountInputSchema: z.ZodObject<{
47
47
  export type CreateTestAccountInputSchema = z.infer<typeof createTestAccountInputSchema>;
48
48
  export declare class CreateTestAccountTool extends Tool<CreateTestAccountInputSchema> {
49
49
  constructor(mcpServer: McpServer, logger: McpLogger);
50
- handler({ absoluteCurrentWorkingDirectory, name, description, marketingLevel, opsLevel, serviceLevel, salesLevel, contentLevel, commerceLevel, configPath, }: CreateTestAccountInputSchema): Promise<TextContentResponse>;
50
+ handler({ absoluteCurrentWorkingDirectory, name, description, marketingLevel, opsLevel, serviceLevel, salesLevel, contentLevel, commerceLevel, configPath, }: CreateTestAccountInputSchema, extra?: ToolExtra): Promise<TextContentResponse>;
51
51
  register(): RegisteredTool;
52
52
  }
53
53
  export {};
@@ -1,8 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import fs from 'fs';
3
3
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
4
- import { addFlag } from '../../utils/command.js';
5
- import { runCommandInDir } from '../../utils/command.js';
4
+ import { HubSpotCommand } from '../../utils/command.js';
6
5
  import { ACCOUNT_LEVELS, ACCOUNT_LEVEL_CHOICES, } from '../../../lib/constants.js';
7
6
  import { Tool } from '../../Tool.js';
8
7
  import { absoluteCurrentWorkingDirectory } from './constants.js';
@@ -70,9 +69,9 @@ export class CreateTestAccountTool extends Tool {
70
69
  constructor(mcpServer, logger) {
71
70
  super(mcpServer, logger, toolName);
72
71
  }
73
- async handler({ absoluteCurrentWorkingDirectory, name, description, marketingLevel, opsLevel, serviceLevel, salesLevel, contentLevel, commerceLevel, configPath, }) {
72
+ async handler({ absoluteCurrentWorkingDirectory, name, description, marketingLevel, opsLevel, serviceLevel, salesLevel, contentLevel, commerceLevel, configPath, }, extra) {
74
73
  setupHubSpotConfig(absoluteCurrentWorkingDirectory);
75
- let command = 'hs test-account create';
74
+ const command = new HubSpotCommand('test-account create');
76
75
  const content = [];
77
76
  // Use config file if provided (LLM should check for config first)
78
77
  if (configPath) {
@@ -105,7 +104,7 @@ export class CreateTestAccountTool extends Tool {
105
104
  });
106
105
  }
107
106
  }
108
- command = addFlag(command, 'config-path', configPath);
107
+ command.addFlag('config-path', configPath);
109
108
  }
110
109
  // Use flags if name is provided (when no config used)
111
110
  else if (name) {
@@ -120,14 +119,14 @@ export class CreateTestAccountTool extends Tool {
120
119
  error: e instanceof Error ? e.message : String(e),
121
120
  });
122
121
  }
123
- command = addFlag(command, 'name', name);
124
- command = addFlag(command, 'description', description || name);
125
- command = addFlag(command, 'marketing-level', marketingLevel || 'ENTERPRISE');
126
- command = addFlag(command, 'ops-level', opsLevel || 'ENTERPRISE');
127
- command = addFlag(command, 'service-level', serviceLevel || 'ENTERPRISE');
128
- command = addFlag(command, 'sales-level', salesLevel || 'ENTERPRISE');
129
- command = addFlag(command, 'content-level', contentLevel || 'ENTERPRISE');
130
- command = addFlag(command, 'commerce-level', commerceLevel || 'ENTERPRISE');
122
+ command.addFlag('name', name);
123
+ command.addFlag('description', description || name);
124
+ command.addFlag('marketing-level', marketingLevel || 'ENTERPRISE');
125
+ command.addFlag('ops-level', opsLevel || 'ENTERPRISE');
126
+ command.addFlag('service-level', serviceLevel || 'ENTERPRISE');
127
+ command.addFlag('sales-level', salesLevel || 'ENTERPRISE');
128
+ command.addFlag('content-level', contentLevel || 'ENTERPRISE');
129
+ command.addFlag('commerce-level', commerceLevel || 'ENTERPRISE');
131
130
  }
132
131
  else {
133
132
  content.push(formatTextContent(`Ask the user for the account config JSON path or the name of the test account to create.`));
@@ -139,7 +138,7 @@ export class CreateTestAccountTool extends Tool {
139
138
  }
140
139
  // No flags or config - command will prompt user interactively
141
140
  try {
142
- const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
141
+ const { stdout, stderr } = await this.runCommand(absoluteCurrentWorkingDirectory, command, extra);
143
142
  return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
144
143
  }
145
144
  catch (error) {
@@ -177,6 +176,6 @@ export class CreateTestAccountTool extends Tool {
177
176
  idempotentHint: false,
178
177
  openWorldHint: true,
179
178
  },
180
- }, input => this.wrappedHandler(input));
179
+ }, (input, extra) => this.wrappedHandler(input, extra));
181
180
  }
182
181
  }
@@ -1,5 +1,5 @@
1
1
  import { TextContentResponse } from '../../types.js';
2
- import { Tool } from '../../Tool.js';
2
+ import { Tool, ToolExtra } from '../../Tool.js';
3
3
  import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
4
4
  import { McpLogger } from '../../utils/logger.js';
5
5
  import { z } from 'zod';
@@ -11,7 +11,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
11
11
  type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
12
12
  export declare class DeployProjectTool extends Tool<InputSchemaType> {
13
13
  constructor(mcpServer: McpServer, logger: McpLogger);
14
- handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, buildNumber, }: InputSchemaType): Promise<TextContentResponse>;
14
+ handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, buildNumber, }: InputSchemaType, extra?: ToolExtra): Promise<TextContentResponse>;
15
15
  register(): RegisteredTool;
16
16
  }
17
17
  export {};
@@ -1,8 +1,7 @@
1
1
  import { Tool } from '../../Tool.js';
2
2
  import { z } from 'zod';
3
- import { addFlag } from '../../utils/command.js';
3
+ import { HubSpotCommand } from '../../utils/command.js';
4
4
  import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
5
- import { runCommandInDir } from '../../utils/command.js';
6
5
  import { formatTextContents, formatTextContent } from '../../utils/content.js';
7
6
  import { setupHubSpotConfig } from '../../utils/config.js';
8
7
  const inputSchema = {
@@ -21,23 +20,24 @@ export class DeployProjectTool extends Tool {
21
20
  constructor(mcpServer, logger) {
22
21
  super(mcpServer, logger, toolName);
23
22
  }
24
- async handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, buildNumber, }) {
23
+ async handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, buildNumber, }, extra) {
25
24
  setupHubSpotConfig(absoluteCurrentWorkingDirectory);
26
- let command = `hs project deploy`;
27
25
  const content = [];
28
26
  if (!buildNumber) {
29
- const { stdout } = await runCommandInDir(absoluteProjectPath, `hs project list-builds --limit 100`);
27
+ const { stdout } = await this.runCommand(absoluteProjectPath, new HubSpotCommand('project list-builds', [
28
+ { name: 'limit', value: 100 },
29
+ ]), extra);
30
30
  content.push(formatTextContent(`Ask the user which build number they would like to deploy? Build information: ${stdout}`));
31
31
  }
32
- else {
33
- command = addFlag(command, 'build', buildNumber);
34
- }
35
32
  if (content.length) {
36
33
  return {
37
34
  content,
38
35
  };
39
36
  }
40
- const { stdout, stderr } = await runCommandInDir(absoluteProjectPath, command);
37
+ const command = new HubSpotCommand('project deploy', [
38
+ { name: 'build', value: buildNumber },
39
+ ]);
40
+ const { stdout, stderr } = await this.runCommand(absoluteProjectPath, command, extra);
41
41
  return formatTextContents(stdout, stderr);
42
42
  }
43
43
  register() {
@@ -51,6 +51,6 @@ export class DeployProjectTool extends Tool {
51
51
  idempotentHint: true,
52
52
  openWorldHint: true,
53
53
  },
54
- }, input => this.wrappedHandler(input));
54
+ }, (input, extra) => this.wrappedHandler(input, extra));
55
55
  }
56
56
  }
@@ -54,6 +54,6 @@ export class DocFetchTool extends Tool {
54
54
  readOnlyHint: true,
55
55
  openWorldHint: true,
56
56
  },
57
- }, input => this.wrappedHandler(input));
57
+ }, (input, extra) => this.wrappedHandler(input, extra));
58
58
  }
59
59
  }
@@ -4,8 +4,8 @@ import { Tool } from '../../Tool.js';
4
4
  import { formatTextContents } from '../../utils/content.js';
5
5
  import { absoluteCurrentWorkingDirectory, docsSearchQuery, } from './constants.js';
6
6
  import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
7
- import { getConfigDefaultAccountIfExists } from '@hubspot/local-dev-lib/config';
8
7
  import { setupHubSpotConfig } from '../../utils/config.js';
8
+ import { discoverAccountTargets } from '../../../lib/accountTargetDiscovery.js';
9
9
  import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
10
10
  const docsSearchLimit = z
11
11
  .number()
@@ -33,12 +33,13 @@ export class DocsSearchTool extends Tool {
33
33
  }
34
34
  async handler({ docsSearchQuery, docsSearchLimit, absoluteCurrentWorkingDirectory, }) {
35
35
  setupHubSpotConfig(absoluteCurrentWorkingDirectory);
36
- const accountId = getConfigDefaultAccountIfExists()?.accountId;
37
- if (!accountId) {
38
- const authErrorMessage = `No account ID found. Please run \`hs account auth\` to configure an account, or set a default account with \`hs account use <account>\``;
39
- return formatTextContents(authErrorMessage);
40
- }
41
36
  try {
37
+ const { recommended } = await discoverAccountTargets();
38
+ const accountId = recommended?.accountId;
39
+ if (!accountId) {
40
+ const authErrorMessage = `No account ID found. Call the auth-account tool to authenticate a HubSpot account.`;
41
+ return formatTextContents(authErrorMessage);
42
+ }
42
43
  const response = await http.post(accountId, {
43
44
  url: 'dev/docs/llms/v1/docs-search',
44
45
  data: {
@@ -87,6 +88,6 @@ export class DocsSearchTool extends Tool {
87
88
  readOnlyHint: true,
88
89
  openWorldHint: true,
89
90
  },
90
- }, input => this.wrappedHandler(input));
91
+ }, (input, extra) => this.wrappedHandler(input, extra));
91
92
  }
92
93
  }
@@ -55,6 +55,6 @@ export class FindProjectsTool extends Tool {
55
55
  openWorldHint: false,
56
56
  idempotentHint: true,
57
57
  },
58
- }, input => this.wrappedHandler(input));
58
+ }, (input, extra) => this.wrappedHandler(input, extra));
59
59
  }
60
60
  }
@@ -5,6 +5,7 @@ import { McpLogger } from '../../utils/logger.js';
5
5
  import { z } from 'zod';
6
6
  declare const inputSchemaZodObject: z.ZodObject<{
7
7
  absoluteCurrentWorkingDirectory: z.ZodString;
8
+ absoluteProjectPath: z.ZodOptional<z.ZodString>;
8
9
  appId: z.ZodString;
9
10
  startDate: z.ZodOptional<z.ZodString>;
10
11
  endDate: z.ZodOptional<z.ZodString>;
@@ -12,7 +13,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
12
13
  export type GetApiUsagePatternsByAppIdInputSchema = z.infer<typeof inputSchemaZodObject>;
13
14
  export declare class GetApiUsagePatternsByAppIdTool extends Tool<GetApiUsagePatternsByAppIdInputSchema> {
14
15
  constructor(mcpServer: McpServer, logger: McpLogger);
15
- handler({ appId, startDate, endDate, absoluteCurrentWorkingDirectory, }: GetApiUsagePatternsByAppIdInputSchema): Promise<TextContentResponse>;
16
+ handler({ appId, startDate, endDate, absoluteCurrentWorkingDirectory, absoluteProjectPath, }: GetApiUsagePatternsByAppIdInputSchema): Promise<TextContentResponse>;
16
17
  register(): RegisteredTool;
17
18
  }
18
19
  export {};
@@ -3,12 +3,13 @@ import { z } from 'zod';
3
3
  import { http } from '@hubspot/local-dev-lib/http';
4
4
  import { formatTextContents } from '../../utils/content.js';
5
5
  import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
6
- import { getConfigDefaultAccountIfExists } from '@hubspot/local-dev-lib/config';
7
- import { absoluteCurrentWorkingDirectory } from './constants.js';
6
+ import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
8
7
  import { setupHubSpotConfig } from '../../utils/config.js';
8
+ import { discoverAccountTargets } from '../../../lib/accountTargetDiscovery.js';
9
9
  import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
10
10
  const inputSchema = {
11
11
  absoluteCurrentWorkingDirectory,
12
+ absoluteProjectPath: absoluteProjectPath.optional(),
12
13
  appId: z
13
14
  .string()
14
15
  .describe('The numeric app ID as a string (e.g., "3003909"). Must contain only digits. Use get-apps-info to find available app IDs.'),
@@ -28,13 +29,13 @@ export class GetApiUsagePatternsByAppIdTool extends Tool {
28
29
  constructor(mcpServer, logger) {
29
30
  super(mcpServer, logger, toolName);
30
31
  }
31
- async handler({ appId, startDate, endDate, absoluteCurrentWorkingDirectory, }) {
32
- setupHubSpotConfig(absoluteCurrentWorkingDirectory);
32
+ async handler({ appId, startDate, endDate, absoluteCurrentWorkingDirectory, absoluteProjectPath, }) {
33
+ setupHubSpotConfig(absoluteProjectPath ?? absoluteCurrentWorkingDirectory);
33
34
  try {
34
- // Get account ID from CLI config
35
- const accountId = getConfigDefaultAccountIfExists()?.accountId;
35
+ const { recommended } = await discoverAccountTargets();
36
+ const accountId = recommended?.accountId;
36
37
  if (!accountId) {
37
- const authErrorMessage = `No account ID found. Please run \`hs account auth\` to configure an account, or set a default account with \`hs account use <account>\``;
38
+ const authErrorMessage = `No account ID found. Call the auth-account tool to authenticate a HubSpot account.`;
38
39
  return formatTextContents(authErrorMessage);
39
40
  }
40
41
  const response = await http.get(accountId, {
@@ -70,6 +71,6 @@ export class GetApiUsagePatternsByAppIdTool extends Tool {
70
71
  readOnlyHint: true,
71
72
  openWorldHint: true,
72
73
  },
73
- }, input => this.wrappedHandler(input));
74
+ }, (input, extra) => this.wrappedHandler(input, extra));
74
75
  }
75
76
  }
@@ -5,11 +5,12 @@ import { McpLogger } from '../../utils/logger.js';
5
5
  import { z } from 'zod';
6
6
  declare const inputSchemaZodObject: z.ZodObject<{
7
7
  absoluteCurrentWorkingDirectory: z.ZodString;
8
+ absoluteProjectPath: z.ZodOptional<z.ZodString>;
8
9
  }, z.core.$strip>;
9
10
  export type GetApplicationInfoInputSchema = z.infer<typeof inputSchemaZodObject>;
10
11
  export declare class GetApplicationInfoTool extends Tool<GetApplicationInfoInputSchema> {
11
12
  constructor(mcpServer: McpServer, logger: McpLogger);
12
- handler({ absoluteCurrentWorkingDirectory, }: GetApplicationInfoInputSchema): Promise<TextContentResponse>;
13
+ handler({ absoluteCurrentWorkingDirectory, absoluteProjectPath, }: GetApplicationInfoInputSchema): Promise<TextContentResponse>;
13
14
  register(): RegisteredTool;
14
15
  }
15
16
  export {};
@@ -3,11 +3,14 @@ import { z } from 'zod';
3
3
  import { http } from '@hubspot/local-dev-lib/http';
4
4
  import { formatTextContents } from '../../utils/content.js';
5
5
  import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
6
- import { getConfigDefaultAccountIfExists } from '@hubspot/local-dev-lib/config';
7
- import { absoluteCurrentWorkingDirectory } from './constants.js';
6
+ import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
8
7
  import { setupHubSpotConfig } from '../../utils/config.js';
8
+ import { discoverAccountTargets } from '../../../lib/accountTargetDiscovery.js';
9
9
  import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
10
- const inputSchema = { absoluteCurrentWorkingDirectory };
10
+ const inputSchema = {
11
+ absoluteCurrentWorkingDirectory,
12
+ absoluteProjectPath: absoluteProjectPath.optional(),
13
+ };
11
14
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
12
15
  const inputSchemaZodObject = z.object({ ...inputSchema });
13
16
  const toolName = 'get-apps-info';
@@ -15,13 +18,13 @@ export class GetApplicationInfoTool extends Tool {
15
18
  constructor(mcpServer, logger) {
16
19
  super(mcpServer, logger, toolName);
17
20
  }
18
- async handler({ absoluteCurrentWorkingDirectory, }) {
19
- setupHubSpotConfig(absoluteCurrentWorkingDirectory);
21
+ async handler({ absoluteCurrentWorkingDirectory, absoluteProjectPath, }) {
22
+ setupHubSpotConfig(absoluteProjectPath ?? absoluteCurrentWorkingDirectory);
20
23
  try {
21
- // Get account ID from CLI config
22
- const accountId = getConfigDefaultAccountIfExists()?.accountId;
24
+ const { recommended } = await discoverAccountTargets();
25
+ const accountId = recommended?.accountId;
23
26
  if (!accountId) {
24
- const authErrorMessage = `No account ID found. Please run \`hs account auth\` to configure an account, or set a default account with \`hs account use <account>\``;
27
+ const authErrorMessage = `No account ID found. Call the auth-account tool to authenticate a HubSpot account.`;
25
28
  return formatTextContents(authErrorMessage);
26
29
  }
27
30
  const response = await http.get(accountId, {
@@ -53,6 +56,6 @@ export class GetApplicationInfoTool extends Tool {
53
56
  readOnlyHint: true,
54
57
  openWorldHint: true,
55
58
  },
56
- }, input => this.wrappedHandler(input));
59
+ }, (input, extra) => this.wrappedHandler(input, extra));
57
60
  }
58
61
  }
@@ -5,8 +5,8 @@ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
5
5
  import { http } from '@hubspot/local-dev-lib/http';
6
6
  import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
7
7
  import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
8
- import { getConfigDefaultAccountIfExists } from '@hubspot/local-dev-lib/config';
9
8
  import { setupHubSpotConfig } from '../../utils/config.js';
9
+ import { discoverAccountTargets } from '../../../lib/accountTargetDiscovery.js';
10
10
  const TOOL_NAME = 'get-build-logs';
11
11
  const PROJECTS_LOGS_API_PATH = 'dfs/logging/v1';
12
12
  const inputSchema = {
@@ -62,14 +62,18 @@ export class GetBuildLogsTool extends Tool {
62
62
  super(mcpServer, logger, TOOL_NAME);
63
63
  }
64
64
  async handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, buildId, logLevel, }) {
65
- setupHubSpotConfig(absoluteCurrentWorkingDirectory);
65
+ setupHubSpotConfig(absoluteProjectPath);
66
66
  try {
67
- const accountId = getConfigDefaultAccountIfExists()?.accountId;
68
- if (!accountId) {
69
- return formatTextContents(absoluteCurrentWorkingDirectory, 'No account ID found. Please run `hs account auth` to configure an account, or set a default account with `hs account use <account>`');
70
- }
71
67
  const { projectConfig, projectDir } = await getProjectConfig(absoluteProjectPath);
72
68
  validateProjectConfig(projectConfig, projectDir);
69
+ const { recommended } = await discoverAccountTargets({
70
+ projectDir,
71
+ projectConfig,
72
+ });
73
+ const accountId = recommended?.accountId;
74
+ if (!accountId) {
75
+ return formatTextContents(absoluteCurrentWorkingDirectory, 'No account ID found. Call the auth-account tool to authenticate a HubSpot account.');
76
+ }
73
77
  const projectName = projectConfig.name;
74
78
  const response = await http.get(accountId, {
75
79
  url: `${PROJECTS_LOGS_API_PATH}/logs/projects/${encodeURIComponent(projectName)}/builds/${buildId}`,
@@ -121,6 +125,6 @@ export class GetBuildLogsTool extends Tool {
121
125
  openWorldHint: true,
122
126
  idempotentHint: true,
123
127
  },
124
- }, input => this.wrappedHandler(input));
128
+ }, (input, extra) => this.wrappedHandler(input, extra));
125
129
  }
126
130
  }
@@ -6,8 +6,8 @@ import { fetchProjectBuilds, getBuildStatus, } from '@hubspot/local-dev-lib/api/
6
6
  import { getProjectConfig, validateProjectConfig, } from '../../../lib/projects/config.js';
7
7
  import moment from 'moment';
8
8
  import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
9
- import { getConfigDefaultAccountIfExists } from '@hubspot/local-dev-lib/config';
10
9
  import { setupHubSpotConfig } from '../../utils/config.js';
10
+ import { discoverAccountTargets } from '../../../lib/accountTargetDiscovery.js';
11
11
  const TOOL_NAME = 'get-build-status';
12
12
  const inputSchema = {
13
13
  absoluteProjectPath,
@@ -107,14 +107,18 @@ export class GetBuildStatusTool extends Tool {
107
107
  super(mcpServer, logger, TOOL_NAME);
108
108
  }
109
109
  async handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, buildId, limit, }) {
110
- setupHubSpotConfig(absoluteCurrentWorkingDirectory);
110
+ setupHubSpotConfig(absoluteProjectPath);
111
111
  try {
112
- const accountId = getConfigDefaultAccountIfExists()?.accountId;
113
- if (!accountId) {
114
- return formatTextContents(absoluteCurrentWorkingDirectory, 'No account ID found. Please run `hs account auth` to configure an account, or set a default account with `hs account use <account>`');
115
- }
116
112
  const { projectConfig, projectDir } = await getProjectConfig(absoluteProjectPath);
117
113
  validateProjectConfig(projectConfig, projectDir);
114
+ const { recommended } = await discoverAccountTargets({
115
+ projectDir,
116
+ projectConfig,
117
+ });
118
+ const accountId = recommended?.accountId;
119
+ if (!accountId) {
120
+ return formatTextContents(absoluteCurrentWorkingDirectory, 'No account ID found. Call the auth-account tool to authenticate a HubSpot account.');
121
+ }
118
122
  const projectName = projectConfig.name;
119
123
  let output;
120
124
  if (buildId) {
@@ -162,6 +166,6 @@ export class GetBuildStatusTool extends Tool {
162
166
  openWorldHint: true,
163
167
  idempotentHint: true,
164
168
  },
165
- }, input => this.wrappedHandler(input));
169
+ }, (input, extra) => this.wrappedHandler(input, extra));
166
170
  }
167
171
  }
@@ -5,13 +5,14 @@ import { McpLogger } from '../../utils/logger.js';
5
5
  import { z } from 'zod';
6
6
  declare const inputSchemaZodObject: z.ZodObject<{
7
7
  absoluteCurrentWorkingDirectory: z.ZodString;
8
+ absoluteProjectPath: z.ZodOptional<z.ZodString>;
8
9
  platformVersion: z.ZodString;
9
10
  featureType: z.ZodString;
10
11
  }, z.core.$strip>;
11
12
  type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
12
13
  export declare class GetConfigValuesTool extends Tool<InputSchemaType> {
13
14
  constructor(mcpServer: McpServer, logger: McpLogger);
14
- handler({ platformVersion, featureType, absoluteCurrentWorkingDirectory, }: InputSchemaType): Promise<TextContentResponse>;
15
+ handler({ platformVersion, featureType, absoluteCurrentWorkingDirectory, absoluteProjectPath, }: InputSchemaType): Promise<TextContentResponse>;
15
16
  register(): RegisteredTool;
16
17
  }
17
18
  export {};