@revfleet/hscli 0.5.3

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.
Files changed (329) hide show
  1. package/CHANGELOG.md +466 -0
  2. package/LICENSE +21 -0
  3. package/README.md +287 -0
  4. package/SECURITY.md +68 -0
  5. package/dist/cli.d.ts +8 -0
  6. package/dist/cli.js +192 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/commands/account/index.d.ts +3 -0
  9. package/dist/commands/account/index.js +65 -0
  10. package/dist/commands/account/index.js.map +1 -0
  11. package/dist/commands/api/index.d.ts +3 -0
  12. package/dist/commands/api/index.js +35 -0
  13. package/dist/commands/api/index.js.map +1 -0
  14. package/dist/commands/auth/index.d.ts +3 -0
  15. package/dist/commands/auth/index.js +229 -0
  16. package/dist/commands/auth/index.js.map +1 -0
  17. package/dist/commands/automation/index.d.ts +3 -0
  18. package/dist/commands/automation/index.js +119 -0
  19. package/dist/commands/automation/index.js.map +1 -0
  20. package/dist/commands/cms/blog-settings.d.ts +3 -0
  21. package/dist/commands/cms/blog-settings.js +70 -0
  22. package/dist/commands/cms/blog-settings.js.map +1 -0
  23. package/dist/commands/cms/content-ops.d.ts +13 -0
  24. package/dist/commands/cms/content-ops.js +262 -0
  25. package/dist/commands/cms/content-ops.js.map +1 -0
  26. package/dist/commands/cms/hubdb.d.ts +3 -0
  27. package/dist/commands/cms/hubdb.js +55 -0
  28. package/dist/commands/cms/hubdb.js.map +1 -0
  29. package/dist/commands/cms/index.d.ts +3 -0
  30. package/dist/commands/cms/index.js +119 -0
  31. package/dist/commands/cms/index.js.map +1 -0
  32. package/dist/commands/cms/source-code.d.ts +3 -0
  33. package/dist/commands/cms/source-code.js +101 -0
  34. package/dist/commands/cms/source-code.js.map +1 -0
  35. package/dist/commands/communication-preferences/index.d.ts +3 -0
  36. package/dist/commands/communication-preferences/index.js +107 -0
  37. package/dist/commands/communication-preferences/index.js.map +1 -0
  38. package/dist/commands/conversations/index.d.ts +3 -0
  39. package/dist/commands/conversations/index.js +233 -0
  40. package/dist/commands/conversations/index.js.map +1 -0
  41. package/dist/commands/crm/associations.d.ts +3 -0
  42. package/dist/commands/crm/associations.js +180 -0
  43. package/dist/commands/crm/associations.js.map +1 -0
  44. package/dist/commands/crm/cards.d.ts +3 -0
  45. package/dist/commands/crm/cards.js +72 -0
  46. package/dist/commands/crm/cards.js.map +1 -0
  47. package/dist/commands/crm/carts.d.ts +3 -0
  48. package/dist/commands/crm/carts.js +5 -0
  49. package/dist/commands/crm/carts.js.map +1 -0
  50. package/dist/commands/crm/communications.d.ts +3 -0
  51. package/dist/commands/crm/communications.js +5 -0
  52. package/dist/commands/crm/communications.js.map +1 -0
  53. package/dist/commands/crm/companies.d.ts +3 -0
  54. package/dist/commands/crm/companies.js +5 -0
  55. package/dist/commands/crm/companies.js.map +1 -0
  56. package/dist/commands/crm/contacts.d.ts +3 -0
  57. package/dist/commands/crm/contacts.js +5 -0
  58. package/dist/commands/crm/contacts.js.map +1 -0
  59. package/dist/commands/crm/custom-objects.d.ts +3 -0
  60. package/dist/commands/crm/custom-objects.js +83 -0
  61. package/dist/commands/crm/custom-objects.js.map +1 -0
  62. package/dist/commands/crm/dated.d.ts +9 -0
  63. package/dist/commands/crm/dated.js +247 -0
  64. package/dist/commands/crm/dated.js.map +1 -0
  65. package/dist/commands/crm/deals.d.ts +3 -0
  66. package/dist/commands/crm/deals.js +5 -0
  67. package/dist/commands/crm/deals.js.map +1 -0
  68. package/dist/commands/crm/describe.d.ts +3 -0
  69. package/dist/commands/crm/describe.js +89 -0
  70. package/dist/commands/crm/describe.js.map +1 -0
  71. package/dist/commands/crm/discounts.d.ts +3 -0
  72. package/dist/commands/crm/discounts.js +5 -0
  73. package/dist/commands/crm/discounts.js.map +1 -0
  74. package/dist/commands/crm/engagements.d.ts +3 -0
  75. package/dist/commands/crm/engagements.js +8 -0
  76. package/dist/commands/crm/engagements.js.map +1 -0
  77. package/dist/commands/crm/fees.d.ts +3 -0
  78. package/dist/commands/crm/fees.js +5 -0
  79. package/dist/commands/crm/fees.js.map +1 -0
  80. package/dist/commands/crm/goals.d.ts +3 -0
  81. package/dist/commands/crm/goals.js +30 -0
  82. package/dist/commands/crm/goals.js.map +1 -0
  83. package/dist/commands/crm/imports.d.ts +3 -0
  84. package/dist/commands/crm/imports.js +45 -0
  85. package/dist/commands/crm/imports.js.map +1 -0
  86. package/dist/commands/crm/index.d.ts +3 -0
  87. package/dist/commands/crm/index.js +64 -0
  88. package/dist/commands/crm/index.js.map +1 -0
  89. package/dist/commands/crm/invoices.d.ts +3 -0
  90. package/dist/commands/crm/invoices.js +5 -0
  91. package/dist/commands/crm/invoices.js.map +1 -0
  92. package/dist/commands/crm/leads.d.ts +3 -0
  93. package/dist/commands/crm/leads.js +5 -0
  94. package/dist/commands/crm/leads.js.map +1 -0
  95. package/dist/commands/crm/line-items.d.ts +3 -0
  96. package/dist/commands/crm/line-items.js +5 -0
  97. package/dist/commands/crm/line-items.js.map +1 -0
  98. package/dist/commands/crm/orders.d.ts +3 -0
  99. package/dist/commands/crm/orders.js +5 -0
  100. package/dist/commands/crm/orders.js.map +1 -0
  101. package/dist/commands/crm/owners.d.ts +3 -0
  102. package/dist/commands/crm/owners.js +22 -0
  103. package/dist/commands/crm/owners.js.map +1 -0
  104. package/dist/commands/crm/payments.d.ts +3 -0
  105. package/dist/commands/crm/payments.js +5 -0
  106. package/dist/commands/crm/payments.js.map +1 -0
  107. package/dist/commands/crm/pipelines.d.ts +3 -0
  108. package/dist/commands/crm/pipelines.js +70 -0
  109. package/dist/commands/crm/pipelines.js.map +1 -0
  110. package/dist/commands/crm/products.d.ts +3 -0
  111. package/dist/commands/crm/products.js +5 -0
  112. package/dist/commands/crm/products.js.map +1 -0
  113. package/dist/commands/crm/properties.d.ts +3 -0
  114. package/dist/commands/crm/properties.js +103 -0
  115. package/dist/commands/crm/properties.js.map +1 -0
  116. package/dist/commands/crm/quotes.d.ts +3 -0
  117. package/dist/commands/crm/quotes.js +5 -0
  118. package/dist/commands/crm/quotes.js.map +1 -0
  119. package/dist/commands/crm/shared.d.ts +17 -0
  120. package/dist/commands/crm/shared.js +256 -0
  121. package/dist/commands/crm/shared.js.map +1 -0
  122. package/dist/commands/crm/subscriptions.d.ts +3 -0
  123. package/dist/commands/crm/subscriptions.js +5 -0
  124. package/dist/commands/crm/subscriptions.js.map +1 -0
  125. package/dist/commands/crm/sync.d.ts +3 -0
  126. package/dist/commands/crm/sync.js +116 -0
  127. package/dist/commands/crm/sync.js.map +1 -0
  128. package/dist/commands/crm/taxes.d.ts +3 -0
  129. package/dist/commands/crm/taxes.js +5 -0
  130. package/dist/commands/crm/taxes.js.map +1 -0
  131. package/dist/commands/crm/tickets.d.ts +3 -0
  132. package/dist/commands/crm/tickets.js +5 -0
  133. package/dist/commands/crm/tickets.js.map +1 -0
  134. package/dist/commands/crm/users.d.ts +3 -0
  135. package/dist/commands/crm/users.js +5 -0
  136. package/dist/commands/crm/users.js.map +1 -0
  137. package/dist/commands/doctor/index.d.ts +3 -0
  138. package/dist/commands/doctor/index.js +232 -0
  139. package/dist/commands/doctor/index.js.map +1 -0
  140. package/dist/commands/domains/shared.d.ts +13 -0
  141. package/dist/commands/domains/shared.js +56 -0
  142. package/dist/commands/domains/shared.js.map +1 -0
  143. package/dist/commands/email-events/index.d.ts +3 -0
  144. package/dist/commands/email-events/index.js +77 -0
  145. package/dist/commands/email-events/index.js.map +1 -0
  146. package/dist/commands/events/index.d.ts +3 -0
  147. package/dist/commands/events/index.js +80 -0
  148. package/dist/commands/events/index.js.map +1 -0
  149. package/dist/commands/exports/index.d.ts +3 -0
  150. package/dist/commands/exports/index.js +45 -0
  151. package/dist/commands/exports/index.js.map +1 -0
  152. package/dist/commands/extensions/index.d.ts +3 -0
  153. package/dist/commands/extensions/index.js +118 -0
  154. package/dist/commands/extensions/index.js.map +1 -0
  155. package/dist/commands/feature-flags/index.d.ts +3 -0
  156. package/dist/commands/feature-flags/index.js +65 -0
  157. package/dist/commands/feature-flags/index.js.map +1 -0
  158. package/dist/commands/files/folders.d.ts +3 -0
  159. package/dist/commands/files/folders.js +74 -0
  160. package/dist/commands/files/folders.js.map +1 -0
  161. package/dist/commands/files/index.d.ts +3 -0
  162. package/dist/commands/files/index.js +30 -0
  163. package/dist/commands/files/index.js.map +1 -0
  164. package/dist/commands/forms/index.d.ts +3 -0
  165. package/dist/commands/forms/index.js +37 -0
  166. package/dist/commands/forms/index.js.map +1 -0
  167. package/dist/commands/integrations/index.d.ts +3 -0
  168. package/dist/commands/integrations/index.js +64 -0
  169. package/dist/commands/integrations/index.js.map +1 -0
  170. package/dist/commands/integrators/index.d.ts +3 -0
  171. package/dist/commands/integrators/index.js +79 -0
  172. package/dist/commands/integrators/index.js.map +1 -0
  173. package/dist/commands/legacy/index.d.ts +13 -0
  174. package/dist/commands/legacy/index.js +254 -0
  175. package/dist/commands/legacy/index.js.map +1 -0
  176. package/dist/commands/legacy-v1/index.d.ts +29 -0
  177. package/dist/commands/legacy-v1/index.js +568 -0
  178. package/dist/commands/legacy-v1/index.js.map +1 -0
  179. package/dist/commands/lists/index.d.ts +3 -0
  180. package/dist/commands/lists/index.js +148 -0
  181. package/dist/commands/lists/index.js.map +1 -0
  182. package/dist/commands/marketing/ads.d.ts +3 -0
  183. package/dist/commands/marketing/ads.js +45 -0
  184. package/dist/commands/marketing/ads.js.map +1 -0
  185. package/dist/commands/marketing/behavioral-events.d.ts +3 -0
  186. package/dist/commands/marketing/behavioral-events.js +38 -0
  187. package/dist/commands/marketing/behavioral-events.js.map +1 -0
  188. package/dist/commands/marketing/events.d.ts +3 -0
  189. package/dist/commands/marketing/events.js +69 -0
  190. package/dist/commands/marketing/events.js.map +1 -0
  191. package/dist/commands/marketing/index.d.ts +3 -0
  192. package/dist/commands/marketing/index.js +55 -0
  193. package/dist/commands/marketing/index.js.map +1 -0
  194. package/dist/commands/marketing/landing-pages.d.ts +3 -0
  195. package/dist/commands/marketing/landing-pages.js +48 -0
  196. package/dist/commands/marketing/landing-pages.js.map +1 -0
  197. package/dist/commands/marketing/seo.d.ts +3 -0
  198. package/dist/commands/marketing/seo.js +35 -0
  199. package/dist/commands/marketing/seo.js.map +1 -0
  200. package/dist/commands/marketing/social.d.ts +3 -0
  201. package/dist/commands/marketing/social.js +45 -0
  202. package/dist/commands/marketing/social.js.map +1 -0
  203. package/dist/commands/marketing/subscriptions.d.ts +3 -0
  204. package/dist/commands/marketing/subscriptions.js +27 -0
  205. package/dist/commands/marketing/subscriptions.js.map +1 -0
  206. package/dist/commands/marketing/transactional.d.ts +3 -0
  207. package/dist/commands/marketing/transactional.js +30 -0
  208. package/dist/commands/marketing/transactional.js.map +1 -0
  209. package/dist/commands/marketing-emails-v1/index.d.ts +3 -0
  210. package/dist/commands/marketing-emails-v1/index.js +72 -0
  211. package/dist/commands/marketing-emails-v1/index.js.map +1 -0
  212. package/dist/commands/mcp.d.ts +2 -0
  213. package/dist/commands/mcp.js +10 -0
  214. package/dist/commands/mcp.js.map +1 -0
  215. package/dist/commands/media-bridge/index.d.ts +3 -0
  216. package/dist/commands/media-bridge/index.js +209 -0
  217. package/dist/commands/media-bridge/index.js.map +1 -0
  218. package/dist/commands/reporting/index.d.ts +3 -0
  219. package/dist/commands/reporting/index.js +73 -0
  220. package/dist/commands/reporting/index.js.map +1 -0
  221. package/dist/commands/sales/calling.d.ts +3 -0
  222. package/dist/commands/sales/calling.js +32 -0
  223. package/dist/commands/sales/calling.js.map +1 -0
  224. package/dist/commands/sales/index.d.ts +3 -0
  225. package/dist/commands/sales/index.js +10 -0
  226. package/dist/commands/sales/index.js.map +1 -0
  227. package/dist/commands/sales/meetings.d.ts +3 -0
  228. package/dist/commands/sales/meetings.js +37 -0
  229. package/dist/commands/sales/meetings.js.map +1 -0
  230. package/dist/commands/sales/sequences.d.ts +3 -0
  231. package/dist/commands/sales/sequences.js +78 -0
  232. package/dist/commands/sales/sequences.js.map +1 -0
  233. package/dist/commands/seed/cms.d.ts +6 -0
  234. package/dist/commands/seed/cms.js +204 -0
  235. package/dist/commands/seed/cms.js.map +1 -0
  236. package/dist/commands/seed/commerce.d.ts +3 -0
  237. package/dist/commands/seed/commerce.js +117 -0
  238. package/dist/commands/seed/commerce.js.map +1 -0
  239. package/dist/commands/seed/context.d.ts +8 -0
  240. package/dist/commands/seed/context.js +76 -0
  241. package/dist/commands/seed/context.js.map +1 -0
  242. package/dist/commands/seed/crm-core.d.ts +3 -0
  243. package/dist/commands/seed/crm-core.js +137 -0
  244. package/dist/commands/seed/crm-core.js.map +1 -0
  245. package/dist/commands/seed/data.d.ts +73 -0
  246. package/dist/commands/seed/data.js +49 -0
  247. package/dist/commands/seed/data.js.map +1 -0
  248. package/dist/commands/seed/engagements.d.ts +3 -0
  249. package/dist/commands/seed/engagements.js +89 -0
  250. package/dist/commands/seed/engagements.js.map +1 -0
  251. package/dist/commands/seed/index.d.ts +3 -0
  252. package/dist/commands/seed/index.js +95 -0
  253. package/dist/commands/seed/index.js.map +1 -0
  254. package/dist/commands/seed/infra.d.ts +6 -0
  255. package/dist/commands/seed/infra.js +163 -0
  256. package/dist/commands/seed/infra.js.map +1 -0
  257. package/dist/commands/seed/marketing.d.ts +3 -0
  258. package/dist/commands/seed/marketing.js +172 -0
  259. package/dist/commands/seed/marketing.js.map +1 -0
  260. package/dist/commands/seed/shared.d.ts +8 -0
  261. package/dist/commands/seed/shared.js +37 -0
  262. package/dist/commands/seed/shared.js.map +1 -0
  263. package/dist/commands/seed/types.d.ts +44 -0
  264. package/dist/commands/seed/types.js +2 -0
  265. package/dist/commands/seed/types.js.map +1 -0
  266. package/dist/commands/service/chatflows.d.ts +3 -0
  267. package/dist/commands/service/chatflows.js +30 -0
  268. package/dist/commands/service/chatflows.js.map +1 -0
  269. package/dist/commands/service/index.d.ts +3 -0
  270. package/dist/commands/service/index.js +25 -0
  271. package/dist/commands/service/index.js.map +1 -0
  272. package/dist/commands/service/knowledge-base.d.ts +3 -0
  273. package/dist/commands/service/knowledge-base.js +19 -0
  274. package/dist/commands/service/knowledge-base.js.map +1 -0
  275. package/dist/commands/service/pipelines.d.ts +3 -0
  276. package/dist/commands/service/pipelines.js +36 -0
  277. package/dist/commands/service/pipelines.js.map +1 -0
  278. package/dist/commands/settings/index.d.ts +3 -0
  279. package/dist/commands/settings/index.js +149 -0
  280. package/dist/commands/settings/index.js.map +1 -0
  281. package/dist/commands/site-search/index.d.ts +3 -0
  282. package/dist/commands/site-search/index.js +36 -0
  283. package/dist/commands/site-search/index.js.map +1 -0
  284. package/dist/commands/timeline/index.d.ts +3 -0
  285. package/dist/commands/timeline/index.js +32 -0
  286. package/dist/commands/timeline/index.js.map +1 -0
  287. package/dist/commands/webhooks/index.d.ts +3 -0
  288. package/dist/commands/webhooks/index.js +41 -0
  289. package/dist/commands/webhooks/index.js.map +1 -0
  290. package/dist/commands/workflows/index.d.ts +3 -0
  291. package/dist/commands/workflows/index.js +13 -0
  292. package/dist/commands/workflows/index.js.map +1 -0
  293. package/dist/core/auth.d.ts +33 -0
  294. package/dist/core/auth.js +137 -0
  295. package/dist/core/auth.js.map +1 -0
  296. package/dist/core/capabilities.d.ts +60 -0
  297. package/dist/core/capabilities.js +559 -0
  298. package/dist/core/capabilities.js.map +1 -0
  299. package/dist/core/http.d.ts +47 -0
  300. package/dist/core/http.js +433 -0
  301. package/dist/core/http.js.map +1 -0
  302. package/dist/core/output.d.ts +23 -0
  303. package/dist/core/output.js +197 -0
  304. package/dist/core/output.js.map +1 -0
  305. package/dist/core/permissions.d.ts +9 -0
  306. package/dist/core/permissions.js +27 -0
  307. package/dist/core/permissions.js.map +1 -0
  308. package/dist/core/plugins.d.ts +42 -0
  309. package/dist/core/plugins.js +94 -0
  310. package/dist/core/plugins.js.map +1 -0
  311. package/dist/core/policy.d.ts +2 -0
  312. package/dist/core/policy.js +38 -0
  313. package/dist/core/policy.js.map +1 -0
  314. package/dist/core/schema-cache.d.ts +56 -0
  315. package/dist/core/schema-cache.js +338 -0
  316. package/dist/core/schema-cache.js.map +1 -0
  317. package/dist/core/schemas.d.ts +96 -0
  318. package/dist/core/schemas.js +104 -0
  319. package/dist/core/schemas.js.map +1 -0
  320. package/dist/core/urls.d.ts +50 -0
  321. package/dist/core/urls.js +122 -0
  322. package/dist/core/urls.js.map +1 -0
  323. package/dist/core/vault.d.ts +37 -0
  324. package/dist/core/vault.js +143 -0
  325. package/dist/core/vault.js.map +1 -0
  326. package/dist/mcp/server.d.ts +5 -0
  327. package/dist/mcp/server.js +680 -0
  328. package/dist/mcp/server.js.map +1 -0
  329. package/package.json +84 -0
