@hubspot/cli 7.7.6-experimental.0 → 7.7.8-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 +16 -5
- package/commands/mcp/start.d.ts +1 -2
- package/commands/mcp/start.js +15 -3
- package/commands/mcp.d.ts +3 -10
- package/commands/mcp.js +14 -10
- 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 +89 -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 +3 -3
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
|
@@ -13,15 +13,16 @@ const SpinniesManager_1 = __importDefault(require("../../lib/ui/SpinniesManager"
|
|
|
13
13
|
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
14
14
|
const promptUtils_1 = require("../../lib/prompts/promptUtils");
|
|
15
15
|
const chalk_1 = __importDefault(require("chalk"));
|
|
16
|
+
const yargsUtils_1 = require("../../lib/yargsUtils");
|
|
16
17
|
const command = ['setup', 'update'];
|
|
17
|
-
const describe = undefined;
|
|
18
|
+
const describe = undefined; // Leave hidden for now
|
|
18
19
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
19
20
|
const supportedTools = [
|
|
20
21
|
{ name: 'Claude', value: 'claude' },
|
|
21
22
|
{ name: 'Claude Desktop', value: 'claude-desktop' },
|
|
22
23
|
{ name: 'Cursor', value: 'cursor' },
|
|
23
24
|
];
|
|
24
|
-
function
|
|
25
|
+
function setupBuilder(yargs) {
|
|
25
26
|
yargs.option('targets', {
|
|
26
27
|
describe: 'Target application to configure',
|
|
27
28
|
type: 'array',
|
|
@@ -29,10 +30,19 @@ function builder(yargs) {
|
|
|
29
30
|
});
|
|
30
31
|
return yargs;
|
|
31
32
|
}
|
|
33
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(setupBuilder, command, describe, {
|
|
34
|
+
useGlobalOptions: true,
|
|
35
|
+
});
|
|
32
36
|
async function handler(argv) {
|
|
37
|
+
try {
|
|
38
|
+
await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
logger_1.logger.error(`This feature requires node >=20`);
|
|
42
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
43
|
+
}
|
|
33
44
|
await addMcpServerToConfig(argv.targets);
|
|
34
45
|
}
|
|
35
|
-
exports.default = { command, describe, builder, handler };
|
|
36
46
|
async function addMcpServerToConfig(targets) {
|
|
37
47
|
try {
|
|
38
48
|
let derivedTargets = [];
|
|
@@ -136,8 +146,8 @@ async function setupClaudeCode() {
|
|
|
136
146
|
// Run claude mcp add command
|
|
137
147
|
const mcpConfig = JSON.stringify({
|
|
138
148
|
type: 'stdio',
|
|
139
|
-
command: '
|
|
140
|
-
args: ['mcp', 'start'],
|
|
149
|
+
command: 'yarn',
|
|
150
|
+
args: ['hs', 'mcp', 'start'],
|
|
141
151
|
});
|
|
142
152
|
const { stdout } = await execAsync('claude mcp list');
|
|
143
153
|
if (stdout.includes('hubspot-cli-mcp')) {
|
|
@@ -236,3 +246,4 @@ function getClaudeDesktopConfigPath() {
|
|
|
236
246
|
return path_1.default.join(homeDir, '.config', 'claude', 'claude_desktop_config.json');
|
|
237
247
|
}
|
|
238
248
|
}
|
|
249
|
+
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
|
@@ -7,15 +7,26 @@ const logger_1 = require("@hubspot/local-dev-lib/logger");
|
|
|
7
7
|
const child_process_1 = require("child_process");
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const fs_1 = __importDefault(require("fs"));
|
|
10
|
+
const exitCodes_1 = require("../../lib/enums/exitCodes");
|
|
11
|
+
const yargsUtils_1 = require("../../lib/yargsUtils");
|
|
10
12
|
const command = 'start';
|
|
11
|
-
const describe = undefined; //
|
|
12
|
-
function
|
|
13
|
+
const describe = undefined; // Leave hidden for now
|
|
14
|
+
function startBuilder(yargs) {
|
|
13
15
|
return yargs;
|
|
14
16
|
}
|
|
17
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(startBuilder, command, describe, {
|
|
18
|
+
useGlobalOptions: true,
|
|
19
|
+
});
|
|
15
20
|
async function handler() {
|
|
21
|
+
try {
|
|
22
|
+
await import('@modelcontextprotocol/sdk/server/mcp.js');
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
logger_1.logger.error(`This feature requires node >=20`);
|
|
26
|
+
process.exit(exitCodes_1.EXIT_CODES.ERROR);
|
|
27
|
+
}
|
|
16
28
|
await startMcpServer();
|
|
17
29
|
}
|
|
18
|
-
exports.default = { command, describe, builder, handler };
|
|
19
30
|
async function startMcpServer() {
|
|
20
31
|
try {
|
|
21
32
|
const serverPath = path_1.default.join(__dirname, '..', '..', 'mcp-server', 'server.js');
|
|
@@ -64,3 +75,4 @@ async function startMcpServer() {
|
|
|
64
75
|
logger_1.logger.error('Error starting MCP server:', error);
|
|
65
76
|
}
|
|
66
77
|
}
|
|
78
|
+
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,20 @@ 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
|
const describe = 'Manage the Model Context Protocol server';
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
.command(setup_1.default)
|
|
14
|
-
.demandCommand(1, 'You must specify a subcommand')
|
|
15
|
-
.help();
|
|
11
|
+
function mcpBuilder(yargs) {
|
|
12
|
+
yargs.command(start_1.default).command(setup_1.default).demandCommand(1, '');
|
|
13
|
+
return yargs;
|
|
16
14
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
|
|
15
|
+
const builder = (0, yargsUtils_1.makeYargsBuilder)(mcpBuilder, command, describe, {
|
|
16
|
+
useGlobalOptions: true,
|
|
17
|
+
});
|
|
18
|
+
const mcpCommand = {
|
|
19
|
+
command,
|
|
20
|
+
describe,
|
|
21
|
+
builder,
|
|
22
|
+
handler: () => { },
|
|
23
|
+
};
|
|
24
|
+
exports.default = mcpCommand;
|
|
@@ -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 {};
|
|
@@ -7,94 +7,100 @@ const constants_1 = require("../../../lib/constants");
|
|
|
7
7
|
const command_1 = require("../../utils/command");
|
|
8
8
|
const constants_2 = require("./constants");
|
|
9
9
|
const project_1 = require("../../utils/project");
|
|
10
|
+
const inputSchema = {
|
|
11
|
+
absoluteProjectPath: constants_2.absoluteProjectPath,
|
|
12
|
+
addApp: zod_1.z.boolean().describe('Would you like to add an app?'),
|
|
13
|
+
distribution: zod_1.z
|
|
14
|
+
.optional(zod_1.z.union([
|
|
15
|
+
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE),
|
|
16
|
+
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.PRIVATE),
|
|
17
|
+
]))
|
|
18
|
+
.describe('Private is used if you do not wish to distribute your application on the HubSpot marketplace. If not specified by the user, do not choose for them. This cannot be changed after a project is uploaded.'),
|
|
19
|
+
auth: zod_1.z
|
|
20
|
+
.optional(zod_1.z.union([
|
|
21
|
+
zod_1.z.literal(constants_1.APP_AUTH_TYPES.STATIC),
|
|
22
|
+
zod_1.z.literal(constants_1.APP_AUTH_TYPES.OAUTH),
|
|
23
|
+
]))
|
|
24
|
+
.describe('Static uses a static non changing authentication token, and is only available for private distribution. If not specified by the user, do not choose for them. This cannot be changed after a project is uploaded.'),
|
|
25
|
+
features: zod_1.z
|
|
26
|
+
.array(zod_1.z
|
|
27
|
+
.union([
|
|
28
|
+
zod_1.z.literal('card'),
|
|
29
|
+
zod_1.z.literal('settings'),
|
|
30
|
+
zod_1.z.literal('app-function'),
|
|
31
|
+
zod_1.z.literal('webhooks'),
|
|
32
|
+
])
|
|
33
|
+
.describe('The features to include in the project, multiple options can be selected'))
|
|
34
|
+
.optional(),
|
|
35
|
+
};
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
37
|
+
const inputSchemaZodObject = zod_1.z.object({
|
|
38
|
+
...inputSchema,
|
|
39
|
+
});
|
|
10
40
|
class AddFeatureToProject extends types_1.Tool {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
auth: zod_1.z
|
|
27
|
-
.optional(zod_1.z.union([
|
|
28
|
-
zod_1.z.literal(constants_1.APP_AUTH_TYPES.STATIC),
|
|
29
|
-
zod_1.z.literal(constants_1.APP_AUTH_TYPES.OAUTH),
|
|
30
|
-
]))
|
|
31
|
-
.describe('Static uses a static non changing authentication token, and is only available for private distribution. If not specified by the user, do not choose for them. This cannot be changed after a project is uploaded.')
|
|
32
|
-
.optional(),
|
|
33
|
-
features: zod_1.z
|
|
34
|
-
.array(zod_1.z
|
|
35
|
-
.union([
|
|
36
|
-
zod_1.z.literal('card'),
|
|
37
|
-
zod_1.z.literal('settings'),
|
|
38
|
-
zod_1.z.literal('app-function'),
|
|
39
|
-
zod_1.z.literal('webhooks'),
|
|
40
|
-
])
|
|
41
|
-
.describe('The features to include in the project, multiple options can be selected'))
|
|
42
|
-
.optional(),
|
|
43
|
-
},
|
|
44
|
-
}, async ({ absoluteProjectPath, distribution, auth, features, addApp }) => {
|
|
45
|
-
try {
|
|
46
|
-
let command = `hs project add`;
|
|
47
|
-
const content = [];
|
|
48
|
-
if (distribution) {
|
|
49
|
-
command = (0, command_1.addFlag)(command, 'distribution', distribution);
|
|
50
|
-
}
|
|
51
|
-
else if (addApp) {
|
|
52
|
-
content.push({
|
|
53
|
-
type: 'text',
|
|
54
|
-
text: `Ask the user how they would you like to distribute the application? Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`,
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
if (auth) {
|
|
58
|
-
command = (0, command_1.addFlag)(command, 'auth', auth);
|
|
59
|
-
}
|
|
60
|
-
else if (addApp) {
|
|
61
|
-
content.push({
|
|
62
|
-
type: 'text',
|
|
63
|
-
text: `Ask the user which auth type they would like to use? Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`,
|
|
64
|
-
});
|
|
65
|
-
}
|
|
66
|
-
if (content.length > 0) {
|
|
67
|
-
return {
|
|
68
|
-
content,
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
// If features isn't provided, pass an empty array to bypass the prompt
|
|
72
|
-
command = (0, command_1.addFlag)(command, 'features', features || []);
|
|
73
|
-
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, command);
|
|
74
|
-
return {
|
|
75
|
-
content: [
|
|
76
|
-
{
|
|
77
|
-
type: 'text',
|
|
78
|
-
text: stdout,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
type: 'text',
|
|
82
|
-
text: stderr,
|
|
83
|
-
},
|
|
84
|
-
],
|
|
85
|
-
};
|
|
41
|
+
constructor(mcpServer) {
|
|
42
|
+
super(mcpServer);
|
|
43
|
+
}
|
|
44
|
+
async handler({ absoluteProjectPath, distribution, auth, features, addApp, }) {
|
|
45
|
+
try {
|
|
46
|
+
let command = `hs project add`;
|
|
47
|
+
const content = [];
|
|
48
|
+
if (distribution) {
|
|
49
|
+
command = (0, command_1.addFlag)(command, 'distribution', distribution);
|
|
50
|
+
}
|
|
51
|
+
else if (addApp) {
|
|
52
|
+
content.push({
|
|
53
|
+
type: 'text',
|
|
54
|
+
text: `Ask the user how they would you like to distribute the application? Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`,
|
|
55
|
+
});
|
|
86
56
|
}
|
|
87
|
-
|
|
57
|
+
if (auth) {
|
|
58
|
+
command = (0, command_1.addFlag)(command, 'auth', auth);
|
|
59
|
+
}
|
|
60
|
+
else if (addApp) {
|
|
61
|
+
content.push({
|
|
62
|
+
type: 'text',
|
|
63
|
+
text: `Ask the user which auth type they would like to use? Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (content.length > 0) {
|
|
88
67
|
return {
|
|
89
|
-
content
|
|
90
|
-
{
|
|
91
|
-
type: 'text',
|
|
92
|
-
text: error instanceof Error ? error.message : `${error}`,
|
|
93
|
-
},
|
|
94
|
-
],
|
|
68
|
+
content,
|
|
95
69
|
};
|
|
96
70
|
}
|
|
97
|
-
|
|
71
|
+
// If features isn't provided, pass an empty array to bypass the prompt
|
|
72
|
+
command = (0, command_1.addFlag)(command, 'features', features || []);
|
|
73
|
+
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, command);
|
|
74
|
+
return {
|
|
75
|
+
content: [
|
|
76
|
+
{
|
|
77
|
+
type: 'text',
|
|
78
|
+
text: stdout,
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
type: 'text',
|
|
82
|
+
text: stderr,
|
|
83
|
+
},
|
|
84
|
+
],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
return {
|
|
89
|
+
content: [
|
|
90
|
+
{
|
|
91
|
+
type: 'text',
|
|
92
|
+
text: error instanceof Error ? error.message : `${error}`,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
register() {
|
|
99
|
+
return this.mcpServer.registerTool('add-feature-to-hubspot-project', {
|
|
100
|
+
title: 'Add feature to HubSpot Project',
|
|
101
|
+
description: 'Adds a feature to an existing HubSpot project',
|
|
102
|
+
inputSchema,
|
|
103
|
+
}, this.handler);
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
exports.AddFeatureToProject = AddFeatureToProject;
|
|
@@ -1,6 +1,35 @@
|
|
|
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
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
|
+
name: z.ZodString;
|
|
7
|
+
destination: z.ZodString;
|
|
8
|
+
projectBase: z.ZodUnion<[z.ZodLiteral<"empty">, z.ZodLiteral<"app">]>;
|
|
9
|
+
distribution: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"marketplace">, z.ZodLiteral<"private">]>>;
|
|
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">]>, "many">>;
|
|
12
|
+
}, "strip", z.ZodTypeAny, {
|
|
13
|
+
name: string;
|
|
14
|
+
projectBase: "app" | "empty";
|
|
15
|
+
absoluteCurrentWorkingDirectory: string;
|
|
16
|
+
destination: string;
|
|
17
|
+
auth?: "oauth" | "static" | undefined;
|
|
18
|
+
distribution?: "marketplace" | "private" | undefined;
|
|
19
|
+
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
name: string;
|
|
22
|
+
projectBase: "app" | "empty";
|
|
23
|
+
absoluteCurrentWorkingDirectory: string;
|
|
24
|
+
destination: string;
|
|
25
|
+
auth?: "oauth" | "static" | undefined;
|
|
26
|
+
distribution?: "marketplace" | "private" | undefined;
|
|
27
|
+
features?: ("card" | "settings" | "app-function" | "webhooks")[] | undefined;
|
|
28
|
+
}>;
|
|
29
|
+
export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
30
|
+
export declare class CreateProjectTool extends Tool<CreateProjectInputSchema> {
|
|
31
|
+
constructor(mcpServer: McpServer);
|
|
32
|
+
handler({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }: CreateProjectInputSchema): Promise<TextContentResponse>;
|
|
33
|
+
register(): RegisteredTool;
|
|
6
34
|
}
|
|
35
|
+
export {};
|
|
@@ -8,112 +8,117 @@ const command_1 = require("../../utils/command");
|
|
|
8
8
|
const v3_1 = require("../../../lib/projects/create/v3");
|
|
9
9
|
const constants_2 = require("./constants");
|
|
10
10
|
const project_1 = require("../../utils/project");
|
|
11
|
+
const inputSchema = {
|
|
12
|
+
absoluteCurrentWorkingDirectory: constants_2.absoluteCurrentWorkingDirectory,
|
|
13
|
+
name: zod_1.z
|
|
14
|
+
.string()
|
|
15
|
+
.describe('The name of the project to be created. This name is how your project will appear in HubSpot.'),
|
|
16
|
+
destination: zod_1.z
|
|
17
|
+
.string()
|
|
18
|
+
.describe('Relative path to the directory the project will be created in. It is not recommended to use the current directory unless it is an empty directory'),
|
|
19
|
+
projectBase: zod_1.z
|
|
20
|
+
.union([zod_1.z.literal(v3_1.EMPTY_PROJECT), zod_1.z.literal(v3_1.PROJECT_WITH_APP)])
|
|
21
|
+
.describe('Empty will create and empty project, and app will create a project with an app inside of it.'),
|
|
22
|
+
distribution: zod_1.z
|
|
23
|
+
.optional(zod_1.z.union([
|
|
24
|
+
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE),
|
|
25
|
+
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.PRIVATE),
|
|
26
|
+
]))
|
|
27
|
+
.describe('Private is used if you do not wish to distribute your application on the HubSpot marketplace. If not specified by the user, do not choose for them. This cannot be changed after a project is uploaded.'),
|
|
28
|
+
auth: zod_1.z
|
|
29
|
+
.optional(zod_1.z.union([
|
|
30
|
+
zod_1.z.literal(constants_1.APP_AUTH_TYPES.STATIC),
|
|
31
|
+
zod_1.z.literal(constants_1.APP_AUTH_TYPES.OAUTH),
|
|
32
|
+
]))
|
|
33
|
+
.describe('Static uses a static non changing authentication token, and is only available for private distribution. If not specified by the user, do not choose for them. This cannot be changed after a project is uploaded.')
|
|
34
|
+
.optional(),
|
|
35
|
+
features: zod_1.z
|
|
36
|
+
.array(zod_1.z
|
|
37
|
+
.union([
|
|
38
|
+
zod_1.z.literal('card'),
|
|
39
|
+
zod_1.z.literal('settings'),
|
|
40
|
+
zod_1.z.literal('app-function'),
|
|
41
|
+
zod_1.z.literal('webhooks'),
|
|
42
|
+
])
|
|
43
|
+
.describe('The features to include in the project, multiple options can be selected'))
|
|
44
|
+
.optional(),
|
|
45
|
+
};
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
47
|
+
const inputSchemaZodObject = zod_1.z.object({ ...inputSchema });
|
|
11
48
|
class CreateProjectTool extends types_1.Tool {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
49
|
+
constructor(mcpServer) {
|
|
50
|
+
super(mcpServer);
|
|
51
|
+
}
|
|
52
|
+
async handler({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }) {
|
|
53
|
+
let command = (0, command_1.addFlag)('hs project create', 'platform-version', '2025.2');
|
|
54
|
+
const content = [];
|
|
55
|
+
if (name) {
|
|
56
|
+
command = (0, command_1.addFlag)(command, 'name', name);
|
|
57
|
+
}
|
|
58
|
+
if (destination) {
|
|
59
|
+
command = (0, command_1.addFlag)(command, 'dest', destination);
|
|
60
|
+
}
|
|
61
|
+
if (projectBase) {
|
|
62
|
+
command = (0, command_1.addFlag)(command, 'project-base', projectBase);
|
|
63
|
+
}
|
|
64
|
+
if (distribution) {
|
|
65
|
+
command = (0, command_1.addFlag)(command, 'distribution', distribution);
|
|
66
|
+
}
|
|
67
|
+
else if (projectBase === v3_1.PROJECT_WITH_APP) {
|
|
68
|
+
content.push({
|
|
69
|
+
type: 'text',
|
|
70
|
+
text: `Ask the user how they would you like to distribute the application? Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
if (auth) {
|
|
74
|
+
command = (0, command_1.addFlag)(command, 'auth', auth);
|
|
75
|
+
}
|
|
76
|
+
else if (projectBase === v3_1.PROJECT_WITH_APP) {
|
|
77
|
+
content.push({
|
|
78
|
+
type: 'text',
|
|
79
|
+
text: `Ask the user which auth type they would like to use? Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
if (content.length > 0) {
|
|
83
|
+
return {
|
|
84
|
+
content,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
if (features && features.length) {
|
|
88
|
+
command = (0, command_1.addFlag)(command, 'features', features);
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteCurrentWorkingDirectory, command);
|
|
92
|
+
return {
|
|
93
|
+
content: [
|
|
94
|
+
{
|
|
95
|
+
type: 'text',
|
|
96
|
+
text: stdout,
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
type: 'text',
|
|
100
|
+
text: stderr,
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return {
|
|
107
|
+
content: [
|
|
108
|
+
{
|
|
109
|
+
type: 'text',
|
|
110
|
+
text: error instanceof Error ? error.message : `${error}`,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
register() {
|
|
15
117
|
return this.mcpServer.registerTool('create-hubspot-project', {
|
|
16
118
|
title: 'Create HubSpot Project',
|
|
17
119
|
description: 'Creates a HubSpot project with the provided name and outputs it in the provided destination',
|
|
18
|
-
inputSchema
|
|
19
|
-
|
|
20
|
-
name: zod_1.z
|
|
21
|
-
.string()
|
|
22
|
-
.describe('The name of the project to be created. This name is how your project will appear in HubSpot.'),
|
|
23
|
-
destination: zod_1.z
|
|
24
|
-
.string()
|
|
25
|
-
.describe('Relative path to the directory the project will be created in. It is not recommended to use the current directory unless it is an empty directory'),
|
|
26
|
-
projectBase: zod_1.z
|
|
27
|
-
.union([zod_1.z.literal(v3_1.EMPTY_PROJECT), zod_1.z.literal(v3_1.PROJECT_WITH_APP)])
|
|
28
|
-
.describe('Empty will create and empty project, and app will create a project with an app inside of it.'),
|
|
29
|
-
distribution: zod_1.z
|
|
30
|
-
.optional(zod_1.z.union([
|
|
31
|
-
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE),
|
|
32
|
-
zod_1.z.literal(constants_1.APP_DISTRIBUTION_TYPES.PRIVATE),
|
|
33
|
-
]))
|
|
34
|
-
.describe('Private is used if you do not wish to distribute your application on the HubSpot marketplace. If not specified by the user, do not choose for them. This cannot be changed after a project is uploaded.'),
|
|
35
|
-
auth: zod_1.z
|
|
36
|
-
.optional(zod_1.z.union([
|
|
37
|
-
zod_1.z.literal(constants_1.APP_AUTH_TYPES.STATIC),
|
|
38
|
-
zod_1.z.literal(constants_1.APP_AUTH_TYPES.OAUTH),
|
|
39
|
-
]))
|
|
40
|
-
.describe('Static uses a static non changing authentication token, and is only available for private distribution. If not specified by the user, do not choose for them. This cannot be changed after a project is uploaded.')
|
|
41
|
-
.optional(),
|
|
42
|
-
features: zod_1.z
|
|
43
|
-
.array(zod_1.z
|
|
44
|
-
.union([
|
|
45
|
-
zod_1.z.literal('card'),
|
|
46
|
-
zod_1.z.literal('settings'),
|
|
47
|
-
zod_1.z.literal('app-function'),
|
|
48
|
-
zod_1.z.literal('webhooks'),
|
|
49
|
-
])
|
|
50
|
-
.describe('The features to include in the project, multiple options can be selected'))
|
|
51
|
-
.optional(),
|
|
52
|
-
},
|
|
53
|
-
}, async ({ name, destination, projectBase, distribution, auth, features, absoluteCurrentWorkingDirectory, }) => {
|
|
54
|
-
let command = (0, command_1.addFlag)('hs project create', 'platform-version', '2025.2');
|
|
55
|
-
const content = [];
|
|
56
|
-
if (name) {
|
|
57
|
-
command = (0, command_1.addFlag)(command, 'name', name);
|
|
58
|
-
}
|
|
59
|
-
if (destination) {
|
|
60
|
-
command = (0, command_1.addFlag)(command, 'dest', destination);
|
|
61
|
-
}
|
|
62
|
-
if (projectBase) {
|
|
63
|
-
command = (0, command_1.addFlag)(command, 'project-base', projectBase);
|
|
64
|
-
}
|
|
65
|
-
if (distribution) {
|
|
66
|
-
command = (0, command_1.addFlag)(command, 'distribution', distribution);
|
|
67
|
-
}
|
|
68
|
-
else if (projectBase === v3_1.PROJECT_WITH_APP) {
|
|
69
|
-
content.push({
|
|
70
|
-
type: 'text',
|
|
71
|
-
text: `Ask the user how they would you like to distribute the application? Options are ${constants_1.APP_DISTRIBUTION_TYPES.MARKETPLACE} and ${constants_1.APP_DISTRIBUTION_TYPES.PRIVATE}`,
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
if (auth) {
|
|
75
|
-
command = (0, command_1.addFlag)(command, 'auth', auth);
|
|
76
|
-
}
|
|
77
|
-
else if (projectBase === v3_1.PROJECT_WITH_APP) {
|
|
78
|
-
content.push({
|
|
79
|
-
type: 'text',
|
|
80
|
-
text: `Ask the user which auth type they would like to use? Options are ${constants_1.APP_AUTH_TYPES.STATIC} and ${constants_1.APP_AUTH_TYPES.OAUTH}`,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
if (content.length > 0) {
|
|
84
|
-
return {
|
|
85
|
-
content,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
if (features && features.length) {
|
|
89
|
-
command = (0, command_1.addFlag)(command, 'features', features);
|
|
90
|
-
}
|
|
91
|
-
try {
|
|
92
|
-
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteCurrentWorkingDirectory, command);
|
|
93
|
-
return {
|
|
94
|
-
content: [
|
|
95
|
-
{
|
|
96
|
-
type: 'text',
|
|
97
|
-
text: stdout,
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
type: 'text',
|
|
101
|
-
text: stderr,
|
|
102
|
-
},
|
|
103
|
-
],
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
catch (error) {
|
|
107
|
-
return {
|
|
108
|
-
content: [
|
|
109
|
-
{
|
|
110
|
-
type: 'text',
|
|
111
|
-
text: error instanceof Error ? error.message : `${error}`,
|
|
112
|
-
},
|
|
113
|
-
],
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
});
|
|
120
|
+
inputSchema,
|
|
121
|
+
}, this.handler);
|
|
117
122
|
}
|
|
118
123
|
}
|
|
119
124
|
exports.CreateProjectTool = CreateProjectTool;
|
|
@@ -1,6 +1,20 @@
|
|
|
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
|
+
buildNumber: z.ZodOptional<z.ZodNumber>;
|
|
7
|
+
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
absoluteProjectPath: string;
|
|
9
|
+
buildNumber?: number | undefined;
|
|
10
|
+
}, {
|
|
11
|
+
absoluteProjectPath: string;
|
|
12
|
+
buildNumber?: number | undefined;
|
|
13
|
+
}>;
|
|
14
|
+
type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
|
|
15
|
+
export declare class DeployProject extends Tool<InputSchemaType> {
|
|
16
|
+
constructor(mcpServer: McpServer);
|
|
17
|
+
handler({ absoluteProjectPath, buildNumber, }: InputSchemaType): Promise<TextContentResponse>;
|
|
18
|
+
register(): RegisteredTool;
|
|
6
19
|
}
|
|
20
|
+
export {};
|
|
@@ -6,45 +6,52 @@ const zod_1 = require("zod");
|
|
|
6
6
|
const command_1 = require("../../utils/command");
|
|
7
7
|
const constants_1 = require("./constants");
|
|
8
8
|
const project_1 = require("../../utils/project");
|
|
9
|
+
const inputSchema = {
|
|
10
|
+
absoluteProjectPath: constants_1.absoluteProjectPath,
|
|
11
|
+
buildNumber: zod_1.z
|
|
12
|
+
.optional(zod_1.z.number())
|
|
13
|
+
.describe('The build number to be deployed. This can be found in the project details page using `hs project open`. If no build number is specified, the most recent build is deployed'),
|
|
14
|
+
};
|
|
15
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
16
|
+
const inputSchemaZodObject = zod_1.z.object({
|
|
17
|
+
...inputSchema,
|
|
18
|
+
});
|
|
9
19
|
class DeployProject extends types_1.Tool {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
constructor(mcpServer) {
|
|
21
|
+
super(mcpServer);
|
|
22
|
+
}
|
|
23
|
+
async handler({ absoluteProjectPath, buildNumber, }) {
|
|
24
|
+
let command = `hs project deploy`;
|
|
25
|
+
const content = [];
|
|
26
|
+
if (!buildNumber) {
|
|
27
|
+
const { stdout } = await (0, project_1.runCommandInDir)(absoluteProjectPath, `hs project list-builds --limit 100`);
|
|
28
|
+
content.push({
|
|
29
|
+
type: 'text',
|
|
30
|
+
text: `Ask the user which build number they would like to deploy? Build information: ${stdout}`,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
command = (0, command_1.addFlag)(command, 'build', buildNumber);
|
|
35
|
+
}
|
|
36
|
+
if (content.length) {
|
|
37
|
+
return {
|
|
38
|
+
content,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, command);
|
|
42
|
+
return {
|
|
43
|
+
content: [
|
|
44
|
+
{ type: 'text', text: stdout },
|
|
45
|
+
{ type: 'text', text: stderr },
|
|
46
|
+
],
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
register() {
|
|
13
50
|
return this.mcpServer.registerTool('deploy-hubspot-project', {
|
|
14
51
|
title: 'Deploy a build of HubSpot Project',
|
|
15
52
|
description: 'Takes a build number and a project name and deploys that build of the project',
|
|
16
|
-
inputSchema
|
|
17
|
-
|
|
18
|
-
buildNumber: zod_1.z
|
|
19
|
-
.optional(zod_1.z.number())
|
|
20
|
-
.describe('The build number to be deployed. This can be found in the project details page using `hs project open`. If no build number is specified, the most recent build is deployed'),
|
|
21
|
-
},
|
|
22
|
-
}, async ({ absoluteProjectPath, buildNumber }) => {
|
|
23
|
-
let command = `hs project deploy`;
|
|
24
|
-
const content = [];
|
|
25
|
-
if (!buildNumber) {
|
|
26
|
-
const { stdout } = await (0, project_1.runCommandInDir)(absoluteProjectPath, `hs project list-builds --limit 100`);
|
|
27
|
-
content.push({
|
|
28
|
-
type: 'text',
|
|
29
|
-
text: `Ask the user which build number they would like to deploy? Build information: ${stdout}`,
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
command = (0, command_1.addFlag)(command, 'build', buildNumber);
|
|
34
|
-
}
|
|
35
|
-
if (content.length) {
|
|
36
|
-
return {
|
|
37
|
-
content,
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, command);
|
|
41
|
-
return {
|
|
42
|
-
content: [
|
|
43
|
-
{ type: 'text', text: stdout },
|
|
44
|
-
{ type: 'text', text: stderr },
|
|
45
|
-
],
|
|
46
|
-
};
|
|
47
|
-
});
|
|
53
|
+
inputSchema,
|
|
54
|
+
}, this.handler);
|
|
48
55
|
}
|
|
49
56
|
}
|
|
50
57
|
exports.DeployProject = DeployProject;
|
|
@@ -1,6 +1,17 @@
|
|
|
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
|
+
command: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"hs init">, z.ZodLiteral<"hs auth">, z.ZodLiteral<"hs project create">, z.ZodLiteral<"hs project upload">]>>;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
command?: "hs auth" | "hs project upload" | "hs project create" | "hs init" | undefined;
|
|
8
|
+
}, {
|
|
9
|
+
command?: "hs auth" | "hs project upload" | "hs project create" | "hs init" | undefined;
|
|
10
|
+
}>;
|
|
11
|
+
type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
|
|
12
|
+
export declare class GuidedWalkthroughTool extends Tool<InputSchemaType> {
|
|
13
|
+
constructor(mcpServer: McpServer);
|
|
14
|
+
handler({ command }: InputSchemaType): Promise<TextContentResponse>;
|
|
15
|
+
register(): RegisteredTool;
|
|
6
16
|
}
|
|
17
|
+
export {};
|
|
@@ -10,10 +10,47 @@ const nextCommands = {
|
|
|
10
10
|
'hs project create': 'hs project upload',
|
|
11
11
|
'hs project upload': 'hs project dev',
|
|
12
12
|
};
|
|
13
|
+
const inputSchema = {
|
|
14
|
+
command: zod_1.z
|
|
15
|
+
.union([
|
|
16
|
+
zod_1.z.literal('hs init'),
|
|
17
|
+
zod_1.z.literal('hs auth'),
|
|
18
|
+
zod_1.z.literal('hs project create'),
|
|
19
|
+
zod_1.z.literal('hs project upload'),
|
|
20
|
+
])
|
|
21
|
+
.describe('The command to learn more about. Start with `hs init`')
|
|
22
|
+
.optional(),
|
|
23
|
+
};
|
|
24
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
25
|
+
const inputSchemaZodObject = zod_1.z.object({
|
|
26
|
+
...inputSchema,
|
|
27
|
+
});
|
|
13
28
|
class GuidedWalkthroughTool extends types_1.Tool {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
29
|
+
constructor(mcpServer) {
|
|
30
|
+
super(mcpServer);
|
|
31
|
+
}
|
|
32
|
+
async handler({ command }) {
|
|
33
|
+
if (command) {
|
|
34
|
+
const { stdout } = await (0, command_1.execAsync)(`${command} --help`);
|
|
35
|
+
return {
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: 'text',
|
|
39
|
+
text: `Display this help output for the user amd wait for them to acknowledge: ${stdout}. ${nextCommands[command] ? `Once they are ready, A good command to look at next is ${nextCommands[command]}` : ''}`,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return {
|
|
45
|
+
content: [
|
|
46
|
+
{
|
|
47
|
+
type: 'text',
|
|
48
|
+
text: 'Is there another command you would like to learn more about?',
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
register() {
|
|
17
54
|
return this.mcpServer.registerTool('guided-walkthrough-hubspot-cli', {
|
|
18
55
|
title: 'Guided walkthrough of the CLI',
|
|
19
56
|
description: 'Give the user a guided walkthrough of the HubSpot CLI.',
|
|
@@ -28,27 +65,7 @@ class GuidedWalkthroughTool extends types_1.Tool {
|
|
|
28
65
|
.describe('The command to learn more about. Start with `hs init`')
|
|
29
66
|
.optional(),
|
|
30
67
|
},
|
|
31
|
-
},
|
|
32
|
-
if (command) {
|
|
33
|
-
const { stdout } = await (0, command_1.execAsync)(`${command} --help`);
|
|
34
|
-
return {
|
|
35
|
-
content: [
|
|
36
|
-
{
|
|
37
|
-
type: 'text',
|
|
38
|
-
text: `Display this help output for the user amd wait for them to acknowledge: ${stdout}. ${nextCommands[command] ? `Once they are ready, A good command to look at next is ${nextCommands[command]}` : ''}`,
|
|
39
|
-
},
|
|
40
|
-
],
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
return {
|
|
44
|
-
content: [
|
|
45
|
-
{
|
|
46
|
-
type: 'text',
|
|
47
|
-
text: 'Is there another command you would like to learn more about?',
|
|
48
|
-
},
|
|
49
|
-
],
|
|
50
|
-
};
|
|
51
|
-
});
|
|
68
|
+
}, this.handler);
|
|
52
69
|
}
|
|
53
70
|
}
|
|
54
71
|
exports.GuidedWalkthroughTool = GuidedWalkthroughTool;
|
|
@@ -1,5 +1,17 @@
|
|
|
1
|
-
import { Tool } from '../../types';
|
|
1
|
+
import { TextContentResponse, Tool } from '../../types';
|
|
2
2
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
import z from 'zod';
|
|
4
|
+
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteProjectPath: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
absoluteProjectPath: string;
|
|
8
|
+
}, {
|
|
9
|
+
absoluteProjectPath: string;
|
|
10
|
+
}>;
|
|
11
|
+
type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
|
|
12
|
+
export declare class UploadProjectTools extends Tool<InputSchemaType> {
|
|
13
|
+
constructor(mcpServer: McpServer);
|
|
14
|
+
handler({ absoluteProjectPath, }: InputSchemaType): Promise<TextContentResponse>;
|
|
15
|
+
register(): RegisteredTool;
|
|
5
16
|
}
|
|
17
|
+
export {};
|
|
@@ -1,26 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.UploadProjectTools = void 0;
|
|
4
7
|
const types_1 = require("../../types");
|
|
5
8
|
const project_1 = require("../../utils/project");
|
|
6
9
|
const constants_1 = require("./constants");
|
|
10
|
+
const zod_1 = __importDefault(require("zod"));
|
|
11
|
+
const inputSchema = {
|
|
12
|
+
absoluteProjectPath: constants_1.absoluteProjectPath,
|
|
13
|
+
};
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
15
|
+
const inputSchemaZodObject = zod_1.default.object({
|
|
16
|
+
...inputSchema,
|
|
17
|
+
});
|
|
7
18
|
class UploadProjectTools extends types_1.Tool {
|
|
8
|
-
|
|
9
|
-
|
|
19
|
+
constructor(mcpServer) {
|
|
20
|
+
super(mcpServer);
|
|
21
|
+
}
|
|
22
|
+
async handler({ absoluteProjectPath, }) {
|
|
23
|
+
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, `hs project upload --force-create`);
|
|
24
|
+
return {
|
|
25
|
+
content: [
|
|
26
|
+
{ type: 'text', text: stdout },
|
|
27
|
+
{ type: 'text', text: stderr },
|
|
28
|
+
],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
register() {
|
|
32
|
+
return this.mcpServer.registerTool('upload-hubspot-project', {
|
|
10
33
|
title: 'Upload HubSpot Project',
|
|
11
34
|
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.',
|
|
12
|
-
inputSchema
|
|
13
|
-
|
|
14
|
-
},
|
|
15
|
-
}, async ({ absoluteProjectPath }) => {
|
|
16
|
-
const { stdout, stderr } = await (0, project_1.runCommandInDir)(absoluteProjectPath, `hs project upload --force-create`);
|
|
17
|
-
return {
|
|
18
|
-
content: [
|
|
19
|
-
{ type: 'text', text: stdout },
|
|
20
|
-
{ type: 'text', text: stderr },
|
|
21
|
-
],
|
|
22
|
-
};
|
|
23
|
-
});
|
|
35
|
+
inputSchema,
|
|
36
|
+
}, this.handler);
|
|
24
37
|
}
|
|
25
38
|
}
|
|
26
39
|
exports.UploadProjectTools = UploadProjectTools;
|
package/mcp-server/types.d.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
export declare class Tool {
|
|
3
|
-
|
|
2
|
+
export declare class Tool<InputSchema, ResponseType = TextContentResponse> {
|
|
3
|
+
protected mcpServer: McpServer;
|
|
4
|
+
constructor(mcpServer: McpServer);
|
|
5
|
+
register(): RegisteredTool;
|
|
6
|
+
handler(input: InputSchema): ResponseType | Promise<ResponseType>;
|
|
4
7
|
}
|
|
5
|
-
export type
|
|
8
|
+
export type TextContent = {
|
|
6
9
|
type: 'text';
|
|
7
10
|
text: string;
|
|
8
11
|
};
|
|
12
|
+
export type TextContentResponse = {
|
|
13
|
+
content: TextContent[];
|
|
14
|
+
};
|
package/mcp-server/types.js
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Tool = void 0;
|
|
4
4
|
class Tool {
|
|
5
|
-
|
|
5
|
+
mcpServer;
|
|
6
|
+
constructor(mcpServer) {
|
|
7
|
+
this.mcpServer = mcpServer;
|
|
8
|
+
}
|
|
9
|
+
register() {
|
|
10
|
+
throw new Error('Must implement register');
|
|
11
|
+
}
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
13
|
+
handler(input) {
|
|
14
|
+
throw new Error('Must implement handler');
|
|
15
|
+
}
|
|
6
16
|
}
|
|
7
17
|
exports.Tool = Tool;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hubspot/cli",
|
|
3
|
-
"version": "7.7.
|
|
3
|
+
"version": "7.7.8-experimental.0",
|
|
4
4
|
"description": "The official CLI for developing on HubSpot",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": "https://github.com/HubSpot/hubspot-cli",
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
"@hubspot/serverless-dev-runtime": "7.0.6",
|
|
11
11
|
"@hubspot/theme-preview-dev-server": "0.0.10",
|
|
12
12
|
"@hubspot/ui-extensions-dev-server": "0.9.2",
|
|
13
|
-
"@modelcontextprotocol/sdk": "1.13.3",
|
|
14
13
|
"archiver": "7.0.1",
|
|
15
14
|
"boxen": "8.0.1",
|
|
16
15
|
"chalk": "4.1.2",
|
|
@@ -62,7 +61,8 @@
|
|
|
62
61
|
"typescript": "^5.6.2"
|
|
63
62
|
},
|
|
64
63
|
"optionalDependencies": {
|
|
65
|
-
"@hubspot/cms-dev-server": "^1.0.9"
|
|
64
|
+
"@hubspot/cms-dev-server": "^1.0.9",
|
|
65
|
+
"@modelcontextprotocol/sdk": "1.13.3"
|
|
66
66
|
},
|
|
67
67
|
"scripts": {
|
|
68
68
|
"build": "ts-node ./scripts/build.ts",
|