@biznetgio/neo-app 0.4.23 → 0.4.24

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/package.json +1 -1
  2. package/src/mcp/tools.js +29 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biznetgio/neo-app",
3
- "version": "0.4.23",
3
+ "version": "0.4.24",
4
4
  "description": "NEO App CLI — one-command agent onboarding, MCP server, and project ops for coding agents (Codex, Claude Code).",
5
5
  "type": "module",
6
6
  "bin": {
package/src/mcp/tools.js CHANGED
@@ -232,6 +232,26 @@ export const TOOLS = [
232
232
  return out;
233
233
  },
234
234
  },
235
+ {
236
+ name: 'neo_set_service_variable',
237
+ description:
238
+ 'Set ONE PER-SERVICE environment variable on a specific service (merged server-side — other vars are preserved, unlike project-wide neo_set_variable). Pass secret:true to store it as a cluster Secret. Redeploy the service (neo_deploy) for it to take effect. The value is never echoed back.',
239
+ mutating: true,
240
+ schema: {
241
+ type: 'object',
242
+ properties: {
243
+ appId: str('Service/app id (from neo_list_services)'),
244
+ key: str('Variable name'),
245
+ value: str('Variable value'),
246
+ secret: { type: 'boolean', description: 'Store as a secret (default false)' },
247
+ },
248
+ required: ['appId', 'key', 'value'],
249
+ },
250
+ async call(api, args) {
251
+ const { status, data } = await api.post(`/api/v1/apps/${args.appId}/variables`, { key: args.key, value: args.value, secret: !!args.secret });
252
+ return result(status, data); // {status:"set", key, redeployRequired} — no value returned
253
+ },
254
+ },
235
255
  {
236
256
  name: 'neo_scale_service',
237
257
  description: 'Scale a service to N replicas. May return pending_approval under org policy.',
@@ -328,17 +348,20 @@ export const TOOLS = [
328
348
  suggestedServiceType: s.type === 'static' ? 'static_site' : 'web',
329
349
  suggestedBuildType: s.type === 'docker' ? 'dockerfile' : 'railpack',
330
350
  contextDir: s.path || undefined,
351
+ detectedDependencies: s.deps || [], // database | queue | object_storage, inferred from the manifest
331
352
  }));
353
+ const anyDeps = components.some((c) => c.detectedDependencies.length);
332
354
  return {
333
355
  repoUrl: args.repoUrl,
334
356
  count: components.length,
335
357
  components,
336
358
  note:
337
- components.length > 1
359
+ (components.length > 1
338
360
  ? 'Monorepo: multiple deployable components. Ask the user which to deploy and create each selected one with its `contextDir` — do NOT collapse them into one service (handoff 6). Worker vs web cannot be inferred from the tree alone; confirm the type with the user.'
339
361
  : components.length === 1
340
362
  ? 'One deployable component found.'
341
- : 'No deployable component found (no Dockerfile/package.json/go.mod/requirements.txt/index.html/… at any root).',
363
+ : 'No deployable component found (no Dockerfile/package.json/go.mod/requirements.txt/index.html/… at any root).')
364
+ + (anyDeps ? ' A component lists detectedDependencies (database/queue/object_storage) from its manifest — consider planning those resources and binding them (neo_bind_resource); confirm with the user first.' : ''),
342
365
  };
343
366
  },
344
367
  },
@@ -676,15 +699,15 @@ export const TOOLS = [
676
699
  {
677
700
  name: 'neo_bind_resource',
678
701
  description:
679
- 'Bind a managed database or queue to a consumer service so its connection is injected as an environment variable at the consumer\'s next deploy — WITHOUT ever exposing the secret to you (handoff 5, write-only). envKey defaults to DATABASE_URL (neo_db) or NATS_URL (neo_queue). After binding, redeploy the consumer (neo_deploy) for it to take effect. The target and consumer must be in the same project.',
702
+ 'Bind a managed database, queue, or object-storage bucket to a consumer service so its connection is injected as environment variable(s) at the consumer\'s next deploy — WITHOUT ever exposing the secret to you (handoff 5, write-only). envKey defaults: DATABASE_URL (neo_db), NATS_URL (neo_queue); for neo_object_storage it is a PREFIX (default S3) injecting <P>_ENDPOINT/_BUCKET/_REGION + secret <P>_ACCESS_KEY/_SECRET_KEY. After binding, redeploy the consumer. Target and consumer must be in the same project.',
680
703
  mutating: true,
681
704
  schema: {
682
705
  type: 'object',
683
706
  properties: {
684
707
  appId: str('Consumer service/app id that will receive the env var (from neo_list_services)'),
685
- targetType: { type: 'string', enum: ['neo_db', 'neo_queue'], description: 'neo_db | neo_queue — the resource to attach' },
686
- targetId: str('The database or queue id to bind'),
687
- envKey: str('Env var name to inject (optional; default DATABASE_URL for neo_db, NATS_URL for neo_queue)'),
708
+ targetType: { type: 'string', enum: ['neo_db', 'neo_queue', 'neo_object_storage'], description: 'neo_db | neo_queue | neo_object_storage — the resource to attach' },
709
+ targetId: str('The database, queue, or bucket id to bind'),
710
+ envKey: str('Env var name / prefix (optional; default DATABASE_URL, NATS_URL, or S3 prefix)'),
688
711
  },
689
712
  required: ['appId', 'targetType', 'targetId'],
690
713
  },