@hs-x/cli 0.3.0 → 0.3.6

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.
@@ -17,7 +17,7 @@ export declare function removeAccountBody(commandName: string, target: Option.Op
17
17
  declare const whoamiCmd: Command.Command<"whoami", AccountStore, CliError, {
18
18
  readonly json: boolean;
19
19
  }>;
20
- export declare const accountCmd: Command.Command<"account", Cwd | AccountStore, CliError, {
20
+ export declare const accountCmd: Command.Command<"account", AccountStore | Cwd, CliError, {
21
21
  readonly subcommand: Option.Option<{
22
22
  readonly cwd: Option.Option<string>;
23
23
  readonly json: boolean;
@@ -42,20 +42,20 @@ export declare const accountCmd: Command.Command<"account", Cwd | AccountStore,
42
42
  readonly yes: boolean;
43
43
  }>;
44
44
  }>;
45
- export declare const accountsCmd: Command.Command<"accounts", Cwd | AccountStore, CliError, {
45
+ export declare const accountsCmd: Command.Command<"accounts", AccountStore | Cwd, CliError, {
46
46
  readonly subcommand: Option.Option<{
47
+ readonly cwd: Option.Option<string>;
47
48
  readonly json: boolean;
48
49
  } | {
49
- readonly 'account-id': Option.Option<string>;
50
+ readonly cwd: Option.Option<string>;
50
51
  readonly json: boolean;
51
52
  } | {
52
- readonly 'account-id': Option.Option<string>;
53
53
  readonly json: boolean;
54
54
  } | {
55
- readonly cwd: Option.Option<string>;
55
+ readonly 'account-id': Option.Option<string>;
56
56
  readonly json: boolean;
57
57
  } | {
58
- readonly cwd: Option.Option<string>;
58
+ readonly 'account-id': Option.Option<string>;
59
59
  readonly json: boolean;
60
60
  } | {
61
61
  readonly 'account-id': Option.Option<string>;
@@ -521,7 +521,7 @@ Examples:
521
521
  hs-x api v1/accounts/me
522
522
  hs-x api v1/deploys --json
523
523
  hs-x api hubspot crm-dev-applications/v3/apps
524
- hs-x api hubspot feature-flags/v3/<appId>/flags
524
+ hs-x api hubspot feature-flags/2026-03/<appId>/flags/hs-release-mcp-server
525
525
  hs-x api hubspot crm-dev-platform/v3/projects/<projectId>/builds
526
526
  `;
527
527
  }
@@ -40,7 +40,7 @@ export declare function resolveOperationProjectForRead(opts: CpReadOptions, inpu
40
40
  readonly message: string;
41
41
  readonly emptyMessage: string;
42
42
  }): Effect.Effect<OperationProjectSelection | undefined, CliError, AccountStore | ControlPlaneClient | Cwd | Reporter>;
43
- export declare const auditCmd: Command.Command<"audit", Cwd | AccountStore | ControlPlaneClient, CliError, {
43
+ export declare const auditCmd: Command.Command<"audit", AccountStore | Cwd | ControlPlaneClient, CliError, {
44
44
  readonly limit: number;
45
45
  readonly since: Option.Option<string>;
46
46
  readonly action: Option.Option<string>;
@@ -53,7 +53,7 @@ export declare const auditCmd: Command.Command<"audit", Cwd | AccountStore | Con
53
53
  readonly projectId: Option.Option<string>;
54
54
  readonly userId: Option.Option<string>;
55
55
  }>;
56
- export declare const auditListCmd: Command.Command<"list", Cwd | AccountStore | ControlPlaneClient, CliError, {
56
+ export declare const auditListCmd: Command.Command<"list", AccountStore | Cwd | ControlPlaneClient, CliError, {
57
57
  readonly limit: number;
58
58
  readonly since: Option.Option<string>;
59
59
  readonly action: Option.Option<string>;
@@ -73,7 +73,7 @@ export declare function parseAuditSince(value: string | undefined, now?: number)
73
73
  readonly ok: false;
74
74
  readonly message: string;
75
75
  };
76
- export declare const driftCmd: Command.Command<"drift", Cwd | AccountStore | ControlPlaneClient, CliError, {
76
+ export declare const driftCmd: Command.Command<"drift", AccountStore | Cwd | ControlPlaneClient, CliError, {
77
77
  readonly json: boolean;
78
78
  readonly controlPlaneUrl: Option.Option<string>;
79
79
  readonly accountId: Option.Option<string>;
@@ -120,14 +120,14 @@ export declare function remoteStatusBody(opts: RemoteStatusOptions, projectId: s
120
120
  export declare function renderRemoteStatus(input: RemoteProjectStatus & {
121
121
  readonly projectId: string;
122
122
  }): string;
123
- export declare const checkpointCmd: Command.Command<"checkpoint", Cwd | AccountStore | ControlPlaneClient, CliError, {
123
+ export declare const checkpointCmd: Command.Command<"checkpoint", AccountStore | Cwd | ControlPlaneClient, CliError, {
124
124
  readonly json: boolean;
125
125
  readonly controlPlaneUrl: Option.Option<string>;
126
126
  readonly accountId: Option.Option<string>;
127
127
  readonly projectId: Option.Option<string>;
128
128
  readonly userId: Option.Option<string>;
129
129
  }>;
130
- export declare const logsCmd: Command.Command<"logs", Cwd | AccountStore | ControlPlaneClient, CliError, {
130
+ export declare const logsCmd: Command.Command<"logs", AccountStore | Cwd | ControlPlaneClient, CliError, {
131
131
  readonly limit: number;
132
132
  readonly sinceMinutes: number;
133
133
  readonly trace: Option.Option<string>;
@@ -152,21 +152,21 @@ export declare function logsBodyForCheckpoint(opts: CpReadOptions, selection: Op
152
152
  export declare function logsBodyForStatus(opts: RemoteStatusOptions, selection: OperationProjectSelection): Effect.Effect<void, CliError, AccountStore | ControlPlaneClient | Cwd | Reporter>;
153
153
  export declare function routesBodyForStatus(opts: RemoteStatusOptions, selection: OperationProjectSelection): Effect.Effect<void, CliError, AccountStore | ControlPlaneClient | Cwd | Reporter>;
154
154
  export declare function driftBodyForStatus(opts: RemoteStatusOptions, selection: OperationProjectSelection): Effect.Effect<void, CliError, AccountStore | ControlPlaneClient | Cwd | Reporter>;
155
- export declare const routingCmd: Command.Command<"routing" | "route" | "routes", Cwd | AccountStore | ControlPlaneClient, CliError, {
155
+ export declare const routingCmd: Command.Command<"routes" | "routing" | "route", AccountStore | Cwd | ControlPlaneClient, CliError, {
156
156
  readonly json: boolean;
157
157
  readonly controlPlaneUrl: Option.Option<string>;
158
158
  readonly accountId: Option.Option<string>;
159
159
  readonly projectId: Option.Option<string>;
160
160
  readonly userId: Option.Option<string>;
161
161
  }>;
162
- export declare const routeCmd: Command.Command<"routing" | "route" | "routes", Cwd | AccountStore | ControlPlaneClient, CliError, {
162
+ export declare const routeCmd: Command.Command<"routes" | "routing" | "route", AccountStore | Cwd | ControlPlaneClient, CliError, {
163
163
  readonly json: boolean;
164
164
  readonly controlPlaneUrl: Option.Option<string>;
165
165
  readonly accountId: Option.Option<string>;
166
166
  readonly projectId: Option.Option<string>;
167
167
  readonly userId: Option.Option<string>;
168
168
  }>;
169
- export declare const routesCmd: Command.Command<"routing" | "route" | "routes", Cwd | AccountStore | ControlPlaneClient, CliError, {
169
+ export declare const routesCmd: Command.Command<"routes" | "routing" | "route", AccountStore | Cwd | ControlPlaneClient, CliError, {
170
170
  readonly json: boolean;
171
171
  readonly controlPlaneUrl: Option.Option<string>;
172
172
  readonly accountId: Option.Option<string>;
@@ -8,7 +8,7 @@ import { AccountStore } from '../services/account-store.js';
8
8
  import { ControlPlaneClient } from '../services/control-plane.js';
9
9
  import { Cwd } from '../services/cwd.js';
10
10
  import { CliHttp } from '../services/http.js';
11
- export declare const promoteCmd: Command.Command<"promote", Cwd | AccountStore | CliHttp | ControlPlaneClient, CliError, {
11
+ export declare const promoteCmd: Command.Command<"promote", AccountStore | Cwd | CliHttp | ControlPlaneClient, CliError, {
12
12
  readonly cwd: Option.Option<string>;
13
13
  readonly json: boolean;
14
14
  readonly deployId: Option.Option<string>;
@@ -1,6 +1,6 @@
1
1
  import * as Command from '@effect/cli/Command';
2
2
  import { type WorkerManifest } from '@hs-x/codegen';
3
- import type { AppAlertsConfiguration, AppEventBatchingConfiguration, AppEventDeclaration, AppObjectAssociationDeclaration, AppObjectDeclaration, AppRedactionConfiguration, CardDefinition, HubSpotRateLimitConfiguration } from '@hs-x/types';
3
+ import type { AppAlertsConfiguration, AppEventBatchingConfiguration, AppEventDeclaration, AppObjectAssociationDeclaration, AppObjectDeclaration, AppRedactionConfiguration, CardDefinition, HubSpotRateLimitConfiguration, McpServerDefinition } from '@hs-x/types';
4
4
  import { Schema, schemas } from '@hs-x/types';
5
5
  import type { AppBillingDeclaration } from '@hs-x/types';
6
6
  import { Option } from 'effect';
@@ -132,8 +132,10 @@ interface HsxAppConfig {
132
132
  readonly alerts?: AppAlertsConfiguration;
133
133
  readonly redaction?: AppRedactionConfiguration;
134
134
  readonly cards: readonly CardDefinition[];
135
+ readonly mcpServers: readonly McpServerDefinition[];
135
136
  readonly billing?: AppBillingDeclaration;
136
137
  }
138
+ export declare function readHsxAppConfig(root: string): Promise<HsxAppConfig>;
137
139
  export declare const deployCmd: Command.Command<"deploy", Cwd, import("../cli-error.js").CliError, {
138
140
  readonly json: boolean;
139
141
  readonly cwd: Option.Option<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { createHash, randomBytes } from 'node:crypto';
3
- import { cp, mkdir, mkdtemp, readFile, readdir, stat, writeFile } from 'node:fs/promises';
3
+ import { cp, lstat, mkdir, mkdtemp, readFile, readdir, realpath, rename, rmdir, stat, unlink, writeFile, } from 'node:fs/promises';
4
4
  import { createServer } from 'node:http';
5
5
  import { tmpdir } from 'node:os';
6
- import { basename, dirname, join, relative, resolve } from 'node:path';
6
+ import { basename, dirname, isAbsolute, join, relative, resolve } from 'node:path';
7
7
  import { pathToFileURL } from 'node:url';
8
8
  import * as Command from '@effect/cli/Command';
9
9
  import * as Options from '@effect/cli/Options';
@@ -646,6 +646,7 @@ export async function deployCommand({ argv, root, json, }) {
646
646
  projectId = await readHsxConfigProjectId(root);
647
647
  }
648
648
  const needsRuntime = workers.some((worker) => worker.capabilities.some((capability) => capability.runtimeNeeds.some((need) => need !== 'hubspot-only')));
649
+ const needsHubSpotBundle = needsRuntime || app.mcpServers.length > 0;
649
650
  const cloudflareDeployRequested = !buildOnly &&
650
651
  (explicitCloudflareDeployRequested || (!planOnly && needsRuntime && !explicitHubspotUpload));
651
652
  const hubspotUploadRequested = !buildOnly && (explicitHubspotUpload || (!planOnly && !cloudflareDryRun && Boolean(projectId)));
@@ -1135,7 +1136,7 @@ export async function deployCommand({ argv, root, json, }) {
1135
1136
  // Default order (skipped when we already uploaded first above): generate the
1136
1137
  // HubSpot bundle from the deployed Worker URL, then upload.
1137
1138
  if (!uploadFirstOrigin && hubspotUploadRequested && validation.ok) {
1138
- const bundleStep = needsRuntime ? progress?.step('Generating HubSpot bundle') : undefined;
1139
+ const bundleStep = needsHubSpotBundle ? progress?.step('Generating HubSpot bundle') : undefined;
1139
1140
  try {
1140
1141
  await ensureHubSpotRuntimeProjectArtifacts({
1141
1142
  argv,
@@ -3121,8 +3122,161 @@ async function resolveUploadFirstRuntimeOrigin(input) {
3121
3122
  return undefined;
3122
3123
  }
3123
3124
  }
3125
+ const HUBSPOT_GENERATED_LEDGER = '.hs-x/hubspot-generated-files.json';
3126
+ const USER_OWNED_GENERATED_PATHS = new Set(['src/app/cards/package.json']);
3127
+ function generatedFileHash(contents) {
3128
+ return createHash('sha256').update(contents).digest('hex');
3129
+ }
3130
+ function isKnownGeneratedHubSpotPath(file) {
3131
+ return (file === 'hsproject.json' ||
3132
+ file === 'src/app/app-hsmeta.json' ||
3133
+ file === 'src/app/cards/package.json' ||
3134
+ file === 'src/app/cards/_hsx-backend.ts' ||
3135
+ /^src\/app\/(?:workflow-actions|app-objects|app-object-associations|app-events|mcp-server|cards)\/[^/]+-hsmeta\.json$/.test(file));
3136
+ }
3137
+ /** Resolve a ledger path only when it is a known, normalized root-relative artifact. */
3138
+ function resolveGeneratedFilePath(root, file) {
3139
+ if (!isKnownGeneratedHubSpotPath(file) || isAbsolute(file) || file.includes('\\')) {
3140
+ return undefined;
3141
+ }
3142
+ const segments = file.split('/');
3143
+ if (segments.some((segment) => segment === '' || segment === '.' || segment === '..')) {
3144
+ return undefined;
3145
+ }
3146
+ const rootPath = resolve(root);
3147
+ const resolved = resolve(rootPath, file);
3148
+ return resolved.startsWith(`${rootPath}/`) ? resolved : undefined;
3149
+ }
3150
+ async function assertGeneratedPathIsContained(root, path) {
3151
+ const rootRealPath = await realpath(root);
3152
+ let existingAncestor = dirname(path);
3153
+ while (true) {
3154
+ try {
3155
+ const ancestorRealPath = await realpath(existingAncestor);
3156
+ const fromRoot = relative(rootRealPath, ancestorRealPath);
3157
+ if (fromRoot.startsWith('..') || isAbsolute(fromRoot)) {
3158
+ throw new Error(`Generated HubSpot artifact parent escapes the project root: ${path}`);
3159
+ }
3160
+ break;
3161
+ }
3162
+ catch (error) {
3163
+ if (error.code !== 'ENOENT')
3164
+ throw error;
3165
+ const parent = dirname(existingAncestor);
3166
+ if (parent === existingAncestor)
3167
+ throw error;
3168
+ existingAncestor = parent;
3169
+ }
3170
+ }
3171
+ const target = await lstat(path).catch((error) => {
3172
+ if (error.code === 'ENOENT')
3173
+ return undefined;
3174
+ throw error;
3175
+ });
3176
+ if (target?.isSymbolicLink()) {
3177
+ throw new Error(`Generated HubSpot artifact path must not be a symbolic link: ${path}`);
3178
+ }
3179
+ }
3180
+ async function readGeneratedFileLedger(root) {
3181
+ try {
3182
+ const parsed = JSON.parse(await readFile(join(root, HUBSPOT_GENERATED_LEDGER), 'utf8'));
3183
+ if (typeof parsed !== 'object' ||
3184
+ parsed === null ||
3185
+ parsed.version !== 1 ||
3186
+ typeof parsed.files !== 'object' ||
3187
+ parsed.files === null) {
3188
+ return { version: 1, files: {} };
3189
+ }
3190
+ const files = {};
3191
+ for (const [file, hash] of Object.entries(parsed.files)) {
3192
+ if (resolveGeneratedFilePath(root, file) && /^[a-f0-9]{64}$/.test(String(hash))) {
3193
+ files[file] = String(hash);
3194
+ }
3195
+ }
3196
+ return { version: 1, files };
3197
+ }
3198
+ catch {
3199
+ // No heuristic cleanup for projects that predate the ledger, or for a
3200
+ // malformed ledger. Generation can safely establish a fresh ledger.
3201
+ return { version: 1, files: {} };
3202
+ }
3203
+ }
3204
+ async function pruneEmptyGeneratedDirectories(root, from) {
3205
+ const rootPath = resolve(root);
3206
+ let directory = resolve(from);
3207
+ while (directory !== rootPath && directory.startsWith(`${rootPath}/`)) {
3208
+ try {
3209
+ if ((await readdir(directory)).length > 0)
3210
+ return;
3211
+ await rmdir(directory);
3212
+ }
3213
+ catch {
3214
+ return;
3215
+ }
3216
+ directory = dirname(directory);
3217
+ }
3218
+ }
3219
+ async function reconcileHubSpotRuntimeProjectFiles(root, generatedFiles, options = {}) {
3220
+ const previous = await readGeneratedFileLedger(root);
3221
+ const generatedPaths = new Set(Object.keys(generatedFiles));
3222
+ const nextFiles = {};
3223
+ for (const [file, expectedHash] of Object.entries(previous.files)) {
3224
+ if (generatedPaths.has(file) || USER_OWNED_GENERATED_PATHS.has(file))
3225
+ continue;
3226
+ if (options.preservePrevious?.(file)) {
3227
+ nextFiles[file] = expectedHash;
3228
+ continue;
3229
+ }
3230
+ const path = resolveGeneratedFilePath(root, file);
3231
+ if (!path)
3232
+ continue;
3233
+ try {
3234
+ await assertGeneratedPathIsContained(root, path);
3235
+ const current = await readFile(path);
3236
+ if (generatedFileHash(current) !== expectedHash)
3237
+ continue;
3238
+ await unlink(path);
3239
+ await pruneEmptyGeneratedDirectories(root, dirname(path));
3240
+ }
3241
+ catch {
3242
+ // Missing and non-file paths are preserved; only a byte-for-byte owned
3243
+ // regular file is eligible for removal.
3244
+ }
3245
+ }
3246
+ for (const [file, contents] of Object.entries(generatedFiles)) {
3247
+ const path = resolveGeneratedFilePath(root, file);
3248
+ if (!path)
3249
+ throw new Error(`Generated HubSpot artifact has an unsafe path: ${file}`);
3250
+ await assertGeneratedPathIsContained(root, path);
3251
+ // HubSpot tells card authors to add dependencies here. Once created, this
3252
+ // file is user-owned and is deliberately never entered in the ledger.
3253
+ if (USER_OWNED_GENERATED_PATHS.has(file)) {
3254
+ if (!(await stat(path).catch(() => undefined))) {
3255
+ await mkdir(dirname(path), { recursive: true });
3256
+ await writeFile(path, contents);
3257
+ }
3258
+ continue;
3259
+ }
3260
+ await mkdir(dirname(path), { recursive: true });
3261
+ await writeFile(path, contents);
3262
+ nextFiles[file] = generatedFileHash(contents);
3263
+ }
3264
+ const ledgerPath = join(root, HUBSPOT_GENERATED_LEDGER);
3265
+ await assertGeneratedPathIsContained(root, ledgerPath);
3266
+ await mkdir(dirname(ledgerPath), { recursive: true });
3267
+ const temporaryLedgerPath = `${ledgerPath}.${process.pid}.${randomBytes(6).toString('hex')}.tmp`;
3268
+ await writeFile(temporaryLedgerPath, `${JSON.stringify({ version: 1, files: nextFiles }, null, 2)}\n`);
3269
+ await rename(temporaryLedgerPath, ledgerPath);
3270
+ }
3124
3271
  export async function ensureHubSpotRuntimeProjectArtifacts({ argv, root, app, workers, cloudflareDeployResult, needsRuntime, controlPlanePlan, runtimeOrigin, }) {
3125
- if (!needsRuntime) {
3272
+ const hasMcpServers = app.mcpServers.length > 0;
3273
+ if (!needsRuntime && !hasMcpServers) {
3274
+ // A prior MCP-only generation may have left ledger-owned MCP files. Remove
3275
+ // those declarations, but retain other generated metadata: a display-only
3276
+ // card or schema declaration remains valid when its runtime worker is gone.
3277
+ await reconcileHubSpotRuntimeProjectFiles(root, {}, {
3278
+ preservePrevious: (file) => !file.startsWith('src/app/mcp-server/'),
3279
+ });
3126
3280
  return;
3127
3281
  }
3128
3282
  const runtimeBaseUrl = runtimeOrigin ??
@@ -3135,26 +3289,17 @@ export async function ensureHubSpotRuntimeProjectArtifacts({ argv, root, app, wo
3135
3289
  const redirectUrls = app.auth === 'oauth' && oauthCallbackPath
3136
3290
  ? [`${runtimeBaseUrl.replace(/\/$/, '')}${oauthCallbackPath}`]
3137
3291
  : [];
3292
+ const platformVersion = resolveFlag(argv, '--platform-version') ?? app.platformVersion;
3138
3293
  const generated = generateHubSpotRuntimeProject({
3139
3294
  ...app,
3295
+ platformVersion,
3140
3296
  workers,
3141
3297
  runtimeBaseUrl,
3142
3298
  redirectUrls,
3143
3299
  });
3144
- for (const [file, contents] of Object.entries(generated.files)) {
3145
- const path = join(root, file);
3146
- // src/app/cards/package.json is user-owned once it exists: HubSpot's own
3147
- // build errors instruct users to add card dependencies (e.g. hs-uix) to
3148
- // it, and regenerating the fixed-dep version here silently dropped those
3149
- // deps so the card never built (cold-stranger run #2 blocker B). Keep the
3150
- // user's file verbatim; only generate one when absent.
3151
- if (file === 'src/app/cards/package.json' && (await stat(path).catch(() => undefined))) {
3152
- continue;
3153
- }
3154
- await mkdir(dirname(path), { recursive: true });
3155
- await writeFile(path, contents);
3156
- }
3300
+ await reconcileHubSpotRuntimeProjectFiles(root, generated.files);
3157
3301
  const migratedShimPath = join(root, 'src', 'app', 'cards', '_hsx-migration-run-serverless.ts');
3302
+ await assertGeneratedPathIsContained(root, migratedShimPath);
3158
3303
  if (await stat(migratedShimPath).catch(() => undefined)) {
3159
3304
  const migratedShim = await readFile(migratedShimPath, 'utf8');
3160
3305
  await writeFile(migratedShimPath, stampMigratedRunServerlessShimOrigin(migratedShim, runtimeBaseUrl));
@@ -3169,9 +3314,19 @@ async function readHsxAppScopesForDeploy(root) {
3169
3314
  return [];
3170
3315
  }
3171
3316
  }
3172
- async function readHsxAppConfig(root) {
3317
+ export async function readHsxAppConfig(root) {
3173
3318
  const raw = await readFile(join(root, 'hsx.config.ts'), 'utf8');
3174
- const loaded = parseHsxAppConfigLiteral(raw) ?? (await loadHsxAppConfigModule(root).catch(() => undefined));
3319
+ let loaded = parseHsxAppConfigLiteral(raw);
3320
+ if (!loaded) {
3321
+ try {
3322
+ loaded = await loadHsxAppConfigModule(root);
3323
+ }
3324
+ catch (error) {
3325
+ if (/\bmcpServer\s*\(|\bmcpServers\b/.test(raw)) {
3326
+ throw new Error('Could not evaluate helper-based MCP declarations in hsx.config.ts; refusing to treat the declaration set as empty because that could remove generated MCP metadata.', { cause: error });
3327
+ }
3328
+ }
3329
+ }
3175
3330
  return {
3176
3331
  appName: loaded?.name ?? /name\s*:\s*["'`]([^"'`]+)["'`]/.exec(raw)?.[1] ?? basename(root),
3177
3332
  // No regex fallback for description: a raw-text match could pick up a
@@ -3193,9 +3348,10 @@ async function readHsxAppConfig(root) {
3193
3348
  ...(loaded?.rateLimits !== undefined ? { rateLimits: loaded.rateLimits } : {}),
3194
3349
  ...(loaded?.alerts !== undefined ? { alerts: loaded.alerts } : {}),
3195
3350
  ...(loaded?.redaction !== undefined ? { redaction: loaded.redaction } : {}),
3196
- // Cards are only recoverable from the loaded module (the literal parser
3197
- // can't evaluate `card(...)` calls); an unloadable config yields none.
3351
+ // Helper-based declarations are only recoverable from the loaded module
3352
+ // (the literal parser cannot evaluate card(...) or mcpServer(...) calls).
3198
3353
  cards: loaded?.cards ?? [],
3354
+ mcpServers: loaded?.mcpServers ?? [],
3199
3355
  ...(loaded?.billing ? { billing: loaded.billing } : {}),
3200
3356
  };
3201
3357
  }
@@ -3527,11 +3683,13 @@ async function executeHubSpotOnlyUpload({ argv, root, local, uploadOnly, }) {
3527
3683
  cwd: root,
3528
3684
  });
3529
3685
  await client.projects.ensureProject({ projectName });
3686
+ const hsproject = await readHubSpotProjectConfig(root);
3687
+ const configuredPlatformVersion = typeof hsproject.platformVersion === 'string' ? hsproject.platformVersion : undefined;
3530
3688
  const upload = await client.projects.upload({
3531
3689
  projectName,
3532
3690
  archivePath,
3533
3691
  message: resolveFlag(argv, '--message') ?? 'HS-X HubSpot-only deploy',
3534
- platformVersion: resolveFlag(argv, '--platform-version') ?? '2026.03',
3692
+ platformVersion: resolveFlag(argv, '--platform-version') ?? configuredPlatformVersion ?? '2026.03',
3535
3693
  intermediateRepresentation,
3536
3694
  });
3537
3695
  const buildStatus = await waitForHubSpotBuildStatus({