@hubspot/cli 8.10.0 → 8.12.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/account/clean.js +1 -1
- package/commands/account/list.js +1 -1
- package/commands/account/remove.js +1 -1
- package/commands/account/rename.js +1 -1
- package/commands/account/use.js +1 -1
- package/commands/api.d.ts +4 -1
- package/commands/api.js +11 -14
- 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 +2 -1
- package/commands/project/appInstallStatus.js +19 -17
- package/commands/project/create.js +0 -1
- package/commands/project/deploy.d.ts +2 -1
- package/commands/project/deploy.js +31 -14
- package/commands/project/dev/index.js +18 -64
- package/commands/project/info.d.ts +2 -1
- package/commands/project/info.js +8 -6
- package/commands/project/installApp.d.ts +2 -1
- package/commands/project/installApp.js +25 -26
- package/commands/project/list.js +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/release/create.d.ts +2 -1
- package/commands/project/release/create.js +68 -69
- package/commands/project/release/info.d.ts +2 -1
- package/commands/project/release/info.js +7 -6
- package/commands/project/release/list.d.ts +2 -1
- package/commands/project/release/list.js +14 -6
- package/commands/project/upload.d.ts +2 -1
- package/commands/project/upload.js +23 -17
- package/commands/project/validate.d.ts +1 -1
- package/commands/project.js +2 -2
- package/commands/testAccount/create.d.ts +2 -1
- package/commands/testAccount/create.js +7 -7
- package/commands/testAccount/importData.d.ts +1 -1
- package/lang/en.d.ts +32 -28
- package/lang/en.js +41 -37
- package/lib/commonOpts.js +6 -1
- package/lib/constants.d.ts +1 -0
- package/lib/constants.js +1 -0
- package/lib/jsonOutput.d.ts +109 -0
- package/lib/jsonOutput.js +94 -0
- package/lib/mcp/setup.d.ts +6 -1
- package/lib/mcp/setup.js +29 -18
- package/lib/projects/builds.d.ts +2 -0
- package/lib/projects/builds.js +22 -0
- package/lib/projects/localDev/DevSessionManager.d.ts +2 -2
- package/lib/projects/localDev/DevSessionManager.js +4 -30
- package/lib/projects/localDev/helpers/account.d.ts +0 -7
- package/lib/projects/localDev/helpers/account.js +1 -80
- package/lib/projects/release.d.ts +4 -0
- package/lib/projects/release.js +90 -0
- package/lib/projects/upload.d.ts +1 -1
- package/lib/projects/upload.js +4 -8
- package/lib/yargs/makeWrappedYargsHandler.d.ts +5 -1
- package/lib/yargs/makeWrappedYargsHandler.js +123 -65
- package/mcp-server/Tool.d.ts +8 -3
- package/mcp-server/Tool.js +58 -32
- 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/logger.d.ts +3 -0
- package/mcp-server/utils/logger.js +30 -0
- package/mcp-server/utils/toolUsageTracking.js +8 -1
- package/package.json +10 -8
- package/types/Yargs.d.ts +3 -1
- package/commands/project/dev/deprecatedFlow.d.ts +0 -11
- package/commands/project/dev/deprecatedFlow.js +0 -180
- package/lib/projects/localDev/DevServerManager_DEPRECATED.d.ts +0 -43
- package/lib/projects/localDev/DevServerManager_DEPRECATED.js +0 -128
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.d.ts +0 -64
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +0 -394
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os from 'os';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { z } from 'zod';
|
|
3
4
|
import { getConfig } from '@hubspot/local-dev-lib/config';
|
|
4
5
|
import { getStateValue, setStateValue, } from '@hubspot/local-dev-lib/config/state';
|
|
5
6
|
import { STATE_FLAGS } from '@hubspot/local-dev-lib/constants/config';
|
|
@@ -11,7 +12,8 @@ import { lib } from '../../lang/en.js';
|
|
|
11
12
|
import { EXIT_CODES } from '../enums/exitCodes.js';
|
|
12
13
|
import { isPromptExitError } from '../errors/PromptExitError.js';
|
|
13
14
|
import { debugError } from '../errorHandlers/index.js';
|
|
14
|
-
|
|
15
|
+
import { MAX_LOG_FILES } from '../constants.js';
|
|
16
|
+
const HANDLER_LOG_DIR = path.join(os.homedir(), '.hscli', 'logs', 'cli');
|
|
15
17
|
function logUsageTrackingMessage(isJsonOutput) {
|
|
16
18
|
if (isJsonOutput) {
|
|
17
19
|
return;
|
|
@@ -32,90 +34,146 @@ function logUsageTrackingMessage(isJsonOutput) {
|
|
|
32
34
|
return;
|
|
33
35
|
}
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
37
|
+
function createUsageTracker(trackingName, derivedAccountId) {
|
|
38
|
+
const startTime = Date.now();
|
|
39
|
+
const meta = {};
|
|
40
|
+
let fired = false;
|
|
41
|
+
const addMetadata = (newMeta) => {
|
|
42
|
+
Object.assign(meta, newMeta);
|
|
43
|
+
};
|
|
44
|
+
const track = async (successful) => {
|
|
45
|
+
if (fired) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
fired = true;
|
|
49
|
+
try {
|
|
50
|
+
const { accountId: overrideAccountId, ...trackingMeta } = meta;
|
|
51
|
+
trackingMeta.successful = successful;
|
|
52
|
+
trackingMeta.executionTime = Date.now() - startTime;
|
|
53
|
+
await _trackCommandUsage(trackingName, trackingMeta, overrideAccountId ?? derivedAccountId);
|
|
54
|
+
}
|
|
55
|
+
catch (_e) { }
|
|
56
|
+
};
|
|
57
|
+
const onForcedExit = () => {
|
|
58
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
59
|
+
};
|
|
60
|
+
const onSigint = async () => {
|
|
61
|
+
process.removeListener('SIGINT', onSigint);
|
|
62
|
+
process.on('SIGINT', onForcedExit);
|
|
63
|
+
try {
|
|
64
|
+
await track(false);
|
|
65
|
+
}
|
|
66
|
+
catch (_e) { }
|
|
67
|
+
process.removeListener('SIGINT', onForcedExit);
|
|
68
|
+
process.exit(EXIT_CODES.SUCCESS);
|
|
69
|
+
};
|
|
70
|
+
process.on('SIGINT', onSigint);
|
|
71
|
+
const trackAndCleanup = async (successful) => {
|
|
72
|
+
await track(successful);
|
|
73
|
+
process.removeListener('SIGINT', onSigint);
|
|
74
|
+
process.removeListener('SIGINT', onForcedExit);
|
|
75
|
+
};
|
|
76
|
+
return { addMetadata, trackAndCleanup };
|
|
77
|
+
}
|
|
78
|
+
function createJsonOutputManager(isJsonOutput, schema) {
|
|
79
|
+
const data = {};
|
|
80
|
+
let emitted = false;
|
|
81
|
+
const add = (newData) => {
|
|
82
|
+
Object.assign(data, newData);
|
|
83
|
+
};
|
|
84
|
+
const emit = () => {
|
|
85
|
+
if (!emitted && isJsonOutput && Object.keys(data).length > 0) {
|
|
86
|
+
emitted = true;
|
|
87
|
+
if (schema) {
|
|
88
|
+
const result = schema.safeParse(data);
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
uiLogger.json(data);
|
|
91
|
+
uiLogger.warn(lib.jsonSchema.validationFailed);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
55
94
|
}
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
95
|
+
uiLogger.json(data);
|
|
96
|
+
}
|
|
97
|
+
return true;
|
|
98
|
+
};
|
|
99
|
+
return { add, emit };
|
|
100
|
+
}
|
|
101
|
+
function createLogFileWriter(trackingName, isJsonOutput) {
|
|
102
|
+
const writeLogFile = () => {
|
|
103
|
+
if (isJsonOutput) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
return ldlLogger.writeBufferedLogsToFile({
|
|
107
|
+
dir: HANDLER_LOG_DIR,
|
|
108
|
+
filenamePrefix: trackingName,
|
|
109
|
+
maxFiles: MAX_LOG_FILES,
|
|
110
|
+
});
|
|
111
|
+
};
|
|
112
|
+
const writeFailureLogFile = () => {
|
|
113
|
+
const savedPath = writeLogFile();
|
|
114
|
+
if (savedPath) {
|
|
115
|
+
uiLogger.log('');
|
|
116
|
+
uiLogger.error(lib.handlerLogFile.saved(savedPath));
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
return { writeLogFile, writeFailureLogFile };
|
|
120
|
+
}
|
|
121
|
+
export function makeWrappedYargsHandler(trackingName, handler, options) {
|
|
122
|
+
return async (args) => {
|
|
123
|
+
const wrappedHandlerArgs = args;
|
|
124
|
+
const isJsonOutput = Boolean(wrappedHandlerArgs.json || wrappedHandlerArgs.formatOutputAsJson);
|
|
125
|
+
const schema = options?.jsonOutputSchema;
|
|
126
|
+
const tracker = createUsageTracker(trackingName, args.derivedAccountId);
|
|
127
|
+
if (wrappedHandlerArgs.jsonSchema) {
|
|
128
|
+
if (schema) {
|
|
129
|
+
uiLogger.json(z.toJSONSchema(schema));
|
|
66
130
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
process.exit(EXIT_CODES.SUCCESS);
|
|
70
|
-
};
|
|
71
|
-
process.on('SIGINT', onSigint);
|
|
72
|
-
const trackCommandUsageAndRemoveListeners = async (successful) => {
|
|
73
|
-
await trackCommandUsage(successful);
|
|
74
|
-
process.removeListener('SIGINT', onSigint);
|
|
75
|
-
process.removeListener('SIGINT', onForcedExit);
|
|
76
|
-
};
|
|
77
|
-
const jsonArgs = args;
|
|
78
|
-
const isJsonOutput = Boolean(jsonArgs.json || jsonArgs.formatOutputAsJson);
|
|
79
|
-
const writeFailureLogFile = () => {
|
|
80
|
-
// Skip in JSON output modes so the side effect + stderr message don't
|
|
81
|
-
// interfere with structured output consumers.
|
|
82
|
-
if (isJsonOutput) {
|
|
83
|
-
return;
|
|
131
|
+
else {
|
|
132
|
+
uiLogger.json({ error: lib.jsonSchema.noSchemaForCommand });
|
|
84
133
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
134
|
+
await tracker.trackAndCleanup(true);
|
|
135
|
+
return process.exit(EXIT_CODES.SUCCESS);
|
|
136
|
+
}
|
|
137
|
+
const json = createJsonOutputManager(isJsonOutput, schema);
|
|
138
|
+
const logs = createLogFileWriter(trackingName, isJsonOutput);
|
|
139
|
+
wrappedHandlerArgs.addUsageMetadata = tracker.addMetadata;
|
|
140
|
+
wrappedHandlerArgs.addJsonOutput = json.add;
|
|
141
|
+
wrappedHandlerArgs.exit = async (code) => {
|
|
142
|
+
const jsonValid = json.emit();
|
|
143
|
+
const exitCode = !jsonValid && code === EXIT_CODES.SUCCESS ? EXIT_CODES.WARNING : code;
|
|
144
|
+
await tracker.trackAndCleanup(exitCode !== EXIT_CODES.ERROR);
|
|
145
|
+
if (exitCode === EXIT_CODES.ERROR) {
|
|
146
|
+
logs.writeFailureLogFile();
|
|
92
147
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
await trackCommandUsageAndRemoveListeners(code !== EXIT_CODES.ERROR);
|
|
96
|
-
if (code === EXIT_CODES.ERROR) {
|
|
97
|
-
writeFailureLogFile();
|
|
148
|
+
else {
|
|
149
|
+
logs.writeLogFile();
|
|
98
150
|
}
|
|
99
|
-
return process.exit(
|
|
151
|
+
return process.exit(exitCode);
|
|
100
152
|
};
|
|
101
153
|
logUsageTrackingMessage(isJsonOutput);
|
|
102
154
|
try {
|
|
103
|
-
await handler(
|
|
155
|
+
await handler(wrappedHandlerArgs);
|
|
104
156
|
}
|
|
105
157
|
catch (e) {
|
|
106
158
|
const isSuccessfulPromptExit = isPromptExitError(e)
|
|
107
159
|
? e.exitCode !== EXIT_CODES.ERROR
|
|
108
160
|
: false;
|
|
109
|
-
await
|
|
161
|
+
await tracker.trackAndCleanup(isSuccessfulPromptExit);
|
|
110
162
|
if (isPromptExitError(e)) {
|
|
163
|
+
logs.writeLogFile();
|
|
111
164
|
return process.exit(e.exitCode);
|
|
112
165
|
}
|
|
113
166
|
else {
|
|
114
167
|
debugError(e);
|
|
115
|
-
writeFailureLogFile();
|
|
168
|
+
logs.writeFailureLogFile();
|
|
116
169
|
return process.exit(EXIT_CODES.ERROR);
|
|
117
170
|
}
|
|
118
171
|
}
|
|
119
|
-
|
|
172
|
+
const jsonValid = json.emit();
|
|
173
|
+
await tracker.trackAndCleanup(true);
|
|
174
|
+
logs.writeLogFile();
|
|
175
|
+
if (!jsonValid) {
|
|
176
|
+
return process.exit(EXIT_CODES.WARNING);
|
|
177
|
+
}
|
|
120
178
|
};
|
|
121
179
|
}
|
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,41 +14,66 @@ 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
|
+
this.logger.debug(this.toolName, message);
|
|
26
|
+
const token = extra?._meta?.progressToken;
|
|
27
|
+
if (token !== undefined && extra?.sendNotification) {
|
|
28
|
+
progressCount++;
|
|
29
|
+
await extra.sendNotification({
|
|
30
|
+
method: 'notifications/progress',
|
|
31
|
+
params: {
|
|
32
|
+
progressToken: token,
|
|
33
|
+
progress: progressCount,
|
|
34
|
+
message,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
// Swallow notification errors so a failed notification never crashes the tool
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
getTrackingMeta(_input) {
|
|
24
45
|
return undefined;
|
|
25
46
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
47
|
+
wrappedHandler(input, extra) {
|
|
48
|
+
return this.logger.runWithBuffer(async () => {
|
|
49
|
+
const startTime = Date.now();
|
|
50
|
+
try {
|
|
51
|
+
// `input` is logged unredacted. Tool input schemas MUST NOT include
|
|
52
|
+
// credentials or other sensitive values, since MCP clients (Claude
|
|
53
|
+
// Desktop, Inspector, etc.) will display these logs.
|
|
54
|
+
this.logger.debug(this.toolName, {
|
|
55
|
+
message: 'Tool invoked',
|
|
56
|
+
args: input,
|
|
57
|
+
});
|
|
58
|
+
await trackToolUsage(this.toolName, this.getTrackingMeta(input));
|
|
59
|
+
const result = await this.handler(input, extra);
|
|
60
|
+
this.logger.debug(this.toolName, {
|
|
61
|
+
message: 'Tool completed',
|
|
62
|
+
durationMs: Date.now() - startTime,
|
|
63
|
+
});
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
this.logger.error(this.toolName, {
|
|
68
|
+
message: 'Tool failed',
|
|
69
|
+
error: error instanceof Error ? error.message : String(error),
|
|
70
|
+
durationMs: Date.now() - startTime,
|
|
71
|
+
});
|
|
72
|
+
return formatTextContents(getErrorMessage(error));
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
this.logger.flushLogsToFile(this.toolName);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
52
78
|
}
|
|
53
79
|
}
|
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 {};
|
|
@@ -1,9 +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 { addFlag, runCommandInDir } from '../../utils/command.js';
|
|
5
4
|
import { formatTextContent, formatTextContents } from '../../utils/content.js';
|
|
6
5
|
import { CONTENT_TYPES } from '../../../types/Cms.js';
|
|
6
|
+
import { HubSpotCommand } from '../../utils/command.js';
|
|
7
7
|
import { setupHubSpotConfig } from '../../utils/config.js';
|
|
8
8
|
import { getErrorMessage } from '../../../lib/errorHandlers/index.js';
|
|
9
9
|
const inputSchema = {
|
|
@@ -52,7 +52,7 @@ export class HsCreateModuleTool extends Tool {
|
|
|
52
52
|
constructor(mcpServer, logger) {
|
|
53
53
|
super(mcpServer, logger, toolName);
|
|
54
54
|
}
|
|
55
|
-
async handler({ userSuppliedName, dest, moduleLabel, reactType, contentTypes, global, availableForNewContent, absoluteCurrentWorkingDirectory, }) {
|
|
55
|
+
async handler({ userSuppliedName, dest, moduleLabel, reactType, contentTypes, global, availableForNewContent, absoluteCurrentWorkingDirectory, }, extra) {
|
|
56
56
|
setupHubSpotConfig(absoluteCurrentWorkingDirectory);
|
|
57
57
|
const content = [];
|
|
58
58
|
// Always require a name
|
|
@@ -74,34 +74,28 @@ export class HsCreateModuleTool extends Tool {
|
|
|
74
74
|
};
|
|
75
75
|
}
|
|
76
76
|
// Build the command
|
|
77
|
-
|
|
77
|
+
const command = new HubSpotCommand('cms module create');
|
|
78
78
|
if (userSuppliedName) {
|
|
79
|
-
command
|
|
79
|
+
command.addArg(userSuppliedName);
|
|
80
80
|
}
|
|
81
81
|
if (dest) {
|
|
82
|
-
command
|
|
82
|
+
command.addArg(dest);
|
|
83
83
|
}
|
|
84
|
-
// Add module-specific flags
|
|
85
84
|
if (moduleLabel) {
|
|
86
|
-
command
|
|
85
|
+
command.addFlag('module-label', moduleLabel);
|
|
87
86
|
}
|
|
88
87
|
if (reactType !== undefined) {
|
|
89
|
-
command
|
|
90
|
-
}
|
|
91
|
-
if (contentTypes) {
|
|
92
|
-
command = addFlag(command, 'content-types', contentTypes);
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
command = addFlag(command, 'content-types', 'ANY');
|
|
88
|
+
command.addFlag('react-type', reactType);
|
|
96
89
|
}
|
|
90
|
+
command.addFlag('content-types', contentTypes ?? 'ANY');
|
|
97
91
|
if (global !== undefined) {
|
|
98
|
-
command
|
|
92
|
+
command.addFlag('global', global);
|
|
99
93
|
}
|
|
100
94
|
if (availableForNewContent !== undefined) {
|
|
101
|
-
command
|
|
95
|
+
command.addFlag('available-for-new-content', availableForNewContent);
|
|
102
96
|
}
|
|
103
97
|
try {
|
|
104
|
-
const { stdout, stderr } = await
|
|
98
|
+
const { stdout, stderr } = await this.runCommand(absoluteCurrentWorkingDirectory, command, extra);
|
|
105
99
|
return formatTextContents(stdout, stderr);
|
|
106
100
|
}
|
|
107
101
|
catch (error) {
|
|
@@ -123,6 +117,6 @@ export class HsCreateModuleTool extends Tool {
|
|
|
123
117
|
idempotentHint: false,
|
|
124
118
|
openWorldHint: false,
|
|
125
119
|
},
|
|
126
|
-
}, input => this.wrappedHandler(input));
|
|
120
|
+
}, (input, extra) => this.wrappedHandler(input, extra));
|
|
127
121
|
}
|
|
128
122
|
}
|
|
@@ -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';
|
|
@@ -21,7 +21,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
21
21
|
export type HsCreateTemplateInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
22
22
|
export declare class HsCreateTemplateTool extends Tool<HsCreateTemplateInputSchema> {
|
|
23
23
|
constructor(mcpServer: McpServer, logger: McpLogger);
|
|
24
|
-
handler({ userSuppliedName, dest, templateType, absoluteCurrentWorkingDirectory, }: HsCreateTemplateInputSchema): Promise<TextContentResponse>;
|
|
24
|
+
handler({ userSuppliedName, dest, templateType, absoluteCurrentWorkingDirectory, }: HsCreateTemplateInputSchema, extra?: ToolExtra): Promise<TextContentResponse>;
|
|
25
25
|
register(): RegisteredTool;
|
|
26
26
|
}
|
|
27
27
|
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 { TEMPLATE_TYPES } 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 = {
|
|
@@ -29,7 +28,7 @@ export class HsCreateTemplateTool extends Tool {
|
|
|
29
28
|
constructor(mcpServer, logger) {
|
|
30
29
|
super(mcpServer, logger, toolName);
|
|
31
30
|
}
|
|
32
|
-
async handler({ userSuppliedName, dest, templateType, absoluteCurrentWorkingDirectory, }) {
|
|
31
|
+
async handler({ userSuppliedName, dest, templateType, absoluteCurrentWorkingDirectory, }, extra) {
|
|
33
32
|
setupHubSpotConfig(absoluteCurrentWorkingDirectory);
|
|
34
33
|
const content = [];
|
|
35
34
|
// Always require a name
|
|
@@ -47,19 +46,18 @@ export class HsCreateTemplateTool extends Tool {
|
|
|
47
46
|
};
|
|
48
47
|
}
|
|
49
48
|
// Build the command
|
|
50
|
-
|
|
49
|
+
const command = new HubSpotCommand('cms template create');
|
|
51
50
|
if (userSuppliedName) {
|
|
52
|
-
command
|
|
51
|
+
command.addArg(userSuppliedName);
|
|
53
52
|
}
|
|
54
53
|
if (dest) {
|
|
55
|
-
command
|
|
54
|
+
command.addArg(dest);
|
|
56
55
|
}
|
|
57
|
-
// Add template type flag
|
|
58
56
|
if (templateType) {
|
|
59
|
-
command
|
|
57
|
+
command.addFlag('template-type', templateType);
|
|
60
58
|
}
|
|
61
59
|
try {
|
|
62
|
-
const { stdout, stderr } = await
|
|
60
|
+
const { stdout, stderr } = await this.runCommand(absoluteCurrentWorkingDirectory, command, extra);
|
|
63
61
|
return formatTextContents(stdout, stderr);
|
|
64
62
|
}
|
|
65
63
|
catch (error) {
|
|
@@ -81,6 +79,6 @@ export class HsCreateTemplateTool extends Tool {
|
|
|
81
79
|
idempotentHint: false,
|
|
82
80
|
openWorldHint: false,
|
|
83
81
|
},
|
|
84
|
-
}, input => this.wrappedHandler(input));
|
|
82
|
+
}, (input, extra) => this.wrappedHandler(input, extra));
|
|
85
83
|
}
|
|
86
84
|
}
|
|
@@ -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';
|
|
@@ -14,7 +14,7 @@ declare const inputSchemaZodObject: z.ZodObject<{
|
|
|
14
14
|
export type HsFunctionLogsInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
15
15
|
export declare class HsFunctionLogsTool extends Tool<HsFunctionLogsInputSchema> {
|
|
16
16
|
constructor(mcpServer: McpServer, logger: McpLogger);
|
|
17
|
-
handler({ endpoint, account, latest, compact, limit, absoluteCurrentWorkingDirectory, }: HsFunctionLogsInputSchema): Promise<TextContentResponse>;
|
|
17
|
+
handler({ endpoint, account, latest, compact, limit, absoluteCurrentWorkingDirectory, }: HsFunctionLogsInputSchema, extra?: ToolExtra): Promise<TextContentResponse>;
|
|
18
18
|
register(): RegisteredTool;
|
|
19
19
|
}
|
|
20
20
|
export {};
|