@hubspot/cli 7.7.7-experimental.0 → 7.7.9-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/mcp/setup.d.ts +1 -2
- package/commands/mcp/setup.js +67 -56
- package/commands/mcp/start.d.ts +1 -2
- package/commands/mcp/start.js +25 -26
- package/commands/mcp.d.ts +3 -10
- package/commands/mcp.js +16 -11
- package/lang/en.d.ts +44 -0
- package/lang/en.js +44 -0
- package/mcp-server/tools/index.js +5 -5
- package/mcp-server/tools/project/AddFeatureToProject.d.ts +27 -4
- package/mcp-server/tools/project/AddFeatureToProject.js +91 -83
- package/mcp-server/tools/project/CreateProjectTool.d.ts +33 -4
- package/mcp-server/tools/project/CreateProjectTool.js +107 -102
- package/mcp-server/tools/project/DeployProject.d.ts +18 -4
- package/mcp-server/tools/project/DeployProject.js +42 -35
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +15 -4
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +41 -24
- package/mcp-server/tools/project/UploadProjectTools.d.ts +15 -3
- package/mcp-server/tools/project/UploadProjectTools.js +27 -14
- package/mcp-server/types.d.ts +9 -3
- package/mcp-server/types.js +11 -1
- package/package.json +1 -1
package/commands/mcp/setup.d.ts
CHANGED
|
@@ -2,12 +2,11 @@ import { ArgumentsCamelCase, Argv } from 'yargs';
|
|
|
2
2
|
interface MCPSetupArgs {
|
|
3
3
|
targets?: string[];
|
|
4
4
|
}
|
|
5
|
-
declare function builder(yargs: Argv): Argv;
|
|
6
5
|
declare function handler(argv: ArgumentsCamelCase<MCPSetupArgs>): Promise<void>;
|
|
7
6
|
declare const _default: {
|
|
8
7
|
command: string[];
|
|
9
8
|
describe: undefined;
|
|
10
|
-
builder:
|
|
9
|
+
builder: (yargs: Argv) => Promise<Argv<{}>>;
|
|
11
10
|
handler: typeof handler;
|
|
12
11
|
};
|
|
13
12
|
export default _default;
|
package/commands/mcp/setup.js
CHANGED
|
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
7
6
|
const child_process_1 = require("child_process");
|
|
8
7
|
const util_1 = require("util");
|
|
9
8
|
const path_1 = __importDefault(require("path"));
|
|
@@ -12,35 +11,45 @@ const os_1 = __importDefault(require("os"));
|
|
|
12
11
|
const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"));
|
|
13
12
|
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
14
13
|
const promptUtils_1 = require("../../lib/prompts/promptUtils");
|
|
15
|
-
const
|
|
14
|
+
const yargsUtils_1 = require("../../lib/yargsUtils");
|
|
15
|
+
const en_1 = require("../../lang/en");
|
|
16
|
+
const errorHandlers_1 = require("../../lib/errorHandlers");
|
|
17
|
+
const logger_1 = require("../../lib/ui/logger");
|
|
16
18
|
const command = ['setup', 'update'];
|
|
17
|
-
const describe = undefined;
|
|
19
|
+
const describe = undefined; // Leave hidden for now
|
|
18
20
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
21
|
+
const claudeCode = 'claude-code';
|
|
22
|
+
const claudeDesktop = 'claude-desktop';
|
|
23
|
+
const cursor = 'cursor';
|
|
24
|
+
const mcpServerName = 'hubspot-cli-mcp';
|
|
19
25
|
const supportedTools = [
|
|
20
|
-
{ name:
|
|
21
|
-
{ name:
|
|
22
|
-
{ name:
|
|
26
|
+
{ name: en_1.commands.mcp.setup.claudeCode, value: claudeCode },
|
|
27
|
+
// { name: commands.mcp.setup.claudeDesktop, value: claudeDesktop },
|
|
28
|
+
{ name: en_1.commands.mcp.setup.cursor, value: cursor },
|
|
23
29
|
];
|
|
24
|
-
|
|
30
|
+
const hsCommand = 'hs';
|
|
31
|
+
const mcpCommandArgs = ['mcp', 'start'];
|
|
32
|
+
function setupBuilder(yargs) {
|
|
25
33
|
yargs.option('targets', {
|
|
26
|
-
describe:
|
|
34
|
+
describe: en_1.commands.mcp.setup.args.targets,
|
|
27
35
|
type: 'array',
|
|
28
36
|
choices: [...supportedTools.map(tool => tool.value)],
|
|
29
37
|
});
|
|
30
38
|
return yargs;
|
|
31
39
|
}
|
|
40
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(setupBuilder, command, describe, {
|
|
41
|
+
useGlobalOptions: true,
|
|
42
|
+
});
|
|
32
43
|
async function handler(argv) {
|
|
33
|
-
const mcpsdk = '@modelcontextprotocol/sdk';
|
|
34
44
|
try {
|
|
35
|
-
await import(
|
|
45
|
+
await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
36
46
|
}
|
|
37
47
|
catch (e) {
|
|
38
|
-
logger_1.
|
|
48
|
+
logger_1.uiLogger.error(en_1.commands.mcp.setup.errors.needsNode20);
|
|
39
49
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
40
50
|
}
|
|
41
51
|
await addMcpServerToConfig(argv.targets);
|
|
42
52
|
}
|
|
43
|
-
exports.default = { command, describe, builder, handler };
|
|
44
53
|
async function addMcpServerToConfig(targets) {
|
|
45
54
|
try {
|
|
46
55
|
let derivedTargets = [];
|
|
@@ -48,10 +57,12 @@ async function addMcpServerToConfig(targets) {
|
|
|
48
57
|
const { selectedTargets } = await (0, promptUtils_1.promptUser)({
|
|
49
58
|
name: 'selectedTargets',
|
|
50
59
|
type: 'checkbox',
|
|
51
|
-
message:
|
|
60
|
+
message: en_1.commands.mcp.setup.prompts.targets,
|
|
52
61
|
choices: supportedTools,
|
|
53
62
|
validate: (choices) => {
|
|
54
|
-
return choices.length === 0
|
|
63
|
+
return choices.length === 0
|
|
64
|
+
? en_1.commands.mcp.setup.prompts.targetsRequired
|
|
65
|
+
: true;
|
|
55
66
|
},
|
|
56
67
|
});
|
|
57
68
|
derivedTargets = selectedTargets;
|
|
@@ -60,22 +71,22 @@ async function addMcpServerToConfig(targets) {
|
|
|
60
71
|
derivedTargets = targets;
|
|
61
72
|
}
|
|
62
73
|
SpinniesManager_1.default.init();
|
|
63
|
-
if (derivedTargets.includes(
|
|
74
|
+
if (derivedTargets.includes(claudeDesktop)) {
|
|
64
75
|
await runSetupFunction(setupClaudeDesktop);
|
|
65
76
|
}
|
|
66
|
-
if (derivedTargets.includes(
|
|
77
|
+
if (derivedTargets.includes(claudeCode)) {
|
|
67
78
|
await runSetupFunction(setupClaudeCode);
|
|
68
79
|
}
|
|
69
|
-
if (derivedTargets.includes(
|
|
80
|
+
if (derivedTargets.includes(cursor)) {
|
|
70
81
|
await runSetupFunction(setupCursor);
|
|
71
82
|
}
|
|
72
|
-
logger_1.
|
|
83
|
+
logger_1.uiLogger.info(en_1.commands.mcp.setup.success(derivedTargets));
|
|
73
84
|
}
|
|
74
85
|
catch (error) {
|
|
75
86
|
SpinniesManager_1.default.fail('mcpSetup', {
|
|
76
|
-
text:
|
|
87
|
+
text: en_1.commands.mcp.setup.spinners.failedToConfigure,
|
|
77
88
|
});
|
|
78
|
-
|
|
89
|
+
(0, errorHandlers_1.logError)(error);
|
|
79
90
|
}
|
|
80
91
|
}
|
|
81
92
|
async function runSetupFunction(func) {
|
|
@@ -88,55 +99,56 @@ async function setupClaudeDesktop() {
|
|
|
88
99
|
try {
|
|
89
100
|
const configPath = getClaudeDesktopConfigPath();
|
|
90
101
|
SpinniesManager_1.default.add('claudeDesktop', {
|
|
91
|
-
text:
|
|
102
|
+
text: en_1.commands.mcp.setup.spinners.configuringClaudeDesktop,
|
|
92
103
|
});
|
|
93
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
104
|
let config = {};
|
|
95
105
|
// Read existing config if it exists
|
|
96
106
|
if (fs_1.default.existsSync(configPath)) {
|
|
97
107
|
try {
|
|
98
108
|
const configContent = fs_1.default.readFileSync(configPath, 'utf8');
|
|
99
109
|
config = JSON.parse(configContent);
|
|
100
|
-
logger_1.logger.debug(`Found existing Claude Desktop config at ${configPath}`);
|
|
101
110
|
}
|
|
102
111
|
catch (error) {
|
|
103
|
-
|
|
112
|
+
SpinniesManager_1.default.fail('claudeDesktop', {
|
|
113
|
+
text: en_1.commands.mcp.setup.spinners.failedToConfigureClaudeDesktop,
|
|
114
|
+
});
|
|
115
|
+
(0, errorHandlers_1.logError)(error);
|
|
116
|
+
return false;
|
|
104
117
|
}
|
|
105
118
|
}
|
|
106
119
|
else {
|
|
107
120
|
// Create config directory if it doesn't exist
|
|
108
121
|
const configDir = path_1.default.dirname(configPath);
|
|
109
122
|
fs_1.default.mkdirSync(configDir, { recursive: true });
|
|
110
|
-
logger_1.logger.debug(`Created Claude Desktop config directory at ${configDir}`);
|
|
111
123
|
}
|
|
112
124
|
// Initialize mcpServers if it doesn't exist
|
|
113
125
|
if (!config.mcpServers) {
|
|
114
126
|
config.mcpServers = {};
|
|
115
127
|
}
|
|
116
128
|
// Add or update HubSpot CLI MCP server
|
|
117
|
-
config.mcpServers[
|
|
118
|
-
command:
|
|
119
|
-
args:
|
|
129
|
+
config.mcpServers[mcpServerName] = {
|
|
130
|
+
command: hsCommand,
|
|
131
|
+
args: mcpCommandArgs,
|
|
120
132
|
};
|
|
121
133
|
// Write the updated config
|
|
122
134
|
fs_1.default.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
123
135
|
SpinniesManager_1.default.succeed('claudeDesktop', {
|
|
124
|
-
text:
|
|
136
|
+
text: en_1.commands.mcp.setup.spinners.configuredClaudeDesktop,
|
|
125
137
|
});
|
|
126
138
|
return true;
|
|
127
139
|
}
|
|
128
140
|
catch (error) {
|
|
129
141
|
SpinniesManager_1.default.fail('claudeDesktop', {
|
|
130
|
-
text:
|
|
142
|
+
text: en_1.commands.mcp.setup.spinners.failedToConfigureClaudeDesktop,
|
|
131
143
|
});
|
|
132
|
-
|
|
144
|
+
(0, errorHandlers_1.logError)(error);
|
|
133
145
|
return false;
|
|
134
146
|
}
|
|
135
147
|
}
|
|
136
148
|
async function setupClaudeCode() {
|
|
137
149
|
try {
|
|
138
150
|
SpinniesManager_1.default.add('claudeCode', {
|
|
139
|
-
text:
|
|
151
|
+
text: en_1.commands.mcp.setup.spinners.configuringClaudeCode,
|
|
140
152
|
});
|
|
141
153
|
try {
|
|
142
154
|
// Check if claude command is available
|
|
@@ -144,19 +156,19 @@ async function setupClaudeCode() {
|
|
|
144
156
|
// Run claude mcp add command
|
|
145
157
|
const mcpConfig = JSON.stringify({
|
|
146
158
|
type: 'stdio',
|
|
147
|
-
command:
|
|
148
|
-
args:
|
|
159
|
+
command: hsCommand,
|
|
160
|
+
args: mcpCommandArgs,
|
|
149
161
|
});
|
|
150
162
|
const { stdout } = await execAsync('claude mcp list');
|
|
151
|
-
if (stdout.includes(
|
|
163
|
+
if (stdout.includes(mcpServerName)) {
|
|
152
164
|
SpinniesManager_1.default.update('claudeCode', {
|
|
153
|
-
text:
|
|
165
|
+
text: en_1.commands.mcp.setup.spinners.alreadyInstalled,
|
|
154
166
|
});
|
|
155
|
-
await execAsync(
|
|
167
|
+
await execAsync(`claude mcp remove "${mcpServerName}" --scope user`);
|
|
156
168
|
}
|
|
157
|
-
await execAsync(`claude mcp add-json "
|
|
169
|
+
await execAsync(`claude mcp add-json "${mcpServerName}" '${mcpConfig}' --scope user`);
|
|
158
170
|
SpinniesManager_1.default.succeed('claudeCode', {
|
|
159
|
-
text:
|
|
171
|
+
text: en_1.commands.mcp.setup.spinners.configuredClaudeCode,
|
|
160
172
|
});
|
|
161
173
|
return true;
|
|
162
174
|
}
|
|
@@ -164,38 +176,36 @@ async function setupClaudeCode() {
|
|
|
164
176
|
if (error instanceof Error &&
|
|
165
177
|
error.message.includes('claude: command not found')) {
|
|
166
178
|
SpinniesManager_1.default.fail('claudeCode', {
|
|
167
|
-
text:
|
|
179
|
+
text: en_1.commands.mcp.setup.spinners.claudeCodeNotFound,
|
|
168
180
|
});
|
|
169
|
-
logger_1.logger.info(' Install Claude Code CLI to enable this configuration');
|
|
170
181
|
}
|
|
171
182
|
else {
|
|
172
183
|
SpinniesManager_1.default.fail('claudeCode', {
|
|
173
|
-
text:
|
|
184
|
+
text: en_1.commands.mcp.setup.spinners.claudeCodeInstallFailed,
|
|
174
185
|
});
|
|
175
|
-
|
|
186
|
+
(0, errorHandlers_1.logError)(error);
|
|
176
187
|
}
|
|
177
188
|
return false;
|
|
178
189
|
}
|
|
179
190
|
}
|
|
180
191
|
catch (error) {
|
|
181
192
|
SpinniesManager_1.default.fail('claudeCode', {
|
|
182
|
-
text:
|
|
193
|
+
text: en_1.commands.mcp.setup.spinners.claudeCodeInstallFailed,
|
|
183
194
|
});
|
|
184
|
-
|
|
195
|
+
(0, errorHandlers_1.logError)(error);
|
|
185
196
|
return false;
|
|
186
197
|
}
|
|
187
198
|
}
|
|
188
199
|
async function setupCursor() {
|
|
189
200
|
try {
|
|
190
201
|
SpinniesManager_1.default.add('cursor', {
|
|
191
|
-
text:
|
|
202
|
+
text: en_1.commands.mcp.setup.spinners.configuringCursor,
|
|
192
203
|
});
|
|
193
204
|
const cursorConfigPath = path_1.default.join(os_1.default.homedir(), '.cursor', 'mcp.json');
|
|
194
205
|
if (!fs_1.default.existsSync(cursorConfigPath)) {
|
|
195
206
|
SpinniesManager_1.default.succeed('cursor', {
|
|
196
|
-
text:
|
|
207
|
+
text: en_1.commands.mcp.setup.spinners.noCursorMcpFile(cursorConfigPath),
|
|
197
208
|
});
|
|
198
|
-
logger_1.logger.info(' Create a .cursor/mcp.json file in your project to enable Cursor MCP support');
|
|
199
209
|
return false;
|
|
200
210
|
}
|
|
201
211
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -204,32 +214,32 @@ async function setupCursor() {
|
|
|
204
214
|
try {
|
|
205
215
|
const configContent = fs_1.default.readFileSync(cursorConfigPath, 'utf8');
|
|
206
216
|
config = JSON.parse(configContent);
|
|
207
|
-
logger_1.logger.debug(`Found existing Cursor config at ${cursorConfigPath}`);
|
|
208
217
|
}
|
|
209
218
|
catch (error) {
|
|
210
|
-
|
|
219
|
+
(0, errorHandlers_1.logError)(error);
|
|
220
|
+
return false;
|
|
211
221
|
}
|
|
212
222
|
// Initialize mcpServers if it doesn't exist
|
|
213
223
|
if (!config.mcpServers) {
|
|
214
224
|
config.mcpServers = {};
|
|
215
225
|
}
|
|
216
226
|
// Add or update HubSpot CLI MCP server
|
|
217
|
-
config.mcpServers[
|
|
218
|
-
command:
|
|
219
|
-
args:
|
|
227
|
+
config.mcpServers[mcpServerName] = {
|
|
228
|
+
command: hsCommand,
|
|
229
|
+
args: mcpCommandArgs,
|
|
220
230
|
};
|
|
221
231
|
// Write the updated config
|
|
222
232
|
fs_1.default.writeFileSync(cursorConfigPath, JSON.stringify(config, null, 2));
|
|
223
233
|
SpinniesManager_1.default.succeed('cursor', {
|
|
224
|
-
text:
|
|
234
|
+
text: en_1.commands.mcp.setup.spinners.configuredCursor,
|
|
225
235
|
});
|
|
226
236
|
return true;
|
|
227
237
|
}
|
|
228
238
|
catch (error) {
|
|
229
239
|
SpinniesManager_1.default.fail('cursor', {
|
|
230
|
-
text:
|
|
240
|
+
text: en_1.commands.mcp.setup.spinners.failedToConfigure,
|
|
231
241
|
});
|
|
232
|
-
|
|
242
|
+
(0, errorHandlers_1.logError)(error);
|
|
233
243
|
return false;
|
|
234
244
|
}
|
|
235
245
|
}
|
|
@@ -244,3 +254,4 @@ function getClaudeDesktopConfigPath() {
|
|
|
244
254
|
return path_1.default.join(homeDir, '.config', 'claude', 'claude_desktop_config.json');
|
|
245
255
|
}
|
|
246
256
|
}
|
|
257
|
+
exports.default = { command, describe, builder, handler };
|
package/commands/mcp/start.d.ts
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { Argv } from 'yargs';
|
|
2
|
-
declare function builder(yargs: Argv): Argv;
|
|
3
2
|
declare function handler(): Promise<void>;
|
|
4
3
|
declare const _default: {
|
|
5
4
|
command: string;
|
|
6
5
|
describe: undefined;
|
|
7
|
-
builder:
|
|
6
|
+
builder: (yargs: Argv) => Promise<Argv<{}>>;
|
|
8
7
|
handler: typeof handler;
|
|
9
8
|
};
|
|
10
9
|
export default _default;
|
package/commands/mcp/start.js
CHANGED
|
@@ -3,40 +3,42 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
7
6
|
const child_process_1 = require("child_process");
|
|
8
7
|
const path_1 = __importDefault(require("path"));
|
|
9
8
|
const fs_1 = __importDefault(require("fs"));
|
|
10
9
|
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
10
|
+
const yargsUtils_1 = require("../../lib/yargsUtils");
|
|
11
|
+
const logger_1 = require("../../lib/ui/logger");
|
|
12
|
+
const errorHandlers_1 = require("../../lib/errorHandlers");
|
|
13
|
+
const en_1 = require("../../lang/en");
|
|
11
14
|
const command = 'start';
|
|
12
|
-
const describe = undefined; //
|
|
13
|
-
function
|
|
15
|
+
const describe = undefined; // Leave hidden for now
|
|
16
|
+
function startBuilder(yargs) {
|
|
14
17
|
return yargs;
|
|
15
18
|
}
|
|
19
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(startBuilder, command, describe, {
|
|
20
|
+
useGlobalOptions: true,
|
|
21
|
+
});
|
|
16
22
|
async function handler() {
|
|
17
|
-
const mcpsdk = '@modelcontextprotocol/sdk';
|
|
18
23
|
try {
|
|
19
|
-
await import(
|
|
24
|
+
await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
20
25
|
}
|
|
21
26
|
catch (e) {
|
|
22
|
-
logger_1.
|
|
27
|
+
logger_1.uiLogger.error(en_1.commands.mcp.start.errors.needsNode20);
|
|
23
28
|
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
24
29
|
}
|
|
25
30
|
await startMcpServer();
|
|
26
31
|
}
|
|
27
|
-
exports.default = { command, describe, builder, handler };
|
|
28
32
|
async function startMcpServer() {
|
|
29
33
|
try {
|
|
30
34
|
const serverPath = path_1.default.join(__dirname, '..', '..', 'mcp-server', 'server.js');
|
|
31
35
|
// Check if server file exists
|
|
32
36
|
if (!fs_1.default.existsSync(serverPath)) {
|
|
33
|
-
logger_1.
|
|
37
|
+
logger_1.uiLogger.error(en_1.commands.mcp.start.errors.serverFileNotFound(serverPath));
|
|
34
38
|
return;
|
|
35
39
|
}
|
|
36
|
-
logger_1.
|
|
37
|
-
logger_1.
|
|
38
|
-
logger_1.logger.info('The server will run in stdio mode for MCP client connections');
|
|
39
|
-
logger_1.logger.info('Press Ctrl+C to stop the server');
|
|
40
|
+
logger_1.uiLogger.info(en_1.commands.mcp.start.startingServer);
|
|
41
|
+
logger_1.uiLogger.info(en_1.commands.mcp.start.stopInstructions);
|
|
40
42
|
// Start the server using ts-node
|
|
41
43
|
const child = (0, child_process_1.spawn)('node', [serverPath], {
|
|
42
44
|
stdio: 'inherit',
|
|
@@ -46,30 +48,27 @@ async function startMcpServer() {
|
|
|
46
48
|
});
|
|
47
49
|
// Handle server process events
|
|
48
50
|
child.on('error', error => {
|
|
49
|
-
|
|
50
|
-
logger_1.
|
|
51
|
+
(0, errorHandlers_1.logError)(error);
|
|
52
|
+
logger_1.uiLogger.error(en_1.commands.mcp.start.errors.failedToStart);
|
|
51
53
|
});
|
|
52
|
-
child.on('close',
|
|
53
|
-
|
|
54
|
-
logger_1.logger.info('MCP server stopped gracefully');
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
logger_1.logger.error(`MCP server exited with code ${code}`);
|
|
58
|
-
}
|
|
54
|
+
child.on('close', () => {
|
|
55
|
+
logger_1.uiLogger.info(en_1.commands.mcp.start.stoppedSuccessfully);
|
|
59
56
|
});
|
|
60
57
|
// Handle graceful shutdown
|
|
61
58
|
process.on('SIGINT', () => {
|
|
62
|
-
logger_1.
|
|
59
|
+
logger_1.uiLogger.info(en_1.commands.mcp.start.shuttingDown);
|
|
63
60
|
child.kill('SIGTERM');
|
|
64
|
-
process.exit(
|
|
61
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
65
62
|
});
|
|
66
63
|
process.on('SIGTERM', () => {
|
|
67
|
-
logger_1.
|
|
64
|
+
logger_1.uiLogger.info(en_1.commands.mcp.start.shuttingDown);
|
|
68
65
|
child.kill('SIGTERM');
|
|
69
|
-
process.exit(
|
|
66
|
+
process.exit(exitCodes_1.EXIT_CODES.SUCCESS);
|
|
70
67
|
});
|
|
71
68
|
}
|
|
72
69
|
catch (error) {
|
|
73
|
-
logger_1.
|
|
70
|
+
logger_1.uiLogger.error(en_1.commands.mcp.start.errors.failedToStart);
|
|
71
|
+
(0, errorHandlers_1.logError)(error);
|
|
74
72
|
}
|
|
75
73
|
}
|
|
74
|
+
exports.default = { command, describe, builder, handler };
|
package/commands/mcp.d.ts
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
declare
|
|
3
|
-
|
|
4
|
-
declare const _default: {
|
|
5
|
-
command: string;
|
|
6
|
-
describe: string;
|
|
7
|
-
builder: typeof builder;
|
|
8
|
-
handler: typeof handler;
|
|
9
|
-
};
|
|
10
|
-
export default _default;
|
|
1
|
+
import { YargsCommandModuleBucket } from '../types/Yargs';
|
|
2
|
+
declare const mcpCommand: YargsCommandModuleBucket;
|
|
3
|
+
export default mcpCommand;
|
package/commands/mcp.js
CHANGED
|
@@ -5,16 +5,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const start_1 = __importDefault(require("./mcp/start"));
|
|
7
7
|
const setup_1 = __importDefault(require("./mcp/setup"));
|
|
8
|
+
const yargsUtils_1 = require("../lib/yargsUtils");
|
|
8
9
|
const command = 'mcp';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
.demandCommand(1, 'You must specify a subcommand')
|
|
15
|
-
.help();
|
|
10
|
+
// Leave this as undefined to hide the command
|
|
11
|
+
const describe = undefined;
|
|
12
|
+
function mcpBuilder(yargs) {
|
|
13
|
+
yargs.command(start_1.default).command(setup_1.default).demandCommand(1, '');
|
|
14
|
+
return yargs;
|
|
16
15
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
16
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(mcpBuilder, command, describe, {
|
|
17
|
+
useGlobalOptions: true,
|
|
18
|
+
});
|
|
19
|
+
const mcpCommand = {
|
|
20
|
+
command,
|
|
21
|
+
describe,
|
|
22
|
+
builder,
|
|
23
|
+
handler: () => { },
|
|
24
|
+
};
|
|
25
|
+
exports.default = mcpCommand;
|
package/lang/en.d.ts
CHANGED
|
@@ -764,6 +764,50 @@ Global configuration replaces hubspot.config.yml, and you will be prompted to mi
|
|
|
764
764
|
};
|
|
765
765
|
readonly tailLogs: (functionPath: string, accountId: string) => string;
|
|
766
766
|
};
|
|
767
|
+
readonly mcp: {
|
|
768
|
+
readonly setup: {
|
|
769
|
+
readonly claudeCode: "Claude Code";
|
|
770
|
+
readonly claudeDesktop: "Claude Desktop";
|
|
771
|
+
readonly cursor: "Cursor";
|
|
772
|
+
readonly args: {
|
|
773
|
+
readonly targets: "Target applications to configure";
|
|
774
|
+
};
|
|
775
|
+
readonly success: (derivedTargets: string[]) => string;
|
|
776
|
+
readonly errors: {
|
|
777
|
+
readonly needsNode20: "This feature requires node >=20";
|
|
778
|
+
};
|
|
779
|
+
readonly spinners: {
|
|
780
|
+
readonly failedToConfigure: "Failed to configure the HubSpot mcp server.";
|
|
781
|
+
readonly configuringClaudeDesktop: "Configuring Claude Desktop...";
|
|
782
|
+
readonly configuredClaudeDesktop: "Configured Claude Desktop";
|
|
783
|
+
readonly configuringClaudeCode: "Configuring Claude Code...";
|
|
784
|
+
readonly configuredClaudeCode: "Configured Claude Code";
|
|
785
|
+
readonly claudeCodeNotFound: "Claude Code not found - skipping configuration";
|
|
786
|
+
readonly claudeCodeInstallFailed: "Claude Code CLI not working - skipping configuration";
|
|
787
|
+
readonly failedToConfigureClaudeDesktop: "Failed to configure Claude Desktop";
|
|
788
|
+
readonly configuringCursor: "Configuring Cursor...";
|
|
789
|
+
readonly noCursorMcpFile: (configFile: string) => string;
|
|
790
|
+
readonly failedToConfigureCursor: "Failed to configure Cursor";
|
|
791
|
+
readonly configuredCursor: "Configured Cursor";
|
|
792
|
+
readonly alreadyInstalled: "HubSpot CLI mcp server already installed, reinstalling";
|
|
793
|
+
};
|
|
794
|
+
readonly prompts: {
|
|
795
|
+
readonly targets: "[--targets] Which tools would you like to add the HubSpot CLI MCP server to?";
|
|
796
|
+
readonly targetsRequired: "Must choose at least one application to configure.";
|
|
797
|
+
};
|
|
798
|
+
};
|
|
799
|
+
readonly start: {
|
|
800
|
+
readonly errors: {
|
|
801
|
+
readonly needsNode20: "This feature requires node >=20";
|
|
802
|
+
readonly serverFileNotFound: (serverPath: string) => string;
|
|
803
|
+
readonly failedToStart: "Failed to start MCP server";
|
|
804
|
+
};
|
|
805
|
+
readonly startingServer: "Starting HubSpot CLI MCP server...";
|
|
806
|
+
readonly stopInstructions: "Press Ctrl+C to stop the server";
|
|
807
|
+
readonly stoppedSuccessfully: "Stopped successfully.";
|
|
808
|
+
readonly shuttingDown: "Shutting down MCP server...";
|
|
809
|
+
};
|
|
810
|
+
};
|
|
767
811
|
readonly mv: {
|
|
768
812
|
readonly describe: "Move a remote file or folder in HubSpot. This feature is currently in beta and the CLI contract is subject to change.";
|
|
769
813
|
readonly errors: {
|
package/lang/en.js
CHANGED
|
@@ -776,6 +776,50 @@ exports.commands = {
|
|
|
776
776
|
},
|
|
777
777
|
tailLogs: (functionPath, accountId) => `Waiting for log entries for "${functionPath}" on account "${accountId}".\n`,
|
|
778
778
|
},
|
|
779
|
+
mcp: {
|
|
780
|
+
setup: {
|
|
781
|
+
claudeCode: 'Claude Code',
|
|
782
|
+
claudeDesktop: 'Claude Desktop',
|
|
783
|
+
cursor: 'Cursor',
|
|
784
|
+
args: {
|
|
785
|
+
targets: 'Target applications to configure',
|
|
786
|
+
},
|
|
787
|
+
success: (derivedTargets) => `You can now use the HubSpot CLI tools in ${derivedTargets.join(', ')}. ${chalk_1.default.bold('You may need to restart these tools to apply the changes')}.`,
|
|
788
|
+
errors: {
|
|
789
|
+
needsNode20: `This feature requires node >=20`,
|
|
790
|
+
},
|
|
791
|
+
spinners: {
|
|
792
|
+
failedToConfigure: 'Failed to configure the HubSpot mcp server.',
|
|
793
|
+
configuringClaudeDesktop: 'Configuring Claude Desktop...',
|
|
794
|
+
configuredClaudeDesktop: 'Configured Claude Desktop',
|
|
795
|
+
configuringClaudeCode: 'Configuring Claude Code...',
|
|
796
|
+
configuredClaudeCode: 'Configured Claude Code',
|
|
797
|
+
claudeCodeNotFound: 'Claude Code not found - skipping configuration',
|
|
798
|
+
claudeCodeInstallFailed: 'Claude Code CLI not working - skipping configuration',
|
|
799
|
+
failedToConfigureClaudeDesktop: 'Failed to configure Claude Desktop',
|
|
800
|
+
configuringCursor: 'Configuring Cursor...',
|
|
801
|
+
noCursorMcpFile: (configFile) => `No ${configFile} file found - skipping Cursor configuration`,
|
|
802
|
+
failedToConfigureCursor: 'Failed to configure Cursor',
|
|
803
|
+
configuredCursor: 'Configured Cursor',
|
|
804
|
+
alreadyInstalled: 'HubSpot CLI mcp server already installed, reinstalling',
|
|
805
|
+
},
|
|
806
|
+
prompts: {
|
|
807
|
+
targets: '[--targets] Which tools would you like to add the HubSpot CLI MCP server to?',
|
|
808
|
+
targetsRequired: 'Must choose at least one application to configure.',
|
|
809
|
+
},
|
|
810
|
+
},
|
|
811
|
+
start: {
|
|
812
|
+
errors: {
|
|
813
|
+
needsNode20: `This feature requires node >=20`,
|
|
814
|
+
serverFileNotFound: (serverPath) => `MCP server file not found at ${serverPath}`,
|
|
815
|
+
failedToStart: 'Failed to start MCP server',
|
|
816
|
+
},
|
|
817
|
+
startingServer: 'Starting HubSpot CLI MCP server...',
|
|
818
|
+
stopInstructions: 'Press Ctrl+C to stop the server',
|
|
819
|
+
stoppedSuccessfully: 'Stopped successfully.',
|
|
820
|
+
shuttingDown: 'Shutting down MCP server...',
|
|
821
|
+
},
|
|
822
|
+
},
|
|
779
823
|
mv: {
|
|
780
824
|
describe: 'Move a remote file or folder in HubSpot. This feature is currently in beta and the CLI contract is subject to change.',
|
|
781
825
|
errors: {
|
|
@@ -8,10 +8,10 @@ const DeployProject_1 = require("./project/DeployProject");
|
|
|
8
8
|
const AddFeatureToProject_1 = require("./project/AddFeatureToProject");
|
|
9
9
|
function registerProjectTools(mcpServer) {
|
|
10
10
|
return [
|
|
11
|
-
UploadProjectTools_1.UploadProjectTools.register(
|
|
12
|
-
CreateProjectTool_1.CreateProjectTool.register(
|
|
13
|
-
GuidedWalkthroughTool_1.GuidedWalkthroughTool.register(
|
|
14
|
-
DeployProject_1.DeployProject.register(
|
|
15
|
-
AddFeatureToProject_1.AddFeatureToProject.register(
|
|
11
|
+
new UploadProjectTools_1.UploadProjectTools(mcpServer).register(),
|
|
12
|
+
new CreateProjectTool_1.CreateProjectTool(mcpServer).register(),
|
|
13
|
+
new GuidedWalkthroughTool_1.GuidedWalkthroughTool(mcpServer).register(),
|
|
14
|
+
new DeployProject_1.DeployProject(mcpServer).register(),
|
|
15
|
+
new AddFeatureToProject_1.AddFeatureToProject(mcpServer).register(),
|
|
16
16
|
];
|
|
17
17
|
}
|
|
@@ -1,6 +1,29 @@
|
|
|
1
|
-
import { Tool } from '../../types';
|
|
1
|
+
import { TextContentResponse, Tool } from '../../types';
|
|
2
2
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteProjectPath: z.ZodString;
|
|
6
|
+
addApp: z.ZodBoolean;
|
|
7
|
+
distribution: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"marketplace">, z.ZodLiteral<"private">]>>;
|
|
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">]>, "many">>;
|
|
10
|
+
}, "strip", z.ZodTypeAny, {
|
|
11
|
+
absoluteProjectPath: string;
|
|
12
|
+
addApp: boolean;
|
|
13
|
+
auth?: "oauth" | "static" | undefined;
|
|
14
|
+
distribution?: "marketplace" | "private" | undefined;
|
|
15
|
+
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
16
|
+
}, {
|
|
17
|
+
absoluteProjectPath: string;
|
|
18
|
+
addApp: boolean;
|
|
19
|
+
auth?: "oauth" | "static" | undefined;
|
|
20
|
+
distribution?: "marketplace" | "private" | undefined;
|
|
21
|
+
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
22
|
+
}>;
|
|
23
|
+
export type AddFeatureInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
24
|
+
export declare class AddFeatureToProject extends Tool<AddFeatureInputSchema> {
|
|
25
|
+
constructor(mcpServer: McpServer);
|
|
26
|
+
handler({ absoluteProjectPath, distribution, auth, features, addApp, }: AddFeatureInputSchema): Promise<TextContentResponse>;
|
|
27
|
+
register(): RegisteredTool;
|
|
6
28
|
}
|
|
29
|
+
export {};
|