@cubis/foundry 0.3.65 → 0.3.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -14,6 +14,16 @@ All notable changes to this project are documented in this file.
14
14
  - Postman CLI is the recommended secondary path after direct MCP execution fails
15
15
  - monitor quota, API rate limits, and runtime timeouts are documented as separate failure classes.
16
16
 
17
+ ## [0.3.67] - 2026-03-08
18
+
19
+ ### Fixed
20
+
21
+ - `cbx init` now keeps MCP runtime selection available when `cubis-foundry` is the only MCP selected.
22
+ - Foundry MCP install/config patching now respects the selected runtime:
23
+ - local runtime keeps the `cbx mcp serve` stdio registration
24
+ - docker runtime points supported clients at the local Docker MCP endpoint
25
+ - `cbx workflows config --mcp-runtime ...` now reapplies managed MCP target wiring so runtime changes update the platform config.
26
+
17
27
  ## [0.3.62] - 2026-03-05
18
28
 
19
29
  ### Fixed
@@ -262,3 +272,5 @@ All notable changes to this project are documented in this file.
262
272
  - Added centralized Postman config via `cbx_config.json`.
263
273
  - Added MCP scope controls (`project/workspace/global/user`) with platform-aware runtime placement.
264
274
  - Kept rules/engineering artifacts in workspace scope while defaulting skills/powers install to global scope.
275
+
276
+
package/README.md CHANGED
@@ -81,7 +81,7 @@ Wizard flow:
81
81
  - Skills profile selection (`core`, `web-backend`, `full`)
82
82
  - MCP selection (`Cubis Foundry`, `Postman`, `Stitch`)
83
83
  - Separate scope selection for Skills and MCP (`project` or `global`)
84
- - MCP runtime selection (`cbx mcp serve` local, Docker pull, Docker local build) when Postman/Stitch is enabled
84
+ - MCP runtime selection (`cbx mcp serve` local, Docker pull, Docker local build) when any MCP integration is enabled
85
85
  - Conditional Postman mode/key/workspace and Stitch key prompts
86
86
  - Final summary + confirmation
87
87
 
@@ -354,6 +354,7 @@ Codex:
354
354
  - Project MCP runtime target: `<workspace>/.vscode/mcp.json`
355
355
  - Foundry side-by-side server id: `cubis-foundry` (command: `cbx mcp serve --transport stdio --scope <global|project>`)
356
356
  - Install now pins scope explicitly (`global` or `project`) in this command.
357
+ - When MCP runtime is set to `docker`, install points `cubis-foundry` at the local Docker endpoint (`http://127.0.0.1:3310/mcp`) instead of the stdio command.
357
358
 
358
359
  Antigravity:
359
360
 
package/dist/cli/core.js CHANGED
@@ -3755,7 +3755,17 @@ function buildFoundryServeArgs({ scope = "auto" } = {}) {
3755
3755
  : "auto";
3756
3756
  return ["mcp", "serve", "--transport", "stdio", "--scope", normalizedScope];
3757
3757
  }
