@hubspot/cli 7.7.31-experimental.0 → 7.7.32-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.
- package/commands/app.js +1 -6
- package/commands/project/upload.d.ts +2 -2
- package/commands/project/upload.js +1 -1
- package/commands/testAccount/create.js +0 -3
- package/lang/en.d.ts +1 -23
- package/lang/en.js +1 -23
- package/lib/mcp/setup.js +1 -1
- package/lib/projectProfiles.d.ts +1 -1
- package/lib/projectProfiles.js +2 -10
- package/lib/projects/structure.d.ts +2 -2
- package/lib/projects/upload.d.ts +1 -2
- package/lib/projects/upload.js +0 -1
- package/mcp-server/tools/cms/HsCreateFunctionTool.d.ts +32 -0
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +96 -0
- package/mcp-server/tools/cms/HsCreateTemplateTool.d.ts +26 -0
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +75 -0
- package/mcp-server/tools/cms/HsListFunctionsTool.d.ts +23 -0
- package/mcp-server/tools/cms/HsListFunctionsTool.js +58 -0
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +251 -0
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +206 -0
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.d.ts +1 -0
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +120 -0
- package/mcp-server/tools/index.js +6 -0
- package/package.json +2 -1
- package/types/Yargs.d.ts +1 -1
- package/ui/components/BoxWithTitle.d.ts +8 -0
- package/ui/components/BoxWithTitle.js +9 -0
- package/ui/components/HorizontalSelectPrompt.d.ts +8 -0
- package/ui/components/HorizontalSelectPrompt.js +30 -0
- package/ui/components/StatusMessageBoxes.d.ts +12 -0
- package/ui/components/StatusMessageBoxes.js +31 -0
- package/ui/lib/ui-testing-utils.d.ts +9 -0
- package/ui/lib/ui-testing-utils.js +47 -0
- package/ui/lib/useTerminalSize.d.ts +13 -0
- package/ui/lib/useTerminalSize.js +31 -0
- package/ui/styles.d.ts +18 -0
- package/ui/styles.js +18 -0
- package/ui/views/UiSandbox.d.ts +5 -0
- package/ui/views/UiSandbox.js +25 -0
- package/commands/app/__tests__/install.test.js +0 -47
- package/commands/app/install.d.ts +0 -8
- package/commands/app/install.js +0 -122
- /package/{commands/app/__tests__/install.test.d.ts → mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.d.ts} +0 -0
package/commands/app.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import migrateCommand from './app/migrate.js';
|
|
2
2
|
import appSecretCommand from './app/secret.js';
|
|
3
|
-
import installAppCommand from './app/install.js';
|
|
4
3
|
import { makeYargsBuilder } from '../lib/yargsUtils.js';
|
|
5
4
|
const command = ['app', 'apps'];
|
|
6
5
|
// Keep the command hidden for now
|
|
7
6
|
const describe = undefined;
|
|
8
7
|
function appBuilder(yargs) {
|
|
9
|
-
yargs
|
|
10
|
-
.command(migrateCommand)
|
|
11
|
-
.command(appSecretCommand)
|
|
12
|
-
.command(installAppCommand)
|
|
13
|
-
.demandCommand(1, '');
|
|
8
|
+
yargs.command(migrateCommand).command(appSecretCommand).demandCommand(1, '');
|
|
14
9
|
return yargs;
|
|
15
10
|
}
|
|
16
11
|
const builder = makeYargsBuilder(appBuilder, command, describe);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CommonArgs,
|
|
2
|
-
type ProjectUploadArgs = CommonArgs & JSONOutputArgs &
|
|
1
|
+
import { CommonArgs, JSONOutputArgs, YargsCommandModule } from '../../types/Yargs.js';
|
|
2
|
+
type ProjectUploadArgs = CommonArgs & JSONOutputArgs & {
|
|
3
3
|
forceCreate: boolean;
|
|
4
4
|
message: string;
|
|
5
5
|
m: string;
|
|
@@ -25,7 +25,7 @@ async function handler(args) {
|
|
|
25
25
|
validateProjectConfig(projectConfig, projectDir);
|
|
26
26
|
let targetAccountId;
|
|
27
27
|
if (useV3Api(projectConfig.platformVersion)) {
|
|
28
|
-
targetAccountId = await loadAndValidateProfile(projectConfig, projectDir, profile
|
|
28
|
+
targetAccountId = await loadAndValidateProfile(projectConfig, projectDir, profile);
|
|
29
29
|
}
|
|
30
30
|
targetAccountId = targetAccountId || derivedAccountId;
|
|
31
31
|
const accountConfig = getAccountConfig(targetAccountId);
|
|
@@ -75,9 +75,6 @@ async function handler(args) {
|
|
|
75
75
|
resultJson.personalAccessKey = createResult.personalAccessKey;
|
|
76
76
|
}
|
|
77
77
|
catch (err) {
|
|
78
|
-
SpinniesManager.fail('createTestAccount', {
|
|
79
|
-
text: commands.testAccount.create.polling.createFailure,
|
|
80
|
-
});
|
|
81
78
|
logError(err);
|
|
82
79
|
SpinniesManager.fail('createTestAccount', {
|
|
83
80
|
text: commands.testAccount.create.polling.createFailure,
|
package/lang/en.d.ts
CHANGED
|
@@ -1550,28 +1550,6 @@ ${string}`;
|
|
|
1550
1550
|
readonly app: {
|
|
1551
1551
|
readonly describe: "Commands for managing apps.";
|
|
1552
1552
|
readonly subcommands: {
|
|
1553
|
-
readonly install: {
|
|
1554
|
-
readonly describe: "Install an OAuth app into a test account.";
|
|
1555
|
-
readonly options: {
|
|
1556
|
-
readonly appUid: "The uid of the app to install";
|
|
1557
|
-
readonly projectName: "The name of the project that contains the app";
|
|
1558
|
-
};
|
|
1559
|
-
readonly positionals: {
|
|
1560
|
-
readonly testAccountId: "The id of the test account to install the app into";
|
|
1561
|
-
};
|
|
1562
|
-
readonly errors: {
|
|
1563
|
-
readonly mustSpecifyProjectName: `You must specify a project name. Use the ${string} flag to specify the project name or run this command from within a project directory.`;
|
|
1564
|
-
readonly noAppUidFound: `No app uid found. Please specify the app uid with the ${string} flag or run this command from within a project that contains an app.`;
|
|
1565
|
-
readonly appMustBeOauth: "This command only supports installing oauth apps. Please specify an app with oauth auth type.";
|
|
1566
|
-
};
|
|
1567
|
-
readonly polling: {
|
|
1568
|
-
readonly start: "Installing app...";
|
|
1569
|
-
readonly success: "App installed successfully";
|
|
1570
|
-
readonly failure: "App installation failed";
|
|
1571
|
-
readonly error: "Error installing app";
|
|
1572
|
-
};
|
|
1573
|
-
readonly example: "Install the app with uid my-app-uid from the project named \"my-project\" into the target account with id 1234567890";
|
|
1574
|
-
};
|
|
1575
1553
|
readonly secret: {
|
|
1576
1554
|
readonly describe: "Commands for managing secrets.";
|
|
1577
1555
|
readonly subcommands: {
|
|
@@ -3404,7 +3382,7 @@ Run ${string} to upgrade to version ${string}`;
|
|
|
3404
3382
|
readonly componentsToBeMigrated: (components: string) => string;
|
|
3405
3383
|
readonly componentsThatWillNotBeMigrated: (components: string) => string;
|
|
3406
3384
|
readonly sourceContentsMoved: (newLocation: string) => string;
|
|
3407
|
-
readonly projectMigrationWarningTitle: "
|
|
3385
|
+
readonly projectMigrationWarningTitle: "Important: Migrating to platformVersion 2025.2 is irreversible";
|
|
3408
3386
|
readonly projectMigrationWarning: string;
|
|
3409
3387
|
readonly success: {
|
|
3410
3388
|
readonly downloadedProject: (projectName: string, projectDest: string) => string;
|
package/lang/en.js
CHANGED
|
@@ -1547,28 +1547,6 @@ export const commands = {
|
|
|
1547
1547
|
app: {
|
|
1548
1548
|
describe: 'Commands for managing apps.',
|
|
1549
1549
|
subcommands: {
|
|
1550
|
-
install: {
|
|
1551
|
-
describe: 'Install an OAuth app into a test account.',
|
|
1552
|
-
options: {
|
|
1553
|
-
appUid: 'The uid of the app to install',
|
|
1554
|
-
projectName: 'The name of the project that contains the app',
|
|
1555
|
-
},
|
|
1556
|
-
positionals: {
|
|
1557
|
-
testAccountId: 'The id of the test account to install the app into',
|
|
1558
|
-
},
|
|
1559
|
-
errors: {
|
|
1560
|
-
mustSpecifyProjectName: `You must specify a project name. Use the ${uiCommandReference('--project-name')} flag to specify the project name or run this command from within a project directory.`,
|
|
1561
|
-
noAppUidFound: `No app uid found. Please specify the app uid with the ${uiCommandReference('--app-uid')} flag or run this command from within a project that contains an app.`,
|
|
1562
|
-
appMustBeOauth: 'This command only supports installing oauth apps. Please specify an app with oauth auth type.',
|
|
1563
|
-
},
|
|
1564
|
-
polling: {
|
|
1565
|
-
start: 'Installing app...',
|
|
1566
|
-
success: 'App installed successfully',
|
|
1567
|
-
failure: 'App installation failed',
|
|
1568
|
-
error: 'Error installing app',
|
|
1569
|
-
},
|
|
1570
|
-
example: 'Install the app with uid my-app-uid from the project named "my-project" into the target account with id 1234567890',
|
|
1571
|
-
},
|
|
1572
1550
|
secret: {
|
|
1573
1551
|
describe: 'Commands for managing secrets.',
|
|
1574
1552
|
subcommands: {
|
|
@@ -3398,7 +3376,7 @@ export const lib = {
|
|
|
3398
3376
|
componentsToBeMigrated: (components) => `The following features will be migrated: ${components}`,
|
|
3399
3377
|
componentsThatWillNotBeMigrated: (components) => `[NOTE] These features are not yet supported for migration but will be available later: ${components}`,
|
|
3400
3378
|
sourceContentsMoved: (newLocation) => `The contents of your old source directory have been moved to ${newLocation}, move any required files to the new source directory.`,
|
|
3401
|
-
projectMigrationWarningTitle: '
|
|
3379
|
+
projectMigrationWarningTitle: 'Important: Migrating to platformVersion 2025.2 is irreversible',
|
|
3402
3380
|
projectMigrationWarning: uiBetaTag(`Running the ${uiCommandReference('hs project migrate')} command will permanently upgrade your project to platformVersion 2025.2. This action cannot be undone. To ensure you have access to your original files, they will be copied to a new directory (archive) for safekeeping.\n\nThis command will guide you through the process, prompting you to enter the required fields and will download the new project source code into your project source directory.`, false),
|
|
3403
3381
|
success: {
|
|
3404
3382
|
downloadedProject: (projectName, projectDest) => `Saved ${projectName} to ${projectDest}`,
|
package/lib/mcp/setup.js
CHANGED
|
@@ -182,7 +182,7 @@ export async function setupClaudeCode(mcpCommand = defaultMcpCommand) {
|
|
|
182
182
|
});
|
|
183
183
|
await execAsync(`claude mcp remove "${mcpServerName}" --scope user`);
|
|
184
184
|
}
|
|
185
|
-
await execAsync(`claude mcp add-json "${mcpServerName}"
|
|
185
|
+
await execAsync(`claude mcp add-json "${mcpServerName}" ${JSON.stringify(mcpConfig)} --scope user`);
|
|
186
186
|
SpinniesManager.succeed('claudeCode', {
|
|
187
187
|
text: commands.mcp.setup.spinners.configuredClaudeCode,
|
|
188
188
|
});
|
package/lib/projectProfiles.d.ts
CHANGED
|
@@ -4,4 +4,4 @@ export declare function logProfileHeader(profileName: string): void;
|
|
|
4
4
|
export declare function logProfileFooter(profile: HsProfileFile, includeVariables?: boolean): void;
|
|
5
5
|
export declare function loadProfile(projectConfig: ProjectConfig | null, projectDir: string | null, profileName: string): HsProfileFile | undefined;
|
|
6
6
|
export declare function exitIfUsingProfiles(projectConfig: ProjectConfig | null, projectDir: string | null): Promise<void>;
|
|
7
|
-
export declare function loadAndValidateProfile(projectConfig: ProjectConfig | null, projectDir: string | null, argsProfile: string | undefined
|
|
7
|
+
export declare function loadAndValidateProfile(projectConfig: ProjectConfig | null, projectDir: string | null, argsProfile: string | undefined): Promise<number | undefined>;
|
package/lib/projectProfiles.js
CHANGED
|
@@ -38,12 +38,7 @@ export function loadProfile(projectConfig, projectDir, profileName) {
|
|
|
38
38
|
uiLogger.error(lib.projectProfiles.loadProfile.errors.missingAccountId(profileFilename));
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
return
|
|
42
|
-
...profile,
|
|
43
|
-
accountId: process.env.HUBSPOT_ACCOUNT_ID
|
|
44
|
-
? Number(process.env.HUBSPOT_ACCOUNT_ID)
|
|
45
|
-
: profile.accountId,
|
|
46
|
-
};
|
|
41
|
+
return profile;
|
|
47
42
|
}
|
|
48
43
|
catch (e) {
|
|
49
44
|
uiLogger.error(lib.projectProfiles.loadProfile.errors.failedToLoadProfile(profileFilename));
|
|
@@ -59,7 +54,7 @@ export async function exitIfUsingProfiles(projectConfig, projectDir) {
|
|
|
59
54
|
}
|
|
60
55
|
}
|
|
61
56
|
}
|
|
62
|
-
export async function loadAndValidateProfile(projectConfig, projectDir, argsProfile
|
|
57
|
+
export async function loadAndValidateProfile(projectConfig, projectDir, argsProfile) {
|
|
63
58
|
if (argsProfile) {
|
|
64
59
|
logProfileHeader(argsProfile);
|
|
65
60
|
const profile = loadProfile(projectConfig, projectDir, argsProfile);
|
|
@@ -68,9 +63,6 @@ export async function loadAndValidateProfile(projectConfig, projectDir, argsProf
|
|
|
68
63
|
process.exit(EXIT_CODES.ERROR);
|
|
69
64
|
}
|
|
70
65
|
logProfileFooter(profile, true);
|
|
71
|
-
if (useEnv) {
|
|
72
|
-
return Number(process.env.HUBSPOT_ACCOUNT_ID);
|
|
73
|
-
}
|
|
74
66
|
return profile.accountId;
|
|
75
67
|
}
|
|
76
68
|
else {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ComponentTypes, Component, GenericComponentConfig, PublicAppComponentConfig, PrivateAppComponentConfig, AppCardComponentConfig } from '../../types/Projects.js';
|
|
2
|
-
import {
|
|
2
|
+
import { IntermediateRepresentationNodeLocalDev } from '@hubspot/project-parsing-lib/src/lib/types.js';
|
|
3
3
|
import { AppIRNode } from '../../types/ProjectComponents.js';
|
|
4
4
|
export declare const CONFIG_FILES: {
|
|
5
5
|
[k in ComponentTypes]: string;
|
|
@@ -15,4 +15,4 @@ export declare function getProjectComponentTypes(components: Array<Component>):
|
|
|
15
15
|
export declare function getComponentUid(component?: Component | null): string | null;
|
|
16
16
|
export declare function componentIsApp(component?: Component | null): component is Component<PublicAppComponentConfig | PrivateAppComponentConfig>;
|
|
17
17
|
export declare function componentIsPublicApp(component?: Component | null): component is Component<PublicAppComponentConfig>;
|
|
18
|
-
export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev
|
|
18
|
+
export declare function isAppIRNode(component: IntermediateRepresentationNodeLocalDev): component is AppIRNode;
|
package/lib/projects/upload.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FileResult } from 'tmp';
|
|
2
|
-
import { IntermediateRepresentation } from '@hubspot/project-parsing-lib';
|
|
3
2
|
import { ProjectConfig } from '../../types/Projects.js';
|
|
4
3
|
type ProjectUploadCallbackFunction<T> = (accountId: number, projectConfig: ProjectConfig, tempFile: FileResult, buildId: number) => Promise<T>;
|
|
5
4
|
type ProjectUploadResult<T> = {
|
|
@@ -21,5 +20,5 @@ type HandleProjectUploadArg<T> = {
|
|
|
21
20
|
export declare function handleProjectUpload<T>({ accountId, projectConfig, projectDir, callbackFunc, profile, uploadMessage, forceCreate, isUploadCommand, sendIR, skipValidation, }: HandleProjectUploadArg<T>): Promise<ProjectUploadResult<T>>;
|
|
22
21
|
export declare function validateSourceDirectory(srcDir: string, projectConfig: ProjectConfig): void;
|
|
23
22
|
export declare function validateNoHSMetaMismatch(srcDir: string, projectConfig: ProjectConfig): Promise<void>;
|
|
24
|
-
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<
|
|
23
|
+
export declare function handleTranslate(projectDir: string, projectConfig: ProjectConfig, accountId: number, skipValidation: boolean, profile: string | undefined): Promise<unknown>;
|
|
25
24
|
export {};
|
package/lib/projects/upload.js
CHANGED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { TextContentResponse, Tool } from '../../types.js';
|
|
2
|
+
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
|
+
dest: z.ZodOptional<z.ZodString>;
|
|
7
|
+
functionsFolder: z.ZodOptional<z.ZodString>;
|
|
8
|
+
filename: z.ZodOptional<z.ZodString>;
|
|
9
|
+
endpointMethod: z.ZodOptional<z.ZodEnum<["DELETE", "GET", "PATCH", "POST", "PUT"]>>;
|
|
10
|
+
endpointPath: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
absoluteCurrentWorkingDirectory: string;
|
|
13
|
+
dest?: string | undefined;
|
|
14
|
+
functionsFolder?: string | undefined;
|
|
15
|
+
filename?: string | undefined;
|
|
16
|
+
endpointMethod?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT" | undefined;
|
|
17
|
+
endpointPath?: string | undefined;
|
|
18
|
+
}, {
|
|
19
|
+
absoluteCurrentWorkingDirectory: string;
|
|
20
|
+
dest?: string | undefined;
|
|
21
|
+
functionsFolder?: string | undefined;
|
|
22
|
+
filename?: string | undefined;
|
|
23
|
+
endpointMethod?: "DELETE" | "GET" | "PATCH" | "POST" | "PUT" | undefined;
|
|
24
|
+
endpointPath?: string | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
export type HsCreateFunctionInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
27
|
+
export declare class HsCreateFunctionTool extends Tool<HsCreateFunctionInputSchema> {
|
|
28
|
+
constructor(mcpServer: McpServer);
|
|
29
|
+
handler({ dest, functionsFolder, filename, endpointMethod, endpointPath, absoluteCurrentWorkingDirectory, }: HsCreateFunctionInputSchema): Promise<TextContentResponse>;
|
|
30
|
+
register(): RegisteredTool;
|
|
31
|
+
}
|
|
32
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Tool } from '../../types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
4
|
+
import { runCommandInDir } from '../../utils/project.js';
|
|
5
|
+
import { formatTextContents, formatTextContent } from '../../utils/content.js';
|
|
6
|
+
import { trackToolUsage } from '../../utils/toolUsageTracking.js';
|
|
7
|
+
import { addFlag } from '../../utils/command.js';
|
|
8
|
+
import { HTTP_METHODS } from '../../../types/Cms.js';
|
|
9
|
+
const inputSchema = {
|
|
10
|
+
absoluteCurrentWorkingDirectory,
|
|
11
|
+
dest: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe('The destination path where the function should be created on the current computer.')
|
|
14
|
+
.optional(),
|
|
15
|
+
functionsFolder: z
|
|
16
|
+
.string()
|
|
17
|
+
.describe('Folder name for function creation. Required for non-interactive function creation. If the user has not specified the folder name, ask them to provide it.')
|
|
18
|
+
.optional(),
|
|
19
|
+
filename: z
|
|
20
|
+
.string()
|
|
21
|
+
.describe('Function filename. Required for non-interactive function creation. If the user has not specified the filename, ask them to provide it.')
|
|
22
|
+
.optional(),
|
|
23
|
+
endpointMethod: z
|
|
24
|
+
.enum(HTTP_METHODS)
|
|
25
|
+
.describe(`HTTP method for the function endpoint. Must be one of: ${HTTP_METHODS.join(', ')}. Defaults to GET.`)
|
|
26
|
+
.optional(),
|
|
27
|
+
endpointPath: z
|
|
28
|
+
.string()
|
|
29
|
+
.describe('API endpoint path for the function. Required for non-interactive function creation. If the user has not specified the endpoint path, ask them to provide it.')
|
|
30
|
+
.optional(),
|
|
31
|
+
};
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
|
+
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
34
|
+
const toolName = 'create-hubspot-cms-function';
|
|
35
|
+
export class HsCreateFunctionTool extends Tool {
|
|
36
|
+
constructor(mcpServer) {
|
|
37
|
+
super(mcpServer);
|
|
38
|
+
}
|
|
39
|
+
async handler({ dest, functionsFolder, filename, endpointMethod, endpointPath, absoluteCurrentWorkingDirectory, }) {
|
|
40
|
+
await trackToolUsage(toolName);
|
|
41
|
+
const content = [];
|
|
42
|
+
// Require functions folder
|
|
43
|
+
if (!functionsFolder) {
|
|
44
|
+
content.push(formatTextContent(`Ask the user to provide the folder name for the function.`));
|
|
45
|
+
}
|
|
46
|
+
// Require filename
|
|
47
|
+
if (!filename) {
|
|
48
|
+
content.push(formatTextContent(`Ask the user to provide the filename for the function.`));
|
|
49
|
+
}
|
|
50
|
+
// Require endpoint path
|
|
51
|
+
if (!endpointPath) {
|
|
52
|
+
content.push(formatTextContent(`Ask the user to provide the API endpoint path for the function.`));
|
|
53
|
+
}
|
|
54
|
+
// If we have missing required information, return the prompts
|
|
55
|
+
if (content.length > 0) {
|
|
56
|
+
return {
|
|
57
|
+
content,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
// Build the command
|
|
61
|
+
let command = 'hs create function';
|
|
62
|
+
if (dest) {
|
|
63
|
+
command += ` "${dest}"`;
|
|
64
|
+
}
|
|
65
|
+
// Add function-specific flags
|
|
66
|
+
if (functionsFolder) {
|
|
67
|
+
command = addFlag(command, 'functions-folder', functionsFolder);
|
|
68
|
+
}
|
|
69
|
+
if (filename) {
|
|
70
|
+
command = addFlag(command, 'filename', filename);
|
|
71
|
+
}
|
|
72
|
+
if (endpointMethod) {
|
|
73
|
+
command = addFlag(command, 'endpoint-method', endpointMethod);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
command = addFlag(command, 'endpoint-method', 'GET');
|
|
77
|
+
}
|
|
78
|
+
if (endpointPath) {
|
|
79
|
+
command = addFlag(command, 'endpoint-path', endpointPath);
|
|
80
|
+
}
|
|
81
|
+
try {
|
|
82
|
+
const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
|
|
83
|
+
return formatTextContents(stdout, stderr);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
return formatTextContents(error instanceof Error ? error.message : `${error}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
register() {
|
|
90
|
+
return this.mcpServer.registerTool(toolName, {
|
|
91
|
+
title: 'Create HubSpot CMS Serverless Function',
|
|
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
|
+
inputSchema,
|
|
94
|
+
}, this.handler);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { TextContentResponse, Tool } from '../../types.js';
|
|
2
|
+
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
|
+
userSuppliedName: z.ZodOptional<z.ZodString>;
|
|
7
|
+
dest: z.ZodOptional<z.ZodString>;
|
|
8
|
+
templateType: z.ZodOptional<z.ZodEnum<["page-template", "email-template", "partial", "global-partial", "blog-listing-template", "blog-post-template", "search-template", "section"]>>;
|
|
9
|
+
}, "strip", z.ZodTypeAny, {
|
|
10
|
+
absoluteCurrentWorkingDirectory: string;
|
|
11
|
+
dest?: string | undefined;
|
|
12
|
+
templateType?: "page-template" | "email-template" | "partial" | "global-partial" | "blog-listing-template" | "blog-post-template" | "search-template" | "section" | undefined;
|
|
13
|
+
userSuppliedName?: string | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
absoluteCurrentWorkingDirectory: string;
|
|
16
|
+
dest?: string | undefined;
|
|
17
|
+
templateType?: "page-template" | "email-template" | "partial" | "global-partial" | "blog-listing-template" | "blog-post-template" | "search-template" | "section" | undefined;
|
|
18
|
+
userSuppliedName?: string | undefined;
|
|
19
|
+
}>;
|
|
20
|
+
export type HsCreateTemplateInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
21
|
+
export declare class HsCreateTemplateTool extends Tool<HsCreateTemplateInputSchema> {
|
|
22
|
+
constructor(mcpServer: McpServer);
|
|
23
|
+
handler({ userSuppliedName, dest, templateType, absoluteCurrentWorkingDirectory, }: HsCreateTemplateInputSchema): Promise<TextContentResponse>;
|
|
24
|
+
register(): RegisteredTool;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Tool } from '../../types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
4
|
+
import { runCommandInDir } from '../../utils/project.js';
|
|
5
|
+
import { formatTextContents, formatTextContent } from '../../utils/content.js';
|
|
6
|
+
import { trackToolUsage } from '../../utils/toolUsageTracking.js';
|
|
7
|
+
import { addFlag } from '../../utils/command.js';
|
|
8
|
+
import { TEMPLATE_TYPES } from '../../../types/Cms.js';
|
|
9
|
+
const inputSchema = {
|
|
10
|
+
absoluteCurrentWorkingDirectory,
|
|
11
|
+
userSuppliedName: z
|
|
12
|
+
.string()
|
|
13
|
+
.describe('REQUIRED - If not specified by the user, DO NOT choose. Ask the user to specify the name of the template they want to create.')
|
|
14
|
+
.optional(),
|
|
15
|
+
dest: z
|
|
16
|
+
.string()
|
|
17
|
+
.describe('The destination path where the template should be created on the current computer.')
|
|
18
|
+
.optional(),
|
|
19
|
+
templateType: z
|
|
20
|
+
.enum(TEMPLATE_TYPES)
|
|
21
|
+
.describe(`Template type for template creation. Must be one of: ${TEMPLATE_TYPES.join(', ')}`)
|
|
22
|
+
.optional(),
|
|
23
|
+
};
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
25
|
+
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
26
|
+
const toolName = 'create-hubspot-cms-template';
|
|
27
|
+
export class HsCreateTemplateTool extends Tool {
|
|
28
|
+
constructor(mcpServer) {
|
|
29
|
+
super(mcpServer);
|
|
30
|
+
}
|
|
31
|
+
async handler({ userSuppliedName, dest, templateType, absoluteCurrentWorkingDirectory, }) {
|
|
32
|
+
await trackToolUsage(toolName);
|
|
33
|
+
const content = [];
|
|
34
|
+
// Always require a name
|
|
35
|
+
if (!userSuppliedName) {
|
|
36
|
+
content.push(formatTextContent(`Ask the user to specify the name of the template they want to create.`));
|
|
37
|
+
}
|
|
38
|
+
// Require template type
|
|
39
|
+
if (!templateType) {
|
|
40
|
+
content.push(formatTextContent(`Ask the user what template type they want to create. Options are: ${TEMPLATE_TYPES.join(', ')}`));
|
|
41
|
+
}
|
|
42
|
+
// If we have missing required information, return the prompts
|
|
43
|
+
if (content.length > 0) {
|
|
44
|
+
return {
|
|
45
|
+
content,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// Build the command
|
|
49
|
+
let command = 'hs create template';
|
|
50
|
+
if (userSuppliedName) {
|
|
51
|
+
command += ` "${userSuppliedName}"`;
|
|
52
|
+
}
|
|
53
|
+
if (dest) {
|
|
54
|
+
command += ` "${dest}"`;
|
|
55
|
+
}
|
|
56
|
+
// Add template type flag
|
|
57
|
+
if (templateType) {
|
|
58
|
+
command = addFlag(command, 'template-type', templateType);
|
|
59
|
+
}
|
|
60
|
+
try {
|
|
61
|
+
const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
|
|
62
|
+
return formatTextContents(stdout, stderr);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return formatTextContents(error instanceof Error ? error.message : `${error}`);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
register() {
|
|
69
|
+
return this.mcpServer.registerTool(toolName, {
|
|
70
|
+
title: 'Create HubSpot CMS Template',
|
|
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
|
+
inputSchema,
|
|
73
|
+
}, this.handler);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { TextContentResponse, Tool } from '../../types.js';
|
|
2
|
+
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
|
+
account: z.ZodOptional<z.ZodString>;
|
|
7
|
+
json: z.ZodOptional<z.ZodBoolean>;
|
|
8
|
+
}, "strip", z.ZodTypeAny, {
|
|
9
|
+
absoluteCurrentWorkingDirectory: string;
|
|
10
|
+
account?: string | undefined;
|
|
11
|
+
json?: boolean | undefined;
|
|
12
|
+
}, {
|
|
13
|
+
absoluteCurrentWorkingDirectory: string;
|
|
14
|
+
account?: string | undefined;
|
|
15
|
+
json?: boolean | undefined;
|
|
16
|
+
}>;
|
|
17
|
+
export type HsListFunctionsInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
18
|
+
export declare class HsListFunctionsTool extends Tool<HsListFunctionsInputSchema> {
|
|
19
|
+
constructor(mcpServer: McpServer);
|
|
20
|
+
handler({ account, json, absoluteCurrentWorkingDirectory, }: HsListFunctionsInputSchema): Promise<TextContentResponse>;
|
|
21
|
+
register(): RegisteredTool;
|
|
22
|
+
}
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Tool } from '../../types.js';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { addFlag } from '../../utils/command.js';
|
|
4
|
+
import { absoluteCurrentWorkingDirectory } from '../project/constants.js';
|
|
5
|
+
import { runCommandInDir } from '../../utils/project.js';
|
|
6
|
+
import { formatTextContents } from '../../utils/content.js';
|
|
7
|
+
import { trackToolUsage } from '../../utils/toolUsageTracking.js';
|
|
8
|
+
const inputSchema = {
|
|
9
|
+
absoluteCurrentWorkingDirectory,
|
|
10
|
+
account: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe('The HubSpot account id or name from the HubSpot config file to use for the operation.')
|
|
13
|
+
.optional(),
|
|
14
|
+
json: z
|
|
15
|
+
.boolean()
|
|
16
|
+
.describe('Return raw JSON output instead of formatted table. Useful for programmatic access.')
|
|
17
|
+
.optional(),
|
|
18
|
+
};
|
|
19
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
|
+
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
21
|
+
const toolName = 'list-hubspot-cms-serverless-functions';
|
|
22
|
+
export class HsListFunctionsTool extends Tool {
|
|
23
|
+
constructor(mcpServer) {
|
|
24
|
+
super(mcpServer);
|
|
25
|
+
}
|
|
26
|
+
async handler({ account, json, absoluteCurrentWorkingDirectory, }) {
|
|
27
|
+
await trackToolUsage(toolName);
|
|
28
|
+
let command = 'hs function list';
|
|
29
|
+
if (json) {
|
|
30
|
+
command += ' --json';
|
|
31
|
+
}
|
|
32
|
+
if (account) {
|
|
33
|
+
command = addFlag(command, 'account', account);
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const { stdout, stderr } = await runCommandInDir(absoluteCurrentWorkingDirectory, command);
|
|
37
|
+
return formatTextContents(stdout, stderr);
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
41
|
+
return {
|
|
42
|
+
content: [
|
|
43
|
+
{
|
|
44
|
+
type: 'text',
|
|
45
|
+
text: `Error executing hs function list command: ${errorMessage}`,
|
|
46
|
+
},
|
|
47
|
+
],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
register() {
|
|
52
|
+
return this.mcpServer.registerTool(toolName, {
|
|
53
|
+
title: 'List HubSpot CMS Serverless Functions',
|
|
54
|
+
description: 'Get a list of all serverless functions deployed in a HubSpot portal/account. Shows function routes, HTTP methods, secrets, and timestamps.',
|
|
55
|
+
inputSchema,
|
|
56
|
+
}, this.handler);
|
|
57
|
+
}
|
|
58
|
+
}
|