@cubis/foundry 0.3.47 → 0.3.49

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/README.md CHANGED
@@ -307,6 +307,25 @@ Notes:
307
307
  - `cbx mcp tools sync` requires `POSTMAN_API_KEY_DEFAULT`.
308
308
  - For `--service stitch` or `--service all`, it also requires `STITCH_API_KEY_DEFAULT`.
309
309
 
310
+ MCP manifest + managed rules block maintenance:
311
+
312
+ ```bash
313
+ # Generate/refresh MCP manifest snapshot
314
+ npm run generate:mcp-manifest
315
+
316
+ # Validate MCP skill catalog + rule references
317
+ npm run validate:mcp-skills
318
+ npm run validate:mcp-manifest
319
+
320
+ # Inject/check managed MCP block in platform rule files
321
+ npm run inject:mcp-rules:all
322
+ npm run check:mcp-rules:all
323
+ ```
324
+
325
+ Generated MCP artifacts:
326
+ - `mcp/generated/mcp-manifest.json` (catalog snapshot used by managed rule blocks)
327
+ - `mcp/generated/README.md` (artifact notes)
328
+
310
329
  Foundry local serve command (canonical entrypoint for MCP client registration):
311
330
 
312
331
  ```bash
@@ -332,6 +351,9 @@ cbx mcp runtime up --scope global --name cbx-mcp --port 3310 --fallback local
332
351
  # Recreate existing container
333
352
  cbx mcp runtime up --scope global --name cbx-mcp --replace --fallback local
334
353
 
354
+ # Force an explicit skill vault mount source
355
+ cbx mcp runtime up --scope global --name cbx-mcp --replace --skills-root ~/.agents/skills
356
+
335
357
  # Stop/remove runtime container
336
358
  cbx mcp runtime down --name cbx-mcp
337
359
  ```
@@ -354,6 +376,14 @@ Optional strict key mode:
354
376
  CBX_MCP_REQUIRE_KEYS=1 npm run test:mcp:docker
355
377
  ```
356
378
 
379
+ Use host skill vault instead of the script's isolated sample vault:
380
+
381
+ ```bash
382
+ CBX_MCP_USE_HOST_SKILLS=1 npm run test:mcp:docker
383
+ # or an explicit path
384
+ CBX_MCP_USE_HOST_SKILLS=1 CBX_MCP_HOST_SKILLS_DIR="$PWD/.agents/skills" npm run test:mcp:docker
385
+ ```
386
+
357
387
  Context budget reporting (from MCP skill tools):
358
388
 
359
389
  - Skill tools now include `structuredContent.metrics` with deterministic estimates.
@@ -364,6 +394,7 @@ Context budget reporting (from MCP skill tools):
364
394
  - `estimatedSavingsVsFullCatalog`
365
395
  - `estimatedSavingsVsFullCatalogPercent`
366
396
  - New rollup tool: `skill_budget_report` for consolidated Skill Log + Context Budget.
397
+ - Docker smoke now prints token estimate lines (`token.full_catalog`, `token.selected`, `token.loaded`, `token.savings`, etc.) for quick visibility.
367
398
  - All token values are estimates using `ceil(char_count / charsPerToken)` (default `charsPerToken=4`), not provider billing tokens.
368
399
 
369
400
  Install profile flags:
@@ -466,6 +497,9 @@ cbx mcp runtime up --scope global --name cbx-mcp --replace
466
497
 
467
498
  # Check mount hint
468
499
  cbx mcp runtime status --scope global --name cbx-mcp
500
+
501
+ # Force mount from an explicit path
502
+ cbx mcp runtime up --scope global --name cbx-mcp --replace --skills-root ~/.agents/skills
469
503
  ```
470
504
 
471
505
  If `~/.agents/skills` is missing, runtime still starts but will warn and skill discovery may return zero.
package/bin/cubis.js CHANGED
@@ -8341,6 +8341,64 @@ function resolveCbxRootPath({ scope, cwd = process.cwd() }) {
8341
8341
  return path.join(workspaceRoot, ".cbx");
8342
8342
  }
8343
8343
 