3758
- function buildVsCodeFoundryServer({ scope = "auto" } = {}) {
3758
+ function buildFoundryDockerUrl({ port = DEFAULT_MCP_DOCKER_HOST_PORT } = {}) {
3759
+ return `http://127.0.0.1:${normalizePortNumber(port, DEFAULT_MCP_DOCKER_HOST_PORT)}/mcp`;
3760
+ }
3761
+ function buildVsCodeFoundryServer({ scope = "auto", runtime = "local", dockerPort = DEFAULT_MCP_DOCKER_HOST_PORT, } = {}) {
3762
+ if (runtime === "docker") {
3763
+ return {
3764
+ type: "http",
3765
+ url: buildFoundryDockerUrl({ port: dockerPort }),
3766
+ headers: {},
3767
+ };
3768
+ }
3759
3769
  return {
3760
3770
  type: "stdio",
3761
3771
  command: FOUNDRY_MCP_COMMAND,
@@ -3773,7 +3783,15 @@ function buildCopilotCliPostmanServer({ apiKeyEnvVar = POSTMAN_API_KEY_ENV_VAR,
3773
3783
  tools: ["*"],
3774
3784
  };
3775
3785
  }
3776
- function buildCopilotCliFoundryServer({ scope = "auto" } = {}) {
3786
+ function buildCopilotCliFoundryServer({ scope = "auto", runtime = "local", dockerPort = DEFAULT_MCP_DOCKER_HOST_PORT, } = {}) {
3787
+ if (runtime === "docker") {
3788
+ return {
3789
+ type: "http",
3790
+ url: buildFoundryDockerUrl({ port: dockerPort }),
3791
+ headers: {},
3792
+ tools: ["*"],
3793
+ };
3794
+ }
3777
3795
  return {
3778
3796
  type: "stdio",
3779
3797
  command: FOUNDRY_MCP_COMMAND,
@@ -3790,7 +3808,13 @@ function buildGeminiPostmanServer({ apiKeyEnvVar = POSTMAN_API_KEY_ENV_VAR, apiK
3790
3808
  },
3791
3809
  };
3792
3810
  }
3793
- function buildGeminiFoundryServer({ scope = "auto" } = {}) {
3811
+ function buildGeminiFoundryServer({ scope = "auto", runtime = "local", dockerPort = DEFAULT_MCP_DOCKER_HOST_PORT, } = {}) {
3812
+ if (runtime === "docker") {
3813
+ return {
3814
+ httpUrl: buildFoundryDockerUrl({ port: dockerPort }),
3815
+ headers: {},
3816
+ };
3817
+ }
3794
3818
  return {
3795
3819
  command: FOUNDRY_MCP_COMMAND,
3796
3820
  args: buildFoundryServeArgs({ scope }),
@@ -4215,12 +4239,27 @@ async function removeGeneratedArtifactIfExists({ targetPath, dryRun = false }) {
4215
4239
  path: targetPath,
4216
4240
  };
4217
4241
  }
4218
- async function applyPostmanMcpForPlatform({ platform, mcpScope, apiKeyEnvVar, mcpUrl, includePostmanMcp = true, stitchApiKeyEnvVar, stitchMcpUrl, includeStitchMcp = false, includeFoundryMcp = true, dryRun = false, cwd = process.cwd(), }) {
4242
+ async function applyPostmanMcpForPlatform({ platform, mcpScope, apiKeyEnvVar, mcpUrl, includePostmanMcp = true, stitchApiKeyEnvVar, stitchMcpUrl, includeStitchMcp = false, includeFoundryMcp = true, foundryRuntime = "local", dryRun = false, cwd = process.cwd(), }) {
4219
4243
  const workspaceRoot = findWorkspaceRoot(cwd);
4220
4244
  const warnings = [];
4221
4245
  const foundryScope = mcpScope === "global" ? "global" : "project";
4246
+ const normalizedFoundryRuntime = normalizeMcpRuntime(foundryRuntime, "local");
4222
4247
  const resolvedPostmanApiKey = normalizePostmanApiKey(process.env[apiKeyEnvVar || POSTMAN_API_KEY_ENV_VAR]);
4223
4248
  const resolvedStitchApiKey = normalizePostmanApiKey(process.env[stitchApiKeyEnvVar || STITCH_API_KEY_ENV_VAR]);
4249
+ let foundryDockerPort = DEFAULT_MCP_DOCKER_HOST_PORT;
4250
+ if (includeFoundryMcp && normalizedFoundryRuntime === "docker") {
4251
+ const runningPort = await resolveDockerContainerHostPort({
4252
+ name: DEFAULT_MCP_DOCKER_CONTAINER_NAME,
4253
+ containerPort: MCP_DOCKER_CONTAINER_PORT,
4254
+ cwd,
4255
+ });
4256
+ if (runningPort) {
4257
+ foundryDockerPort = runningPort;
4258
+ }
4259
+ else {
4260
+ warnings.push(`Foundry MCP is configured for Docker runtime at ${buildFoundryDockerUrl({ port: foundryDockerPort })}. Start it with 'cbx mcp runtime up --scope ${mcpScope}'.`);
4261
+ }
4262
+ }
4224
4263
  if (platform === "antigravity") {
4225
4264
  const settingsPath = mcpScope === "global"
4226
4265
  ? path.join(os.homedir(), ".gemini", "settings.json")
@@ -4244,6 +4283,8 @@ async function applyPostmanMcpForPlatform({ platform, mcpScope, apiKeyEnvVar, mc
4244
4283
  if (includeFoundryMcp) {
4245
4284
  mcpServers[FOUNDRY_MCP_SERVER_ID] = buildGeminiFoundryServer({
4246
4285
  scope: foundryScope,
4286
+ runtime: normalizedFoundryRuntime,
4287
+ dockerPort: foundryDockerPort,
4247
4288
  });
4248
4289
  }
4249
4290
  else {
@@ -4293,6 +4334,8 @@ async function applyPostmanMcpForPlatform({ platform, mcpScope, apiKeyEnvVar, mc
4293
4334
  if (includeFoundryMcp) {
4294
4335
  mcpServers[FOUNDRY_MCP_SERVER_ID] = buildCopilotCliFoundryServer({
4295
4336
  scope: foundryScope,
4337
+ runtime: normalizedFoundryRuntime,
4338
+ dockerPort: foundryDockerPort,
4296
4339
  });
4297
4340
  }
4298
4341
  else {
@@ -4316,6 +4359,8 @@ async function applyPostmanMcpForPlatform({ platform, mcpScope, apiKeyEnvVar, mc
4316
4359
  if (includeFoundryMcp) {
4317
4360
  servers[FOUNDRY_MCP_SERVER_ID] = buildVsCodeFoundryServer({
4318
4361
  scope: foundryScope,
4362
+ runtime: normalizedFoundryRuntime,
4363
+ dockerPort: foundryDockerPort,
4319
4364
  });
4320
4365
  }
4321
4366
  else {
@@ -4364,6 +4409,8 @@ async function applyPostmanMcpForPlatform({ platform, mcpScope, apiKeyEnvVar, mc
4364
4409
  if (includeFoundryMcp) {
4365
4410
  servers[FOUNDRY_MCP_SERVER_ID] = buildVsCodeFoundryServer({
4366
4411
  scope: foundryScope,
4412
+ runtime: normalizedFoundryRuntime,
4413
+ dockerPort: foundryDockerPort,
4367
4414
  });
4368
4415
  }
4369
4416
  else {
@@ -4444,14 +4491,25 @@ async function applyPostmanMcpForPlatform({ platform, mcpScope, apiKeyEnvVar, mc
4444
4491
  }
4445
4492
  if (includeFoundryMcp) {
4446
4493
  try {
4447
- await execFile("codex", [
4448
- "mcp",
4449
- "add",
4450
- FOUNDRY_MCP_SERVER_ID,
4451
- "--",
4452
- FOUNDRY_MCP_COMMAND,
4453
- ...buildFoundryServeArgs({ scope: foundryScope }),
4454
- ], { cwd });
4494
+ if (normalizedFoundryRuntime === "docker") {
4495
+ await execFile("codex", [
4496
+ "mcp",
4497
+ "add",
4498
+ FOUNDRY_MCP_SERVER_ID,
4499
+ "--url",
4500
+ buildFoundryDockerUrl({ port: foundryDockerPort }),
4501
+ ], { cwd });
4502
+ }
4503
+ else {
4504
+ await execFile("codex", [
4505
+ "mcp",
4506
+ "add",
4507
+ FOUNDRY_MCP_SERVER_ID,
4508
+ "--",
4509
+ FOUNDRY_MCP_COMMAND,
4510
+ ...buildFoundryServeArgs({ scope: foundryScope }),
4511
+ ], { cwd });
4512
+ }
4455
4513
  }
4456
4514
  catch (error) {
4457
4515
  warnings.push(`Failed to register ${FOUNDRY_MCP_SERVER_ID} MCP via Codex CLI. Ensure 'cbx' and 'codex' are installed and rerun. (${error.message})`);
@@ -4880,6 +4938,7 @@ async function configurePostmanInstallArtifacts({ platform, scope, profilePaths,
4880
4938
  stitchMcpUrl: effectiveStitchMcpUrl,
4881
4939
  includeStitchMcp: shouldInstallStitch,
4882
4940
  includeFoundryMcp: postmanSelection.foundryMcpEnabled,
4941
+ foundryRuntime: postmanSelection.effectiveMcpRuntime || "local",
4883
4942
  dryRun,
4884
4943
  cwd,
4885
4944
  });
@@ -4969,6 +5028,7 @@ async function applyPostmanConfigArtifacts({ platform, mcpScope, configValue, dr
4969
5028
  const stitchEnabled = Boolean(stitchState);
4970
5029
  const stitchApiKeyEnvVar = normalizePostmanApiKey(stitchState?.apiKeyEnvVar) || STITCH_API_KEY_ENV_VAR;
4971
5030
  const stitchMcpUrl = stitchState?.mcpUrl || STITCH_MCP_URL;
5031
+ const foundryRuntime = normalizeMcpRuntime(configValue?.mcp?.effectiveRuntime || configValue?.mcp?.runtime, "local");
4972
5032
  const resolvedPostmanApiKey = normalizePostmanApiKey(process.env[postmanApiKeyEnvVar]);
4973
5033
  const resolvedStitchApiKey = normalizePostmanApiKey(process.env[stitchApiKeyEnvVar]);
4974
5034
  const mcpDefinitionPath = resolvePostmanMcpDefinitionPath({
@@ -5018,6 +5078,7 @@ async function applyPostmanConfigArtifacts({ platform, mcpScope, configValue, dr
5018
5078
  stitchMcpUrl,
5019
5079
  includeStitchMcp: stitchEnabled,
5020
5080
  includeFoundryMcp: true,
5081
+ foundryRuntime,
5021
5082
  dryRun,
5022
5083
  cwd,
5023
5084
  });
@@ -5773,7 +5834,7 @@ function printPostmanSetupSummary({ postmanSetup }) {
5773
5834
  console.log(`- MCP build local: ${postmanSetup.mcpBuildLocal ? "yes" : "no"}`);
5774
5835
  console.log(`- MCP image prepare: ${postmanSetup.dockerImageAction}`);
5775
5836
  console.log(`- MCP tool sync: ${postmanSetup.mcpToolSync ? "enabled" : "disabled"}`);
5776
- console.log(`- Foundry MCP side-by-side: ${postmanSetup.foundryMcpEnabled ? "enabled" : "disabled"}`);
5837
+ console.log(`- Foundry MCP side-by-side: ${postmanSetup.foundryMcpEnabled ? postmanSetup.effectiveMcpRuntime === "docker" ? "enabled (docker endpoint)" : "enabled (cbx mcp serve)" : "disabled"}`);
5777
5838
  if (postmanSetup.postmanEnabled) {
5778
5839
  console.log(`- Postman API key source: ${postmanSetup.apiKeySource}`);
5779
5840
  }
@@ -8162,7 +8223,7 @@ async function runWorkflowConfig(options) {
8162
8223
  const effectivePostmanState = ensureCredentialServiceState(next, "postman");
8163
8224
  const effectivePostmanMode = resolvePostmanModeFromUrl(effectivePostmanState.mcpUrl, DEFAULT_POSTMAN_CONFIG_MODE);
8164
8225
  let postmanArtifacts = null;
8165
- if (hasPostmanModeOption) {
8226
+ if (hasPostmanModeOption || hasMcpRuntimeOption) {
8166
8227
  const mcpScope = resolveMcpScopeFromConfigDocument(next, scope);
8167
8228
  let platform = null;
8168
8229
  const explicitPlatform = normalizePlatform(opts.platform);
@@ -9411,9 +9472,8 @@ async function runInitWizard(options) {
9411
9472
  if (selections.platforms.length === 0) {
9412
9473
  throw new Error("No platforms selected.");
9413
9474
  }
9414
- const remoteMcpSelected = selections.selectedMcps.includes("postman") ||
9415
- selections.selectedMcps.includes("stitch");
9416
- if (remoteMcpSelected && isInteractive) {
9475
+ const runtimeSelectableMcp = selections.selectedMcps.length > 0;
9476
+ if (runtimeSelectableMcp && isInteractive) {
9417
9477
  const runtimeSelection = await promptInitMcpRuntime({
9418
9478
  defaultRuntime: selections.mcpRuntime,
9419
9479
  defaultBuildLocal: selections.mcpBuildLocal,
@@ -9421,7 +9481,7 @@ async function runInitWizard(options) {
9421
9481
  selections.mcpRuntime = runtimeSelection.mcpRuntime;
9422
9482
  selections.mcpBuildLocal = runtimeSelection.mcpBuildLocal;
9423
9483
  }
9424
- else if (!remoteMcpSelected) {
9484
+ else if (!runtimeSelectableMcp) {
9425
9485
  selections.mcpRuntime = "local";
9426
9486
  selections.mcpBuildLocal = false;
9427
9487
  }