@hubspot/cli 7.9.0-beta.1 → 7.9.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/project/__tests__/deploy.test.js +4 -3
- package/lang/en.d.ts +10 -10
- package/lang/en.js +13 -13
- package/lib/__tests__/npm.test.js +1 -1
- package/lib/__tests__/sandboxSync.test.js +1 -1
- package/lib/__tests__/usageTracking.test.js +2 -2
- package/lib/configMigrate.js +3 -3
- package/lib/doctor/DiagnosticInfoBuilder.js +1 -1
- package/lib/doctor/Doctor.js +1 -1
- package/lib/doctor/__tests__/DiagnosticInfoBuilder.test.js +4 -2
- package/lib/doctor/__tests__/Doctor.test.js +1 -1
- package/lib/jsonLoader.d.ts +14 -0
- package/lib/jsonLoader.js +60 -0
- package/lib/middleware/__test__/requestMiddleware.test.js +1 -1
- package/lib/middleware/autoUpdateMiddleware.js +1 -1
- package/lib/middleware/commandTargetingUtils.js +1 -0
- package/lib/middleware/fireAlarmMiddleware.js +1 -1
- package/lib/middleware/notificationsMiddleware.js +1 -1
- package/lib/middleware/requestMiddleware.js +1 -1
- package/lib/npm.js +1 -1
- package/lib/projects/__tests__/AppDevModeInterface.test.js +3 -0
- package/lib/projects/create/__tests__/v2.test.js +20 -14
- package/lib/projects/create/v2.js +8 -13
- package/lib/projects/localDev/LocalDevLogger.js +2 -2
- package/lib/projects/localDev/LocalDevManager_DEPRECATED.js +3 -3
- package/lib/projects/localDev/LocalDevWebsocketServer.js +1 -1
- package/lib/prompts/promptUtils.d.ts +8 -0
- package/lib/prompts/promptUtils.js +7 -1
- package/lib/prompts/selectProjectTemplatePrompt.js +4 -0
- package/lib/sandboxSync.js +1 -1
- package/lib/usageTracking.js +2 -2
- package/mcp-server/tools/cms/HsCreateFunctionTool.js +2 -2
- package/mcp-server/tools/cms/HsCreateModuleTool.js +2 -2
- package/mcp-server/tools/cms/HsCreateTemplateTool.js +2 -2
- package/mcp-server/tools/cms/HsFunctionLogsTool.js +2 -9
- package/mcp-server/tools/cms/HsListFunctionsTool.js +1 -1
- package/mcp-server/tools/cms/HsListTool.js +1 -1
- package/mcp-server/tools/cms/__tests__/HsCreateFunctionTool.test.js +7 -4
- package/mcp-server/tools/cms/__tests__/HsCreateModuleTool.test.js +7 -3
- package/mcp-server/tools/cms/__tests__/HsCreateTemplateTool.test.js +7 -4
- package/mcp-server/tools/cms/__tests__/HsFunctionLogsTool.test.js +5 -1
- package/mcp-server/tools/cms/__tests__/HsListFunctionsTool.test.js +8 -3
- package/mcp-server/tools/cms/__tests__/HsListTool.test.js +8 -3
- package/mcp-server/tools/project/AddFeatureToProjectTool.d.ts +4 -1
- package/mcp-server/tools/project/AddFeatureToProjectTool.js +6 -5
- package/mcp-server/tools/project/CreateProjectTool.js +2 -2
- package/mcp-server/tools/project/DeployProjectTool.d.ts +4 -1
- package/mcp-server/tools/project/DeployProjectTool.js +4 -3
- package/mcp-server/tools/project/DocFetchTool.d.ts +4 -1
- package/mcp-server/tools/project/DocFetchTool.js +7 -6
- package/mcp-server/tools/project/DocsSearchTool.js +5 -5
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.d.ts +4 -1
- package/mcp-server/tools/project/GetApiUsagePatternsByAppIdTool.js +7 -5
- package/mcp-server/tools/project/GetApplicationInfoTool.d.ts +8 -2
- package/mcp-server/tools/project/GetApplicationInfoTool.js +7 -6
- package/mcp-server/tools/project/GetConfigValuesTool.js +4 -4
- package/mcp-server/tools/project/GuidedWalkthroughTool.d.ts +4 -1
- package/mcp-server/tools/project/GuidedWalkthroughTool.js +6 -14
- package/mcp-server/tools/project/UploadProjectTools.d.ts +4 -1
- package/mcp-server/tools/project/UploadProjectTools.js +4 -3
- package/mcp-server/tools/project/ValidateProjectTool.d.ts +4 -1
- package/mcp-server/tools/project/ValidateProjectTool.js +5 -4
- package/mcp-server/tools/project/__tests__/AddFeatureToProjectTool.test.js +6 -1
- package/mcp-server/tools/project/__tests__/CreateProjectTool.test.js +7 -3
- package/mcp-server/tools/project/__tests__/DeployProjectTool.test.js +7 -2
- package/mcp-server/tools/project/__tests__/DocFetchTool.test.js +8 -3
- package/mcp-server/tools/project/__tests__/DocsSearchTool.test.js +6 -2
- package/mcp-server/tools/project/__tests__/GetApiUsagePatternsByAppIdTool.test.js +8 -3
- package/mcp-server/tools/project/__tests__/GetApplicationInfoTool.test.js +9 -5
- package/mcp-server/tools/project/__tests__/GetConfigValuesTool.test.js +6 -2
- package/mcp-server/tools/project/__tests__/GuidedWalkthroughTool.test.js +43 -13
- package/mcp-server/tools/project/__tests__/UploadProjectTools.test.js +8 -2
- package/mcp-server/tools/project/__tests__/ValidateProjectTool.test.js +8 -2
- package/mcp-server/utils/__tests__/content.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/content.test.js +166 -0
- package/mcp-server/utils/__tests__/feedbackTracking.test.d.ts +1 -0
- package/mcp-server/utils/__tests__/feedbackTracking.test.js +121 -0
- package/mcp-server/utils/content.d.ts +1 -1
- package/mcp-server/utils/content.js +8 -1
- package/mcp-server/utils/feedbackTracking.d.ts +1 -0
- package/mcp-server/utils/feedbackTracking.js +41 -0
- package/package.json +2 -2
- package/commands/project/__tests__/fixtures/exampleProject.json +0 -33
|
@@ -2,22 +2,25 @@ import { TextContentResponse, Tool } from '../../types.js';
|
|
|
2
2
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
5
6
|
appId: z.ZodString;
|
|
6
7
|
startDate: z.ZodOptional<z.ZodString>;
|
|
7
8
|
endDate: z.ZodOptional<z.ZodString>;
|
|
8
9
|
}, "strip", z.ZodTypeAny, {
|
|
9
10
|
appId: string;
|
|
11
|
+
absoluteCurrentWorkingDirectory: string;
|
|
10
12
|
startDate?: string | undefined;
|
|
11
13
|
endDate?: string | undefined;
|
|
12
14
|
}, {
|
|
13
15
|
appId: string;
|
|
16
|
+
absoluteCurrentWorkingDirectory: string;
|
|
14
17
|
startDate?: string | undefined;
|
|
15
18
|
endDate?: string | undefined;
|
|
16
19
|
}>;
|
|
17
20
|
export type GetApiUsagePatternsByAppIdInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
18
21
|
export declare class GetApiUsagePatternsByAppIdTool extends Tool<GetApiUsagePatternsByAppIdInputSchema> {
|
|
19
22
|
constructor(mcpServer: McpServer);
|
|
20
|
-
handler({ appId, startDate, endDate, }: GetApiUsagePatternsByAppIdInputSchema): Promise<TextContentResponse>;
|
|
23
|
+
handler({ absoluteCurrentWorkingDirectory, appId, startDate, endDate, }: GetApiUsagePatternsByAppIdInputSchema): Promise<TextContentResponse>;
|
|
21
24
|
register(): RegisteredTool;
|
|
22
25
|
}
|
|
23
26
|
export {};
|
|
@@ -5,7 +5,9 @@ import { http } from '@hubspot/local-dev-lib/http';
|
|
|
5
5
|
import { formatTextContents } from '../../utils/content.js';
|
|
6
6
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
7
7
|
import { getAccountId } from '@hubspot/local-dev-lib/config';
|
|
8
|
+
import { absoluteCurrentWorkingDirectory } from './constants.js';
|
|
8
9
|
const inputSchema = {
|
|
10
|
+
absoluteCurrentWorkingDirectory,
|
|
9
11
|
appId: z
|
|
10
12
|
.string()
|
|
11
13
|
.regex(/^\d+$/, 'App ID must be a numeric string')
|
|
@@ -28,14 +30,14 @@ export class GetApiUsagePatternsByAppIdTool extends Tool {
|
|
|
28
30
|
constructor(mcpServer) {
|
|
29
31
|
super(mcpServer);
|
|
30
32
|
}
|
|
31
|
-
async handler({ appId, startDate, endDate, }) {
|
|
33
|
+
async handler({ absoluteCurrentWorkingDirectory, appId, startDate, endDate, }) {
|
|
32
34
|
await trackToolUsage(toolName);
|
|
33
35
|
try {
|
|
34
36
|
// Get account ID from CLI config
|
|
35
37
|
const accountId = getAccountId();
|
|
36
38
|
if (!accountId) {
|
|
37
39
|
const authErrorMessage = `No account ID found. Please run \`hs account auth\` to configure an account, or set a default account with \`hs account use <account>\``;
|
|
38
|
-
return formatTextContents(authErrorMessage);
|
|
40
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, authErrorMessage);
|
|
39
41
|
}
|
|
40
42
|
const response = await http.get(accountId, {
|
|
41
43
|
url: `app/feature/utilization/public/v3/insights/app/${appId}/usage-patterns`,
|
|
@@ -47,15 +49,15 @@ export class GetApiUsagePatternsByAppIdTool extends Tool {
|
|
|
47
49
|
// Format the response for display
|
|
48
50
|
const { data } = response;
|
|
49
51
|
const formattedResult = JSON.stringify(data, null, 2);
|
|
50
|
-
return formatTextContents(formattedResult);
|
|
52
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, formattedResult);
|
|
51
53
|
}
|
|
52
54
|
catch (error) {
|
|
53
55
|
if (isHubSpotHttpError(error)) {
|
|
54
56
|
// Handle HubSpot-specific HTTP errors
|
|
55
|
-
return formatTextContents(error.toString());
|
|
57
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, error.toString());
|
|
56
58
|
}
|
|
57
59
|
const errorMessage = `${error instanceof Error ? error.message : String(error)}`;
|
|
58
|
-
return formatTextContents(errorMessage);
|
|
60
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, errorMessage);
|
|
59
61
|
}
|
|
60
62
|
}
|
|
61
63
|
register() {
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { TextContentResponse, Tool } from '../../types.js';
|
|
2
2
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
declare const inputSchemaZodObject: z.ZodObject<{
|
|
4
|
+
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
|
+
}, "strip", z.ZodTypeAny, {
|
|
7
|
+
absoluteCurrentWorkingDirectory: string;
|
|
8
|
+
}, {
|
|
9
|
+
absoluteCurrentWorkingDirectory: string;
|
|
10
|
+
}>;
|
|
5
11
|
export type GetApplicationInfoInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
6
12
|
export declare class GetApplicationInfoTool extends Tool<GetApplicationInfoInputSchema> {
|
|
7
13
|
constructor(mcpServer: McpServer);
|
|
8
|
-
handler({}: GetApplicationInfoInputSchema): Promise<TextContentResponse>;
|
|
14
|
+
handler({ absoluteCurrentWorkingDirectory, }: GetApplicationInfoInputSchema): Promise<TextContentResponse>;
|
|
9
15
|
register(): RegisteredTool;
|
|
10
16
|
}
|
|
11
17
|
export {};
|
|
@@ -5,7 +5,8 @@ import { http } from '@hubspot/local-dev-lib/http';
|
|
|
5
5
|
import { formatTextContents } from '../../utils/content.js';
|
|
6
6
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
7
7
|
import { getAccountId } from '@hubspot/local-dev-lib/config';
|
|
8
|
-
|
|
8
|
+
import { absoluteCurrentWorkingDirectory } from './constants.js';
|
|
9
|
+
const inputSchema = { absoluteCurrentWorkingDirectory };
|
|
9
10
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
10
11
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
11
12
|
const toolName = 'get-applications-info';
|
|
@@ -13,14 +14,14 @@ export class GetApplicationInfoTool extends Tool {
|
|
|
13
14
|
constructor(mcpServer) {
|
|
14
15
|
super(mcpServer);
|
|
15
16
|
}
|
|
16
|
-
async handler({}) {
|
|
17
|
+
async handler({ absoluteCurrentWorkingDirectory, }) {
|
|
17
18
|
await trackToolUsage(toolName);
|
|
18
19
|
try {
|
|
19
20
|
// Get account ID from CLI config
|
|
20
21
|
const accountId = getAccountId();
|
|
21
22
|
if (!accountId) {
|
|
22
23
|
const authErrorMessage = `No account ID found. Please run \`hs account auth\` to configure an account, or set a default account with \`hs account use <account>\``;
|
|
23
|
-
return formatTextContents(authErrorMessage);
|
|
24
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, authErrorMessage);
|
|
24
25
|
}
|
|
25
26
|
const response = await http.get(accountId, {
|
|
26
27
|
url: `app/feature/utilization/public/v3/insights/apps`,
|
|
@@ -28,15 +29,15 @@ export class GetApplicationInfoTool extends Tool {
|
|
|
28
29
|
// Format the response for display
|
|
29
30
|
const { data } = response;
|
|
30
31
|
const formattedResult = JSON.stringify(data, null, 2);
|
|
31
|
-
return formatTextContents(formattedResult);
|
|
32
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, formattedResult);
|
|
32
33
|
}
|
|
33
34
|
catch (error) {
|
|
34
35
|
if (isHubSpotHttpError(error)) {
|
|
35
36
|
// Handle HubSpot-specific HTTP errors
|
|
36
|
-
return formatTextContents(error.toString());
|
|
37
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, error.toString());
|
|
37
38
|
}
|
|
38
39
|
const errorMessage = `${error instanceof Error ? error.message : String(error)}`;
|
|
39
|
-
return formatTextContents(errorMessage);
|
|
40
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, errorMessage);
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
register() {
|
|
@@ -26,12 +26,12 @@ export class GetConfigValuesTool extends Tool {
|
|
|
26
26
|
async handler({ absoluteCurrentWorkingDirectory, platformVersion, featureType, }) {
|
|
27
27
|
try {
|
|
28
28
|
if (!isV2Project(platformVersion)) {
|
|
29
|
-
return formatTextContents(`Can only be used on projects with a minimum platformVersion of 2025.2`);
|
|
29
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, `Can only be used on projects with a minimum platformVersion of 2025.2`);
|
|
30
30
|
}
|
|
31
31
|
const accountId = getAccountIdFromCliConfig(absoluteCurrentWorkingDirectory);
|
|
32
32
|
if (!accountId) {
|
|
33
33
|
const authErrorMessage = `No account ID found. Please run \`hs account auth\` to configure an account, or set a default account with \`hs account use <account>\``;
|
|
34
|
-
return formatTextContents(authErrorMessage);
|
|
34
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, authErrorMessage);
|
|
35
35
|
}
|
|
36
36
|
const schema = await getIntermediateRepresentationSchema({
|
|
37
37
|
platformVersion,
|
|
@@ -40,11 +40,11 @@ export class GetConfigValuesTool extends Tool {
|
|
|
40
40
|
});
|
|
41
41
|
const internalComponentType = mapToInternalType(featureType);
|
|
42
42
|
if (schema[internalComponentType]) {
|
|
43
|
-
return formatTextContents(JSON.stringify({ config: schema[internalComponentType] }));
|
|
43
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, JSON.stringify({ config: schema[internalComponentType] }));
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
catch (error) { }
|
|
47
|
-
return formatTextContents(`Unable to locate JSON schema for type ${featureType}`);
|
|
47
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, `Unable to locate JSON schema for type ${featureType}`);
|
|
48
48
|
}
|
|
49
49
|
register() {
|
|
50
50
|
return this.mcpServer.registerTool(toolName, {
|
|
@@ -2,16 +2,19 @@ import { TextContentResponse, Tool } from '../../types.js';
|
|
|
2
2
|
import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
5
6
|
command: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"hs init">, z.ZodLiteral<"hs auth">, z.ZodLiteral<"hs project create">, z.ZodLiteral<"hs project upload">]>>;
|
|
6
7
|
}, "strip", z.ZodTypeAny, {
|
|
8
|
+
absoluteCurrentWorkingDirectory: string;
|
|
7
9
|
command?: "hs auth" | "hs project create" | "hs project upload" | "hs init" | undefined;
|
|
8
10
|
}, {
|
|
11
|
+
absoluteCurrentWorkingDirectory: string;
|
|
9
12
|
command?: "hs auth" | "hs project create" | "hs project upload" | "hs init" | undefined;
|
|
10
13
|
}>;
|
|
11
14
|
type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
|
|
12
15
|
export declare class GuidedWalkthroughTool extends Tool<InputSchemaType> {
|
|
13
16
|
constructor(mcpServer: McpServer);
|
|
14
|
-
handler({ command }: InputSchemaType): Promise<TextContentResponse>;
|
|
17
|
+
handler({ absoluteCurrentWorkingDirectory, command, }: InputSchemaType): Promise<TextContentResponse>;
|
|
15
18
|
register(): RegisteredTool;
|
|
16
19
|
}
|
|
17
20
|
export {};
|
|
@@ -3,6 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { execAsync } from '../../utils/command.js';
|
|
4
4
|
import { formatTextContents } from '../../utils/content.js';
|
|
5
5
|
import { trackToolUsage } from '../../utils/toolUsageTracking.js';
|
|
6
|
+
import { absoluteCurrentWorkingDirectory } from './constants.js';
|
|
6
7
|
const nextCommands = {
|
|
7
8
|
'hs init': 'hs auth',
|
|
8
9
|
'hs auth': 'hs project create',
|
|
@@ -10,6 +11,7 @@ const nextCommands = {
|
|
|
10
11
|
'hs project upload': 'hs project dev',
|
|
11
12
|
};
|
|
12
13
|
const inputSchema = {
|
|
14
|
+
absoluteCurrentWorkingDirectory,
|
|
13
15
|
command: z
|
|
14
16
|
.union([
|
|
15
17
|
z.literal('hs init'),
|
|
@@ -29,29 +31,19 @@ export class GuidedWalkthroughTool extends Tool {
|
|
|
29
31
|
constructor(mcpServer) {
|
|
30
32
|
super(mcpServer);
|
|
31
33
|
}
|
|
32
|
-
async handler({ command }) {
|
|
34
|
+
async handler({ absoluteCurrentWorkingDirectory, command, }) {
|
|
33
35
|
await trackToolUsage(toolName);
|
|
34
36
|
if (command) {
|
|
35
37
|
const { stdout } = await execAsync(`${command} --help`);
|
|
36
|
-
return formatTextContents(`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]}` : ''}`);
|
|
38
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, `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]}` : ''}`);
|
|
37
39
|
}
|
|
38
|
-
return formatTextContents('Is there another command you would like to learn more about?');
|
|
40
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, 'Is there another command you would like to learn more about?');
|
|
39
41
|
}
|
|
40
42
|
register() {
|
|
41
43
|
return this.mcpServer.registerTool(toolName, {
|
|
42
44
|
title: 'Guided walkthrough of the CLI',
|
|
43
45
|
description: 'Give the user a guided walkthrough of the HubSpot CLI.',
|
|
44
|
-
inputSchema
|
|
45
|
-
command: z
|
|
46
|
-
.union([
|
|
47
|
-
z.literal('hs init'),
|
|
48
|
-
z.literal('hs auth'),
|
|
49
|
-
z.literal('hs project create'),
|
|
50
|
-
z.literal('hs project upload'),
|
|
51
|
-
])
|
|
52
|
-
.describe('The command to learn more about. Start with `hs init`')
|
|
53
|
-
.optional(),
|
|
54
|
-
},
|
|
46
|
+
inputSchema,
|
|
55
47
|
}, this.handler);
|
|
56
48
|
}
|
|
57
49
|
}
|
|
@@ -3,15 +3,18 @@ import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.
|
|
|
3
3
|
import z from 'zod';
|
|
4
4
|
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
5
|
absoluteProjectPath: z.ZodString;
|
|
6
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
7
|
}, "strip", z.ZodTypeAny, {
|
|
7
8
|
absoluteProjectPath: string;
|
|
9
|
+
absoluteCurrentWorkingDirectory: string;
|
|
8
10
|
}, {
|
|
9
11
|
absoluteProjectPath: string;
|
|
12
|
+
absoluteCurrentWorkingDirectory: string;
|
|
10
13
|
}>;
|
|
11
14
|
type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
|
|
12
15
|
export declare class UploadProjectTools extends Tool<InputSchemaType> {
|
|
13
16
|
constructor(mcpServer: McpServer);
|
|
14
|
-
handler({ absoluteProjectPath, }: InputSchemaType): Promise<TextContentResponse>;
|
|
17
|
+
handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, }: InputSchemaType): Promise<TextContentResponse>;
|
|
15
18
|
register(): RegisteredTool;
|
|
16
19
|
}
|
|
17
20
|
export {};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Tool } from '../../types.js';
|
|
2
2
|
import { runCommandInDir } from '../../utils/project.js';
|
|
3
|
-
import { absoluteProjectPath } from './constants.js';
|
|
3
|
+
import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
|
|
4
4
|
import z from 'zod';
|
|
5
5
|
import { formatTextContents } from '../../utils/content.js';
|
|
6
6
|
import { trackToolUsage } from '../../utils/toolUsageTracking.js';
|
|
7
7
|
const inputSchema = {
|
|
8
8
|
absoluteProjectPath,
|
|
9
|
+
absoluteCurrentWorkingDirectory,
|
|
9
10
|
};
|
|
10
11
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
12
|
const inputSchemaZodObject = z.object({
|
|
@@ -16,10 +17,10 @@ export class UploadProjectTools extends Tool {
|
|
|
16
17
|
constructor(mcpServer) {
|
|
17
18
|
super(mcpServer);
|
|
18
19
|
}
|
|
19
|
-
async handler({ absoluteProjectPath, }) {
|
|
20
|
+
async handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, }) {
|
|
20
21
|
await trackToolUsage(toolName);
|
|
21
22
|
const { stdout, stderr } = await runCommandInDir(absoluteProjectPath, `hs project upload --force-create`);
|
|
22
|
-
return formatTextContents(stdout, stderr);
|
|
23
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
|
|
23
24
|
}
|
|
24
25
|
register() {
|
|
25
26
|
return this.mcpServer.registerTool(toolName, {
|
|
@@ -3,15 +3,18 @@ import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
declare const inputSchemaZodObject: z.ZodObject<{
|
|
5
5
|
absoluteProjectPath: z.ZodString;
|
|
6
|
+
absoluteCurrentWorkingDirectory: z.ZodString;
|
|
6
7
|
}, "strip", z.ZodTypeAny, {
|
|
7
8
|
absoluteProjectPath: string;
|
|
9
|
+
absoluteCurrentWorkingDirectory: string;
|
|
8
10
|
}, {
|
|
9
11
|
absoluteProjectPath: string;
|
|
12
|
+
absoluteCurrentWorkingDirectory: string;
|
|
10
13
|
}>;
|
|
11
14
|
export type CreateProjectInputSchema = z.infer<typeof inputSchemaZodObject>;
|
|
12
15
|
export declare class ValidateProjectTool extends Tool<CreateProjectInputSchema> {
|
|
13
16
|
constructor(mcpServer: McpServer);
|
|
14
|
-
handler({ absoluteProjectPath, }: CreateProjectInputSchema): Promise<TextContentResponse>;
|
|
17
|
+
handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, }: CreateProjectInputSchema): Promise<TextContentResponse>;
|
|
15
18
|
register(): RegisteredTool;
|
|
16
19
|
}
|
|
17
20
|
export {};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { Tool } from '../../types.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { absoluteProjectPath } from './constants.js';
|
|
3
|
+
import { absoluteCurrentWorkingDirectory, absoluteProjectPath, } from './constants.js';
|
|
4
4
|
import { runCommandInDir } from '../../utils/project.js';
|
|
5
5
|
import { formatTextContents } from '../../utils/content.js';
|
|
6
6
|
import { trackToolUsage } from '../../utils/toolUsageTracking.js';
|
|
7
7
|
const inputSchema = {
|
|
8
8
|
absoluteProjectPath,
|
|
9
|
+
absoluteCurrentWorkingDirectory,
|
|
9
10
|
};
|
|
10
11
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
12
|
const inputSchemaZodObject = z.object({ ...inputSchema });
|
|
@@ -14,14 +15,14 @@ export class ValidateProjectTool extends Tool {
|
|
|
14
15
|
constructor(mcpServer) {
|
|
15
16
|
super(mcpServer);
|
|
16
17
|
}
|
|
17
|
-
async handler({ absoluteProjectPath, }) {
|
|
18
|
+
async handler({ absoluteProjectPath, absoluteCurrentWorkingDirectory, }) {
|
|
18
19
|
await trackToolUsage(toolName);
|
|
19
20
|
try {
|
|
20
21
|
const { stdout, stderr } = await runCommandInDir(absoluteProjectPath, 'hs project validate');
|
|
21
|
-
return formatTextContents(stdout, stderr);
|
|
22
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, stdout, stderr);
|
|
22
23
|
}
|
|
23
24
|
catch (error) {
|
|
24
|
-
return formatTextContents(error instanceof Error ? error.message : `${error}`);
|
|
25
|
+
return formatTextContents(absoluteCurrentWorkingDirectory, error instanceof Error ? error.message : `${error}`);
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
register() {
|
|
@@ -2,11 +2,14 @@ import { AddFeatureToProjectTool, } from '../AddFeatureToProjectTool.js';
|
|
|
2
2
|
import { runCommandInDir } from '../../../utils/project.js';
|
|
3
3
|
import { addFlag } from '../../../utils/command.js';
|
|
4
4
|
import { APP_AUTH_TYPES, APP_DISTRIBUTION_TYPES, } from '../../../../lib/constants.js';
|
|
5
|
+
import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
|
|
5
6
|
vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
|
|
6
7
|
vi.mock('../../../utils/project');
|
|
7
8
|
vi.mock('../../../utils/command');
|
|
8
9
|
vi.mock('../../../../lib/constants');
|
|
9
10
|
vi.mock('../../../utils/toolUsageTracking');
|
|
11
|
+
vi.mock('../../../utils/feedbackTracking');
|
|
12
|
+
const mockMcpFeedbackRequest = mcpFeedbackRequest;
|
|
10
13
|
const mockRunCommandInDir = runCommandInDir;
|
|
11
14
|
const mockAddFlag = addFlag;
|
|
12
15
|
describe('mcp-server/tools/project/AddFeatureToProject', () => {
|
|
@@ -21,6 +24,7 @@ describe('mcp-server/tools/project/AddFeatureToProject', () => {
|
|
|
21
24
|
};
|
|
22
25
|
mockRegisteredTool = {};
|
|
23
26
|
mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
|
|
27
|
+
mockMcpFeedbackRequest.mockResolvedValue('');
|
|
24
28
|
tool = new AddFeatureToProjectTool(mockMcpServer);
|
|
25
29
|
// Mock addFlag to simulate command building
|
|
26
30
|
mockAddFlag.mockImplementation((command, flag, value) => `${command} --${flag} "${value}"`);
|
|
@@ -32,12 +36,13 @@ describe('mcp-server/tools/project/AddFeatureToProject', () => {
|
|
|
32
36
|
title: 'Add feature to HubSpot Project',
|
|
33
37
|
description: expect.stringContaining('Adds a feature to an existing HubSpot project'),
|
|
34
38
|
inputSchema: expect.any(Object),
|
|
35
|
-
}),
|
|
39
|
+
}), expect.any(Function));
|
|
36
40
|
expect(result).toBe(mockRegisteredTool);
|
|
37
41
|
});
|
|
38
42
|
});
|
|
39
43
|
describe('handler', () => {
|
|
40
44
|
const baseInput = {
|
|
45
|
+
absoluteCurrentWorkingDirectory: '/test/dir',
|
|
41
46
|
absoluteProjectPath: '/test/project',
|
|
42
47
|
addApp: false,
|
|
43
48
|
};
|
|
@@ -2,12 +2,15 @@ import { CreateProjectTool, } from '../CreateProjectTool.js';
|
|
|
2
2
|
import { runCommandInDir } from '../../../utils/project.js';
|
|
3
3
|
import { addFlag } from '../../../utils/command.js';
|
|
4
4
|
import { APP_DISTRIBUTION_TYPES, EMPTY_PROJECT, PROJECT_WITH_APP, } from '../../../../lib/constants.js';
|
|
5
|
+
import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
|
|
5
6
|
vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
|
|
6
7
|
vi.mock('../../../utils/project');
|
|
7
8
|
vi.mock('../../../utils/command');
|
|
8
9
|
vi.mock('../../../../lib/constants');
|
|
9
10
|
vi.mock('../../../../lib/projects/create/v2');
|
|
10
11
|
vi.mock('../../../utils/toolUsageTracking');
|
|
12
|
+
vi.mock('../../../utils/feedbackTracking');
|
|
13
|
+
const mockMcpFeedbackRequest = mcpFeedbackRequest;
|
|
11
14
|
const mockRunCommandInDir = runCommandInDir;
|
|
12
15
|
const mockAddFlag = addFlag;
|
|
13
16
|
describe('mcp-server/tools/project/CreateProjectTool', () => {
|
|
@@ -22,6 +25,7 @@ describe('mcp-server/tools/project/CreateProjectTool', () => {
|
|
|
22
25
|
};
|
|
23
26
|
mockRegisteredTool = {};
|
|
24
27
|
mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
|
|
28
|
+
mockMcpFeedbackRequest.mockResolvedValue('');
|
|
25
29
|
tool = new CreateProjectTool(mockMcpServer);
|
|
26
30
|
// Mock addFlag to simulate command building
|
|
27
31
|
mockAddFlag.mockImplementation((command, flag, value) => `${command} --${flag} "${value}"`);
|
|
@@ -29,11 +33,11 @@ describe('mcp-server/tools/project/CreateProjectTool', () => {
|
|
|
29
33
|
describe('register', () => {
|
|
30
34
|
it('should register tool with correct parameters', () => {
|
|
31
35
|
const result = tool.register();
|
|
32
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-project', {
|
|
36
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('create-project', expect.objectContaining({
|
|
33
37
|
title: 'Create HubSpot Project',
|
|
34
|
-
description: 'Creates a HubSpot project with the provided name
|
|
38
|
+
description: expect.stringContaining('Creates a HubSpot project with the provided name'),
|
|
35
39
|
inputSchema: expect.any(Object),
|
|
36
|
-
},
|
|
40
|
+
}), expect.any(Function));
|
|
37
41
|
expect(result).toBe(mockRegisteredTool);
|
|
38
42
|
});
|
|
39
43
|
});
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { DeployProjectTool } from '../DeployProjectTool.js';
|
|
2
2
|
import { runCommandInDir } from '../../../utils/project.js';
|
|
3
3
|
import { addFlag } from '../../../utils/command.js';
|
|
4
|
+
import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
|
|
4
5
|
vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
|
|
5
6
|
vi.mock('../../../utils/project');
|
|
6
7
|
vi.mock('../../../utils/command');
|
|
7
8
|
vi.mock('../../../utils/toolUsageTracking');
|
|
9
|
+
vi.mock('../../../utils/feedbackTracking');
|
|
10
|
+
const mockMcpFeedbackRequest = mcpFeedbackRequest;
|
|
8
11
|
const mockRunCommandInDir = runCommandInDir;
|
|
9
12
|
const mockAddFlag = addFlag;
|
|
10
13
|
describe('mcp-server/tools/project/DeployProject', () => {
|
|
@@ -19,6 +22,7 @@ describe('mcp-server/tools/project/DeployProject', () => {
|
|
|
19
22
|
};
|
|
20
23
|
mockRegisteredTool = {};
|
|
21
24
|
mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
|
|
25
|
+
mockMcpFeedbackRequest.mockResolvedValue('');
|
|
22
26
|
tool = new DeployProjectTool(mockMcpServer);
|
|
23
27
|
// Mock addFlag to simulate command building
|
|
24
28
|
mockAddFlag.mockImplementation((command, flag, value) => `${command} --${flag} "${value}"`);
|
|
@@ -26,16 +30,17 @@ describe('mcp-server/tools/project/DeployProject', () => {
|
|
|
26
30
|
describe('register', () => {
|
|
27
31
|
it('should register tool with correct parameters', () => {
|
|
28
32
|
const result = tool.register();
|
|
29
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('deploy-project', {
|
|
33
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('deploy-project', expect.objectContaining({
|
|
30
34
|
title: 'Deploy a build of HubSpot Project',
|
|
31
35
|
description: expect.stringContaining('Takes a build number and a project name and deploys that build of the project'),
|
|
32
36
|
inputSchema: expect.any(Object),
|
|
33
|
-
},
|
|
37
|
+
}), expect.any(Function));
|
|
34
38
|
expect(result).toBe(mockRegisteredTool);
|
|
35
39
|
});
|
|
36
40
|
});
|
|
37
41
|
describe('handler', () => {
|
|
38
42
|
const baseInput = {
|
|
43
|
+
absoluteCurrentWorkingDirectory: '/test/dir',
|
|
39
44
|
absoluteProjectPath: '/test/project',
|
|
40
45
|
};
|
|
41
46
|
it('should deploy project with specified build number', async () => {
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { DocFetchTool } from '../DocFetchTool.js';
|
|
2
2
|
import { http } from '@hubspot/local-dev-lib/http/unauthed';
|
|
3
3
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
4
|
+
import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
|
|
4
5
|
vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
|
|
5
6
|
vi.mock('@hubspot/local-dev-lib/http/unauthed');
|
|
6
7
|
vi.mock('@hubspot/local-dev-lib/errors/index');
|
|
7
8
|
vi.mock('../../utils/toolUsageTracking');
|
|
9
|
+
vi.mock('../../../utils/feedbackTracking');
|
|
10
|
+
const mockMcpFeedbackRequest = mcpFeedbackRequest;
|
|
8
11
|
const mockHttp = http;
|
|
9
12
|
const mockIsHubSpotHttpError = vi.mocked(isHubSpotHttpError);
|
|
10
13
|
describe('mcp-server/tools/project/DocFetchTool', () => {
|
|
@@ -19,21 +22,23 @@ describe('mcp-server/tools/project/DocFetchTool', () => {
|
|
|
19
22
|
};
|
|
20
23
|
mockRegisteredTool = {};
|
|
21
24
|
mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
|
|
25
|
+
mockMcpFeedbackRequest.mockResolvedValue('');
|
|
22
26
|
tool = new DocFetchTool(mockMcpServer);
|
|
23
27
|
});
|
|
24
28
|
describe('register', () => {
|
|
25
29
|
it('should register tool with correct parameters', () => {
|
|
26
30
|
const result = tool.register();
|
|
27
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('fetch-doc', {
|
|
31
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('fetch-doc', expect.objectContaining({
|
|
28
32
|
title: 'Fetch HubSpot Developer Documentation (single file)',
|
|
29
|
-
description: 'Always use this immediately after `search-docs`
|
|
33
|
+
description: expect.stringContaining('Always use this immediately after `search-docs`'),
|
|
30
34
|
inputSchema: expect.any(Object),
|
|
31
|
-
},
|
|
35
|
+
}), expect.any(Function));
|
|
32
36
|
expect(result).toBe(mockRegisteredTool);
|
|
33
37
|
});
|
|
34
38
|
});
|
|
35
39
|
describe('handler', () => {
|
|
36
40
|
const mockInput = {
|
|
41
|
+
absoluteCurrentWorkingDirectory: '/test/dir',
|
|
37
42
|
docUrl: 'https://example.com/docs/test-doc',
|
|
38
43
|
};
|
|
39
44
|
it('should successfully fetch and return markdown content', async () => {
|
|
@@ -2,11 +2,14 @@ import { DocsSearchTool } from '../DocsSearchTool.js';
|
|
|
2
2
|
import { http } from '@hubspot/local-dev-lib/http';
|
|
3
3
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
4
4
|
import { getAccountIdFromCliConfig } from '../../../utils/cliConfig.js';
|
|
5
|
+
import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
|
|
5
6
|
vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
|
|
6
7
|
vi.mock('@hubspot/local-dev-lib/http');
|
|
7
8
|
vi.mock('@hubspot/local-dev-lib/errors/index');
|
|
8
9
|
vi.mock('../../../utils/toolUsageTracking');
|
|
9
10
|
vi.mock('../../../utils/cliConfig.js');
|
|
11
|
+
vi.mock('../../../utils/feedbackTracking');
|
|
12
|
+
const mockMcpFeedbackRequest = mcpFeedbackRequest;
|
|
10
13
|
const mockHttp = http;
|
|
11
14
|
const mockGetAccountIdFromCliConfig = getAccountIdFromCliConfig;
|
|
12
15
|
const mockIsHubSpotHttpError = vi.mocked(isHubSpotHttpError);
|
|
@@ -22,16 +25,17 @@ describe('mcp-server/tools/project/DocsSearchTool', () => {
|
|
|
22
25
|
};
|
|
23
26
|
mockRegisteredTool = {};
|
|
24
27
|
mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
|
|
28
|
+
mockMcpFeedbackRequest.mockResolvedValue('');
|
|
25
29
|
tool = new DocsSearchTool(mockMcpServer);
|
|
26
30
|
});
|
|
27
31
|
describe('register', () => {
|
|
28
|
-
it('should register tool with correct parameters', () => {
|
|
32
|
+
it('should register tool with correct parameters and enhanced description', () => {
|
|
29
33
|
const result = tool.register();
|
|
30
34
|
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('search-docs', {
|
|
31
35
|
title: 'Search HubSpot Developer Documentation',
|
|
32
36
|
description: 'Use this first whenever you need details about HubSpot APIs, SDKs, integrations, or developer platform features. This searches the official HubSpot Developer Documentation and returns the most relevant pages, each with a URL for use in `fetch-doc`. Always follow this with a fetch to get the full, authoritative content before making plans or writing answers.',
|
|
33
37
|
inputSchema: expect.any(Object),
|
|
34
|
-
},
|
|
38
|
+
}, expect.any(Function));
|
|
35
39
|
expect(result).toBe(mockRegisteredTool);
|
|
36
40
|
});
|
|
37
41
|
});
|
|
@@ -3,11 +3,14 @@ import { z } from 'zod';
|
|
|
3
3
|
import { getAccountId } from '@hubspot/local-dev-lib/config';
|
|
4
4
|
import { http } from '@hubspot/local-dev-lib/http';
|
|
5
5
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
6
|
+
import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
|
|
6
7
|
vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
|
|
7
8
|
vi.mock('../../../utils/toolUsageTracking');
|
|
8
9
|
vi.mock('@hubspot/local-dev-lib/http');
|
|
9
10
|
vi.mock('@hubspot/local-dev-lib/errors/index');
|
|
10
11
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
12
|
+
vi.mock('../../../utils/feedbackTracking');
|
|
13
|
+
const mockMcpFeedbackRequest = mcpFeedbackRequest;
|
|
11
14
|
const mockGetAccountId = getAccountId;
|
|
12
15
|
const mockHttp = http;
|
|
13
16
|
const mockIsHubSpotHttpError = isHubSpotHttpError;
|
|
@@ -23,14 +26,15 @@ describe('mcp-server/tools/project/GetApiUsagePatternsByAppIdTool', () => {
|
|
|
23
26
|
};
|
|
24
27
|
mockRegisteredTool = {};
|
|
25
28
|
mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
|
|
29
|
+
mockMcpFeedbackRequest.mockResolvedValue('');
|
|
26
30
|
tool = new GetApiUsagePatternsByAppIdTool(mockMcpServer);
|
|
27
31
|
});
|
|
28
32
|
describe('register', () => {
|
|
29
33
|
it('should register tool with correct parameters', () => {
|
|
30
34
|
const result = tool.register();
|
|
31
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-api-usage-patterns-by-app-id', {
|
|
35
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-api-usage-patterns-by-app-id', expect.objectContaining({
|
|
32
36
|
title: 'Get API Usage Patterns by App ID',
|
|
33
|
-
description: 'Retrieves detailed API usage pattern analytics for a specific HubSpot application
|
|
37
|
+
description: expect.stringContaining('Retrieves detailed API usage pattern analytics for a specific HubSpot application'),
|
|
34
38
|
inputSchema: expect.objectContaining({
|
|
35
39
|
appId: expect.objectContaining({
|
|
36
40
|
describe: expect.any(Function),
|
|
@@ -42,7 +46,7 @@ describe('mcp-server/tools/project/GetApiUsagePatternsByAppIdTool', () => {
|
|
|
42
46
|
optional: expect.any(Function),
|
|
43
47
|
}),
|
|
44
48
|
}),
|
|
45
|
-
},
|
|
49
|
+
}), expect.any(Function));
|
|
46
50
|
expect(result).toBe(mockRegisteredTool);
|
|
47
51
|
});
|
|
48
52
|
});
|
|
@@ -79,6 +83,7 @@ describe('mcp-server/tools/project/GetApiUsagePatternsByAppIdTool', () => {
|
|
|
79
83
|
});
|
|
80
84
|
describe('handler', () => {
|
|
81
85
|
const input = {
|
|
86
|
+
absoluteCurrentWorkingDirectory: '/test/dir',
|
|
82
87
|
appId: '12345',
|
|
83
88
|
startDate: '2025-01-01',
|
|
84
89
|
endDate: '2025-12-31',
|
|
@@ -2,11 +2,14 @@ import { GetApplicationInfoTool } from '../GetApplicationInfoTool.js';
|
|
|
2
2
|
import { getAccountId } from '@hubspot/local-dev-lib/config';
|
|
3
3
|
import { http } from '@hubspot/local-dev-lib/http';
|
|
4
4
|
import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
|
|
5
|
+
import { mcpFeedbackRequest } from '../../../utils/feedbackTracking.js';
|
|
5
6
|
vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
|
|
6
7
|
vi.mock('../../utils/toolUsageTracking');
|
|
7
8
|
vi.mock('@hubspot/local-dev-lib/http');
|
|
8
9
|
vi.mock('@hubspot/local-dev-lib/errors/index');
|
|
9
10
|
vi.mock('@hubspot/local-dev-lib/config');
|
|
11
|
+
vi.mock('../../../utils/feedbackTracking');
|
|
12
|
+
const mockMcpFeedbackRequest = mcpFeedbackRequest;
|
|
10
13
|
const mockGetAccountId = getAccountId;
|
|
11
14
|
const mockHttp = http;
|
|
12
15
|
const mockIsHubSpotHttpError = isHubSpotHttpError;
|
|
@@ -22,21 +25,22 @@ describe('mcp-server/tools/project/GetApplicationInfoTool', () => {
|
|
|
22
25
|
};
|
|
23
26
|
mockRegisteredTool = {};
|
|
24
27
|
mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
|
|
28
|
+
mockMcpFeedbackRequest.mockResolvedValue('');
|
|
25
29
|
tool = new GetApplicationInfoTool(mockMcpServer);
|
|
26
30
|
});
|
|
27
31
|
describe('register', () => {
|
|
28
32
|
it('should register tool with correct parameters', () => {
|
|
29
33
|
const result = tool.register();
|
|
30
|
-
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-applications-info', {
|
|
34
|
+
expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-applications-info', expect.objectContaining({
|
|
31
35
|
title: 'Get Applications Information',
|
|
32
|
-
description: 'Retrieves a list of all HubSpot applications available in the current account
|
|
33
|
-
inputSchema:
|
|
34
|
-
},
|
|
36
|
+
description: expect.stringContaining('Retrieves a list of all HubSpot applications available in the current account'),
|
|
37
|
+
inputSchema: expect.any(Object),
|
|
38
|
+
}), expect.any(Function));
|
|
35
39
|
expect(result).toBe(mockRegisteredTool);
|
|
36
40
|
});
|
|
37
41
|
});
|
|
38
42
|
describe('handler', () => {
|
|
39
|
-
const input = {};
|
|
43
|
+
const input = { absoluteCurrentWorkingDirectory: '/test/dir' };
|
|
40
44
|
beforeEach(() => {
|
|
41
45
|
mockGetAccountId.mockReturnValue(123456789);
|
|
42
46
|
mockIsHubSpotHttpError.mockReturnValue(false);
|