@hubspot/cli 7.8.0-experimental.0 → 7.8.2-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/bin/cli.js +0 -2
- package/commands/__tests__/getStarted.test.js +2 -2
- package/commands/__tests__/mcp.test.js +1 -1
- package/commands/__tests__/project.test.js +0 -3
- package/commands/app/__tests__/migrate.test.js +0 -1
- package/commands/app/migrate.js +4 -5
- package/commands/app/secret/add.js +2 -1
- package/commands/app/secret/delete.js +2 -1
- package/commands/app/secret/list.js +2 -1
- package/commands/app/secret/update.js +2 -1
- package/commands/app/secret.js +2 -1
- package/commands/app.js +2 -2
- package/commands/config/set.js +0 -1
- package/commands/feedback.js +1 -1
- package/commands/getStarted.d.ts +1 -3
- package/commands/getStarted.js +66 -18
- package/commands/mcp/__tests__/setup.test.js +2 -2
- package/commands/mcp/setup.js +11 -2
- package/commands/mcp.js +3 -3
- package/commands/project/__tests__/create.test.js +6 -6
- package/commands/project/__tests__/deploy.test.js +0 -3
- package/commands/project/__tests__/devUnifiedFlow.test.js +2 -4
- package/commands/project/__tests__/logs.test.js +0 -3
- package/commands/project/__tests__/migrate.test.js +1 -2
- package/commands/project/__tests__/migrateApp.test.js +1 -2
- package/commands/project/__tests__/profile.test.js +1 -1
- package/commands/project/add.js +1 -5
- package/commands/project/create.js +3 -9
- package/commands/project/deploy.js +2 -2
- package/commands/project/dev/index.js +4 -3
- package/commands/project/dev/unifiedFlow.js +6 -4
- package/commands/project/download.js +1 -2
- package/commands/project/installDeps.js +1 -2
- package/commands/project/listBuilds.js +2 -2
- package/commands/project/logs.js +2 -2
- package/commands/project/migrate.js +28 -10
- package/commands/project/migrateApp.js +1 -2
- package/commands/project/open.js +1 -2
- package/commands/project/profile/add.js +3 -3
- package/commands/project/profile/delete.js +1 -2
- package/commands/project/profile.js +2 -3
- package/commands/project/upload.js +2 -2
- package/commands/project/validate.js +1 -1
- package/commands/project/watch.js +2 -2
- package/commands/project.js +1 -2
- package/commands/sandbox/delete.js +1 -1
- package/commands/testAccount/importData.d.ts +1 -1
- package/commands/testAccount/importData.js +1 -1
- package/commands/testAccount.js +1 -1
- package/lang/en.d.ts +15 -4
- package/lang/en.js +18 -6
- package/lib/__tests__/hasFeature.test.js +145 -7
- package/lib/app/__tests__/migrate.test.js +14 -51
- package/lib/app/migrate.d.ts +2 -8
- package/lib/app/migrate.js +5 -80
- package/lib/constants.d.ts +8 -0
- package/lib/constants.js +8 -0
- package/lib/dependencyManagement.d.ts +0 -5
- package/lib/dependencyManagement.js +0 -9
- package/lib/hasFeature.js +6 -0
- package/lib/links.d.ts +1 -0
- package/lib/links.js +10 -3
- package/lib/mcp/setup.js +1 -1
- package/lib/middleware/fireAlarmMiddleware.js +15 -5
- package/lib/projects/__tests__/LocalDevProcess.test.js +227 -16
- package/lib/projects/__tests__/LocalDevWebsocketServer.test.js +16 -21
- package/lib/projects/__tests__/deploy.test.js +71 -6
- package/lib/projects/__tests__/localDevProjectHelpers.test.js +4 -2
- package/lib/projects/create/__tests__/v3.test.js +79 -4
- package/lib/projects/create/v3.js +11 -8
- package/lib/projects/localDev/AppDevModeInterface.js +5 -5
- package/lib/projects/localDev/LocalDevLogger.d.ts +4 -0
- package/lib/projects/localDev/LocalDevLogger.js +22 -0
- package/lib/projects/localDev/LocalDevProcess.d.ts +7 -5
- package/lib/projects/localDev/LocalDevProcess.js +90 -19
- package/lib/projects/localDev/LocalDevState.d.ts +9 -8
- package/lib/projects/localDev/LocalDevState.js +18 -17
- package/lib/projects/localDev/LocalDevWebsocketServer.d.ts +2 -0
- package/lib/projects/localDev/LocalDevWebsocketServer.js +55 -23
- package/lib/projects/localDev/helpers/project.d.ts +2 -2
- package/lib/projects/localDev/helpers/project.js +10 -7
- package/lib/projects/localDev/localDevWebsocketServerUtils.d.ts +4 -0
- package/lib/projects/localDev/localDevWebsocketServerUtils.js +10 -0
- package/lib/projects/pollProjectBuildAndDeploy.js +4 -4
- package/lib/prompts/projectAddPrompt.js +2 -1
- package/lib/prompts/promptUtils.js +3 -0
- package/lib/prompts/selectProjectTemplatePrompt.js +2 -0
- package/lib/theme/__tests__/migrate.test.d.ts +1 -0
- package/lib/theme/__tests__/migrate.test.js +233 -0
- package/lib/theme/migrate.d.ts +13 -0
- package/lib/theme/migrate.js +90 -0
- package/lib/ui/SpinniesManager.js +105 -8
- package/lib/usageTracking.js +2 -2
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +1 -1
- package/mcp-server/tools/cms/HsCreateModuleTool.js +1 -1
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +1 -1
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +2 -2
- package/mcp-server/tools/cms/HsListFunctionsTool.js +1 -1
- package/mcp-server/tools/cms/HsListTool.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +2 -2
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +1 -1
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +3 -3
- package/mcp-server/tools/project/CreateProjectTool.d.ts +3 -3
- package/mcp-server/tools/project/CreateProjectTool.js +5 -5
- package/mcp-server/tools/project/DeployProjectTool.js +1 -1
- package/mcp-server/tools/project/DocFetchTool.js +2 -2
- package/mcp-server/tools/project/DocsSearchTool.d.ts +4 -1
- package/mcp-server/tools/project/DocsSearchTool.js +7 -7
- package/mcp-server/tools/project/GetConfigValuesTool.d.ts +4 -1
- package/mcp-server/tools/project/GetConfigValuesTool.js +11 -5
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +1 -1
- package/mcp-server/tools/project/UploadProjectTools.js +2 -2
- package/mcp-server/tools/project/ValidateProjectTool.js +1 -1
- package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +2 -2
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +14 -12
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +9 -8
- package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +1 -1
- package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +1 -1
- package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +1 -1
- package/mcp-server/tools/project/constants.d.ts +1 -1
- package/mcp-server/tools/project/constants.js +9 -3
- package/mcp-server/utils/__tests__/cliConfig.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/cliConfig.test.js +110 -0
- package/mcp-server/utils/cliConfig.d.ts +1 -0
- package/mcp-server/utils/cliConfig.js +12 -0
- package/package.json +4 -9
- package/types/LocalDev.d.ts +19 -3
- package/ui/components/HorizontalSelectPrompt.js +1 -1
- package/ui/index.js +1 -1
- package/commands/getStartedV2.d.ts +0 -9
- package/commands/getStartedV2.js +0 -39
- package/ui/components/Ascii.d.ts +0 -10
- package/ui/components/Ascii.js +0 -11
- package/ui/views/GetStarted.d.ts +0 -7
- package/ui/views/GetStarted.js +0 -157
|
@@ -7,8 +7,10 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
|
7
7
|
|
|
8
8
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
9
9
|
**/
|
|
10
|
+
import readline from 'readline';
|
|
10
11
|
import chalk from 'chalk';
|
|
11
|
-
import
|
|
12
|
+
import cliCursor from 'cli-cursor';
|
|
13
|
+
import { breakText, cleanStream, colorOptions, getLinesLength, purgeSpinnerOptions, purgeSpinnersOptions, SPINNERS, terminalSupportsUnicode, writeStream, prefixOptions, } from './spinniesUtils.js';
|
|
12
14
|
function safeColor(text, color) {
|
|
13
15
|
const chalkFn = chalk[color];
|
|
14
16
|
if (typeof chalkFn === 'function') {
|
|
@@ -34,10 +36,14 @@ class SpinniesManager {
|
|
|
34
36
|
succeedColor: 'green',
|
|
35
37
|
failColor: 'red',
|
|
36
38
|
spinner: terminalSupportsUnicode() ? SPINNERS.dots : SPINNERS.dashes,
|
|
37
|
-
disableSpins:
|
|
39
|
+
disableSpins: false,
|
|
38
40
|
...purgeSpinnersOptions(options),
|
|
39
41
|
};
|
|
40
|
-
this.spin =
|
|
42
|
+
this.spin =
|
|
43
|
+
!this.options.disableSpins &&
|
|
44
|
+
!process.env.CI &&
|
|
45
|
+
process.stderr &&
|
|
46
|
+
process.stderr.isTTY;
|
|
41
47
|
if (!this.hasAnySpinners()) {
|
|
42
48
|
this.resetState();
|
|
43
49
|
}
|
|
@@ -135,7 +141,22 @@ class SpinniesManager {
|
|
|
135
141
|
status = status || 'spinning';
|
|
136
142
|
this.spinners[name] = { ...this.spinners[name], ...options, status };
|
|
137
143
|
}
|
|
138
|
-
updateSpinnerState() {
|
|
144
|
+
updateSpinnerState() {
|
|
145
|
+
if (this.spin) {
|
|
146
|
+
if (this.currentInterval) {
|
|
147
|
+
clearInterval(this.currentInterval);
|
|
148
|
+
}
|
|
149
|
+
this.currentInterval = this.loopStream();
|
|
150
|
+
if (!this.isCursorHidden) {
|
|
151
|
+
cliCursor.hide();
|
|
152
|
+
}
|
|
153
|
+
this.isCursorHidden = true;
|
|
154
|
+
this.checkIfActiveSpinners();
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
this.setRawStreamOutput();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
139
160
|
loopStream() {
|
|
140
161
|
const frames = this.options.spinner?.frames || SPINNERS.dots.frames;
|
|
141
162
|
const interval = this.options.spinner?.interval || SPINNERS.dots.interval;
|
|
@@ -147,10 +168,86 @@ class SpinniesManager {
|
|
|
147
168
|
: ++this.currentFrameIndex;
|
|
148
169
|
}, interval);
|
|
149
170
|
}
|
|
150
|
-
setStreamOutput(frame = '') {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
setStreamOutput(frame = '') {
|
|
172
|
+
let output = '';
|
|
173
|
+
const linesLength = [];
|
|
174
|
+
const hasActiveSpinners = this.hasActiveSpinners();
|
|
175
|
+
Object.values(this.spinners).forEach(spinner => {
|
|
176
|
+
let { text } = spinner;
|
|
177
|
+
const { status, color, spinnerColor, succeedColor, failColor, indent = 0, succeedPrefix = prefixOptions(this.options).succeedPrefix, failPrefix = prefixOptions(this.options).failPrefix, } = spinner;
|
|
178
|
+
let line;
|
|
179
|
+
let prefixLength = indent;
|
|
180
|
+
text = text ?? '';
|
|
181
|
+
if (status === 'spinning') {
|
|
182
|
+
prefixLength += frame.length + 1;
|
|
183
|
+
text = breakText(text, prefixLength);
|
|
184
|
+
const colorizedFrame = safeColor(frame, spinnerColor);
|
|
185
|
+
const colorizedText = safeColor(text, color);
|
|
186
|
+
line = `${colorizedFrame} ${colorizedText}`;
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
if (status === 'succeed') {
|
|
190
|
+
prefixLength += succeedPrefix.length + 1;
|
|
191
|
+
if (hasActiveSpinners) {
|
|
192
|
+
text = breakText(text, prefixLength);
|
|
193
|
+
}
|
|
194
|
+
const colorizedText = safeColor(text, succeedColor);
|
|
195
|
+
line = `${chalk.green(succeedPrefix)} ${colorizedText}`;
|
|
196
|
+
}
|
|
197
|
+
else if (status === 'fail') {
|
|
198
|
+
prefixLength += failPrefix.length + 1;
|
|
199
|
+
if (hasActiveSpinners) {
|
|
200
|
+
text = breakText(text, prefixLength);
|
|
201
|
+
}
|
|
202
|
+
const colorizedText = safeColor(text, failColor);
|
|
203
|
+
line = `${chalk.red(failPrefix)} ${colorizedText}`;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
if (hasActiveSpinners) {
|
|
207
|
+
text = breakText(text, prefixLength);
|
|
208
|
+
}
|
|
209
|
+
line = safeColor(text, color);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
linesLength.push(...getLinesLength(text, prefixLength));
|
|
213
|
+
output += indent ? `${' '.repeat(indent)}${line}\n` : `${line}\n`;
|
|
214
|
+
});
|
|
215
|
+
if (!hasActiveSpinners) {
|
|
216
|
+
readline.clearScreenDown(this.stream);
|
|
217
|
+
}
|
|
218
|
+
writeStream(this.stream, output, linesLength);
|
|
219
|
+
if (hasActiveSpinners) {
|
|
220
|
+
cleanStream(this.stream, linesLength);
|
|
221
|
+
}
|
|
222
|
+
this.lineCount = linesLength.length;
|
|
223
|
+
}
|
|
224
|
+
setRawStreamOutput() {
|
|
225
|
+
Object.values(this.spinners).forEach(i => {
|
|
226
|
+
process.stderr.write(`- ${i.text}\n`);
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
checkIfActiveSpinners() {
|
|
230
|
+
if (!this.hasActiveSpinners()) {
|
|
231
|
+
if (this.spin) {
|
|
232
|
+
this.setStreamOutput();
|
|
233
|
+
readline.moveCursor(this.stream, 0, this.lineCount);
|
|
234
|
+
if (this.currentInterval) {
|
|
235
|
+
clearInterval(this.currentInterval);
|
|
236
|
+
}
|
|
237
|
+
this.isCursorHidden = false;
|
|
238
|
+
cliCursor.show();
|
|
239
|
+
}
|
|
240
|
+
this.spinners = {};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
bindSigint() {
|
|
244
|
+
process.removeAllListeners('SIGINT');
|
|
245
|
+
process.on('SIGINT', () => {
|
|
246
|
+
cliCursor.show();
|
|
247
|
+
readline.moveCursor(process.stderr, 0, this.lineCount);
|
|
248
|
+
process.exit(0);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
154
251
|
}
|
|
155
252
|
const toExport = new SpinniesManager();
|
|
156
253
|
export default toExport;
|
package/lib/usageTracking.js
CHANGED
|
@@ -44,7 +44,7 @@ export async function trackCommandUsage(command, meta = {}, accountId) {
|
|
|
44
44
|
action: 'cli-command',
|
|
45
45
|
command,
|
|
46
46
|
authType,
|
|
47
|
-
|
|
47
|
+
meta,
|
|
48
48
|
accountId,
|
|
49
49
|
});
|
|
50
50
|
}
|
|
@@ -133,12 +133,12 @@ async function trackCliInteraction({ action, accountId, command, authType, meta
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
try {
|
|
136
|
+
logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
|
|
136
137
|
return trackUsage('cli-interaction', EventClass.INTERACTION, usageTrackingEvent, accountId);
|
|
137
138
|
}
|
|
138
139
|
catch (error) {
|
|
139
140
|
debugError(error);
|
|
140
141
|
}
|
|
141
|
-
logger.debug('Sent usage tracking command event: %o', usageTrackingEvent);
|
|
142
142
|
}
|
|
143
143
|
catch (e) {
|
|
144
144
|
debugError(e);
|
|
@@ -31,7 +31,7 @@ const inputSchema = {
|
|
|
31
31
|
};
|
|
32
32
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
33
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
34
|
-
const toolName = 'create-
|
|
34
|
+
const toolName = 'create-cms-function';
|
|
35
35
|
export class HsCreateFunctionTool extends Tool {
|
|
36
36
|
constructor(mcpServer) {
|
|
37
37
|
super(mcpServer);
|
|
@@ -47,7 +47,7 @@ const inputSchema = {
|
|
|
47
47
|
};
|
|
48
48
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
49
49
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
50
|
-
const toolName = 'create-
|
|
50
|
+
const toolName = 'create-cms-module';
|
|
51
51
|
export class HsCreateModuleTool extends Tool {
|
|
52
52
|
constructor(mcpServer) {
|
|
53
53
|
super(mcpServer);
|
|
@@ -23,7 +23,7 @@ const inputSchema = {
|
|
|
23
23
|
};
|
|
24
24
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
25
25
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
26
|
-
const toolName = 'create-
|
|
26
|
+
const toolName = 'create-cms-template';
|
|
27
27
|
export class HsCreateTemplateTool extends Tool {
|
|
28
28
|
constructor(mcpServer) {
|
|
29
29
|
super(mcpServer);
|
|
@@ -26,7 +26,7 @@ const inputSchema = {
|
|
|
26
26
|
};
|
|
27
27
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
28
28
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
29
|
-
const toolName = 'get-
|
|
29
|
+
const toolName = 'get-cms-serverless-function-logs';
|
|
30
30
|
export class HsFunctionLogsTool extends Tool {
|
|
31
31
|
constructor(mcpServer) {
|
|
32
32
|
super(mcpServer);
|
|
@@ -69,7 +69,7 @@ export class HsFunctionLogsTool extends Tool {
|
|
|
69
69
|
register() {
|
|
70
70
|
return this.mcpServer.registerTool(toolName, {
|
|
71
71
|
title: 'Get HubSpot CMS serverless function logs for an endpoint',
|
|
72
|
-
description: 'Retrieve logs for HubSpot CMS serverless functions. Use this tool to help debug issues with serverless functions by reading the production logs. Supports various options like latest, compact, and limiting results. Use after listing functions with list-
|
|
72
|
+
description: 'Retrieve logs for HubSpot CMS serverless functions. Use this tool to help debug issues with serverless functions by reading the production logs. Supports various options like latest, compact, and limiting results. Use after listing functions with list-cms-serverless-functions to get the endpoint path.',
|
|
73
73
|
inputSchema,
|
|
74
74
|
}, this.handler);
|
|
75
75
|
}
|
|
@@ -18,7 +18,7 @@ const inputSchema = {
|
|
|
18
18
|
};
|
|
19
19
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
20
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
21
|
-
const toolName = 'list-
|
|
21
|
+
const toolName = 'list-cms-serverless-functions';
|
|
22
22
|
export class HsListFunctionsTool extends Tool {
|
|
23
23
|
constructor(mcpServer) {
|
|
24
24
|
super(mcpServer);
|
|
@@ -18,7 +18,7 @@ const inputSchema = {
|
|
|
18
18
|
};
|
|
19
19
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
20
20
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
21
|
-
const toolName = 'list-
|
|
21
|
+
const toolName = 'list-cms-remote-contents';
|
|
22
22
|
export class HsListTool extends Tool {
|
|
23
23
|
constructor(mcpServer) {
|
|
24
24
|
super(mcpServer);
|
|
@@ -28,7 +28,7 @@ describe('HsCreateFunctionTool', () => {
|
|
|
28
28
|
describe('register', () => {
|
|
29
29
|
it('should register the tool with the MCP server', () => {
|
|
30
30
|
const result = tool.register();
|
|
31
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-
|
|
31
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-cms-function', {
|
|
32
32
|
title: 'Create HubSpot CMS Serverless Function',
|
|
33
33
|
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(', ')}).`,
|
|
34
34
|
inputSchema: expect.any(Object),
|
|
@@ -27,7 +27,7 @@ describe('HsCreateModuleTool', () => {
|
|
|
27
27
|
describe('register', () => {
|
|
28
28
|
it('should register the tool with the MCP server', () => {
|
|
29
29
|
const result = tool.register();
|
|
30
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-
|
|
30
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-cms-module', {
|
|
31
31
|
title: 'Create HubSpot CMS Module',
|
|
32
32
|
description: 'Creates a new HubSpot CMS module using the hs create module command. Modules can be created non-interactively by specifying moduleLabel and other module options. You can create either HubL or React modules by setting the reactType parameter.',
|
|
33
33
|
inputSchema: expect.any(Object),
|
|
@@ -28,7 +28,7 @@ describe('HsCreateTemplateTool', () => {
|
|
|
28
28
|
describe('register', () => {
|
|
29
29
|
it('should register the tool with the MCP server', () => {
|
|
30
30
|
const result = tool.register();
|
|
31
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-
|
|
31
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-cms-template', {
|
|
32
32
|
title: 'Create HubSpot CMS Template',
|
|
33
33
|
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(', ')}.`,
|
|
34
34
|
inputSchema: expect.any(Object),
|
|
@@ -27,9 +27,9 @@ describe('HsFunctionLogsTool', () => {
|
|
|
27
27
|
describe('register', () => {
|
|
28
28
|
it('should register the tool with the MCP server', () => {
|
|
29
29
|
const result = tool.register();
|
|
30
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-
|
|
30
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-cms-serverless-function-logs', expect.objectContaining({
|
|
31
31
|
title: 'Get HubSpot CMS serverless function logs for an endpoint',
|
|
32
|
-
description: 'Retrieve logs for HubSpot CMS serverless functions. Use this tool to help debug issues with serverless functions by reading the production logs. Supports various options like latest, compact, and limiting results. Use after listing functions with list-
|
|
32
|
+
description: 'Retrieve logs for HubSpot CMS serverless functions. Use this tool to help debug issues with serverless functions by reading the production logs. Supports various options like latest, compact, and limiting results. Use after listing functions with list-cms-serverless-functions to get the endpoint path.',
|
|
33
33
|
inputSchema: expect.any(Object),
|
|
34
34
|
}), expect.any(Function));
|
|
35
35
|
expect(result).toBe(mockRegisteredTool);
|
|
@@ -27,7 +27,7 @@ describe('HsListFunctionsTool', () => {
|
|
|
27
27
|
describe('register', () => {
|
|
28
28
|
it('should register the tool with the MCP server', () => {
|
|
29
29
|
const result = tool.register();
|
|
30
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('list-
|
|
30
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('list-cms-serverless-functions', {
|
|
31
31
|
title: 'List HubSpot CMS Serverless Functions',
|
|
32
32
|
description: 'Get a list of all serverless functions deployed in a HubSpot portal/account. Shows function routes, HTTP methods, secrets, and timestamps.',
|
|
33
33
|
inputSchema: expect.any(Object),
|
|
@@ -27,7 +27,7 @@ describe('HsListTool', () => {
|
|
|
27
27
|
describe('register', () => {
|
|
28
28
|
it('should register the tool with the MCP server', () => {
|
|
29
29
|
const result = tool.register();
|
|
30
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('list-
|
|
30
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('list-cms-remote-contents', {
|
|
31
31
|
title: 'List HubSpot CMS Directory Contents',
|
|
32
32
|
description: 'List remote contents of a HubSpot CMS directory.',
|
|
33
33
|
inputSchema: expect.any(Object),
|
|
@@ -6,19 +6,19 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
6
6
|
addApp: z.ZodBoolean;
|
|
7
7
|
distribution: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"marketplace">, z.ZodLiteral<"private">]>>;
|
|
8
8
|
auth: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"static">, z.ZodLiteral<"oauth">]>>;
|
|
9
|
-
features: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">, z.ZodLiteral<"workflow-action">, z.ZodLiteral<"workflow-action-tool">, z.ZodLiteral<"app-object">, z.ZodLiteral<"scim">]>, "many">>;
|
|
9
|
+
features: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">, z.ZodLiteral<"workflow-action">, z.ZodLiteral<"workflow-action-tool">, z.ZodLiteral<"app-object">, z.ZodLiteral<"app-event">, z.ZodLiteral<"scim">, z.ZodLiteral<"page">]>, "many">>;
|
|
10
10
|
}, "strip", z.ZodTypeAny, {
|
|
11
11
|
absoluteProjectPath: string;
|
|
12
12
|
addApp: boolean;
|
|
13
13
|
auth?: "oauth" | "static" | undefined;
|
|
14
14
|
distribution?: "marketplace" | "private" | undefined;
|
|
15
|
-
features?: ("card" | "settings" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
15
|
+
features?: ("card" | "settings" | "page" | "app-event" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
16
16
|
}, {
|
|
17
17
|
absoluteProjectPath: string;
|
|
18
18
|
addApp: boolean;
|
|
19
19
|
auth?: "oauth" | "static" | undefined;
|
|
20
20
|
distribution?: "marketplace" | "private" | undefined;
|
|
21
|
-
features?: ("card" | "settings" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
21
|
+
features?: ("card" | "settings" | "page" | "app-event" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
22
22
|
}>;
|
|
23
23
|
export type AddFeatureInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
24
24
|
export declare class AddFeatureToProjectTool extends Tool<AddFeatureInputSchema> {
|
|
@@ -16,20 +16,20 @@ const inputSchema = {
|
|
|
16
16
|
z.literal(APP_DISTRIBUTION_TYPES.MARKETPLACE),
|
|
17
17
|
z.literal(APP_DISTRIBUTION_TYPES.PRIVATE),
|
|
18
18
|
]))
|
|
19
|
-
.describe('
|
|
19
|
+
.describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Private is used if you do not wish to distribute your application on the HubSpot marketplace. '),
|
|
20
20
|
auth: z
|
|
21
21
|
.optional(z.union([
|
|
22
22
|
z.literal(APP_AUTH_TYPES.STATIC),
|
|
23
23
|
z.literal(APP_AUTH_TYPES.OAUTH),
|
|
24
24
|
]))
|
|
25
|
-
.describe('
|
|
25
|
+
.describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Static uses a static non changing authentication token, and is only available for private distribution. '),
|
|
26
26
|
features,
|
|
27
27
|
};
|
|
28
28
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
29
29
|
const inputSchemaZodObject = z.object({
|
|
30
30
|
...inputSchema,
|
|
31
31
|
});
|
|
32
|
-
const toolName = 'add-feature-to-
|
|
32
|
+
const toolName = 'add-feature-to-project';
|
|
33
33
|
export class AddFeatureToProjectTool extends Tool {
|
|
34
34
|
constructor(mcpServer) {
|
|
35
35
|
super(mcpServer);
|
|
@@ -8,7 +8,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
8
8
|
projectBase: z.ZodUnion<[z.ZodLiteral<"empty">, z.ZodLiteral<"app">]>;
|
|
9
9
|
distribution: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"marketplace">, z.ZodLiteral<"private">]>>;
|
|
10
10
|
auth: z.ZodOptional<z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"static">, z.ZodLiteral<"oauth">]>>>;
|
|
11
|
-
features: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">, z.ZodLiteral<"workflow-action">, z.ZodLiteral<"workflow-action-tool">, z.ZodLiteral<"app-object">, z.ZodLiteral<"scim">]>, "many">>;
|
|
11
|
+
features: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">, z.ZodLiteral<"workflow-action">, z.ZodLiteral<"workflow-action-tool">, z.ZodLiteral<"app-object">, z.ZodLiteral<"app-event">, z.ZodLiteral<"scim">, z.ZodLiteral<"page">]>, "many">>;
|
|
12
12
|
}, "strip", z.ZodTypeAny, {
|
|
13
13
|
projectBase: "app" | "empty";
|
|
14
14
|
absoluteCurrentWorkingDirectory: string;
|
|
@@ -16,7 +16,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
16
16
|
name?: string | undefined;
|
|
17
17
|
auth?: "oauth" | "static" | undefined;
|
|
18
18
|
distribution?: "marketplace" | "private" | undefined;
|
|
19
|
-
features?: ("card" | "settings" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
19
|
+
features?: ("card" | "settings" | "page" | "app-event" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
20
20
|
}, {
|
|
21
21
|
projectBase: "app" | "empty";
|
|
22
22
|
absoluteCurrentWorkingDirectory: string;
|
|
@@ -24,7 +24,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
24
24
|
name?: string | undefined;
|
|
25
25
|
auth?: "oauth" | "static" | undefined;
|
|
26
26
|
distribution?: "marketplace" | "private" | undefined;
|
|
27
|
-
features?: ("card" | "settings" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
27
|
+
features?: ("card" | "settings" | "page" | "app-event" | "workflow-action-tool" | "workflow-action" | "app-function" | "webhooks" | "app-object" | "scim")[] | undefined;
|
|
28
28
|
}>;
|
|
29
29
|
export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
30
30
|
export declare class CreateProjectTool extends Tool<CreateProjectInputSchema> {
|
|
@@ -10,11 +10,11 @@ const inputSchema = {
|
|
|
10
10
|
absoluteCurrentWorkingDirectory,
|
|
11
11
|
name: z
|
|
12
12
|
.string()
|
|
13
|
-
.describe('The name of the project to be created. This name is how your project will appear in HubSpot.
|
|
13
|
+
.describe('If not specified by the user, DO NOT choose for them. Changing this is potentially destructive.The name of the project to be created. This name is how your project will appear in HubSpot. ')
|
|
14
14
|
.optional(),
|
|
15
15
|
destination: z
|
|
16
16
|
.string()
|
|
17
|
-
.describe('
|
|
17
|
+
.describe('DO NOT use the current directory unless the user has explicitly stated to do so. Relative path to the directory the project will be created in.'),
|
|
18
18
|
projectBase: z
|
|
19
19
|
.union([z.literal(EMPTY_PROJECT), z.literal(PROJECT_WITH_APP)])
|
|
20
20
|
.describe('Empty will create an empty project, and app will create a project with an app inside of it.'),
|
|
@@ -23,19 +23,19 @@ const inputSchema = {
|
|
|
23
23
|
z.literal(APP_DISTRIBUTION_TYPES.MARKETPLACE),
|
|
24
24
|
z.literal(APP_DISTRIBUTION_TYPES.PRIVATE),
|
|
25
25
|
]))
|
|
26
|
-
.describe('
|
|
26
|
+
.describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Private is used if you do not wish to distribute your application on the HubSpot marketplace. '),
|
|
27
27
|
auth: z
|
|
28
28
|
.optional(z.union([
|
|
29
29
|
z.literal(APP_AUTH_TYPES.STATIC),
|
|
30
30
|
z.literal(APP_AUTH_TYPES.OAUTH),
|
|
31
31
|
]))
|
|
32
|
-
.describe('
|
|
32
|
+
.describe('If not specified by the user, DO NOT choose for them. This cannot be changed after a project is uploaded. Static uses a static non changing authentication token, and is only available for private distribution. ')
|
|
33
33
|
.optional(),
|
|
34
34
|
features,
|
|
35
35
|
};
|
|
36
36
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
37
37
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
38
|
-
const toolName = 'create-
|
|
38
|
+
const toolName = 'create-project';
|
|
39
39
|
export class CreateProjectTool extends Tool {
|
|
40
40
|
constructor(mcpServer) {
|
|
41
41
|
super(mcpServer);
|
|
@@ -15,7 +15,7 @@ const inputSchema = {
|
|
|
15
15
|
const inputSchemaZodObject = z.object({
|
|
16
16
|
...inputSchema,
|
|
17
17
|
});
|
|
18
|
-
const toolName = 'deploy-
|
|
18
|
+
const toolName = 'deploy-project';
|
|
19
19
|
export class DeployProjectTool extends Tool {
|
|
20
20
|
constructor(mcpServer) {
|
|
21
21
|
super(mcpServer);
|
|
@@ -12,7 +12,7 @@ const inputSchema = {
|
|
|
12
12
|
const inputSchemaZodObject = z.object({
|
|
13
13
|
...inputSchema,
|
|
14
14
|
});
|
|
15
|
-
const toolName = 'fetch-
|
|
15
|
+
const toolName = 'fetch-doc';
|
|
16
16
|
export class DocFetchTool extends Tool {
|
|
17
17
|
constructor(mcpServer) {
|
|
18
18
|
super(mcpServer);
|
|
@@ -42,7 +42,7 @@ export class DocFetchTool extends Tool {
|
|
|
42
42
|
register() {
|
|
43
43
|
return this.mcpServer.registerTool(toolName, {
|
|
44
44
|
title: 'Fetch HubSpot Developer Documentation (single file)',
|
|
45
|
-
description: 'Always use this immediately after `search-
|
|
45
|
+
description: 'Always use this immediately after `search-docs` and before creating a plan, writing code, or answering technical questions. This tool retrieves the full, authoritative content of a HubSpot Developer Documentation page from its URL, ensuring responses are accurate, up-to-date, and grounded in the official docs.',
|
|
46
46
|
inputSchema,
|
|
47
47
|
}, this.handler);
|
|
48
48
|
}
|
|
@@ -2,10 +2,13 @@ import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.
|
|
|
2
2
|
import z from 'zod';
|
|
3
3
|
import { TextContentResponse, Tool } from '../../types.js';
|
|
4
4
|
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
5
6
|
docsSearchQuery: z.ZodString;
|
|
6
7
|
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
absoluteCurrentWorkingDirectory: string;
|
|
7
9
|
docsSearchQuery: string;
|
|
8
10
|
}, {
|
|
11
|
+
absoluteCurrentWorkingDirectory: string;
|
|
9
12
|
docsSearchQuery: string;
|
|
10
13
|
}>;
|
|
11
14
|
export interface DocsSearchResponse {
|
|
@@ -20,7 +23,7 @@ export interface DocsSearchResponse {
|
|
|
20
23
|
type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
|
|
21
24
|
export declare class DocsSearchTool extends Tool<InputSchemaType> {
|
|
22
25
|
constructor(mcpServer: McpServer);
|
|
23
|
-
handler({ docsSearchQuery, }: InputSchemaType): Promise<TextContentResponse>;
|
|
26
|
+
handler({ absoluteCurrentWorkingDirectory, docsSearchQuery, }: InputSchemaType): Promise<TextContentResponse>;
|
|
24
27
|
register(): RegisteredTool;
|
|
25
28
|
}
|
|
26
29
|
export {};
|
|
@@ -3,25 +3,25 @@ import z from 'zod';
|
|
|
3
3
|
import { Tool } from '../../types.js';
|
|
4
4
|
import { formatTextContents } from '../../utils/content.js';
|
|
5
5
|
import { trackToolUsage } from '../../utils/toolUsageTracking.js';
|
|
6
|
-
import { docsSearchQuery } from './constants.js';
|
|
7
|
-
import { getAccountId, getConfigPath, loadConfig, } from '@hubspot/local-dev-lib/config';
|
|
6
|
+
import { absoluteCurrentWorkingDirectory, docsSearchQuery, } from './constants.js';
|
|
8
7
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
8
|
+
import { getAccountIdFromCliConfig } from '../../utils/cliConfig.js';
|
|
9
9
|
const inputSchema = {
|
|
10
|
+
absoluteCurrentWorkingDirectory,
|
|
10
11
|
docsSearchQuery,
|
|
11
12
|
};
|
|
12
13
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
13
14
|
const inputSchemaZodObject = z.object({
|
|
14
15
|
...inputSchema,
|
|
15
16
|
});
|
|
16
|
-
const toolName = 'search-
|
|
17
|
+
const toolName = 'search-docs';
|
|
17
18
|
export class DocsSearchTool extends Tool {
|
|
18
19
|
constructor(mcpServer) {
|
|
19
20
|
super(mcpServer);
|
|
20
21
|
}
|
|
21
|
-
async handler({ docsSearchQuery, }) {
|
|
22
|
+
async handler({ absoluteCurrentWorkingDirectory, docsSearchQuery, }) {
|
|
22
23
|
await trackToolUsage(toolName, { mode: docsSearchQuery });
|
|
23
|
-
|
|
24
|
-
const accountId = getAccountId();
|
|
24
|
+
const accountId = getAccountIdFromCliConfig(absoluteCurrentWorkingDirectory);
|
|
25
25
|
if (!accountId) {
|
|
26
26
|
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
27
|
return formatTextContents(authErrorMessage);
|
|
@@ -55,7 +55,7 @@ export class DocsSearchTool extends Tool {
|
|
|
55
55
|
register() {
|
|
56
56
|
return this.mcpServer.registerTool(toolName, {
|
|
57
57
|
title: 'Search HubSpot Developer Documentation',
|
|
58
|
-
description: 'Use this first whenever you need details about HubSpot APIs, SDKs, integrations, or developer platform features. This searches the official HubSpot Developer Documentation and returns the most relevant pages, each with a URL for use in `fetch-
|
|
58
|
+
description: 'Use this first whenever you need details about HubSpot APIs, SDKs, integrations, or developer platform features. This searches the official HubSpot Developer Documentation and returns the most relevant pages, each with a URL for use in `fetch-doc`. Always follow this with a fetch to get the full, authoritative content before making plans or writing answers.',
|
|
59
59
|
inputSchema,
|
|
60
60
|
}, this.handler);
|
|
61
61
|
}
|
|
@@ -2,19 +2,22 @@ import { TextContentResponse, Tool } from '../../types.js';
|
|
|
2
2
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
5
6
|
platformVersion: z.ZodString;
|
|
6
7
|
featureType: z.ZodString;
|
|
7
8
|
}, "strip", z.ZodTypeAny, {
|
|
8
9
|
platformVersion: string;
|
|
10
|
+
absoluteCurrentWorkingDirectory: string;
|
|
9
11
|
featureType: string;
|
|
10
12
|
}, {
|
|
11
13
|
platformVersion: string;
|
|
14
|
+
absoluteCurrentWorkingDirectory: string;
|
|
12
15
|
featureType: string;
|
|
13
16
|
}>;
|
|
14
17
|
type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
|
|
15
18
|
export declare class GetConfigValuesTool extends Tool<InputSchemaType> {
|
|
16
19
|
constructor(mcpServer: McpServer);
|
|
17
|
-
handler({ platformVersion, featureType, }: InputSchemaType): Promise<TextContentResponse>;
|
|
20
|
+
handler({ absoluteCurrentWorkingDirectory, platformVersion, featureType, }: InputSchemaType): Promise<TextContentResponse>;
|
|
18
21
|
register(): RegisteredTool;
|
|
19
22
|
}
|
|
20
23
|
export {};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Tool } from '../../types.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { formatTextContents } from '../../utils/content.js';
|
|
4
|
+
import { absoluteCurrentWorkingDirectory } from './constants.js';
|
|
4
5
|
import { getIntermediateRepresentationSchema, mapToInternalType, } from '@hubspot/project-parsing-lib';
|
|
5
|
-
import { getAccountId, getConfigPath, loadConfig, } from '@hubspot/local-dev-lib/config';
|
|
6
6
|
import { useV3Api } from '../../../lib/projects/platformVersion.js';
|
|
7
|
+
import { getAccountIdFromCliConfig } from '../../utils/cliConfig.js';
|
|
7
8
|
const inputSchema = {
|
|
9
|
+
absoluteCurrentWorkingDirectory,
|
|
8
10
|
platformVersion: z
|
|
9
11
|
.string()
|
|
10
12
|
.describe('The platform version for the project. Located in the hsproject.json file.'),
|
|
@@ -16,21 +18,25 @@ const inputSchema = {
|
|
|
16
18
|
const inputSchemaZodObject = z.object({
|
|
17
19
|
...inputSchema,
|
|
18
20
|
});
|
|
19
|
-
const toolName = 'get-
|
|
21
|
+
const toolName = 'get-feature-config-schema';
|
|
20
22
|
export class GetConfigValuesTool extends Tool {
|
|
21
23
|
constructor(mcpServer) {
|
|
22
24
|
super(mcpServer);
|
|
23
25
|
}
|
|
24
|
-
async handler({ platformVersion, featureType, }) {
|
|
26
|
+
async handler({ absoluteCurrentWorkingDirectory, platformVersion, featureType, }) {
|
|
25
27
|
try {
|
|
26
28
|
if (!useV3Api(platformVersion)) {
|
|
27
29
|
return formatTextContents(`Can only be used on projects with a minimum platformVersion of 2025.2`);
|
|
28
30
|
}
|
|
29
|
-
|
|
31
|
+
const accountId = getAccountIdFromCliConfig(absoluteCurrentWorkingDirectory);
|
|
32
|
+
if (!accountId) {
|
|
33
|
+
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>\``;
|
|
34
|
+
return formatTextContents(authErrorMessage);
|
|
35
|
+
}
|
|
30
36
|
const schema = await getIntermediateRepresentationSchema({
|
|
31
37
|
platformVersion,
|
|
32
38
|
projectSourceDir: '',
|
|
33
|
-
accountId
|
|
39
|
+
accountId,
|
|
34
40
|
});
|
|
35
41
|
const internalComponentType = mapToInternalType(featureType);
|
|
36
42
|
if (schema[internalComponentType]) {
|
|
@@ -24,7 +24,7 @@ const inputSchema = {
|
|
|
24
24
|
const inputSchemaZodObject = z.object({
|
|
25
25
|
...inputSchema,
|
|
26
26
|
});
|
|
27
|
-
const toolName = 'guided-walkthrough-
|
|
27
|
+
const toolName = 'guided-walkthrough-cli';
|
|
28
28
|
export class GuidedWalkthroughTool extends Tool {
|
|
29
29
|
constructor(mcpServer) {
|
|
30
30
|
super(mcpServer);
|
|
@@ -11,7 +11,7 @@ const inputSchema = {
|
|
|
11
11
|
const inputSchemaZodObject = z.object({
|
|
12
12
|
...inputSchema,
|
|
13
13
|
});
|
|
14
|
-
const toolName = 'upload-
|
|
14
|
+
const toolName = 'upload-project';
|
|
15
15
|
export class UploadProjectTools extends Tool {
|
|
16
16
|
constructor(mcpServer) {
|
|
17
17
|
super(mcpServer);
|
|
@@ -24,7 +24,7 @@ export class UploadProjectTools extends Tool {
|
|
|
24
24
|
register() {
|
|
25
25
|
return this.mcpServer.registerTool(toolName, {
|
|
26
26
|
title: 'Upload HubSpot Project',
|
|
27
|
-
description: 'Uploads the HubSpot project in current working directory. If the project does not exist, it will be created. MUST be ran from within the project directory.
|
|
27
|
+
description: 'DO NOT run this tool unless the user specifies they would like to upload the project, it is potentially destructive. Uploads the HubSpot project in current working directory. If the project does not exist, it will be created. MUST be ran from within the project directory.',
|
|
28
28
|
inputSchema,
|
|
29
29
|
}, this.handler);
|
|
30
30
|
}
|
|
@@ -9,7 +9,7 @@ const inputSchema = {
|
|
|
9
9
|
};
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
11
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
12
|
-
const toolName = 'validate-
|
|
12
|
+
const toolName = 'validate-project';
|
|
13
13
|
export class ValidateProjectTool extends Tool {
|
|
14
14
|
constructor(mcpServer) {
|
|
15
15
|
super(mcpServer);
|
|
@@ -28,7 +28,7 @@ describe('mcp-server/tools/project/AddFeatureToProject', () => {
|
|
|
28
28
|
describe('register', () => {
|
|
29
29
|
it('should register tool with correct parameters', () => {
|
|
30
30
|
const result = tool.register();
|
|
31
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('add-feature-to-
|
|
31
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('add-feature-to-project', expect.objectContaining({
|
|
32
32
|
title: 'Add feature to HubSpot Project',
|
|
33
33
|
description: expect.stringContaining('Adds a feature to an existing HubSpot project'),
|
|
34
34
|
inputSchema: expect.any(Object),
|