@zibby/mcp-cli 0.3.5 → 0.3.7

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 (2) hide show
  1. package/index.js +66 -1
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -484,8 +484,18 @@ server.tool(
484
484
  architecture: z.enum(['x86_64', 'arm64']).optional().describe('CPU architecture for the Fargate task. "arm64" runs on AWS Graviton — ~20% cheaper compute (same price to user). "x86_64" is the historical default + widest catalog compatibility. Omit to accept the catalog tile\'s preferred arch (first entry in its `architectures` array — usually arm64 for tiles that support it).'),
485
485
  model: z.string().min(1).optional().describe('Claude model identifier (e.g. claude-sonnet-4-6). Overrides the agent-ops bootstrap default. Use a stronger model (Opus) for complex installs; cheaper (Haiku) for trivial.'),
486
486
  anthropicToken: z.string().regex(/^sk-ant-(oat01|api03)-/, 'must be sk-ant-oat01-* or sk-ant-api03-*').optional().describe('Per-deploy Claude credential override. Defaults to the workspace-stored token. SENSITIVE — never log or persist.'),
487
+ maxTurns: z.number().int().min(1).max(200).optional().describe('Claude subprocess max turns. Default 25. Bump for heavy installs (n8n, OpenHands) that need background tool calls + retries.'),
488
+ timeoutMin: z.number().int().min(1).max(120).optional().describe('Bootstrap task wall-clock minutes. Default 30. Bump when npm install / docker pull / native compile dominates wall time.'),
489
+ // Optional Caddy auth sidecar — wraps the public URL with basic-auth
490
+ // or bearer-token validation. Apps like Grafana ship admin/admin and
491
+ // raw n8n/openhands ship with nothing, so gating the public URL is a
492
+ // common ask. Catalog never declares this — it's per-instance.
493
+ authType: z.enum(['basic', 'token', 'none']).optional().describe('Optional reverse-proxy auth in front of the public URL. "basic" = username + password (browser challenge), "token" = Authorization: Bearer header (machine-friendly), "none" = no gate (default, current behavior). Caddy sidecar adds ~30MB image / ~10MB RAM — no tier bump.'),
494
+ authUser: z.string().min(1).max(64).optional().describe('Username for authType=basic. Required when enabling basic. Printable ASCII, no spaces.'),
495
+ authPassword: z.string().min(8).max(256).optional().describe('Password for authType=basic. SENSITIVE — bcrypt-hashed server-side, plaintext never persisted. Required when enabling basic.'),
496
+ authToken: z.string().min(16).max(128).regex(/^[A-Za-z0-9_-]+$/, 'base64url alphabet only').optional().describe('Optional bearer token for authType=token. Omit to let the backend auto-generate a 32-byte token (returned ONCE in the deploy response — surface it to the user with a save-it warning). SENSITIVE.'),
487
497
  },
488
- async ({ appType, goal, projectId, name, provider, architecture, model, anthropicToken }) => {
498
+ async ({ appType, goal, projectId, name, provider, architecture, model, anthropicToken, maxTurns, timeoutMin, authType, authUser, authPassword, authToken }) => {
489
499
  // Enforce mutual exclusivity client-side so the agent gets a clear
490
500
  // error before we burn an HTTP round-trip. Backend enforces the
491
501
  // same invariant (apps.js::deployApp) but this gives a faster
@@ -510,12 +520,24 @@ server.tool(
510
520
  if (provider) args.push('--provider', provider);
511
521
  if (architecture) args.push('--arch', architecture);
512
522
  if (model) args.push('--model', model);
523
+ // --max-turns / --timeout-min are integer caps on the per-instance
524
+ // bootstrap. Both forwarded as argv — neither is sensitive. CLI
525
+ // re-validates the ranges (1..200, 1..120) so a malformed value 400s
526
+ // locally before hitting the backend.
527
+ if (maxTurns !== undefined) args.push('--max-turns', String(maxTurns));
528
+ if (timeoutMin !== undefined) args.push('--timeout-min', String(timeoutMin));
529
+ if (authType) args.push('--auth-type', authType);
530
+ if (authUser) args.push('--auth-user', authUser);
513
531
  // anthropicToken is SENSITIVE. Forwarded to the @zibby/cli subprocess
514
532
  // via ZIBBY_ANTHROPIC_TOKEN env (NOT argv) so the token never lands
515
533
  // in /proc/<pid>/cmdline or argv-scraping ps tools. The CLI sees the
516
534
  // env, applies the same regex check, and passes it as a body field.
535
+ // Same treatment for authPassword / authToken — both pulled by the
536
+ // CLI from env so the password / bearer never appears in argv.
517
537
  const extraEnv = { ZIBBY_API_KEY: apiKey };
518
538
  if (anthropicToken) extraEnv.ZIBBY_ANTHROPIC_TOKEN = anthropicToken;
539
+ if (authPassword) extraEnv.ZIBBY_APP_AUTH_PASSWORD = authPassword;
540
+ if (authToken) extraEnv.ZIBBY_APP_AUTH_TOKEN = authToken;
519
541
  return cliResult(await runCli(args, { extraEnv }));
520
542
  }
521
543
  );
@@ -676,6 +698,49 @@ server.tool(
676
698
  }
677
699
  );