8344
+ function dedupePaths(paths) {
8345
+ const seen = new Set();
8346
+ const out = [];
8347
+ for (const value of paths) {
8348
+ const normalized = path.resolve(value);
8349
+ if (seen.has(normalized)) continue;
8350
+ seen.add(normalized);
8351
+ out.push(normalized);
8352
+ }
8353
+ return out;
8354
+ }
8355
+
8356
+ function resolveMcpSkillRootCandidates({
8357
+ scope,
8358
+ cwd = process.cwd(),
8359
+ explicitSkillsRoot = null,
8360
+ }) {
8361
+ if (explicitSkillsRoot) {
8362
+ return dedupePaths([path.resolve(cwd, explicitSkillsRoot)]);
8363
+ }
8364
+
8365
+ const workspaceRoot = findWorkspaceRoot(cwd);
8366
+ const workspaceCandidates = [
8367
+ path.join(workspaceRoot, ".agents", "skills"),
8368
+ path.join(workspaceRoot, ".github", "skills"),
8369
+ path.join(workspaceRoot, ".agent", "skills"),
8370
+ ];
8371
+ const homeCandidates = [
8372
+ path.join(os.homedir(), ".agents", "skills"),
8373
+ path.join(os.homedir(), ".copilot", "skills"),
8374
+ path.join(os.homedir(), ".gemini", "antigravity", "skills"),
8375
+ ];
8376
+
8377
+ return dedupePaths(
8378
+ scope === "global"
8379
+ ? [...homeCandidates, ...workspaceCandidates]
8380
+ : [...workspaceCandidates, ...homeCandidates],
8381
+ );
8382
+ }
8383
+
8384
+ async function resolveMcpSkillRoot({
8385
+ scope,
8386
+ cwd = process.cwd(),
8387
+ explicitSkillsRoot = null,
8388
+ }) {
8389
+ const candidates = resolveMcpSkillRootCandidates({
8390
+ scope,
8391
+ cwd,
8392
+ explicitSkillsRoot,
8393
+ });
8394
+ for (const candidate of candidates) {
8395
+ if (await pathExists(candidate)) {
8396
+ return { resolvedPath: candidate, candidates };
8397
+ }
8398
+ }
8399
+ return { resolvedPath: null, candidates };
8400
+ }
8401
+
8344
8402
  function resolveMcpRuntimeDefaultsFromConfig(configValue) {
8345
8403
  const mcp =
8346
8404
  configValue && typeof configValue.mcp === "object" && !Array.isArray(configValue.mcp)
@@ -8391,15 +8449,21 @@ async function runMcpRuntimeStatus(options) {
8391
8449
  const opts = resolveActionOptions(options);
8392
8450
  const cwd = process.cwd();
8393
8451
  const scope = normalizeMcpScope(opts.scope, "global");
8452
+ const explicitSkillsRoot = normalizePostmanApiKey(opts.skillsRoot);
8394
8453
  const defaults = await loadMcpRuntimeDefaults({ scope, cwd });
8395
8454
  const containerName =
8396
8455
  normalizePostmanApiKey(opts.name) || DEFAULT_MCP_DOCKER_CONTAINER_NAME;
8397
8456
  const dockerAvailable = await checkDockerAvailable({ cwd });
8457
+ const { resolvedPath: skillsRoot, candidates: skillRootCandidates } =
8458
+ await resolveMcpSkillRoot({
8459
+ scope,
8460
+ cwd,
8461
+ explicitSkillsRoot,
8462
+ });
8398
8463
  const container = dockerAvailable
8399
8464
  ? await inspectDockerContainerByName({ name: containerName, cwd })
8400
8465
  : null;
8401
- const skillsRoot = path.join(os.homedir(), ".agents", "skills");
8402
- const skillsRootExists = await pathExists(skillsRoot);
8466
+ const skillsRootExists = Boolean(skillsRoot);
8403
8467
 
8404
8468
  console.log(`Scope: ${scope}`);
8405
8469
  console.log(`Config file: ${defaults.configPath}`);
@@ -8409,9 +8473,13 @@ async function runMcpRuntimeStatus(options) {
8409
8473
  console.log(`Configured image: ${defaults.defaults.image}`);
8410
8474
  console.log(`Configured update policy: ${defaults.defaults.updatePolicy}`);
8411
8475
  console.log(`Configured build local: ${defaults.defaults.buildLocal ? "yes" : "no"}`);
8412
- console.log(
8413
- `Host skills root: ${skillsRoot} (${skillsRootExists ? "present" : "missing"})`,
8414
- );
8476
+ console.log(`Requested skills root: ${explicitSkillsRoot || "(auto)"}`);
8477
+ if (skillsRootExists) {
8478
+ console.log(`Resolved host skills root: ${skillsRoot} (present)`);
8479
+ } else {
8480
+ console.log("Resolved host skills root: not found");
8481
+ console.log(`Skill root candidates: ${skillRootCandidates.join(", ")}`);
8482
+ }
8415
8483
  console.log(`Docker available: ${dockerAvailable ? "yes" : "no"}`);
8416
8484
  console.log(`Container name: ${containerName}`);
8417
8485
  if (!dockerAvailable) {
@@ -8422,7 +8490,7 @@ async function runMcpRuntimeStatus(options) {
8422
8490
  console.log("Container status: not found");
8423
8491
  if (!skillsRootExists) {
8424
8492
  console.log(
8425
- "Hint: ~/.agents/skills is missing. Create/populate it before starting runtime to enable vault discovery.",
8493
+ "Hint: no host skill directory was found from auto-detect candidates. Pass --skills-root <path> to force a mount source.",
8426
8494
  );
8427
8495
  }
8428
8496
  return;
@@ -8445,7 +8513,7 @@ async function runMcpRuntimeStatus(options) {
8445
8513
  } else {
8446
8514
  console.log("Skills mount: missing");
8447
8515
  console.log(
8448
- "Hint: recreate runtime with a skills mount (host ~/.agents/skills -> /workflows/skills).",
8516
+ "Hint: recreate runtime with a skills mount (for example: cbx mcp runtime up --replace --skills-root <path>).",
8449
8517
  );
8450
8518
  }
8451
8519
  if (isRunning) {
@@ -8484,6 +8552,7 @@ async function runMcpRuntimeUp(options) {
8484
8552
  const opts = resolveActionOptions(options);
8485
8553
  const cwd = process.cwd();
8486
8554
  const scope = normalizeMcpScope(opts.scope, "global");
8555
+ const explicitSkillsRoot = normalizePostmanApiKey(opts.skillsRoot);
8487
8556
  const defaults = await loadMcpRuntimeDefaults({ scope, cwd });
8488
8557
  const containerName =
8489
8558
  normalizePostmanApiKey(opts.name) || DEFAULT_MCP_DOCKER_CONTAINER_NAME;
@@ -8528,12 +8597,17 @@ async function runMcpRuntimeUp(options) {
8528
8597
  }
8529
8598
 
8530
8599
  const cbxRoot = resolveCbxRootPath({ scope, cwd });
8531
- const skillsRoot = path.join(os.homedir(), ".agents", "skills");
8532
- const skillsRootExists = await pathExists(skillsRoot);
8600
+ const { resolvedPath: skillsRoot, candidates: skillRootCandidates } =
8601
+ await resolveMcpSkillRoot({
8602
+ scope,
8603
+ cwd,
8604
+ explicitSkillsRoot,
8605
+ });
8606
+ const skillsRootExists = Boolean(skillsRoot);
8533
8607
  const runtimeWarnings = [];
8534
8608
  if (!skillsRootExists) {
8535
8609
  runtimeWarnings.push(
8536
- `Skill mount source is missing: ${skillsRoot}. Runtime will start without /workflows/skills and vault discovery can return zero skills.`,
8610
+ `No skill mount source found from candidates (${skillRootCandidates.join(", ")}). Runtime will start without /workflows/skills and vault discovery can return zero skills.`,
8537
8611
  );
8538
8612
  }
8539
8613
  await mkdir(cbxRoot, { recursive: true });
@@ -8579,6 +8653,7 @@ async function runMcpRuntimeUp(options) {
8579
8653
  console.log(`Fallback: ${fallback}`);
8580
8654
  console.log(`Build local: ${buildLocal ? "yes" : "no"}`);
8581
8655
  console.log(`Mount: ${cbxRoot} -> /root/.cbx`);
8656
+ console.log(`Requested skills root: ${explicitSkillsRoot || "(auto)"}`);
8582
8657
  if (skillsRootExists) {
8583
8658
  console.log(`Mount: ${skillsRoot} -> /workflows/skills (ro)`);
8584
8659
  } else {
@@ -9145,6 +9220,10 @@ mcpRuntimeCommand
9145
9220
  "container name",
9146
9221
  DEFAULT_MCP_DOCKER_CONTAINER_NAME,
9147
9222
  )
9223
+ .option(
9224
+ "--skills-root <path>",
9225
+ "host skills directory to resolve/mount (default: auto-detect)",
9226
+ )
9148
9227
  .action(runMcpRuntimeStatus);
9149
9228
 
9150
9229
  mcpRuntimeCommand
@@ -9171,6 +9250,10 @@ mcpRuntimeCommand
9171
9250
  "build MCP Docker image from local package mcp/ directory instead of pulling",
9172
9251
  )
9173
9252
  .option("--port <port>", "host port to map to container :3100")
9253
+ .option(
9254
+ "--skills-root <path>",
9255
+ "host skills directory to mount into /workflows/skills (default: auto-detect)",
9256
+ )
9174
9257
  .option("--replace", "remove existing container with same name before start")
9175
9258
  .action(runMcpRuntimeUp);
9176
9259