@hubspot/cli 8.10.0 → 8.11.0-beta.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.
- package/commands/hubdb/list.d.ts +1 -1
- package/commands/mcp/setup.d.ts +2 -0
- package/commands/mcp/setup.js +29 -1
- package/commands/project/appInstallStatus.d.ts +1 -1
- package/commands/project/info.d.ts +1 -1
- package/commands/project/installApp.d.ts +1 -1
- package/commands/project/profile/add.d.ts +2 -1
- package/commands/project/profile/add.js +22 -1
- package/commands/project/profile/delete.d.ts +1 -1
- package/commands/project/upload.js +4 -1
- package/commands/project/validate.d.ts +1 -1
- package/commands/testAccount/importData.d.ts +1 -1
- package/lang/en.d.ts +11 -0
- package/lang/en.js +11 -0
- package/lib/mcp/setup.d.ts +6 -1
- package/lib/mcp/setup.js +29 -18
- package/lib/projects/upload.d.ts +1 -1
- package/lib/projects/upload.js +4 -8
- package/mcp-server/Tool.d.ts +8 -3
- package/mcp-server/Tool.js +28 -8
- package/mcp-server/server.js +10 -6
- package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +10 -17
- package/mcp-server/tools/cms/HsCreateModuleTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +12 -18
- package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +8 -10
- package/mcp-server/tools/cms/HsFunctionLogsTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +9 -9
- package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsListFunctionsTool.js +7 -7
- package/mcp-server/tools/cms/HsListTool.d.ts +2 -2
- package/mcp-server/tools/cms/HsListTool.js +6 -10
- package/mcp-server/tools/index.js +2 -0
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +8 -9
- package/mcp-server/tools/project/AuthAccountTool.d.ts +18 -0
- package/mcp-server/tools/project/AuthAccountTool.js +78 -0
- package/mcp-server/tools/project/CreateProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/CreateProjectTool.js +13 -12
- package/mcp-server/tools/project/CreateTestAccountTool.d.ts +2 -2
- package/mcp-server/tools/project/CreateTestAccountTool.js +14 -15
- package/mcp-server/tools/project/DeployProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/DeployProjectTool.js +10 -10
- package/mcp-server/tools/project/DocFetchTool.js +1 -1
- package/mcp-server/tools/project/DocsSearchTool.js +9 -3
- package/mcp-server/tools/project/FindProjectsTool.js +1 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +9 -4
- package/mcp-server/tools/project/GetApplicationInfoTool.js +9 -4
- package/mcp-server/tools/project/GetBuildLogsTool.js +9 -3
- package/mcp-server/tools/project/GetBuildStatusTool.js +9 -3
- package/mcp-server/tools/project/GetConfigValuesTool.js +9 -3
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.d.ts +2 -2
- package/mcp-server/tools/project/UploadProjectTools.js +9 -8
- package/mcp-server/tools/project/ValidateProjectTool.d.ts +2 -2
- package/mcp-server/tools/project/ValidateProjectTool.js +5 -4
- package/mcp-server/utils/command.d.ts +25 -2
- package/mcp-server/utils/command.js +67 -17
- package/mcp-server/utils/toolUsageTracking.js +8 -1
- package/package.json +3 -3
package/commands/hubdb/list.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { CommonArgs, ConfigArgs, AccountArgs, EnvironmentArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
-
type HubdbListArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs;
|
|
2
|
+
export type HubdbListArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs;
|
|
3
3
|
declare const hubdbListCommand: YargsCommandModule<unknown, HubdbListArgs>;
|
|
4
4
|
export default hubdbListCommand;
|
package/commands/mcp/setup.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { CommonArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
2
|
interface MCPSetupArgs extends CommonArgs {
|
|
3
3
|
client?: string[];
|
|
4
|
+
standalone?: boolean;
|
|
5
|
+
cliVersion?: string;
|
|
4
6
|
}
|
|
5
7
|
declare const mcpSetupCommand: YargsCommandModule<unknown, MCPSetupArgs>;
|
|
6
8
|
export default mcpSetupCommand;
|
package/commands/mcp/setup.js
CHANGED
|
@@ -8,7 +8,11 @@ const describe = commands.mcp.setup.describe;
|
|
|
8
8
|
async function handler(args) {
|
|
9
9
|
const { exit } = args;
|
|
10
10
|
try {
|
|
11
|
-
await configureMcpServer(
|
|
11
|
+
await configureMcpServer({
|
|
12
|
+
targets: args.client,
|
|
13
|
+
standalone: args.standalone,
|
|
14
|
+
cliVersion: args.cliVersion,
|
|
15
|
+
});
|
|
12
16
|
}
|
|
13
17
|
catch (e) {
|
|
14
18
|
return exit(EXIT_CODES.ERROR);
|
|
@@ -21,6 +25,30 @@ function setupBuilder(yargs) {
|
|
|
21
25
|
type: 'array',
|
|
22
26
|
choices: [...supportedTools.map(tool => tool.value)],
|
|
23
27
|
});
|
|
28
|
+
yargs.option('standalone', {
|
|
29
|
+
describe: commands.mcp.setup.args.standalone,
|
|
30
|
+
type: 'boolean',
|
|
31
|
+
});
|
|
32
|
+
yargs.option('cli-version', {
|
|
33
|
+
describe: commands.mcp.setup.args.cliVersion,
|
|
34
|
+
type: 'string',
|
|
35
|
+
});
|
|
36
|
+
yargs.check(argv => {
|
|
37
|
+
if (argv.cliVersion !== undefined && argv.standalone !== true) {
|
|
38
|
+
throw new Error(commands.mcp.setup.errors.cliVersionRequiresStandalone);
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
});
|
|
42
|
+
yargs.example([
|
|
43
|
+
[
|
|
44
|
+
'$0 mcp setup --client claude --no-standalone',
|
|
45
|
+
commands.mcp.setup.examples.nonInteractive,
|
|
46
|
+
],
|
|
47
|
+
[
|
|
48
|
+
'$0 mcp setup --client cursor --standalone --cli-version 8.0.1',
|
|
49
|
+
commands.mcp.setup.examples.standalone,
|
|
50
|
+
],
|
|
51
|
+
]);
|
|
24
52
|
return yargs;
|
|
25
53
|
}
|
|
26
54
|
const builder = makeYargsBuilder(setupBuilder, command, describe, {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
-
type ProjectInstallStatusArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
|
|
2
|
+
export type ProjectInstallStatusArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
|
|
3
3
|
declare const projectInstallStatusCommand: YargsCommandModule<unknown, ProjectInstallStatusArgs>;
|
|
4
4
|
export default projectInstallStatusCommand;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
-
type ProjectInfoArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
|
|
2
|
+
export type ProjectInfoArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs;
|
|
3
3
|
declare const projectInfoCommand: YargsCommandModule<unknown, ProjectInfoArgs>;
|
|
4
4
|
export default projectInfoCommand;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
-
type ProjectInstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
2
|
+
export type ProjectInstallAppArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & JSONOutputArgs & {
|
|
3
3
|
force: boolean;
|
|
4
4
|
profile?: string;
|
|
5
5
|
};
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { YargsCommandModule, CommonArgs } from '../../../types/Yargs.js';
|
|
2
|
-
type ProjectProfileAddArgs = CommonArgs & {
|
|
2
|
+
export type ProjectProfileAddArgs = CommonArgs & {
|
|
3
3
|
name?: string;
|
|
4
4
|
targetAccount?: number;
|
|
5
|
+
copyFrom?: string;
|
|
5
6
|
};
|
|
6
7
|
declare const projectProfileAddCommand: YargsCommandModule<unknown, ProjectProfileAddArgs>;
|
|
7
8
|
export default projectProfileAddCommand;
|
|
@@ -157,7 +157,20 @@ async function handler(args) {
|
|
|
157
157
|
accountId: targetAccountId,
|
|
158
158
|
variables: {},
|
|
159
159
|
};
|
|
160
|
-
|
|
160
|
+
let profileToCopyVariablesFrom;
|
|
161
|
+
if (args.copyFrom) {
|
|
162
|
+
if (existingProfiles.includes(args.copyFrom)) {
|
|
163
|
+
profileToCopyVariablesFrom = args.copyFrom;
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
uiLogger.error(commands.project.profile.add.errors.copyFromProfileNotFound(args.copyFrom));
|
|
167
|
+
return exit(EXIT_CODES.ERROR);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
profileToCopyVariablesFrom =
|
|
172
|
+
await selectProfileToCopyVariablesFrom(existingProfiles);
|
|
173
|
+
}
|
|
161
174
|
if (profileToCopyVariablesFrom) {
|
|
162
175
|
try {
|
|
163
176
|
const profileToCopyFileContent = loadHsProfileFile(projectSourceDir, profileToCopyVariablesFrom);
|
|
@@ -190,8 +203,16 @@ function projectProfileAddBuilder(yargs) {
|
|
|
190
203
|
describe: commands.project.profile.add.options.targetAccount,
|
|
191
204
|
type: 'number',
|
|
192
205
|
});
|
|
206
|
+
yargs.option('copy-from', {
|
|
207
|
+
describe: commands.project.profile.add.options.copyFrom,
|
|
208
|
+
type: 'string',
|
|
209
|
+
});
|
|
193
210
|
yargs.example([
|
|
194
211
|
['$0 project profile add qa', commands.project.profile.add.example],
|
|
212
|
+
[
|
|
213
|
+
'$0 project profile add qa --target-account 123 --copy-from staging',
|
|
214
|
+
commands.project.profile.add.exampleCopyFrom,
|
|
215
|
+
],
|
|
195
216
|
]);
|
|
196
217
|
return yargs;
|
|
197
218
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { YargsCommandModule, CommonArgs } from '../../../types/Yargs.js';
|
|
2
|
-
type ProjectProfileDeleteArgs = CommonArgs & {
|
|
2
|
+
export type ProjectProfileDeleteArgs = CommonArgs & {
|
|
3
3
|
name?: string;
|
|
4
4
|
};
|
|
5
5
|
declare const projectProfileDeleteCommand: YargsCommandModule<unknown, ProjectProfileDeleteArgs>;
|
|
@@ -113,7 +113,10 @@ async function handler(args) {
|
|
|
113
113
|
(!result.buildResult.isAutoDeployEnabled || preview || skipAutoDeploy)) {
|
|
114
114
|
uiLogger.log(chalk.bold(commands.project.upload.logs.buildSucceeded(result.buildId)));
|
|
115
115
|
if (!preview) {
|
|
116
|
-
|
|
116
|
+
const deployCommand = `hs project deploy --build=${result.buildId}`;
|
|
117
|
+
uiLogger.log(skipAutoDeploy
|
|
118
|
+
? commands.project.upload.logs.autoDeploySkipped(deployCommand)
|
|
119
|
+
: commands.project.upload.logs.autoDeployDisabled(deployCommand));
|
|
117
120
|
logFeedbackMessage(result.buildId);
|
|
118
121
|
}
|
|
119
122
|
await displayWarnLogs(targetAccountId, projectConfig.name, result.buildId);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CommonArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
-
type ProjectValidateArgs = CommonArgs & {
|
|
2
|
+
export type ProjectValidateArgs = CommonArgs & {
|
|
3
3
|
profile?: string;
|
|
4
4
|
};
|
|
5
5
|
declare const projectValidateCommand: YargsCommandModule<unknown, ProjectValidateArgs>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AccountArgs, CommonArgs, ConfigArgs, EnvironmentArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
2
|
export declare const command = "import-data";
|
|
3
3
|
export declare const describe: string;
|
|
4
|
-
type CrmImportDataArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
|
|
4
|
+
export type CrmImportDataArgs = CommonArgs & ConfigArgs & AccountArgs & EnvironmentArgs & {
|
|
5
5
|
filePath: string | undefined;
|
|
6
6
|
skipConfirm: boolean | undefined;
|
|
7
7
|
};
|
package/lang/en.d.ts
CHANGED
|
@@ -1330,11 +1330,18 @@ export declare const commands: {
|
|
|
1330
1330
|
vsCode: string;
|
|
1331
1331
|
args: {
|
|
1332
1332
|
client: string;
|
|
1333
|
+
standalone: string;
|
|
1334
|
+
cliVersion: string;
|
|
1333
1335
|
docsSearch: string;
|
|
1334
1336
|
};
|
|
1337
|
+
examples: {
|
|
1338
|
+
nonInteractive: string;
|
|
1339
|
+
standalone: string;
|
|
1340
|
+
};
|
|
1335
1341
|
success: (derivedTargets: string[]) => string;
|
|
1336
1342
|
errors: {
|
|
1337
1343
|
errorParsingJsonFIle: (filename: string, errorMessage: string) => string;
|
|
1344
|
+
cliVersionRequiresStandalone: string;
|
|
1338
1345
|
};
|
|
1339
1346
|
spinners: {
|
|
1340
1347
|
failedToConfigure: string;
|
|
@@ -1429,6 +1436,7 @@ export declare const commands: {
|
|
|
1429
1436
|
describe: string;
|
|
1430
1437
|
verboseDescribe: string;
|
|
1431
1438
|
example: string;
|
|
1439
|
+
exampleCopyFrom: string;
|
|
1432
1440
|
logs: {
|
|
1433
1441
|
copyExistingProfile: (profileName: string) => string;
|
|
1434
1442
|
copyExistingProfiles: string;
|
|
@@ -1452,6 +1460,7 @@ export declare const commands: {
|
|
|
1452
1460
|
invalidTargetAccount: string;
|
|
1453
1461
|
noAccountsConfigured: string;
|
|
1454
1462
|
failedToLoadProfile: (profileName: string) => string;
|
|
1463
|
+
copyFromProfileNotFound: (profileName: string) => string;
|
|
1455
1464
|
failedToCreateProfile: string;
|
|
1456
1465
|
};
|
|
1457
1466
|
positionals: {
|
|
@@ -1459,6 +1468,7 @@ export declare const commands: {
|
|
|
1459
1468
|
};
|
|
1460
1469
|
options: {
|
|
1461
1470
|
targetAccount: string;
|
|
1471
|
+
copyFrom: string;
|
|
1462
1472
|
};
|
|
1463
1473
|
};
|
|
1464
1474
|
delete: {
|
|
@@ -1880,6 +1890,7 @@ export declare const commands: {
|
|
|
1880
1890
|
readyToGoLive: string;
|
|
1881
1891
|
runCommand: (command: string) => string;
|
|
1882
1892
|
autoDeployDisabled: (deployCommand: string) => string;
|
|
1893
|
+
autoDeploySkipped: (deployCommand: string) => string;
|
|
1883
1894
|
};
|
|
1884
1895
|
errors: {
|
|
1885
1896
|
noProjectConfig: string;
|
package/lang/en.js
CHANGED
|
@@ -1339,11 +1339,18 @@ export const commands = {
|
|
|
1339
1339
|
vsCode: 'VSCode',
|
|
1340
1340
|
args: {
|
|
1341
1341
|
client: 'Target apps to configure',
|
|
1342
|
+
standalone: 'Use npx for all of the hs commands run by the MCP server. This allows you to use the MCP server without having the CLI globally installed.',
|
|
1343
|
+
cliVersion: 'Pin a specific CLI version for standalone mode',
|
|
1342
1344
|
docsSearch: 'Should the docs search mcp server be installed',
|
|
1343
1345
|
},
|
|
1346
|
+
examples: {
|
|
1347
|
+
nonInteractive: 'Configure Claude Code without prompts',
|
|
1348
|
+
standalone: 'Configure Cursor in standalone mode with a pinned CLI version',
|
|
1349
|
+
},
|
|
1344
1350
|
success: (derivedTargets) => `You can now use the HubSpot CLI MCP Server in ${derivedTargets.join(', ')}. ${chalk.bold('You may need to restart these tools to apply the changes')}.`,
|
|
1345
1351
|
errors: {
|
|
1346
1352
|
errorParsingJsonFIle: (filename, errorMessage) => `Unable to update ${chalk.bold(filename)} due to invalid JSON: ${errorMessage}`,
|
|
1353
|
+
cliVersionRequiresStandalone: '`--cli-version` requires `--standalone`. Pass `--standalone` to use a specific CLI version.',
|
|
1347
1354
|
},
|
|
1348
1355
|
spinners: {
|
|
1349
1356
|
failedToConfigure: 'Failed to configure the HubSpot mcp server.',
|
|
@@ -1444,6 +1451,7 @@ export const commands = {
|
|
|
1444
1451
|
describe: 'Add a new project profile',
|
|
1445
1452
|
verboseDescribe: `Add a new project profile\n\nProfiles enable you to reference variables in your component configuration files. Use the syntax ${chalk.bold('\${VARIABLE_NAME}')} to reference profile variables in your component configuration files. Then target the profile using the ${uiCommandReference('--profile')} flag when you upload your project.`,
|
|
1446
1453
|
example: 'Add a new project profile named hsprofile.qa.json',
|
|
1454
|
+
exampleCopyFrom: 'Add a profile and copy variables from the staging profile',
|
|
1447
1455
|
logs: {
|
|
1448
1456
|
copyExistingProfile: (profileName) => `Found an existing profile. We can copy the variables from ${chalk.bold(profileName)} into your new profile.`,
|
|
1449
1457
|
copyExistingProfiles: 'We can copy the variables from one of your existing profiles into your new profile.',
|
|
@@ -1467,6 +1475,7 @@ export const commands = {
|
|
|
1467
1475
|
invalidTargetAccount: 'Target account is not configured in the CLI',
|
|
1468
1476
|
noAccountsConfigured: 'No accounts configured in the CLI',
|
|
1469
1477
|
failedToLoadProfile: (profileName) => `Unable to copy variables. Failed to load profile ${chalk.bold(profileName)}`,
|
|
1478
|
+
copyFromProfileNotFound: (profileName) => `Profile ${chalk.bold(profileName)} does not exist. Available profiles can be found in your project source directory.`,
|
|
1470
1479
|
failedToCreateProfile: 'Failed to create profile',
|
|
1471
1480
|
},
|
|
1472
1481
|
positionals: {
|
|
@@ -1474,6 +1483,7 @@ export const commands = {
|
|
|
1474
1483
|
},
|
|
1475
1484
|
options: {
|
|
1476
1485
|
targetAccount: 'The target account ID for this profile',
|
|
1486
|
+
copyFrom: 'Copy variables from an existing profile',
|
|
1477
1487
|
},
|
|
1478
1488
|
},
|
|
1479
1489
|
delete: {
|
|
@@ -1895,6 +1905,7 @@ export const commands = {
|
|
|
1895
1905
|
readyToGoLive: '🚀 Ready to take your project live?',
|
|
1896
1906
|
runCommand: (command) => `Run \`${uiCommandReference(command)}\``,
|
|
1897
1907
|
autoDeployDisabled: (deployCommand) => `Automatic deploys are disabled for this project. Run ${uiCommandReference(deployCommand)} to deploy this build.`,
|
|
1908
|
+
autoDeploySkipped: (deployCommand) => `Auto-deploy was skipped for this build. Run ${uiCommandReference(deployCommand)} to deploy this build.`,
|
|
1898
1909
|
},
|
|
1899
1910
|
errors: {
|
|
1900
1911
|
noProjectConfig: 'No project detected. Run this command from a project directory.',
|
package/lib/mcp/setup.d.ts
CHANGED
|
@@ -8,7 +8,12 @@ interface McpCommand {
|
|
|
8
8
|
args: string[];
|
|
9
9
|
env?: Record<string, string>;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
interface ConfigureMcpServerOptions {
|
|
12
|
+
targets?: string[];
|
|
13
|
+
standalone?: boolean;
|
|
14
|
+
cliVersion?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function configureMcpServer(options: ConfigureMcpServerOptions): Promise<string[]>;
|
|
12
17
|
export declare function setupVsCode(mcpCommand?: McpCommand): Promise<boolean>;
|
|
13
18
|
export declare function setupClaudeCode(mcpCommand?: McpCommand): Promise<boolean>;
|
|
14
19
|
export declare function setupCursor(mcpCommand?: McpCommand): boolean;
|
package/lib/mcp/setup.js
CHANGED
|
@@ -32,8 +32,9 @@ const defaultMcpCommand = {
|
|
|
32
32
|
command: 'hs',
|
|
33
33
|
args: ['mcp', 'start'],
|
|
34
34
|
};
|
|
35
|
-
export async function configureMcpServer(
|
|
35
|
+
export async function configureMcpServer(options) {
|
|
36
36
|
try {
|
|
37
|
+
const { targets, standalone, cliVersion: cliVersionFlag } = options;
|
|
37
38
|
let derivedTargets = [];
|
|
38
39
|
if (!targets || targets.length === 0) {
|
|
39
40
|
const { selectedTargets } = await promptUser({
|
|
@@ -52,23 +53,33 @@ export async function configureMcpServer(targets) {
|
|
|
52
53
|
else {
|
|
53
54
|
derivedTargets = targets;
|
|
54
55
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
56
|
+
let useStandaloneMode = standalone;
|
|
57
|
+
if (useStandaloneMode === undefined) {
|
|
58
|
+
const response = await promptUser({
|
|
59
|
+
name: 'useStandaloneMode',
|
|
60
|
+
type: 'confirm',
|
|
61
|
+
message: commands.mcp.setup.prompts.standaloneMode,
|
|
62
|
+
default: false,
|
|
63
|
+
});
|
|
64
|
+
useStandaloneMode = response.useStandaloneMode;
|
|
65
|
+
}
|
|
66
|
+
let cliVersion = '';
|
|
67
|
+
if (useStandaloneMode) {
|
|
68
|
+
if (cliVersionFlag !== undefined) {
|
|
69
|
+
cliVersion = cliVersionFlag;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const response = await promptUser({
|
|
73
|
+
name: 'cliVersion',
|
|
74
|
+
type: 'input',
|
|
75
|
+
message: commands.mcp.setup.prompts.cliVersion,
|
|
76
|
+
validate: (v) => !v || /^[\d]+\.[\d]+\.[\d]+([-+][\w.]+)?$/.test(v.trim())
|
|
77
|
+
? true
|
|
78
|
+
: 'Please enter a valid semver version (e.g. 8.0.1) or leave blank for latest.',
|
|
79
|
+
});
|
|
80
|
+
cliVersion = response.cliVersion;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
72
83
|
const cliPackage = cliVersion
|
|
73
84
|
? `@hubspot/cli@${cliVersion}`
|
|
74
85
|
: '@hubspot/cli';
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ type HandleProjectUploadArg<T> = {
|
|
|
24
24
|
profile?: string;
|
|
25
25
|
force?: boolean;
|
|
26
26
|
};
|
|
27
|
-
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, skipNpmAudit, skipAutoDeploy
|
|
27
|
+
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, skipNpmAudit, skipAutoDeploy, force, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
|
|
28
28
|
export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig, projectDir: string): Promise<void>;
|
|
29
29
|
export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
30
30
|
type HandleTranslateArg = {
|
package/lib/projects/upload.js
CHANGED
|
@@ -21,7 +21,7 @@ import { archiveWorkspacesAndDependencies, getPackageJsonPathsToUpdate, getLockf
|
|
|
21
21
|
import { isLegacyProject } from '@hubspot/project-parsing-lib/projects';
|
|
22
22
|
import { validateLintConfigOnUpload } from './validateLintConfigOnUpload.js';
|
|
23
23
|
import { runNpmAuditsBeforeProjectUpload } from './npmAuditOnUpload.js';
|
|
24
|
-
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation) {
|
|
24
|
+
async function uploadProjectFiles(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation, skipAutoDeploy) {
|
|
25
25
|
const accountIdentifier = uiAccountDescription(accountId) || `${accountId}`;
|
|
26
26
|
SpinniesManager.add('upload', {
|
|
27
27
|
text: lib.projectUpload.uploadProjectFiles.add(projectName, accountIdentifier),
|
|
@@ -30,8 +30,7 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
|
|
|
30
30
|
let buildId;
|
|
31
31
|
let error;
|
|
32
32
|
try {
|
|
33
|
-
|
|
34
|
-
const { data: upload } = await uploadProject(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation);
|
|
33
|
+
const { data: upload } = await uploadProject(accountId, projectName, filePath, uploadMessage, platformVersion, intermediateRepresentation, skipAutoDeploy);
|
|
35
34
|
buildId = upload.buildId;
|
|
36
35
|
SpinniesManager.succeed('upload', {
|
|
37
36
|
text: lib.projectUpload.uploadProjectFiles.succeed(projectName, accountIdentifier),
|
|
@@ -48,10 +47,7 @@ async function uploadProjectFiles(accountId, projectName, filePath, uploadMessag
|
|
|
48
47
|
}
|
|
49
48
|
return { buildId, error };
|
|
50
49
|
}
|
|
51
|
-
|
|
52
|
-
export async function handleProjectUpload({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage = '', forceCreate = false, isUploadCommand = false, sendIR = false, skipValidation = false, skipNpmAudit = false,
|
|
53
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
54
|
-
skipAutoDeploy: _skipAutoDeploy = false, force = false, }) {
|
|
50
|
+
export async function handleProjectUpload({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage = '', forceCreate = false, isUploadCommand = false, sendIR = false, skipValidation = false, skipNpmAudit = false, skipAutoDeploy = false, force = false, }) {
|
|
55
51
|
const srcDir = path.resolve(projectDir, projectConfig.srcDir);
|
|
56
52
|
await validateSourceDirectory(srcDir, projectConfig, projectDir);
|
|
57
53
|
await validateNoHSMetaMismatch(srcDir, projectConfig);
|
|
@@ -119,7 +115,7 @@ skipAutoDeploy: _skipAutoDeploy = false, force = false, }) {
|
|
|
119
115
|
return resolve({ projectNotFound: true });
|
|
120
116
|
}
|
|
121
117
|
const projectId = project?.id;
|
|
122
|
-
const { buildId, error } = await uploadProjectFiles(accountId, projectConfig.name, tempFile.name, uploadMessage, projectConfig.platformVersion, intermediateRepresentation);
|
|
118
|
+
const { buildId, error } = await uploadProjectFiles(accountId, projectConfig.name, tempFile.name, uploadMessage, projectConfig.platformVersion, intermediateRepresentation, skipAutoDeploy);
|
|
123
119
|
if (error) {
|
|
124
120
|
resolve({ uploadError: error, projectId });
|
|
125
121
|
}
|
package/mcp-server/Tool.d.ts
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import { RequestHandlerExtra } from '@modelcontextprotocol/sdk/shared/protocol.js';
|
|
3
|
+
import { ServerNotification, ServerRequest } from '@modelcontextprotocol/sdk/types.js';
|
|
2
4
|
import { McpLogger } from './utils/logger.js';
|
|
3
5
|
import { TextContentResponse } from './types.js';
|
|
6
|
+
import { CommandResults, Command } from './utils/command.js';
|
|
7
|
+
export type ToolExtra = RequestHandlerExtra<ServerRequest, ServerNotification>;
|
|
4
8
|
export declare class Tool<InputSchema> {
|
|
5
9
|
protected mcpServer: McpServer;
|
|
6
10
|
protected logger: McpLogger;
|
|
7
11
|
protected toolName: string;
|
|
8
12
|
constructor(mcpServer: McpServer, logger: McpLogger, toolName: string);
|
|
9
13
|
register(): RegisteredTool;
|
|
10
|
-
handler(
|
|
11
|
-
protected
|
|
14
|
+
handler(_input: InputSchema): TextContentResponse | Promise<TextContentResponse>;
|
|
15
|
+
protected runCommand(directory: string, command: Command, extra?: ToolExtra): Promise<CommandResults>;
|
|
16
|
+
protected getTrackingMeta(_input: InputSchema): {
|
|
12
17
|
[key: string]: string;
|
|
13
18
|
} | undefined;
|
|
14
|
-
protected wrappedHandler(input: InputSchema): Promise<TextContentResponse>;
|
|
19
|
+
protected wrappedHandler(input: InputSchema, extra?: ToolExtra): Promise<TextContentResponse>;
|
|
15
20
|
}
|
package/mcp-server/Tool.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { formatTextContents } from './utils/content.js';
|
|
2
2
|
import { getErrorMessage } from '../lib/errorHandlers/index.js';
|
|
3
3
|
import { trackToolUsage } from './utils/toolUsageTracking.js';
|
|
4
|
+
import { runCommandInDir } from './utils/command.js';
|
|
4
5
|
export class Tool {
|
|
5
6
|
mcpServer;
|
|
6
7
|
logger;
|
|
@@ -13,17 +14,36 @@ export class Tool {
|
|
|
13
14
|
register() {
|
|
14
15
|
throw new Error('Must implement register');
|
|
15
16
|
}
|
|
16
|
-
handler(
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
18
|
-
input) {
|
|
17
|
+
handler(_input) {
|
|
19
18
|
throw new Error('Must implement handler');
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
runCommand(directory, command, extra) {
|
|
21
|
+
let progressCount = 0;
|
|
22
|
+
return runCommandInDir(directory, command, async (chunk) => {
|
|
23
|
+
try {
|
|
24
|
+
const message = `${chunk.trimEnd()}`;
|
|
25
|
+
const token = extra?._meta?.progressToken;
|
|
26
|
+
if (token !== undefined && extra?.sendNotification) {
|
|
27
|
+
progressCount++;
|
|
28
|
+
await extra.sendNotification({
|
|
29
|
+
method: 'notifications/progress',
|
|
30
|
+
params: {
|
|
31
|
+
progressToken: token,
|
|
32
|
+
progress: progressCount,
|
|
33
|
+
message,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Swallow notification errors so a failed notification never crashes the tool
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
getTrackingMeta(_input) {
|
|
24
44
|
return undefined;
|
|
25
45
|
}
|
|
26
|
-
async wrappedHandler(input) {
|
|
46
|
+
async wrappedHandler(input, extra) {
|
|
27
47
|
const startTime = Date.now();
|
|
28
48
|
try {
|
|
29
49
|
// `input` is logged unredacted. Tool input schemas MUST NOT include
|
|
@@ -34,7 +54,7 @@ export class Tool {
|
|
|
34
54
|
args: input,
|
|
35
55
|
});
|
|
36
56
|
await trackToolUsage(this.toolName, this.getTrackingMeta(input));
|
|
37
|
-
const result = await this.handler(input);
|
|
57
|
+
const result = await this.handler(input, extra);
|
|
38
58
|
this.logger.debug(this.toolName, {
|
|
39
59
|
message: 'Tool completed',
|
|
40
60
|
durationMs: Date.now() - startTime,
|
package/mcp-server/server.js
CHANGED
|
@@ -17,22 +17,26 @@ WHEN TO USE THIS SERVER
|
|
|
17
17
|
via \`search-docs\` + \`fetch-doc\` rather than from prior knowledge.
|
|
18
18
|
|
|
19
19
|
REQUIRED WORKFLOWS
|
|
20
|
-
1.
|
|
20
|
+
1. Authentication: call \`auth-account\` when the user wants to connect a
|
|
21
|
+
HubSpot account, when any tool reports "No account ID found", or when
|
|
22
|
+
there are no authenticated accounts. The tool opens a browser tab for
|
|
23
|
+
the user to authorize — no Personal Access Key is required up front.
|
|
24
|
+
2. Documentation lookup: always call \`search-docs\` first, then
|
|
21
25
|
\`fetch-doc\` on the most relevant result(s) before planning, writing
|
|
22
26
|
code, or answering platform/API questions. Do not answer from memory.
|
|
23
|
-
|
|
27
|
+
3. Locating a HubSpot project: when the current working directory is not
|
|
24
28
|
a HubSpot project (no \`hsproject.json\`) or you need to determine
|
|
25
29
|
whether a directory contains one, call \`find-projects\` before
|
|
26
30
|
running any tool that requires a project path.
|
|
27
|
-
|
|
31
|
+
4. Editing \`*-hsmeta.json\`: call \`get-feature-config-schema\` for that
|
|
28
32
|
feature type first to learn the allowed fields and values.
|
|
29
|
-
|
|
33
|
+
5. Debugging a failed build: start with \`get-build-status\` to surface
|
|
30
34
|
error messages, and only reach for \`get-build-logs\` for deeper
|
|
31
35
|
troubleshooting or warnings.
|
|
32
|
-
|
|
36
|
+
6. Reading serverless function logs: call \`list-cms-serverless-functions\`
|
|
33
37
|
first to discover the endpoint path, then
|
|
34
38
|
\`get-cms-serverless-function-logs\`.
|
|
35
|
-
|
|
39
|
+
7. App analytics: call \`get-apps-info\` to discover \`appId\` values
|
|
36
40
|
before \`get-api-usage-patterns-by-app-id\`.
|
|
37
41
|
|
|
38
42
|
OUTPUT
|
|
@@ -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';
|
|
@@ -20,7 +20,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
20
20
|
export type HsCreateFunctionInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
21
21
|
export declare class HsCreateFunctionTool extends Tool<HsCreateFunctionInputSchema> {
|
|
22
22
|
constructor(mcpServer: McpServer, logger: McpLogger);
|
|
23
|
-
handler({ dest, functionsFolder, filename, endpointMethod, endpointPath, absoluteCurrentWorkingDirectory, }: HsCreateFunctionInputSchema): Promise<TextContentResponse>;
|
|
23
|
+
handler({ dest, functionsFolder, filename, endpointMethod, endpointPath, absoluteCurrentWorkingDirectory, }: HsCreateFunctionInputSchema, extra?: ToolExtra): Promise<TextContentResponse>;
|
|
24
24
|
register(): RegisteredTool;
|
|
25
25
|
}
|
|
26
26
|
export {};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Tool } from '../../Tool.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
4
|
-
import { runCommandInDir } from '../../utils/command.js';
|
|
5
4
|
import { formatTextContents, formatTextContent } from '../../utils/content.js';
|
|
6
|
-
import { addFlag } from '../../utils/command.js';
|
|
7
5
|
import { HTTP_METHODS } from '../../../types/Cms.js';
|
|
6
|
+
import { HubSpotCommand } from '../../utils/command.js';
|
|
8
7
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
9
8
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
10
9
|
const inputSchema = {
|
|
@@ -37,7 +36,7 @@ export class HsCreateFunctionTool extends Tool {
|
|
|
37
36
|
constructor(mcpServer, logger) {
|
|
38
37
|
super(mcpServer, logger, toolName);
|
|
39
38
|
}
|
|
40
|
-
async handler({ dest, functionsFolder, filename, endpointMethod, endpointPath, absoluteCurrentWorkingDirectory, }) {
|
|
39
|
+
async handler({ dest, functionsFolder, filename, endpointMethod, endpointPath, absoluteCurrentWorkingDirectory, }, extra) {
|
|
41
40
|
setupHubSpotConfig(absoluteCurrentWorkingDirectory);
|
|
42
41
|
const content = [];
|
|
43
42
|
// Require functions folder
|
|
@@ -59,28 +58,22 @@ export class HsCreateFunctionTool extends Tool {
|
|
|
59
58
|
};
|
|
60
59
|
}
|
|
61
60
|
// Build the command
|
|
62
|
-
|
|
61
|
+
const command = new HubSpotCommand('cms function create');
|
|
63
62
|
if (dest) {
|
|
64
|
-
command
|
|
63
|
+
command.addArg(dest);
|
|
65
64
|
}
|
|
66
|
-
// Add function-specific flags
|
|
67
65
|
if (functionsFolder) {
|
|
68
|
-
command
|
|
66
|
+
command.addFlag('functions-folder', functionsFolder);
|
|
69
67
|
}
|
|
70
68
|
if (filename) {
|
|
71
|
-
command
|
|
72
|
-
}
|
|
73
|
-
if (endpointMethod) {
|
|
74
|
-
command = addFlag(command, 'endpoint-method', endpointMethod);
|
|
75
|
-
}
|
|
76
|
-
else {
|
|
77
|
-
command = addFlag(command, 'endpoint-method', 'GET');
|
|
69
|
+
command.addFlag('filename', filename);
|
|
78
70
|
}
|
|
71
|
+
command.addFlag('endpoint-method', endpointMethod ?? 'GET');
|
|
79
72
|
if (endpointPath) {
|
|
80
|
-
command
|
|
73
|
+
command.addFlag('endpoint-path', endpointPath);
|
|
81
74
|
}
|
|
82
75
|
try {
|
|
83
|
-
const { stdout, stderr } = await
|
|
76
|
+
const { stdout, stderr } = await this.runCommand(absoluteCurrentWorkingDirectory, command, extra);
|
|
84
77
|
return formatTextContents(stdout, stderr);
|
|
85
78
|
}
|
|
86
79
|
catch (error) {
|
|
@@ -102,6 +95,6 @@ export class HsCreateFunctionTool extends Tool {
|
|
|
102
95
|
idempotentHint: false,
|
|
103
96
|
openWorldHint: false,
|
|
104
97
|
},
|
|
105
|
-
}, input => this.wrappedHandler(input));
|
|
98
|
+
}, (input, extra) => this.wrappedHandler(input, extra));
|
|
106
99
|
}
|
|
107
100
|
}
|
|
@@ -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';
|
|
@@ -16,7 +16,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
16
16
|
export type HsCreateModuleInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
17
17
|
export declare class HsCreateModuleTool extends Tool<HsCreateModuleInputSchema> {
|
|
18
18
|
constructor(mcpServer: McpServer, logger: McpLogger);
|
|
19
|
-
handler({ userSuppliedName, dest, moduleLabel, reactType, contentTypes, global, availableForNewContent, absoluteCurrentWorkingDirectory, }: HsCreateModuleInputSchema): Promise<TextContentResponse>;
|
|
19
|
+
handler({ userSuppliedName, dest, moduleLabel, reactType, contentTypes, global, availableForNewContent, absoluteCurrentWorkingDirectory, }: HsCreateModuleInputSchema, extra?: ToolExtra): Promise<TextContentResponse>;
|
|
20
20
|
register(): RegisteredTool;
|
|
21
21
|
}
|
|
22
22
|
export {};
|