678
700
 
701
+ // ── Tool: enable / rotate / disable the Caddy auth sidecar on a running
702
+ // instance. Per-instance opt-in reverse-proxy that gates the public URL
703
+ // with basic-auth (username + bcrypt'd password) or bearer-token
704
+ // validation. Use cases:
705
+ // - User says "lock down my Grafana with admin / hunter2"
706
+ // → authType:'basic', authUser:'admin', authPassword:'hunter2-strong'
707
+ // - User says "give me a token for my n8n public URL"
708
+ // → authType:'token' (backend auto-generates; agent prints once + warns)
709
+ // - User says "rotate the password to <new>" on an existing basic-auth
710
+ // → authPassword:'<new>' (omit authType; PATCH preserves it)
711
+ // - User says "remove auth from my app"
712
+ // → authType:'none'
713
+ server.tool(
714
+ 'zibby_set_app_auth',
715
+ 'Enable, rotate, or disable the optional Caddy reverse-proxy auth sidecar on a running app instance. The sidecar fronts the public URL with basic-auth or bearer-token validation, useful for apps that ship with weak / no built-in auth (Grafana=admin/admin, raw n8n / openhands = none). PATCH semantics: omitted fields preserve current state, so e.g. passing just authPassword on a basic-auth instance rotates the password without re-specifying the user. For token mode WITHOUT an explicit authToken, the backend generates a fresh 32-byte token and returns it ONCE in the response — surface it to the user with a save-this-now warning since it can never be retrieved again. Triggers a rolling ECS task replace (~30s); EFS data preserved.',
716
+ {
717
+ instanceId: z.string().min(1).describe('Instance ID to update auth on'),
718
+ projectId: z.string().min(1).optional().describe('Project the instance belongs to (picks the right cached API token)'),
719
+ authType: z.enum(['basic', 'token', 'none']).optional().describe('"basic" | "token" | "none". Omit to preserve current type (e.g. rotate just the password). "none" disables the sidecar — public URL exposes the app port directly again.'),
720
+ authUser: z.string().min(1).max(64).optional().describe('Username for basic auth. Required when SWITCHING TO basic; preserved on subsequent rotations.'),
721
+ authPassword: z.string().min(8).max(256).optional().describe('Password for basic auth. SENSITIVE — bcrypt-hashed server-side. Pass to rotate; omit to preserve current.'),
722
+ authToken: z.string().min(16).max(128).regex(/^[A-Za-z0-9_-]+$/, 'base64url alphabet only').optional().describe('Optional explicit bearer token for token auth. Omit on token-mode to let the backend regenerate (returned ONCE — print + warn user). SENSITIVE.'),
723
+ off: z.boolean().optional().describe('Operator-friendly alias for authType:"none". When true, disables the auth sidecar entirely.'),
724
+ },
725
+ async ({ instanceId, projectId, authType, authUser, authPassword, authToken, off }) => {
726
+ const extraEnv = {};
727
+ if (projectId) {
728
+ const apiKey = getProjectApiToken(projectId);
729
+ if (apiKey) extraEnv.ZIBBY_API_KEY = apiKey;
730
+ }
731
+ const args = ['app', 'set-auth', instanceId];
732
+ if (off) args.push('--off');
733
+ if (authType) args.push('--auth-type', authType);
734
+ if (authUser) args.push('--auth-user', authUser);
735
+ // Sensitive args via env (NOT argv) so password / token never lands in
736
+ // /proc/<pid>/cmdline or argv-scraping ps tools — same pattern as
737
+ // anthropicToken on zibby_deploy_app.
738
+ if (authPassword) extraEnv.ZIBBY_APP_AUTH_PASSWORD = authPassword;
739
+ if (authToken) extraEnv.ZIBBY_APP_AUTH_TOKEN = authToken;
740
+ return cliResult(await runCli(args, { extraEnv }));
741
+ }
742
+ );
743
+
679
744
  // ── Connect ─────────────────────────────────────────────────────────────
680
745
 
681
746
  await server.connect(new StdioServerTransport());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zibby/mcp-cli",
3
- "version": "0.3.5",
3
+ "version": "0.3.7",
4
4
  "description": "Zibby local-essential MCP Server — local workflow scaffold/validate/run + deploy/download (bundles local files). Pure-API tools live in the Zibby Remote MCP (api-prod.zibby.app/mcp).",
5
5
  "type": "module",
6
6
  "main": "index.js",