@hubspot/cli 7.6.0-beta.7 → 7.6.0-beta.8

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.
@@ -5,6 +5,8 @@ import { DeployProjectTool } from './project/DeployProjectTool.js';
5
5
  import { AddFeatureToProjectTool } from './project/AddFeatureToProjectTool.js';
6
6
  import { ValidateProjectTool } from './project/ValidateProjectTool.js';
7
7
  import { GetConfigValuesTool } from './project/GetConfigValuesTool.js';
8
+ import { DocsSearchTool } from './project/DocsSearchTool.js';
9
+ import { DocFetchTool } from './project/DocFetchTool.js';
8
10
  export function registerProjectTools(mcpServer) {
9
11
  return [
10
12
  new UploadProjectTools(mcpServer).register(),
@@ -14,5 +16,7 @@ export function registerProjectTools(mcpServer) {
14
16
  new AddFeatureToProjectTool(mcpServer).register(),
15
17
  new ValidateProjectTool(mcpServer).register(),
16
18
  new GetConfigValuesTool(mcpServer).register(),
19
+ new DocsSearchTool(mcpServer).register(),
20
+ new DocFetchTool(mcpServer).register(),
17
21
  ];
18
22
  }
@@ -0,0 +1,17 @@
1
+ import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import z from 'zod';
3
+ import { TextContentResponse, Tool } from '../../types.js';
4
+ declare const inputSchemaZodObject: z.ZodObject<{
5
+ docUrl: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ docUrl: string;
8
+ }, {
9
+ docUrl: string;
10
+ }>;
11
+ type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
12
+ export declare class DocFetchTool extends Tool<InputSchemaType> {
13
+ constructor(mcpServer: McpServer);
14
+ handler({ docUrl }: InputSchemaType): Promise<TextContentResponse>;
15
+ register(): RegisteredTool;
16
+ }
17
+ export {};
@@ -0,0 +1,49 @@
1
+ import z from 'zod';
2
+ import { Tool } from '../../types.js';
3
+ import { formatTextContents } from '../../utils/content.js';
4
+ import { trackToolUsage } from '../../utils/toolUsageTracking.js';
5
+ import { docUrl } from './constants.js';
6
+ import { http } from '@hubspot/local-dev-lib/http/unauthed';
7
+ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
8
+ const inputSchema = {
9
+ docUrl,
10
+ };
11
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
12
+ const inputSchemaZodObject = z.object({
13
+ ...inputSchema,
14
+ });
15
+ const toolName = 'fetch-hubspot-doc';
16
+ export class DocFetchTool extends Tool {
17
+ constructor(mcpServer) {
18
+ super(mcpServer);
19
+ }
20
+ async handler({ docUrl }) {
21
+ await trackToolUsage(toolName);
22
+ try {
23
+ // Append .md extension to the URL
24
+ const markdownUrl = `${docUrl}.md`;
25
+ const response = await http.get({
26
+ url: markdownUrl,
27
+ });
28
+ const content = response.data;
29
+ if (!content || content.trim().length === 0) {
30
+ return formatTextContents('Document is empty or contains no content.');
31
+ }
32
+ return formatTextContents(content);
33
+ }
34
+ catch (error) {
35
+ if (isHubSpotHttpError(error)) {
36
+ return formatTextContents(error.toString());
37
+ }
38
+ const errorMessage = `Error fetching documentation: ${error instanceof Error ? error.message : String(error)}`;
39
+ return formatTextContents(errorMessage);
40
+ }
41
+ }
42
+ register() {
43
+ return this.mcpServer.registerTool(toolName, {
44
+ title: 'Fetch a single HubSpot Developer Documentation file',
45
+ description: 'Fetch a single HubSpot Developer Documentation file by URL. Call after search-hubspot-docs.',
46
+ inputSchema,
47
+ }, this.handler);
48
+ }
49
+ }
@@ -0,0 +1,26 @@
1
+ import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import z from 'zod';
3
+ import { TextContentResponse, Tool } from '../../types.js';
4
+ declare const inputSchemaZodObject: z.ZodObject<{
5
+ docsSearchQuery: z.ZodString;
6
+ }, "strip", z.ZodTypeAny, {
7
+ docsSearchQuery: string;
8
+ }, {
9
+ docsSearchQuery: string;
10
+ }>;
11
+ export interface DocsSearchResponse {
12
+ results: {
13
+ title: string;
14
+ content: string;
15
+ description: string;
16
+ url: string;
17
+ score: number;
18
+ }[];
19
+ }
20
+ type InputSchemaType = z.infer<typeof inputSchemaZodObject>;
21
+ export declare class DocsSearchTool extends Tool<InputSchemaType> {
22
+ constructor(mcpServer: McpServer);
23
+ handler({ docsSearchQuery, }: InputSchemaType): Promise<TextContentResponse>;
24
+ register(): RegisteredTool;
25
+ }
26
+ export {};
@@ -0,0 +1,62 @@
1
+ import { http } from '@hubspot/local-dev-lib/http';
2
+ import z from 'zod';
3
+ import { Tool } from '../../types.js';
4
+ import { formatTextContents } from '../../utils/content.js';
5
+ import { trackToolUsage } from '../../utils/toolUsageTracking.js';
6
+ import { docsSearchQuery } from './constants.js';
7
+ import { getAccountId, getConfigPath, loadConfig, } from '@hubspot/local-dev-lib/config';
8
+ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
9
+ const inputSchema = {
10
+ docsSearchQuery,
11
+ };
12
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
13
+ const inputSchemaZodObject = z.object({
14
+ ...inputSchema,
15
+ });
16
+ const toolName = 'search-hubspot-docs';
17
+ export class DocsSearchTool extends Tool {
18
+ constructor(mcpServer) {
19
+ super(mcpServer);
20
+ }
21
+ async handler({ docsSearchQuery, }) {
22
+ await trackToolUsage(toolName, { mode: docsSearchQuery });
23
+ loadConfig(getConfigPath());
24
+ const accountId = getAccountId();
25
+ if (!accountId) {
26
+ const authErrorMessage = `No account ID found. Please run \`hs account auth\` to configure an account, or set a default account with \`hs account use <account>\``;
27
+ return formatTextContents(authErrorMessage);
28
+ }
29
+ try {
30
+ const response = await http.post(accountId, {
31
+ url: 'dev/docs/llms/v1/docs-search',
32
+ data: {
33
+ query: docsSearchQuery,
34
+ },
35
+ });
36
+ const results = response.data.results;
37
+ if (!results || results.length === 0) {
38
+ return formatTextContents('No documentation found for your query.');
39
+ }
40
+ const formattedResults = results
41
+ .map(result => `**${result.title}**\n${result.description}\nURL: ${result.url}\nScore: ${result.score}\n\n${result.content}\n---\n`)
42
+ .join('\n');
43
+ const successMessage = `Found ${results.length} documentation results:\n\n${formattedResults}`;
44
+ return formatTextContents(successMessage);
45
+ }
46
+ catch (error) {
47
+ if (isHubSpotHttpError(error)) {
48
+ // Handle different status codes
49
+ return formatTextContents(error.toString());
50
+ }
51
+ const errorMessage = `Error searching documentation: ${error instanceof Error ? error.message : String(error)}`;
52
+ return formatTextContents(errorMessage);
53
+ }
54
+ }
55
+ register() {
56
+ return this.mcpServer.registerTool(toolName, {
57
+ title: 'Search the HubSpot docs',
58
+ description: 'Search the HubSpot docs for information. This will return results that include a url to be used in fetch-hubspot-doc.',
59
+ inputSchema,
60
+ }, this.handler);
61
+ }
62
+ }
@@ -2,7 +2,7 @@ import { Tool } from '../../types.js';
2
2
  import { z } from 'zod';
3
3
  import { formatTextContents } from '../../utils/content.js';
4
4
  import { getIntermediateRepresentationSchema, mapToInternalType, } from '@hubspot/project-parsing-lib';
5
- import { getAccountId } from '@hubspot/local-dev-lib/config';
5
+ import { getAccountId, getConfigPath, loadConfig, } from '@hubspot/local-dev-lib/config';
6
6
  import { useV3Api } from '../../../lib/projects/buildAndDeploy.js';
7
7
  const inputSchema = {
8
8
  platformVersion: z
@@ -16,7 +16,7 @@ const inputSchema = {
16
16
  const inputSchemaZodObject = z.object({
17
17
  ...inputSchema,
18
18
  });
19
- const toolName = 'get-hubspot-project-feature-config-schema';
19
+ const toolName = 'get-hubspot-feature-config-schema';
20
20
  export class GetConfigValuesTool extends Tool {
21
21
  constructor(mcpServer) {
22
22
  super(mcpServer);
@@ -26,6 +26,7 @@ export class GetConfigValuesTool extends Tool {
26
26
  if (!useV3Api(platformVersion)) {
27
27
  return formatTextContents(`Can only be used on projects with a minimum platformVersion of 2025.2`);
28
28
  }
29
+ loadConfig(getConfigPath());
29
30
  const schema = await getIntermediateRepresentationSchema({
30
31
  platformVersion,
31
32
  projectSourceDir: '',
@@ -0,0 +1,117 @@
1
+ import { DocFetchTool } from '../DocFetchTool.js';
2
+ import { http } from '@hubspot/local-dev-lib/http/unauthed';
3
+ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
4
+ vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
5
+ vi.mock('@hubspot/local-dev-lib/http/unauthed');
6
+ vi.mock('@hubspot/local-dev-lib/errors/index');
7
+ vi.mock('../../utils/toolUsageTracking');
8
+ const mockHttp = http;
9
+ const mockIsHubSpotHttpError = vi.mocked(isHubSpotHttpError);
10
+ describe('mcp-server/tools/project/DocFetchTool', () => {
11
+ let mockMcpServer;
12
+ let tool;
13
+ let mockRegisteredTool;
14
+ beforeEach(() => {
15
+ vi.clearAllMocks();
16
+ // @ts-expect-error Not mocking whole server
17
+ mockMcpServer = {
18
+ registerTool: vi.fn(),
19
+ };
20
+ mockRegisteredTool = {};
21
+ mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
22
+ tool = new DocFetchTool(mockMcpServer);
23
+ });
24
+ describe('register', () => {
25
+ it('should register tool with correct parameters', () => {
26
+ const result = tool.register();
27
+ expect(mockMcpServer.registerTool).toHaveBeenCalledWith('fetch-hubspot-doc', {
28
+ title: 'Fetch a single HubSpot Developer Documentation file',
29
+ description: 'Fetch a single HubSpot Developer Documentation file by URL. Call after search-hubspot-docs.',
30
+ inputSchema: expect.any(Object),
31
+ }, tool.handler);
32
+ expect(result).toBe(mockRegisteredTool);
33
+ });
34
+ });
35
+ describe('handler', () => {
36
+ const mockInput = {
37
+ docUrl: 'https://example.com/docs/test-doc',
38
+ };
39
+ it('should successfully fetch and return markdown content', async () => {
40
+ const mockContent = '# Test Document\n\nThis is a test markdown document.';
41
+ // @ts-expect-error - Mocking axios response structure
42
+ mockHttp.get.mockResolvedValue({
43
+ data: mockContent,
44
+ });
45
+ const result = await tool.handler(mockInput);
46
+ expect(mockHttp.get).toHaveBeenCalledWith({
47
+ url: 'https://example.com/docs/test-doc.md',
48
+ });
49
+ expect(result).toEqual({
50
+ content: [
51
+ {
52
+ type: 'text',
53
+ text: mockContent,
54
+ },
55
+ ],
56
+ });
57
+ });
58
+ it('should handle HubSpot HTTP errors', async () => {
59
+ const mockError = {
60
+ toString: () => 'HubSpotHttpError: \n- message: The request was not found.\n- status: 404\n- statusText: Not Found\n- method: get\n- code: ERR_BAD_REQUEST\n- derivedContext: {\n "request": "https://example.com/docs/test-doc.md"\n}',
61
+ };
62
+ mockHttp.get.mockRejectedValue(mockError);
63
+ mockIsHubSpotHttpError.mockReturnValue(true);
64
+ const result = await tool.handler(mockInput);
65
+ expect(result).toEqual({
66
+ content: [
67
+ {
68
+ type: 'text',
69
+ text: 'HubSpotHttpError: \n- message: The request was not found.\n- status: 404\n- statusText: Not Found\n- method: get\n- code: ERR_BAD_REQUEST\n- derivedContext: {\n "request": "https://example.com/docs/test-doc.md"\n}',
70
+ },
71
+ ],
72
+ });
73
+ });
74
+ it('should handle empty content', async () => {
75
+ // @ts-expect-error - Mocking axios response structure
76
+ mockHttp.get.mockResolvedValue({
77
+ data: ' ',
78
+ });
79
+ const result = await tool.handler(mockInput);
80
+ expect(result).toEqual({
81
+ content: [
82
+ {
83
+ type: 'text',
84
+ text: 'Document is empty or contains no content.',
85
+ },
86
+ ],
87
+ });
88
+ });
89
+ it('should handle generic errors', async () => {
90
+ const mockError = new Error('Network error');
91
+ mockHttp.get.mockRejectedValue(mockError);
92
+ mockIsHubSpotHttpError.mockReturnValue(false);
93
+ const result = await tool.handler(mockInput);
94
+ expect(result).toEqual({
95
+ content: [
96
+ {
97
+ type: 'text',
98
+ text: 'Error fetching documentation: Network error',
99
+ },
100
+ ],
101
+ });
102
+ });
103
+ it('should handle non-Error rejections', async () => {
104
+ mockHttp.get.mockRejectedValue('String error');
105
+ mockIsHubSpotHttpError.mockReturnValue(false);
106
+ const result = await tool.handler(mockInput);
107
+ expect(result).toEqual({
108
+ content: [
109
+ {
110
+ type: 'text',
111
+ text: 'Error fetching documentation: String error',
112
+ },
113
+ ],
114
+ });
115
+ });
116
+ });
117
+ });
@@ -0,0 +1,190 @@
1
+ import { DocsSearchTool } from '../DocsSearchTool.js';
2
+ import { http } from '@hubspot/local-dev-lib/http';
3
+ import { getAccountId } from '@hubspot/local-dev-lib/config';
4
+ import { isHubSpotHttpError } from '@hubspot/local-dev-lib/errors/index';
5
+ vi.mock('@modelcontextprotocol/sdk/server/mcp.js');
6
+ vi.mock('@hubspot/local-dev-lib/http');
7
+ vi.mock('@hubspot/local-dev-lib/config');
8
+ vi.mock('@hubspot/local-dev-lib/errors/index');
9
+ vi.mock('../../../utils/toolUsageTracking');
10
+ const mockHttp = http;
11
+ const mockGetAccountId = getAccountId;
12
+ const mockIsHubSpotHttpError = vi.mocked(isHubSpotHttpError);
13
+ describe('mcp-server/tools/project/DocsSearchTool', () => {
14
+ let mockMcpServer;
15
+ let tool;
16
+ let mockRegisteredTool;
17
+ beforeEach(() => {
18
+ vi.clearAllMocks();
19
+ // @ts-expect-error Not mocking whole server
20
+ mockMcpServer = {
21
+ registerTool: vi.fn(),
22
+ };
23
+ mockRegisteredTool = {};
24
+ mockMcpServer.registerTool.mockReturnValue(mockRegisteredTool);
25
+ tool = new DocsSearchTool(mockMcpServer);
26
+ });
27
+ describe('register', () => {
28
+ it('should register tool with correct parameters', () => {
29
+ const result = tool.register();
30
+ expect(mockMcpServer.registerTool).toHaveBeenCalledWith('search-hubspot-docs', {
31
+ title: 'Search the HubSpot docs',
32
+ description: 'Search the HubSpot docs for information. This will return results that include a url to be used in fetch-hubspot-doc.',
33
+ inputSchema: expect.any(Object),
34
+ }, tool.handler);
35
+ expect(result).toBe(mockRegisteredTool);
36
+ });
37
+ });
38
+ describe('handler', () => {
39
+ const mockInput = {
40
+ docsSearchQuery: 'test query',
41
+ };
42
+ it('should return auth error message when no account ID is found', async () => {
43
+ mockGetAccountId.mockReturnValue(null);
44
+ const result = await tool.handler(mockInput);
45
+ expect(result).toEqual({
46
+ content: [
47
+ {
48
+ type: 'text',
49
+ text: 'No account ID found. Please run `hs account auth` to configure an account, or set a default account with `hs account use <account>`',
50
+ },
51
+ ],
52
+ });
53
+ });
54
+ it('should return successful results when docs are found', async () => {
55
+ mockGetAccountId.mockReturnValue(12345);
56
+ const mockResponse = {
57
+ results: [
58
+ {
59
+ title: 'Test Doc 1',
60
+ content: 'Test content 1',
61
+ description: 'Test description 1',
62
+ url: 'https://example.com/doc1',
63
+ score: 0.9,
64
+ },
65
+ {
66
+ title: 'Test Doc 2',
67
+ content: 'Test content 2',
68
+ description: 'Test description 2',
69
+ url: 'https://example.com/doc2',
70
+ score: 0.8,
71
+ },
72
+ ],
73
+ };
74
+ // @ts-expect-error - Mocking axios response structure
75
+ mockHttp.post.mockResolvedValue({
76
+ data: mockResponse,
77
+ });
78
+ const result = await tool.handler(mockInput);
79
+ expect(mockHttp.post).toHaveBeenCalledWith(12345, {
80
+ url: 'dev/docs/llms/v1/docs-search',
81
+ data: {
82
+ query: 'test query',
83
+ },
84
+ });
85
+ expect(result).toEqual({
86
+ content: [
87
+ {
88
+ type: 'text',
89
+ text: expect.stringContaining('Found 2 documentation results:'),
90
+ },
91
+ ],
92
+ });
93
+ const resultText = result.content[0].text;
94
+ expect(resultText).toContain('**Test Doc 1**');
95
+ expect(resultText).toContain('Test description 1');
96
+ expect(resultText).toContain('https://example.com/doc1');
97
+ expect(resultText).toContain('Score: 0.9');
98
+ expect(resultText).toContain('Test content 1');
99
+ expect(resultText).toContain('**Test Doc 2**');
100
+ expect(resultText).toContain('Test description 2');
101
+ expect(resultText).toContain('https://example.com/doc2');
102
+ expect(resultText).toContain('Score: 0.8');
103
+ expect(resultText).toContain('Test content 2');
104
+ });
105
+ it('should return no results message when no documentation is found', async () => {
106
+ mockGetAccountId.mockReturnValue(12345);
107
+ const mockResponse = {
108
+ results: [],
109
+ };
110
+ // @ts-expect-error - Mocking axios response structure
111
+ mockHttp.post.mockResolvedValue({
112
+ data: mockResponse,
113
+ });
114
+ const result = await tool.handler(mockInput);
115
+ expect(result).toEqual({
116
+ content: [
117
+ {
118
+ type: 'text',
119
+ text: 'No documentation found for your query.',
120
+ },
121
+ ],
122
+ });
123
+ });
124
+ it('should return no results message when results is null', async () => {
125
+ mockGetAccountId.mockReturnValue(12345);
126
+ const mockResponse = {
127
+ results: null,
128
+ };
129
+ // @ts-expect-error - Mocking axios response structure
130
+ mockHttp.post.mockResolvedValue({
131
+ data: mockResponse,
132
+ });
133
+ const result = await tool.handler(mockInput);
134
+ expect(result).toEqual({
135
+ content: [
136
+ {
137
+ type: 'text',
138
+ text: 'No documentation found for your query.',
139
+ },
140
+ ],
141
+ });
142
+ });
143
+ it('should handle HubSpot HTTP errors', async () => {
144
+ mockGetAccountId.mockReturnValue(12345);
145
+ const mockError = {
146
+ toString: () => 'HubSpot API Error: 404 Not Found',
147
+ };
148
+ mockHttp.post.mockRejectedValue(mockError);
149
+ mockIsHubSpotHttpError.mockReturnValue(true);
150
+ const result = await tool.handler(mockInput);
151
+ expect(result).toEqual({
152
+ content: [
153
+ {
154
+ type: 'text',
155
+ text: 'HubSpot API Error: 404 Not Found',
156
+ },
157
+ ],
158
+ });
159
+ });
160
+ it('should handle generic errors', async () => {
161
+ mockGetAccountId.mockReturnValue(12345);
162
+ const mockError = new Error('Network error');
163
+ mockHttp.post.mockRejectedValue(mockError);
164
+ mockIsHubSpotHttpError.mockReturnValue(false);
165
+ const result = await tool.handler(mockInput);
166
+ expect(result).toEqual({
167
+ content: [
168
+ {
169
+ type: 'text',
170
+ text: 'Error searching documentation: Network error',
171
+ },
172
+ ],
173
+ });
174
+ });
175
+ it('should handle non-Error rejections', async () => {
176
+ mockGetAccountId.mockReturnValue(12345);
177
+ mockHttp.post.mockRejectedValue('String error');
178
+ mockIsHubSpotHttpError.mockReturnValue(false);
179
+ const result = await tool.handler(mockInput);
180
+ expect(result).toEqual({
181
+ content: [
182
+ {
183
+ type: 'text',
184
+ text: 'Error searching documentation: String error',
185
+ },
186
+ ],
187
+ });
188
+ });
189
+ });
190
+ });
@@ -25,7 +25,7 @@ describe('mcp-server/tools/project/GetConfigValuesTool', () => {
25
25
  describe('register', () => {
26
26
  it('should register tool with correct parameters', () => {
27
27
  const result = tool.register();
28
- expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-hubspot-project-feature-config-schema', {
28
+ expect(mockMcpServer.registerTool).toHaveBeenCalledWith('get-hubspot-feature-config-schema', {
29
29
  title: 'Fetch the JSON Schema for component',
30
30
  description: expect.stringContaining('Fetches and returns the JSON schema for the provided feature'),
31
31
  inputSchema: expect.objectContaining({
@@ -2,3 +2,5 @@ import z from 'zod';
2
2
  export declare const absoluteProjectPath: z.ZodString;
3
3
  export declare const absoluteCurrentWorkingDirectory: z.ZodString;
4
4
  export declare const features: z.ZodOptional<z.ZodArray<z.ZodUnion<[z.ZodLiteral<"card">, z.ZodLiteral<"settings">, z.ZodLiteral<"app-function">, z.ZodLiteral<"webhooks">, z.ZodLiteral<"workflow-action">]>, "many">>;
5
+ export declare const docsSearchQuery: z.ZodString;
6
+ export declare const docUrl: z.ZodString;
@@ -16,3 +16,9 @@ export const features = z
16
16
  ])
17
17
  .describe('The features to include in the project, multiple options can be selected'))
18
18
  .optional();
19
+ export const docsSearchQuery = z
20
+ .string()
21
+ .describe('The query to search the HubSpot Developer Documentation for.');
22
+ export const docUrl = z
23
+ .string()
24
+ .describe('The URL of the HubSpot Developer Documentation to fetch.');
@@ -1 +1,3 @@
1
- export declare function trackToolUsage(toolName: string): Promise<void>;
1
+ export declare function trackToolUsage(toolName: string, meta?: {
2
+ [key: string]: string;
3
+ }): Promise<void>;
@@ -2,7 +2,7 @@ import { trackUsage } from '@hubspot/local-dev-lib/trackUsage';
2
2
  import { logger } from '@hubspot/local-dev-lib/logger';
3
3
  import { EventClass, getNodeVersionData, getPlatform, } from '../../lib/usageTracking.js';
4
4
  import { getAccountId, isTrackingAllowed } from '@hubspot/local-dev-lib/config';
5
- export async function trackToolUsage(toolName) {
5
+ export async function trackToolUsage(toolName, meta) {
6
6
  if (!isTrackingAllowed()) {
7
7
  return;
8
8
  }
@@ -12,6 +12,7 @@ export async function trackToolUsage(toolName) {
12
12
  ...getNodeVersionData(),
13
13
  command: toolName,
14
14
  type: process.env.HUBSPOT_MCP_AI_AGENT,
15
+ ...meta,
15
16
  };
16
17
  const accountId = getAccountId() || undefined;
17
18
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hubspot/cli",
3
- "version": "7.6.0-beta.7",
3
+ "version": "7.6.0-beta.8",
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",