@biznetgio/neo-app 0.4.16 → 0.4.17
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/package.json +1 -1
- package/src/mcp/tools.js +35 -10
package/package.json
CHANGED
package/src/mcp/tools.js
CHANGED
|
@@ -28,6 +28,17 @@ function result(status, data) {
|
|
|
28
28
|
// (password, connection string, access/secret key, token) back to the agent.
|
|
29
29
|
// Recursively replace any secret-looking value with a reference marker so the
|
|
30
30
|
// agent still sees the resource's shape and non-secret identifiers.
|
|
31
|
+
// §2 safety: a create/deploy mutation must name its environment explicitly —
|
|
32
|
+
// NEVER default to production. A silent prod mutation is the exact risk the
|
|
33
|
+
// handoff calls out ("Never default a missing environment to production").
|
|
34
|
+
function requireEnv(env) {
|
|
35
|
+
const e = String(env || '').toLowerCase();
|
|
36
|
+
if (e !== 'staging' && e !== 'production') {
|
|
37
|
+
throw new Error('environment is required and must be "staging" or "production" — it is never defaulted (handoff §2: never silently mutate production). Test on staging first.');
|
|
38
|
+
}
|
|
39
|
+
return e;
|
|
40
|
+
}
|
|
41
|
+
|
|
31
42
|
const SECRET_KEY = /(password|secret|secretkey|accesskey|connectionstring|connstr|dsn|token|privatekey|apikey)/i;
|
|
32
43
|
function redactSecrets(value) {
|
|
33
44
|
if (Array.isArray(value)) return value.map(redactSecrets);
|
|
@@ -85,7 +96,7 @@ export const TOOLS = [
|
|
|
85
96
|
{ type: 'worker', create: 'via_folder', deploy: true, scale: true, logs: true, variables: true, delete: true, note: 'neo_deploy_folder serviceType=worker — no public ingress; repo auto-detection still TODO (handoff 6)' },
|
|
86
97
|
{ type: 'database', create: true, get: true, list: true, delete: true, note: 'neo_create/list/get/delete_database (0.4.15); update/plan still TODO (handoff 4.4)' },
|
|
87
98
|
{ type: 'queue', create: true, get: true, list: true, delete: true, note: 'neo_create/list/get/delete_queue (0.4.15); update/plan still TODO (handoff 4.5)' },
|
|
88
|
-
{ type: 'cron', create: true, get: true, list: true, delete: true, note: 'neo_create/list/get/delete_cron (0.4.15);
|
|
99
|
+
{ type: 'cron', create: true, get: true, list: true, run: true, delete: true, note: 'neo_create/list/get/run/delete_cron (0.4.15-0.4.17); run-history still TODO (handoff 4.6)' },
|
|
89
100
|
{ type: 'object_storage', create: true, get: true, list: true, delete: true, note: 'neo_create/list/get/delete_bucket (0.4.15); object put/get still TODO (handoff 4.7)' },
|
|
90
101
|
];
|
|
91
102
|
|
|
@@ -329,12 +340,13 @@ export const TOOLS = [
|
|
|
329
340
|
name: str('Service name (optional)'),
|
|
330
341
|
serviceType: { type: 'string', enum: ['web', 'worker', 'static_site'], description: 'web (default) | worker (no public URL) | static_site. Auto-detects static_site for a static-only folder; else web.' },
|
|
331
342
|
port: int('Container port (optional; ignored for worker)'),
|
|
332
|
-
environment:
|
|
343
|
+
environment: { type: 'string', enum: ['staging', 'production'], description: 'REQUIRED — staging or production. Never defaulted (handoff §2). Deploy to staging first.' },
|
|
333
344
|
dryRun: { type: 'boolean', description: 'Preview the plan without creating/uploading/deploying anything (JNG #93)' },
|
|
334
345
|
},
|
|
335
|
-
required: ['projectId', 'path'],
|
|
346
|
+
required: ['projectId', 'path', 'environment'],
|
|
336
347
|
},
|
|
337
348
|
async call(api, args) {
|
|
349
|
+
const environment = requireEnv(args.environment);
|
|
338
350
|
const p = resolve(args.path);
|
|
339
351
|
let src;
|
|
340
352
|
try {
|
|
@@ -351,7 +363,7 @@ export const TOOLS = [
|
|
|
351
363
|
name: args.name,
|
|
352
364
|
serviceType: args.serviceType,
|
|
353
365
|
port: args.port,
|
|
354
|
-
environment
|
|
366
|
+
environment,
|
|
355
367
|
dryRun: !!args.dryRun,
|
|
356
368
|
});
|
|
357
369
|
if (r.dryRun) return { status: 'dry_run', plan: r.plan, service: r.service, environment: r.environment, estimatedCost: r.estimatedCost };
|
|
@@ -390,14 +402,15 @@ export const TOOLS = [
|
|
|
390
402
|
name: str('Database name'),
|
|
391
403
|
engine: { type: 'string', description: 'postgres | mysql (engine)' },
|
|
392
404
|
version: str('Engine version, e.g. "16" (optional)'),
|
|
393
|
-
environment:
|
|
405
|
+
environment: { type: 'string', enum: ['staging', 'production'], description: 'REQUIRED — staging or production (never defaulted, handoff §2)' },
|
|
394
406
|
volumeSize: str('Storage size, e.g. "10Gi" (optional)'),
|
|
395
407
|
replicas: int('Read/failover replicas for HA (optional; postgres/CNPG only)'),
|
|
396
408
|
deploymentMode: { type: 'string', description: 'single | ha (optional)' },
|
|
397
409
|
},
|
|
398
|
-
required: ['projectId', 'name', 'engine'],
|
|
410
|
+
required: ['projectId', 'name', 'engine', 'environment'],
|
|
399
411
|
},
|
|
400
412
|
async call(api, args) {
|
|
413
|
+
requireEnv(args.environment);
|
|
401
414
|
const { projectId, ...body } = args;
|
|
402
415
|
const { status, data } = await api.post(`/api/v1/projects/${projectId}/databases`, body);
|
|
403
416
|
return redactSecrets(result(status, data));
|
|
@@ -431,13 +444,14 @@ export const TOOLS = [
|
|
|
431
444
|
projectId: str('Project id'),
|
|
432
445
|
name: str('Queue name'),
|
|
433
446
|
planClass: str('Plan/engine class (optional)'),
|
|
434
|
-
environment:
|
|
447
|
+
environment: { type: 'string', enum: ['staging', 'production'], description: 'REQUIRED — staging or production (never defaulted, handoff §2)' },
|
|
435
448
|
volumeSize: str('Storage size, e.g. "10Gi" (optional)'),
|
|
436
449
|
dlqEnabled: { type: 'boolean', description: 'Enable a dead-letter queue (optional)' },
|
|
437
450
|
},
|
|
438
|
-
required: ['projectId', 'name'],
|
|
451
|
+
required: ['projectId', 'name', 'environment'],
|
|
439
452
|
},
|
|
440
453
|
async call(api, args) {
|
|
454
|
+
requireEnv(args.environment);
|
|
441
455
|
const { projectId, ...body } = args;
|
|
442
456
|
const { status, data } = await api.post(`/api/v1/projects/${projectId}/queues`, body);
|
|
443
457
|
return redactSecrets(result(status, data));
|
|
@@ -480,11 +494,12 @@ export const TOOLS = [
|
|
|
480
494
|
command: { type: 'array', items: { type: 'string' }, description: 'Command argv (mode=app_command)' },
|
|
481
495
|
url: str('Target URL (mode=http_endpoint)'),
|
|
482
496
|
method: str('HTTP method (mode=http_endpoint), e.g. GET/POST'),
|
|
483
|
-
environment:
|
|
497
|
+
environment: { type: 'string', enum: ['staging', 'production'], description: 'REQUIRED — staging or production (never defaulted, handoff §2)' },
|
|
484
498
|
},
|
|
485
|
-
required: ['projectId', 'name', 'mode', 'scheduleType'],
|
|
499
|
+
required: ['projectId', 'name', 'mode', 'scheduleType', 'environment'],
|
|
486
500
|
},
|
|
487
501
|
async call(api, args) {
|
|
502
|
+
requireEnv(args.environment);
|
|
488
503
|
const { projectId, ...body } = args;
|
|
489
504
|
const { status, data } = await api.post(`/api/v1/projects/${projectId}/crons`, body);
|
|
490
505
|
return redactSecrets(result(status, data));
|
|
@@ -508,6 +523,16 @@ export const TOOLS = [
|
|
|
508
523
|
return redactSecrets((await api.get(`/api/v1/crons/${args.cronId}`)).data);
|
|
509
524
|
},
|
|
510
525
|
},
|
|
526
|
+
{
|
|
527
|
+
name: 'neo_run_cron',
|
|
528
|
+
description: 'Trigger a scheduled job (cron) to run now, out of schedule (handoff 4.6). Returns the run result. Not applicable to a continuous "seconds" cron.',
|
|
529
|
+
mutating: true,
|
|
530
|
+
schema: { type: 'object', properties: { cronId: str('Cron/scheduled-job id') }, required: ['cronId'] },
|
|
531
|
+
async call(api, args) {
|
|
532
|
+
const { status, data } = await api.post(`/api/v1/crons/${args.cronId}/run`);
|
|
533
|
+
return redactSecrets(result(status, data));
|
|
534
|
+
},
|
|
535
|
+
},
|
|
511
536
|
{
|
|
512
537
|
name: 'neo_create_bucket',
|
|
513
538
|
description: 'Create an S3-compatible object-storage bucket in a project (handoff 4.7). Access keys are provisioned server-side and are NOT returned (write-only). May return pending_approval.',
|