@@ -0,0 +1,680 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { getToken, getApiBaseUrl } from "../core/auth.js";
5
+ import { HubSpotClient } from "../core/http.js";
6
+ import { CliError, redactSensitive } from "../core/output.js";
7
+ import { ENGAGEMENT_OBJECT_TYPES, OBJECT_COMMAND_TYPES, PIPELINE_OBJECT_TYPES, PROPERTY_OBJECT_TYPES, appendOptional, encodePathSegment, maybeWrite, parseBooleanFlag, parseNumberFlag, parseSupportedObjectType, } from "../commands/crm/shared.js";
8
+ import { resolvePortalContext, enrichListResponse, enrichRecordUrl, enrichCustomListResponse, enrichCustomRecordUrl, } from "../core/urls.js";
9
+ const baseArgsSchema = {
10
+ profile: z.string().min(1).optional(),
11
+ force: z.boolean().optional(),
12
+ dryRun: z.boolean().optional(),
13
+ };
14
+ export function resolveProfile(requested) {
15
+ // Priority order:
16
+ // 1. HSCLI_MCP_PROFILE — hard lock (any other profile request throws)
17
+ // 2. Explicit `profile` arg on the tool call
18
+ // 3. HSCLI_PROFILE — set by the CLI's preAction hook when user passes
19
+ // `hubcli --profile prod mcp`. Without this, launching MCP with
20
+ // `--profile prod` silently fell back to "default" and could send
21
+ // reads/writes to the wrong portal.
22
+ // 4. "default"
23
+ const isolatedProfile = process.env.HSCLI_MCP_PROFILE?.trim();
24
+ if (isolatedProfile) {
25
+ const selected = requested?.trim() || isolatedProfile;
26
+ if (selected !== isolatedProfile) {
27
+ throw new CliError("MCP_PROFILE_ISOLATED", `MCP server is locked to profile '${isolatedProfile}'.`);
28
+ }
29
+ return isolatedProfile;
30
+ }
31
+ const requestedTrimmed = requested?.trim();
32
+ if (requestedTrimmed)
33
+ return requestedTrimmed;
34
+ const inheritedProfile = process.env.HSCLI_PROFILE?.trim();
35
+ if (inheritedProfile)
36
+ return inheritedProfile;
37
+ return "default";
38
+ }
39
+ function mcpContext(args) {
40
+ const force = Boolean(args.force);
41
+ const dryRun = args.dryRun ?? !force;
42
+ return {
43
+ profile: resolveProfile(args.profile),
44
+ json: true,
45
+ dryRun,
46
+ force,
47
+ };
48
+ }
49
+ function asStructuredContent(value) {
50
+ if (value && typeof value === "object" && !Array.isArray(value)) {
51
+ return value;
52
+ }
53
+ return { result: value };
54
+ }
55
+ function textResult(data) {
56
+ const safe = redactSensitive(data);
57
+ return {
58
+ content: [{ type: "text", text: JSON.stringify(safe, null, 2) }],
59
+ structuredContent: asStructuredContent(safe),
60
+ };
61
+ }
62
+ async function executeTool(args, fn) {
63
+ try {
64
+ const ctx = mcpContext(args);
65
+ const client = new HubSpotClient(getToken(ctx.profile), {
66
+ profile: ctx.profile,
67
+ strictCapabilities: isEnvTrue(process.env.HSCLI_MCP_STRICT_CAPABILITIES),
68
+ apiBaseUrl: getApiBaseUrl(ctx.profile),
69
+ });
70
+ const result = await fn(ctx, client);
71
+ return textResult(result);
72
+ }
73
+ catch (error) {
74
+ const err = error instanceof CliError
75
+ ? error
76
+ : new CliError("UNEXPECTED_ERROR", error instanceof Error ? error.message : String(error));
77
+ return {
78
+ isError: true,
79
+ ...textResult({
80
+ code: err.code,
81
+ message: err.message,
82
+ status: err.status,
83
+ details: err.details,
84
+ }),
85
+ };
86
+ }
87
+ }
88
+ function isEnvTrue(value) {
89
+ if (!value)
90
+ return false;
91
+ const normalized = value.trim().toLowerCase();
92
+ return normalized === "1" || normalized === "true" || normalized === "yes";
93
+ }
94
+ function registerStandardObjectTools(server, objectType) {
95
+ server.registerTool(`crm_${objectType}_list`, {
96
+ description: `List ${objectType}`,
97
+ inputSchema: {
98
+ ...baseArgsSchema,
99
+ limit: z.number().int().positive().default(10),
100
+ after: z.string().optional(),
101
+ archived: z.boolean().optional(),
102
+ properties: z.string().optional(),
103
+ },
104
+ }, (args) => executeTool(args, async (ctx, client) => {
105
+ const portal = resolvePortalContext(ctx.profile);
106
+ const params = new URLSearchParams();
107
+ params.set("limit", String(parseNumberFlag(String(args.limit ?? 10), "limit")));
108
+ appendOptional(params, "after", args.after);
109
+ if (args.archived !== undefined) {
110
+ params.set("archived", String(parseBooleanFlag(String(args.archived), "archived")));
111
+ }
112
+ appendOptional(params, "properties", args.properties);
113
+ const res = await client.request(`/crm/v3/objects/${objectType}?${params.toString()}`);
114
+ enrichListResponse(res, portal, objectType);
115
+ return res;
116
+ }));
117
+ server.registerTool(`crm_${objectType}_get`, {
118
+ description: `Get one ${objectType.slice(0, -1)} by ID`,
119
+ inputSchema: {
120
+ ...baseArgsSchema,
121
+ id: z.string().min(1),
122
+ properties: z.string().optional(),
123
+ },
124
+ }, (args) => executeTool(args, async (ctx, client) => {
125
+ const portal = resolvePortalContext(ctx.profile);
126
+ const idSegment = encodePathSegment(args.id, "id");
127
+ const suffix = args.properties ? `?properties=${encodeURIComponent(args.properties)}` : "";
128
+ const res = await client.request(`/crm/v3/objects/${objectType}/${idSegment}${suffix}`);
129
+ if (res && typeof res === "object")
130
+ enrichRecordUrl(res, portal, objectType);
131
+ return res;
132
+ }));
133
+ server.registerTool(`crm_${objectType}_search`, {
134
+ description: `Search ${objectType}`,
135
+ inputSchema: {
136
+ ...baseArgsSchema,
137
+ query: z.string().min(1),
138
+ limit: z.number().int().positive().default(10),
139
+ after: z.number().int().positive().optional(),
140
+ },
141
+ }, (args) => executeTool(args, async (ctx, client) => {
142
+ const portal = resolvePortalContext(ctx.profile);
143
+ const body = {
144
+ query: args.query,
145
+ limit: parseNumberFlag(String(args.limit ?? 10), "limit"),
146
+ };
147
+ if (args.after !== undefined) {
148
+ body.after = parseNumberFlag(String(args.after), "after");
149
+ }
150
+ const res = await client.request(`/crm/v3/objects/${objectType}/search`, { method: "POST", body });
151
+ enrichListResponse(res, portal, objectType);
152
+ return res;
153
+ }));
154
+ server.registerTool(`crm_${objectType}_create`, {
155
+ description: `Create ${objectType.slice(0, -1)} (dry-run by default unless force=true)`,
156
+ inputSchema: {
157
+ ...baseArgsSchema,
158
+ data: z.record(z.string(), z.unknown()),
159
+ },
160
+ }, (args) => executeTool(args, async (ctx, client) => {
161
+ const portal = resolvePortalContext(ctx.profile);
162
+ const res = await maybeWrite(ctx, client, "POST", `/crm/v3/objects/${objectType}`, args.data);
163
+ if (res && typeof res === "object")
164
+ enrichRecordUrl(res, portal, objectType);
165
+ return res;
166
+ }));
167
+ server.registerTool(`crm_${objectType}_update`, {
168
+ description: `Update ${objectType.slice(0, -1)} (dry-run by default unless force=true)`,
169
+ inputSchema: {
170
+ ...baseArgsSchema,
171
+ id: z.string().min(1),
172
+ data: z.record(z.string(), z.unknown()),
173
+ },
174
+ }, (args) => executeTool(args, async (ctx, client) => {
175
+ const portal = resolvePortalContext(ctx.profile);
176
+ const idSegment = encodePathSegment(args.id, "id");
177
+ const res = await maybeWrite(ctx, client, "PATCH", `/crm/v3/objects/${objectType}/${idSegment}`, args.data);
178
+ if (res && typeof res === "object")
179
+ enrichRecordUrl(res, portal, objectType);
180
+ return res;
181
+ }));
182
+ server.registerTool(`crm_${objectType}_delete`, {
183
+ description: `Delete/archive ${objectType.slice(0, -1)} by ID (dry-run by default unless force=true)`,
184
+ inputSchema: { ...baseArgsSchema, id: z.string().min(1) },
185
+ }, (args) => executeTool(args, (ctx, client) => {
186
+ const idSegment = encodePathSegment(args.id, "id");
187
+ return maybeWrite(ctx, client, "DELETE", `/crm/v3/objects/${objectType}/${idSegment}`);
188
+ }));
189
+ server.registerTool(`crm_${objectType}_merge`, {
190
+ description: `Merge ${objectType} records (endpoint support varies by object)`,
191
+ inputSchema: { ...baseArgsSchema, data: z.record(z.string(), z.unknown()) },
192
+ }, (args) => executeTool(args, (ctx, client) => maybeWrite(ctx, client, "POST", `/crm/v3/objects/${objectType}/merge`, args.data)));
193
+ server.registerTool(`crm_${objectType}_batch_read`, {
194
+ description: `Batch read ${objectType}`,
195
+ inputSchema: { ...baseArgsSchema, data: z.record(z.string(), z.unknown()) },
196
+ }, (args) => executeTool(args, (_ctx, client) => client.request(`/crm/v3/objects/${objectType}/batch/read`, { method: "POST", body: args.data })));
197
+ server.registerTool(`crm_${objectType}_batch_upsert`, {
198
+ description: `Batch upsert ${objectType} (dry-run by default unless force=true)`,
199
+ inputSchema: { ...baseArgsSchema, data: z.record(z.string(), z.unknown()) },
200
+ }, (args) => executeTool(args, (ctx, client) => maybeWrite(ctx, client, "POST", `/crm/v3/objects/${objectType}/batch/upsert`, args.data)));
201
+ server.registerTool(`crm_${objectType}_batch_archive`, {
202
+ description: `Batch archive ${objectType} (dry-run by default unless force=true)`,
203
+ inputSchema: { ...baseArgsSchema, data: z.record(z.string(), z.unknown()) },
204
+ }, (args) => executeTool(args, (ctx, client) => maybeWrite(ctx, client, "POST", `/crm/v3/objects/${objectType}/batch/archive`, args.data)));
205
+ }
206
+ export function registerHubSpotTools(server) {
207
+ for (const objectType of OBJECT_COMMAND_TYPES) {
208
+ registerStandardObjectTools(server, objectType);
209
+ }
210
+ for (const objectType of ENGAGEMENT_OBJECT_TYPES) {
211
+ registerStandardObjectTools(server, objectType);
212
+ }
213
+ server.registerTool("crm_properties_list", {
214
+ description: "List properties for an object type",
215
+ inputSchema: { ...baseArgsSchema, objectType: z.enum(PROPERTY_OBJECT_TYPES) },
216
+ }, (args) => executeTool(args, (_ctx, client) => {
217
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PROPERTY_OBJECT_TYPES, "objectType");
218
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
219
+ return client.request(`/crm/v3/properties/${objectTypeSegment}`);
220
+ }));
221
+ server.registerTool("crm_properties_get", {
222
+ description: "Get one property definition",
223
+ inputSchema: { ...baseArgsSchema, objectType: z.enum(PROPERTY_OBJECT_TYPES), propertyName: z.string().min(1) },
224
+ }, (args) => executeTool(args, (_ctx, client) => {
225
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PROPERTY_OBJECT_TYPES, "objectType");
226
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
227
+ const propertyNameSegment = encodePathSegment(args.propertyName, "propertyName");
228
+ return client.request(`/crm/v3/properties/${objectTypeSegment}/${propertyNameSegment}`);
229
+ }));
230
+ server.registerTool("crm_properties_create", {
231
+ description: "Create property (dry-run by default unless force=true)",
232
+ inputSchema: { ...baseArgsSchema, objectType: z.enum(PROPERTY_OBJECT_TYPES), data: z.record(z.string(), z.unknown()) },
233
+ }, (args) => executeTool(args, (ctx, client) => {
234
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PROPERTY_OBJECT_TYPES, "objectType");
235
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
236
+ return maybeWrite(ctx, client, "POST", `/crm/v3/properties/${objectTypeSegment}`, args.data);
237
+ }));
238
+ server.registerTool("crm_properties_update", {
239
+ description: "Update property (dry-run by default unless force=true)",
240
+ inputSchema: {
241
+ ...baseArgsSchema,
242
+ objectType: z.enum(PROPERTY_OBJECT_TYPES),
243
+ propertyName: z.string().min(1),
244
+ data: z.record(z.string(), z.unknown()),
245
+ },
246
+ }, (args) => executeTool(args, (ctx, client) => {
247
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PROPERTY_OBJECT_TYPES, "objectType");
248
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
249
+ const propertyNameSegment = encodePathSegment(args.propertyName, "propertyName");
250
+ return maybeWrite(ctx, client, "PATCH", `/crm/v3/properties/${objectTypeSegment}/${propertyNameSegment}`, args.data);
251
+ }));
252
+ server.registerTool("crm_associations_list", {
253
+ description: "List associations between CRM objects (supports standard types, engagements, and custom object type IDs like 2-199622513)",
254
+ inputSchema: {
255
+ ...baseArgsSchema,
256
+ fromObjectType: z.string().min(1).describe("Object type name (contacts, deals, notes, calls, etc.) or custom object type ID (e.g. 2-199622513)"),
257
+ fromObjectId: z.string().min(1),
258
+ toObjectType: z.string().min(1).describe("Object type name or custom object type ID"),
259
+ limit: z.number().int().positive().default(100),
260
+ after: z.string().optional(),
261
+ },
262
+ }, (args) => executeTool(args, async (_ctx, client) => {
263
+ const fromObjectTypeSegment = encodePathSegment(args.fromObjectType.trim().toLowerCase(), "fromObjectType");
264
+ const fromObjectIdSegment = encodePathSegment(args.fromObjectId, "fromObjectId");
265
+ const toObjectTypeSegment = encodePathSegment(args.toObjectType.trim().toLowerCase(), "toObjectType");
266
+ const params = new URLSearchParams();
267
+ params.set("limit", String(parseNumberFlag(String(args.limit ?? 100), "limit")));
268
+ appendOptional(params, "after", args.after);
269
+ return client.request(`/crm/v4/objects/${fromObjectTypeSegment}/${fromObjectIdSegment}/associations/${toObjectTypeSegment}?${params.toString()}`);
270
+ }));
271
+ server.registerTool("crm_associations_create", {
272
+ description: "Create default association (dry-run by default unless force=true). Supports standard types, engagements, and custom object type IDs.",
273
+ inputSchema: {
274
+ ...baseArgsSchema,
275
+ fromObjectType: z.string().min(1).describe("Object type name (contacts, deals, notes, calls, etc.) or custom object type ID (e.g. 2-199622513)"),
276
+ fromObjectId: z.string().min(1),
277
+ toObjectType: z.string().min(1).describe("Object type name or custom object type ID"),
278
+ toObjectId: z.string().min(1),
279
+ },
280
+ }, (args) => executeTool(args, (ctx, client) => {
281
+ return maybeWrite(ctx, client, "PUT", `/crm/v4/objects/${encodePathSegment(args.fromObjectType.trim().toLowerCase(), "fromObjectType")}/${encodePathSegment(args.fromObjectId, "fromObjectId")}/associations/default/${encodePathSegment(args.toObjectType.trim().toLowerCase(), "toObjectType")}/${encodePathSegment(args.toObjectId, "toObjectId")}`);
282
+ }));
283
+ server.registerTool("crm_associations_remove", {
284
+ description: "Remove default association (dry-run by default unless force=true). Supports standard types, engagements, and custom object type IDs.",
285
+ inputSchema: {
286
+ ...baseArgsSchema,
287
+ fromObjectType: z.string().min(1).describe("Object type name (contacts, deals, notes, calls, etc.) or custom object type ID (e.g. 2-199622513)"),
288
+ fromObjectId: z.string().min(1),
289
+ toObjectType: z.string().min(1).describe("Object type name or custom object type ID"),
290
+ toObjectId: z.string().min(1),
291
+ },
292
+ }, (args) => executeTool(args, (ctx, client) => {
293
+ return maybeWrite(ctx, client, "DELETE", `/crm/v4/objects/${encodePathSegment(args.fromObjectType.trim().toLowerCase(), "fromObjectType")}/${encodePathSegment(args.fromObjectId, "fromObjectId")}/associations/default/${encodePathSegment(args.toObjectType.trim().toLowerCase(), "toObjectType")}/${encodePathSegment(args.toObjectId, "toObjectId")}`);
294
+ }));
295
+ server.registerTool("crm_imports_create", {
296
+ description: "Create import (dry-run by default unless force=true)",
297
+ inputSchema: { ...baseArgsSchema, data: z.record(z.string(), z.unknown()) },
298
+ }, (args) => executeTool(args, (ctx, client) => maybeWrite(ctx, client, "POST", "/crm/v3/imports", args.data)));
299
+ server.registerTool("crm_imports_list", {
300
+ description: "List import jobs",
301
+ inputSchema: { ...baseArgsSchema, limit: z.number().int().positive().default(100), after: z.string().optional() },
302
+ }, (args) => executeTool(args, (_ctx, client) => {
303
+ const params = new URLSearchParams();
304
+ params.set("limit", String(parseNumberFlag(String(args.limit ?? 100), "limit")));
305
+ appendOptional(params, "after", args.after);
306
+ return client.request(`/crm/v3/imports?${params.toString()}`);
307
+ }));
308
+ server.registerTool("crm_imports_get", {
309
+ description: "Get import by ID",
310
+ inputSchema: { ...baseArgsSchema, importId: z.string().min(1) },
311
+ }, (args) => executeTool(args, (_ctx, client) => {
312
+ const importIdSegment = encodePathSegment(args.importId, "importId");
313
+ return client.request(`/crm/v3/imports/${importIdSegment}`);
314
+ }));
315
+ server.registerTool("crm_imports_errors", {
316
+ description: "Get import errors",
317
+ inputSchema: { ...baseArgsSchema, importId: z.string().min(1) },
318
+ }, (args) => executeTool(args, (_ctx, client) => {
319
+ const importIdSegment = encodePathSegment(args.importId, "importId");
320
+ return client.request(`/crm/v3/imports/${importIdSegment}/errors`);
321
+ }));
322
+ server.registerTool("crm_owners_list", {
323
+ description: "List HubSpot owners",
324
+ inputSchema: {
325
+ ...baseArgsSchema,
326
+ limit: z.number().int().positive().default(100),
327
+ after: z.string().optional(),
328
+ email: z.string().email().optional(),
329
+ },
330
+ }, (args) => executeTool(args, (_ctx, client) => {
331
+ const params = new URLSearchParams();
332
+ params.set("limit", String(parseNumberFlag(String(args.limit ?? 100), "limit")));
333
+ appendOptional(params, "after", args.after);
334
+ appendOptional(params, "email", args.email);
335
+ return client.request(`/crm/v3/owners/?${params.toString()}`);
336
+ }));
337
+ server.registerTool("crm_custom_schemas_list", {
338
+ description: "List custom object schemas",
339
+ inputSchema: { ...baseArgsSchema },
340
+ }, (args) => executeTool(args, (_ctx, client) => client.request("/crm/v3/schemas")));
341
+ server.registerTool("crm_custom_schemas_get", {
342
+ description: "Get custom object schema by objectType",
343
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1) },
344
+ }, (args) => executeTool(args, (_ctx, client) => client.request(`/crm/v3/schemas/${encodePathSegment(args.objectType, "objectType")}`)));
345
+ server.registerTool("crm_custom_schemas_create", {
346
+ description: "Create custom object schema (dry-run by default unless force=true)",
347
+ inputSchema: { ...baseArgsSchema, data: z.record(z.string(), z.unknown()) },
348
+ }, (args) => executeTool(args, (ctx, client) => maybeWrite(ctx, client, "POST", "/crm/v3/schemas", args.data)));
349
+ server.registerTool("crm_custom_schemas_update", {
350
+ description: "Update custom object schema (dry-run by default unless force=true)",
351
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1), data: z.record(z.string(), z.unknown()) },
352
+ }, (args) => executeTool(args, (ctx, client) => maybeWrite(ctx, client, "PATCH", `/crm/v3/schemas/${encodePathSegment(args.objectType, "objectType")}`, args.data)));
353
+ server.registerTool("crm_custom_records_list", {
354
+ description: "List custom object records by objectType",
355
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1), limit: z.number().int().positive().default(50), after: z.string().optional() },
356
+ }, (args) => executeTool(args, async (ctx, client) => {
357
+ const portal = resolvePortalContext(ctx.profile);
358
+ const params = new URLSearchParams();
359
+ params.set("limit", String(parseNumberFlag(String(args.limit ?? 50), "limit")));
360
+ appendOptional(params, "after", args.after);
361
+ const res = await client.request(`/crm/v3/objects/${encodePathSegment(args.objectType, "objectType")}?${params.toString()}`);
362
+ enrichCustomListResponse(res, portal, args.objectType);
363
+ return res;
364
+ }));
365
+ server.registerTool("crm_custom_records_get", {
366
+ description: "Get custom object record by objectType and id",
367
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1), id: z.string().min(1) },
368
+ }, (args) => executeTool(args, async (ctx, client) => {
369
+ const portal = resolvePortalContext(ctx.profile);
370
+ const res = await client.request(`/crm/v3/objects/${encodePathSegment(args.objectType, "objectType")}/${encodePathSegment(args.id, "id")}`);
371
+ if (res && typeof res === "object")
372
+ enrichCustomRecordUrl(res, portal, args.objectType);
373
+ return res;
374
+ }));
375
+ server.registerTool("crm_custom_records_search", {
376
+ description: "Search custom object records",
377
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1), data: z.record(z.string(), z.unknown()) },
378
+ }, (args) => executeTool(args, async (ctx, client) => {
379
+ const portal = resolvePortalContext(ctx.profile);
380
+ const res = await client.request(`/crm/v3/objects/${encodePathSegment(args.objectType, "objectType")}/search`, { method: "POST", body: args.data });
381
+ enrichCustomListResponse(res, portal, args.objectType);
382
+ return res;
383
+ }));
384
+ server.registerTool("crm_custom_records_create", {
385
+ description: "Create custom object record (dry-run by default unless force=true)",
386
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1), data: z.record(z.string(), z.unknown()) },
387
+ }, (args) => executeTool(args, async (ctx, client) => {
388
+ const portal = resolvePortalContext(ctx.profile);
389
+ const res = await maybeWrite(ctx, client, "POST", `/crm/v3/objects/${encodePathSegment(args.objectType, "objectType")}`, args.data);
390
+ if (res && typeof res === "object")
391
+ enrichCustomRecordUrl(res, portal, args.objectType);
392
+ return res;
393
+ }));
394
+ server.registerTool("crm_custom_records_update", {
395
+ description: "Update custom object record (dry-run by default unless force=true)",
396
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1), id: z.string().min(1), data: z.record(z.string(), z.unknown()) },
397
+ }, (args) => executeTool(args, async (ctx, client) => {
398
+ const portal = resolvePortalContext(ctx.profile);
399
+ const res = await maybeWrite(ctx, client, "PATCH", `/crm/v3/objects/${encodePathSegment(args.objectType, "objectType")}/${encodePathSegment(args.id, "id")}`, args.data);
400
+ if (res && typeof res === "object")
401
+ enrichCustomRecordUrl(res, portal, args.objectType);
402
+ return res;
403
+ }));
404
+ server.registerTool("crm_custom_records_delete", {
405
+ description: "Delete custom object record (dry-run by default unless force=true)",
406
+ inputSchema: { ...baseArgsSchema, objectType: z.string().min(1), id: z.string().min(1) },
407
+ }, (args) => executeTool(args, (ctx, client) => maybeWrite(ctx, client, "DELETE", `/crm/v3/objects/${encodePathSegment(args.objectType, "objectType")}/${encodePathSegment(args.id, "id")}`)));
408
+ server.registerTool("crm_pipelines_list", {
409
+ description: "List pipelines for object type",
410
+ inputSchema: { ...baseArgsSchema, objectType: z.enum(PIPELINE_OBJECT_TYPES) },
411
+ }, (args) => executeTool(args, (_ctx, client) => {
412
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PIPELINE_OBJECT_TYPES, "objectType");
413
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
414
+ return client.request(`/crm/v3/pipelines/${objectTypeSegment}`);
415
+ }));
416
+ server.registerTool("crm_pipelines_get", {
417
+ description: "Get one pipeline",
418
+ inputSchema: { ...baseArgsSchema, objectType: z.enum(PIPELINE_OBJECT_TYPES), pipelineId: z.string().min(1) },
419
+ }, (args) => executeTool(args, (_ctx, client) => {
420
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PIPELINE_OBJECT_TYPES, "objectType");
421
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
422
+ const pipelineIdSegment = encodePathSegment(args.pipelineId, "pipelineId");
423
+ return client.request(`/crm/v3/pipelines/${objectTypeSegment}/${pipelineIdSegment}`);
424
+ }));
425
+ server.registerTool("hub_api_request", {
426
+ description: "Raw HubSpot API request with safety controls",
427
+ inputSchema: {
428
+ ...baseArgsSchema,
429
+ method: z.enum(["GET", "POST", "PATCH", "PUT", "DELETE"]).default("GET"),
430
+ path: z.string().min(1),
431
+ data: z.record(z.string(), z.unknown()).optional(),
432
+ },
433
+ }, (args) => executeTool(args, (ctx, client) => {
434
+ const method = args.method;
435
+ if (method === "GET") {
436
+ return client.request(args.path, { method });
437
+ }
438
+ return maybeWrite(ctx, client, method, args.path, args.data);
439
+ }));
440
+ // ── Lists ──────────────────────────────────────────────────────────────
441
+ server.registerTool("crm_lists_list", {
442
+ description: "List CRM lists with pagination",
443
+ inputSchema: {
444
+ ...baseArgsSchema,
445
+ limit: z.number().min(1).max(250).optional(),
446
+ after: z.string().optional(),
447
+ },
448
+ }, (args) => executeTool(args, async (_ctx, client) => {
449
+ const params = new URLSearchParams();
450
+ if (args.limit)
451
+ params.set("limit", String(args.limit));
452
+ if (args.after)
453
+ params.set("after", args.after);
454
+ const qs = params.toString();
455
+ return await client.request(`/crm/v3/lists${qs ? `?${qs}` : ""}`);
456
+ }));
457
+ server.registerTool("crm_lists_get", {
458
+ description: "Get a CRM list by ID",
459
+ inputSchema: {
460
+ ...baseArgsSchema,
461
+ listId: z.string().min(1),
462
+ },
463
+ }, (args) => executeTool(args, async (_ctx, client) => {
464
+ const listIdSegment = encodePathSegment(args.listId, "listId");
465
+ return await client.request(`/crm/v3/lists/${listIdSegment}`);
466
+ }));
467
+ server.registerTool("crm_lists_create", {
468
+ description: "Create a CRM list (dry-run by default unless force=true)",
469
+ inputSchema: {
470
+ ...baseArgsSchema,
471
+ data: z.record(z.string(), z.unknown()),
472
+ },
473
+ }, (args) => executeTool(args, (ctx, client) => {
474
+ return maybeWrite(ctx, client, "POST", "/crm/v3/lists", args.data);
475
+ }));
476
+ server.registerTool("crm_lists_update", {
477
+ description: "Update a CRM list (dry-run by default unless force=true)",
478
+ inputSchema: {
479
+ ...baseArgsSchema,
480
+ listId: z.string().min(1),
481
+ data: z.record(z.string(), z.unknown()),
482
+ },
483
+ }, (args) => executeTool(args, (ctx, client) => {
484
+ const listIdSegment = encodePathSegment(args.listId, "listId");
485
+ return maybeWrite(ctx, client, "PATCH", `/crm/v3/lists/${listIdSegment}`, args.data);
486
+ }));
487
+ server.registerTool("crm_lists_delete", {
488
+ description: "Delete a CRM list (dry-run by default unless force=true)",
489
+ inputSchema: {
490
+ ...baseArgsSchema,
491
+ listId: z.string().min(1),
492
+ },
493
+ }, (args) => executeTool(args, (ctx, client) => {
494
+ const listIdSegment = encodePathSegment(args.listId, "listId");
495
+ return maybeWrite(ctx, client, "DELETE", `/crm/v3/lists/${listIdSegment}`);
496
+ }));
497
+ server.registerTool("crm_lists_memberships", {
498
+ description: "Get memberships of a CRM list",
499
+ inputSchema: {
500
+ ...baseArgsSchema,
501
+ listId: z.string().min(1),
502
+ },
503
+ }, (args) => executeTool(args, async (_ctx, client) => {
504
+ const listIdSegment = encodePathSegment(args.listId, "listId");
505
+ return await client.request(`/crm/v3/lists/${listIdSegment}/memberships`);
506
+ }));
507
+ // ── Sequences ──────────────────────────────────────────────────────────
508
+ server.registerTool("sales_sequences_list", {
509
+ description: "List sales sequences with pagination",
510
+ inputSchema: {
511
+ ...baseArgsSchema,
512
+ limit: z.number().min(1).max(250).optional(),
513
+ after: z.string().optional(),
514
+ },
515
+ }, (args) => executeTool(args, async (_ctx, client) => {
516
+ const params = new URLSearchParams();
517
+ if (args.limit)
518
+ params.set("limit", String(args.limit));
519
+ if (args.after)
520
+ params.set("after", args.after);
521
+ const qs = params.toString();
522
+ return await client.request(`/automation/v4/sequences${qs ? `?${qs}` : ""}`);
523
+ }));
524
+ server.registerTool("sales_sequences_get", {
525
+ description: "Get a sales sequence by ID",
526
+ inputSchema: {
527
+ ...baseArgsSchema,
528
+ sequenceId: z.string().min(1),
529
+ },
530
+ }, (args) => executeTool(args, async (_ctx, client) => {
531
+ const sequenceIdSegment = encodePathSegment(args.sequenceId, "sequenceId");
532
+ return await client.request(`/automation/v4/sequences/${sequenceIdSegment}`);
533
+ }));
534
+ server.registerTool("sales_sequences_enrollments", {
535
+ description: "Get enrollments for a sales sequence",
536
+ inputSchema: {
537
+ ...baseArgsSchema,
538
+ sequenceId: z.string().min(1),
539
+ },
540
+ }, (args) => executeTool(args, async (_ctx, client) => {
541
+ const sequenceIdSegment = encodePathSegment(args.sequenceId, "sequenceId");
542
+ return await client.request(`/automation/v4/sequences/${sequenceIdSegment}/enrollments`);
543
+ }));
544
+ // ── Reporting ──────────────────────────────────────────────────────────
545
+ server.registerTool("reporting_dashboards_list", {
546
+ description: "List analytics reports/dashboards with pagination",
547
+ inputSchema: {
548
+ ...baseArgsSchema,
549
+ limit: z.number().min(1).max(250).optional(),
550
+ after: z.string().optional(),
551
+ },
552
+ }, (args) => executeTool(args, async (_ctx, client) => {
553
+ const params = new URLSearchParams();
554
+ if (args.limit)
555
+ params.set("limit", String(args.limit));
556
+ if (args.after)
557
+ params.set("after", args.after);
558
+ const qs = params.toString();
559
+ return await client.request(`/analytics/v2/reports${qs ? `?${qs}` : ""}`);
560
+ }));
561
+ server.registerTool("reporting_dashboards_get", {
562
+ description: "Get an analytics report/dashboard by ID",
563
+ inputSchema: {
564
+ ...baseArgsSchema,
565
+ dashboardId: z.string().min(1),
566
+ },
567
+ }, (args) => executeTool(args, async (_ctx, client) => {
568
+ const dashboardIdSegment = encodePathSegment(args.dashboardId, "dashboardId");
569
+ return await client.request(`/analytics/v2/reports/${dashboardIdSegment}`);
570
+ }));
571
+ // ── Exports ────────────────────────────────────────────────────────────
572
+ server.registerTool("crm_exports_create", {
573
+ description: "Create a CRM export (dry-run by default unless force=true)",
574
+ inputSchema: {
575
+ ...baseArgsSchema,
576
+ data: z.record(z.string(), z.unknown()),
577
+ },
578
+ }, (args) => executeTool(args, (ctx, client) => {
579
+ return maybeWrite(ctx, client, "POST", "/crm/v3/exports", args.data);
580
+ }));
581
+ server.registerTool("crm_exports_list", {
582
+ description: "List CRM exports with pagination",
583
+ inputSchema: {
584
+ ...baseArgsSchema,
585
+ limit: z.number().min(1).max(250).optional(),
586
+ after: z.string().optional(),
587
+ },
588
+ }, (args) => executeTool(args, async (_ctx, client) => {
589
+ const params = new URLSearchParams();
590
+ if (args.limit)
591
+ params.set("limit", String(args.limit));
592
+ if (args.after)
593
+ params.set("after", args.after);
594
+ const qs = params.toString();
595
+ return await client.request(`/crm/v3/exports${qs ? `?${qs}` : ""}`);
596
+ }));
597
+ server.registerTool("crm_exports_get", {
598
+ description: "Get a CRM export by ID",
599
+ inputSchema: {
600
+ ...baseArgsSchema,
601
+ exportId: z.string().min(1),
602
+ },
603
+ }, (args) => executeTool(args, async (_ctx, client) => {
604
+ const exportIdSegment = encodePathSegment(args.exportId, "exportId");
605
+ return await client.request(`/crm/v3/exports/${exportIdSegment}`);
606
+ }));
607
+ server.registerTool("crm_exports_status", {
608
+ description: "Get the status of a CRM export",
609
+ inputSchema: {
610
+ ...baseArgsSchema,
611
+ exportId: z.string().min(1),
612
+ },
613
+ }, (args) => executeTool(args, async (_ctx, client) => {
614
+ const exportIdSegment = encodePathSegment(args.exportId, "exportId");
615
+ return await client.request(`/crm/v3/exports/${exportIdSegment}/status`);
616
+ }));
617
+ // ── Pipeline Stages ────────────────────────────────────────────────────
618
+ server.registerTool("crm_pipelines_stages", {
619
+ description: "List stages for a pipeline",
620
+ inputSchema: {
621
+ ...baseArgsSchema,
622
+ objectType: z.enum(PIPELINE_OBJECT_TYPES),
623
+ pipelineId: z.string().min(1),
624
+ },
625
+ }, (args) => executeTool(args, (_ctx, client) => {
626
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PIPELINE_OBJECT_TYPES, "objectType");
627
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
628
+ const pipelineIdSegment = encodePathSegment(args.pipelineId, "pipelineId");
629
+ return client.request(`/crm/v3/pipelines/${objectTypeSegment}/${pipelineIdSegment}/stages`);
630
+ }));
631
+ // ── Property Groups ────────────────────────────────────────────────────
632
+ server.registerTool("crm_property_groups_list", {
633
+ description: "List property groups for an object type",
634
+ inputSchema: {
635
+ ...baseArgsSchema,
636
+ objectType: z.enum(PROPERTY_OBJECT_TYPES),
637
+ },
638
+ }, (args) => executeTool(args, (_ctx, client) => {
639
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PROPERTY_OBJECT_TYPES, "objectType");
640
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
641
+ return client.request(`/crm/v3/properties/${objectTypeSegment}/groups`);
642
+ }));
643
+ server.registerTool("crm_property_groups_create", {
644
+ description: "Create a property group (dry-run by default unless force=true)",
645
+ inputSchema: {
646
+ ...baseArgsSchema,
647
+ objectType: z.enum(PROPERTY_OBJECT_TYPES),
648
+ data: z.record(z.string(), z.unknown()),
649
+ },
650
+ }, (args) => executeTool(args, (ctx, client) => {
651
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PROPERTY_OBJECT_TYPES, "objectType");
652
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
653
+ return maybeWrite(ctx, client, "POST", `/crm/v3/properties/${objectTypeSegment}/groups`, args.data);
654
+ }));
655
+ server.registerTool("crm_property_groups_update", {
656
+ description: "Update a property group (dry-run by default unless force=true)",
657
+ inputSchema: {
658
+ ...baseArgsSchema,
659
+ objectType: z.enum(PROPERTY_OBJECT_TYPES),
660
+ groupName: z.string().min(1),
661
+ data: z.record(z.string(), z.unknown()),
662
+ },
663
+ }, (args) => executeTool(args, (ctx, client) => {
664
+ const objectTypeValue = parseSupportedObjectType(args.objectType, PROPERTY_OBJECT_TYPES, "objectType");
665
+ const objectTypeSegment = encodePathSegment(objectTypeValue, "objectType");
666
+ const groupNameSegment = encodePathSegment(args.groupName, "groupName");
667
+ return maybeWrite(ctx, client, "PATCH", `/crm/v3/properties/${objectTypeSegment}/groups/${groupNameSegment}`, args.data);
668
+ }));
669
+ }
670
+ export function createMcpServer() {
671
+ const server = new McpServer({ name: "hubcli", version: "0.1.0" });
672
+ registerHubSpotTools(server);
673
+ return server;
674
+ }
675
+ export async function runMcpServer() {
676
+ const server = createMcpServer();
677
+ const transport = new StdioServerTransport();
678
+ await server.connect(transport);
679
+ }
680
+ //# sourceMappingURL=server.js.map