@sfdxy/anypoint-connect 0.15.0 → 0.16.3
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 +32 -14
- package/dist/analysis/LogAnalyzer.d.ts +9 -3
- package/dist/analysis/LogAnalyzer.d.ts.map +1 -1
- package/dist/analysis/LogAnalyzer.js +28 -17
- package/dist/analysis/LogAnalyzer.js.map +1 -1
- package/dist/analysis/error-context.d.ts +2 -0
- package/dist/analysis/error-context.d.ts.map +1 -1
- package/dist/analysis/error-context.js +2 -1
- package/dist/analysis/error-context.js.map +1 -1
- package/dist/analysis/filter.d.ts +54 -0
- package/dist/analysis/filter.d.ts.map +1 -0
- package/dist/analysis/filter.js +100 -0
- package/dist/analysis/filter.js.map +1 -0
- package/dist/analysis/parser.d.ts.map +1 -1
- package/dist/analysis/parser.js +31 -14
- package/dist/analysis/parser.js.map +1 -1
- package/dist/analysis/stats.d.ts +25 -0
- package/dist/analysis/stats.d.ts.map +1 -1
- package/dist/analysis/stats.js +34 -0
- package/dist/analysis/stats.js.map +1 -1
- package/dist/analysis/summary.d.ts +51 -0
- package/dist/analysis/summary.d.ts.map +1 -0
- package/dist/analysis/summary.js +47 -0
- package/dist/analysis/summary.js.map +1 -0
- package/dist/analysis/types.d.ts +14 -0
- package/dist/analysis/types.d.ts.map +1 -1
- package/dist/api/ApiManagerApi.d.ts +53 -0
- package/dist/api/ApiManagerApi.d.ts.map +1 -1
- package/dist/api/ApiManagerApi.js +53 -2
- package/dist/api/ApiManagerApi.js.map +1 -1
- package/dist/api/CloudHub2Api.d.ts +24 -4
- package/dist/api/CloudHub2Api.d.ts.map +1 -1
- package/dist/api/CloudHub2Api.js +10 -22
- package/dist/api/CloudHub2Api.js.map +1 -1
- package/dist/api/ExchangeApi.d.ts +15 -0
- package/dist/api/ExchangeApi.d.ts.map +1 -1
- package/dist/api/ExchangeApi.js +51 -0
- package/dist/api/ExchangeApi.js.map +1 -1
- package/dist/api/LogsApi.d.ts +72 -19
- package/dist/api/LogsApi.d.ts.map +1 -1
- package/dist/api/LogsApi.js +116 -99
- package/dist/api/LogsApi.js.map +1 -1
- package/dist/api/RuntimesApi.d.ts +56 -0
- package/dist/api/RuntimesApi.d.ts.map +1 -0
- package/dist/api/RuntimesApi.js +58 -0
- package/dist/api/RuntimesApi.js.map +1 -0
- package/dist/cli.js +5 -1
- package/dist/cli.js.map +1 -1
- package/dist/client/AnypointClient.d.ts +2 -0
- package/dist/client/AnypointClient.d.ts.map +1 -1
- package/dist/client/AnypointClient.js +3 -0
- package/dist/client/AnypointClient.js.map +1 -1
- package/dist/client/smoke-test.d.ts +111 -0
- package/dist/client/smoke-test.d.ts.map +1 -0
- package/dist/client/smoke-test.js +275 -0
- package/dist/client/smoke-test.js.map +1 -0
- package/dist/commands/api.d.ts +1 -1
- package/dist/commands/api.d.ts.map +1 -1
- package/dist/commands/api.js +147 -10
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/app-change-cli.d.ts +52 -0
- package/dist/commands/app-change-cli.d.ts.map +1 -0
- package/dist/commands/app-change-cli.js +149 -0
- package/dist/commands/app-change-cli.js.map +1 -0
- package/dist/commands/apps.d.ts +1 -1
- package/dist/commands/apps.d.ts.map +1 -1
- package/dist/commands/apps.js +198 -17
- package/dist/commands/apps.js.map +1 -1
- package/dist/commands/compare.d.ts +8 -0
- package/dist/commands/compare.d.ts.map +1 -0
- package/dist/commands/compare.js +104 -0
- package/dist/commands/compare.js.map +1 -0
- package/dist/commands/deploy.d.ts +4 -3
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +59 -33
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.d.ts.map +1 -1
- package/dist/commands/index.js +1 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/logs.d.ts +3 -2
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +158 -17
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/runtimes.d.ts +7 -0
- package/dist/commands/runtimes.d.ts.map +1 -0
- package/dist/commands/runtimes.js +66 -0
- package/dist/commands/runtimes.js.map +1 -0
- package/dist/config/profiles.d.ts +8 -0
- package/dist/config/profiles.d.ts.map +1 -1
- package/dist/config/profiles.js.map +1 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +2 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools/analysis.d.ts.map +1 -1
- package/dist/mcp/tools/analysis.js +74 -30
- package/dist/mcp/tools/analysis.js.map +1 -1
- package/dist/mcp/tools/anypoint-mq.d.ts.map +1 -1
- package/dist/mcp/tools/anypoint-mq.js +5 -2
- package/dist/mcp/tools/anypoint-mq.js.map +1 -1
- package/dist/mcp/tools/api-manager.d.ts +2 -1
- package/dist/mcp/tools/api-manager.d.ts.map +1 -1
- package/dist/mcp/tools/api-manager.js +127 -38
- package/dist/mcp/tools/api-manager.js.map +1 -1
- package/dist/mcp/tools/app-inputs.d.ts +92 -0
- package/dist/mcp/tools/app-inputs.d.ts.map +1 -0
- package/dist/mcp/tools/app-inputs.js +142 -0
- package/dist/mcp/tools/app-inputs.js.map +1 -0
- package/dist/mcp/tools/apps-deploy.d.ts +6 -1
- package/dist/mcp/tools/apps-deploy.d.ts.map +1 -1
- package/dist/mcp/tools/apps-deploy.js +279 -307
- package/dist/mcp/tools/apps-deploy.js.map +1 -1
- package/dist/mcp/tools/apps-lifecycle.d.ts +3 -0
- package/dist/mcp/tools/apps-lifecycle.d.ts.map +1 -1
- package/dist/mcp/tools/apps-lifecycle.js +105 -136
- package/dist/mcp/tools/apps-lifecycle.js.map +1 -1
- package/dist/mcp/tools/apps-read.d.ts +2 -1
- package/dist/mcp/tools/apps-read.d.ts.map +1 -1
- package/dist/mcp/tools/apps-read.js +177 -14
- package/dist/mcp/tools/apps-read.js.map +1 -1
- package/dist/mcp/tools/artifacts.d.ts +8 -0
- package/dist/mcp/tools/artifacts.d.ts.map +1 -0
- package/dist/mcp/tools/artifacts.js +81 -0
- package/dist/mcp/tools/artifacts.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +1 -0
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +1 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/logs.d.ts +50 -2
- package/dist/mcp/tools/logs.d.ts.map +1 -1
- package/dist/mcp/tools/logs.js +221 -38
- package/dist/mcp/tools/logs.js.map +1 -1
- package/dist/mcp/tools/shared.d.ts +27 -0
- package/dist/mcp/tools/shared.d.ts.map +1 -1
- package/dist/mcp/tools/shared.js +42 -0
- package/dist/mcp/tools/shared.js.map +1 -1
- package/dist/safety/deployment.d.ts +47 -2
- package/dist/safety/deployment.d.ts.map +1 -1
- package/dist/safety/deployment.js +148 -14
- package/dist/safety/deployment.js.map +1 -1
- package/dist/safety/paths.d.ts +29 -0
- package/dist/safety/paths.d.ts.map +1 -0
- package/dist/safety/paths.js +76 -0
- package/dist/safety/paths.js.map +1 -0
- package/dist/safety/runtime.d.ts +24 -0
- package/dist/safety/runtime.d.ts.map +1 -0
- package/dist/safety/runtime.js +59 -0
- package/dist/safety/runtime.js.map +1 -0
- package/dist/safety/secret-sources.d.ts +51 -0
- package/dist/safety/secret-sources.d.ts.map +1 -0
- package/dist/safety/secret-sources.js +124 -0
- package/dist/safety/secret-sources.js.map +1 -0
- package/dist/safety/secrets.d.ts +32 -0
- package/dist/safety/secrets.d.ts.map +1 -0
- package/dist/safety/secrets.js +91 -0
- package/dist/safety/secrets.js.map +1 -0
- package/dist/utils/errors.d.ts +2 -1
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +5 -3
- package/dist/utils/errors.js.map +1 -1
- package/dist/workflows/app-change.d.ts +124 -0
- package/dist/workflows/app-change.d.ts.map +1 -0
- package/dist/workflows/app-change.js +305 -0
- package/dist/workflows/app-change.js.map +1 -0
- package/dist/workflows/app-state.d.ts +60 -0
- package/dist/workflows/app-state.d.ts.map +1 -0
- package/dist/workflows/app-state.js +95 -0
- package/dist/workflows/app-state.js.map +1 -0
- package/dist/workflows/artifact-compare.d.ts +134 -0
- package/dist/workflows/artifact-compare.d.ts.map +1 -0
- package/dist/workflows/artifact-compare.js +419 -0
- package/dist/workflows/artifact-compare.js.map +1 -0
- package/dist/workflows/asset-naming.d.ts +72 -0
- package/dist/workflows/asset-naming.d.ts.map +1 -0
- package/dist/workflows/asset-naming.js +116 -0
- package/dist/workflows/asset-naming.js.map +1 -0
- package/dist/workflows/jar-deployment.d.ts +76 -39
- package/dist/workflows/jar-deployment.d.ts.map +1 -1
- package/dist/workflows/jar-deployment.js +125 -64
- package/dist/workflows/jar-deployment.js.map +1 -1
- package/package.json +3 -3
|
@@ -1,385 +1,357 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Tool Registrar — Application deployment tools (production-guarded)
|
|
3
|
-
* deploy_jar, deploy_app, update_app_artifact, rollback_app
|
|
3
|
+
* deploy_jar, deploy_app, update_app, update_app_artifact, rollback_app
|
|
4
|
+
*
|
|
5
|
+
* Every tool previews by default and applies on confirm: true; production also needs
|
|
6
|
+
* confirmProduction: true. Changes to an existing app go through one workflow
|
|
7
|
+
* (src/workflows/app-change.ts): one PATCH, a runtime check against the target, and
|
|
8
|
+
* an optional stop, change, start sequence.
|
|
4
9
|
*/
|
|
5
10
|
import { z } from 'zod';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
11
|
+
import { guardWrite, mcpText, resolveEnvironment, writeInputs } from './shared.js';
|
|
12
|
+
import { modeInput, runAppChangeTool, runtimeFromArgs, runtimeInputs, settingsFromArgs, settingsInputs, updateStrategyInput, waitInputs, } from './app-inputs.js';
|
|
13
|
+
import { buildCreatePayload, resolveRollbackTarget } from '../../safety/deployment.js';
|
|
14
|
+
import { redactText } from '../../safety/secrets.js';
|
|
8
15
|
import { errorMessage } from '../../utils/errors.js';
|
|
16
|
+
import { resolveSettingsInput } from '../../workflows/app-change.js';
|
|
17
|
+
import { waitForAppPhase } from '../../workflows/app-state.js';
|
|
9
18
|
import { describeJarDeployment, executeJarDeployment, planJarDeployment } from '../../workflows/jar-deployment.js';
|
|
19
|
+
const createOnlyInputs = {
|
|
20
|
+
replicas: z.number().min(1).max(8).optional().describe('[new app only] Number of replicas (default: 1)'),
|
|
21
|
+
region: z.string().optional().describe('[new app only] CloudHub 2.0 target region (default: "cloudhub-us-east-2")'),
|
|
22
|
+
vcores: z
|
|
23
|
+
.string()
|
|
24
|
+
.optional()
|
|
25
|
+
.describe('[new app only] vCore size (default: "0.1"). Options: 0.1, 0.2, 0.5, 1, 1.5, 2, 2.5, 3, 4'),
|
|
26
|
+
jvmArgs: z.string().optional().describe('[new app only] JVM arguments'),
|
|
27
|
+
};
|
|
28
|
+
const refInputs = {
|
|
29
|
+
artifactId: z.string().optional().describe('Maven artifact ID. Default: keep the current one'),
|
|
30
|
+
groupId: z.string().optional().describe('Maven group ID. Default: keep the current one'),
|
|
31
|
+
packaging: z.string().optional().describe('Artifact packaging. Default: keep the current one (usually "jar")'),
|
|
32
|
+
};
|
|
33
|
+
function errorText(error, secretValues) {
|
|
34
|
+
return {
|
|
35
|
+
content: [{ type: 'text', text: `Error: ${redactText(errorMessage(error), secretValues)}` }],
|
|
36
|
+
isError: true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
10
39
|
export function registerAppDeployTools(server, client) {
|
|
11
40
|
server.registerTool('deploy_jar', {
|
|
12
41
|
title: 'Deploy JAR (Publish + Deploy)',
|
|
13
|
-
description: '
|
|
42
|
+
description: 'Publishes a locally built Mule application JAR to Exchange and deploys it to CloudHub 2.0: creates the app if it does not exist, otherwise updates it in one change (artifact plus any runtime or settings change). ' +
|
|
43
|
+
'Asset coordinates come from explicit inputs, then the project naming convention, then the pattern of the asset the app runs today, then the JAR. ' +
|
|
44
|
+
'Region, vCores, replicas and JVM arguments apply only to a new app. Previews by default; pass confirm: true to publish and deploy.',
|
|
14
45
|
inputSchema: {
|
|
15
46
|
jarPath: z
|
|
16
47
|
.string()
|
|
17
|
-
.describe('Path to the built .jar file (e.g. "target/
|
|
48
|
+
.describe('Path to the built .jar file (e.g. "target/orders-sapi-1.0.0-mule-application.jar")'),
|
|
18
49
|
appName: z.string().describe('CloudHub 2.0 application name'),
|
|
19
|
-
environment: z.string().describe('Environment name (e.g. "Sandbox"
|
|
50
|
+
environment: z.string().describe('Environment name (e.g. "Sandbox") or ID'),
|
|
20
51
|
assetId: z
|
|
21
52
|
.string()
|
|
22
53
|
.optional()
|
|
23
|
-
.describe('Exchange asset ID
|
|
24
|
-
assetVersion: z
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.number()
|
|
33
|
-
.min(1)
|
|
34
|
-
.max(8)
|
|
35
|
-
.optional()
|
|
36
|
-
.describe('[new app only] Number of replicas (default: 1).'),
|
|
37
|
-
region: z
|
|
38
|
-
.string()
|
|
39
|
-
.optional()
|
|
40
|
-
.describe('[new app only] CloudHub 2.0 target region (default: "cloudhub-us-east-2").'),
|
|
41
|
-
vcores: z.string().optional().describe('[new app only] vCore size (default: "0.1").'),
|
|
42
|
-
properties: z.record(z.string()).optional().describe('[new app only] Application properties.'),
|
|
43
|
-
secureProperties: z
|
|
44
|
-
.record(z.string())
|
|
45
|
-
.optional()
|
|
46
|
-
.describe('[new app only] Secure application properties.'),
|
|
47
|
-
jvmArgs: z.string().optional().describe('[new app only] JVM arguments.'),
|
|
48
|
-
wait: z
|
|
49
|
-
.boolean()
|
|
50
|
-
.optional()
|
|
51
|
-
.describe('Wait for the deployment to reach a running state (default: false).'),
|
|
54
|
+
.describe('Exchange asset ID, also the deployment artifactId. Default: naming convention'),
|
|
55
|
+
assetVersion: z.string().optional().describe('Exchange asset version. Default: naming convention'),
|
|
56
|
+
groupId: z.string().optional().describe('Exchange/Maven group ID (default: the organization ID)'),
|
|
57
|
+
...runtimeInputs,
|
|
58
|
+
...createOnlyInputs,
|
|
59
|
+
...settingsInputs,
|
|
60
|
+
mode: modeInput,
|
|
61
|
+
updateStrategy: updateStrategyInput,
|
|
62
|
+
...waitInputs,
|
|
52
63
|
expectedSha256: z
|
|
53
64
|
.string()
|
|
54
65
|
.regex(/^[a-fA-F0-9]{64}$/)
|
|
55
66
|
.optional()
|
|
56
|
-
.describe('SHA-256
|
|
57
|
-
|
|
58
|
-
.boolean()
|
|
59
|
-
.optional()
|
|
60
|
-
.describe('Set true to publish and deploy. When omitted/false, returns a dry-run preview only.'),
|
|
67
|
+
.describe('SHA-256 from the preview; rejects changed artifact bytes'),
|
|
68
|
+
...writeInputs,
|
|
61
69
|
},
|
|
62
70
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
63
|
-
}, async (
|
|
71
|
+
}, async (args) => {
|
|
72
|
+
let secretValues = [];
|
|
64
73
|
try {
|
|
65
|
-
const { orgId, env } = await resolveEnvironment(client, environment);
|
|
74
|
+
const { orgId, env } = await resolveEnvironment(client, args.environment);
|
|
66
75
|
const plan = await planJarDeployment(client, {
|
|
67
|
-
jarPath,
|
|
68
|
-
appName,
|
|
76
|
+
jarPath: args.jarPath,
|
|
77
|
+
appName: args.appName,
|
|
69
78
|
orgId,
|
|
70
79
|
env,
|
|
71
|
-
assetId,
|
|
72
|
-
assetVersion,
|
|
73
|
-
groupId,
|
|
74
|
-
expectedSha256,
|
|
75
|
-
runtime,
|
|
76
|
-
replicas,
|
|
77
|
-
region,
|
|
78
|
-
vcores,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
assetId: args.assetId,
|
|
81
|
+
assetVersion: args.assetVersion,
|
|
82
|
+
groupId: args.groupId,
|
|
83
|
+
expectedSha256: args.expectedSha256,
|
|
84
|
+
runtime: runtimeFromArgs(args),
|
|
85
|
+
replicas: args.replicas,
|
|
86
|
+
region: args.region,
|
|
87
|
+
vcores: args.vcores,
|
|
88
|
+
jvmArgs: args.jvmArgs,
|
|
89
|
+
settings: settingsFromArgs(args),
|
|
90
|
+
mode: args.mode,
|
|
91
|
+
updateStrategy: args.updateStrategy,
|
|
82
92
|
});
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
secretValues = plan.secretValues;
|
|
94
|
+
const preview = describeJarDeployment(plan);
|
|
95
|
+
if (plan.rejectedSettings.length > 0 || plan.change?.blockers.length) {
|
|
96
|
+
return {
|
|
97
|
+
...mcpText({
|
|
98
|
+
refused: true,
|
|
99
|
+
message: plan.rejectedSettings.length > 0
|
|
100
|
+
? `"${args.appName}" already exists in ${env.name}; region, vCores, replicas and JVM arguments apply only to a new app. Remove: ${plan.rejectedSettings.join(', ')}`
|
|
101
|
+
: 'The change cannot be applied.',
|
|
102
|
+
...preview,
|
|
103
|
+
}),
|
|
104
|
+
isError: true,
|
|
105
|
+
};
|
|
87
106
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
waitResult = `did not settle: ${errorMessage(waitErr)}`;
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return mcpText({
|
|
103
|
-
message: `✅ Deployed "${appName}" to ${env.name} (${plan.existing ? 'updated' : 'created'})`,
|
|
104
|
-
published,
|
|
105
|
-
deploymentId: deployment.id,
|
|
106
|
-
status: deployment.status,
|
|
107
|
-
...(plan.existing ? { previousVersion: plan.existing.application?.ref?.version } : {}),
|
|
108
|
-
...(wait ? { waitResult } : { tip: 'Use get_app_status to monitor progress.' }),
|
|
107
|
+
const gate = guardWrite({
|
|
108
|
+
env,
|
|
109
|
+
confirm: args.confirm,
|
|
110
|
+
confirmProduction: args.confirmProduction,
|
|
111
|
+
preview,
|
|
112
|
+
});
|
|
113
|
+
if (gate)
|
|
114
|
+
return gate;
|
|
115
|
+
const result = await executeJarDeployment(client, plan, {
|
|
116
|
+
wait: args.wait,
|
|
117
|
+
timeoutMs: args.waitTimeoutSeconds ? args.waitTimeoutSeconds * 1000 : undefined,
|
|
109
118
|
});
|
|
119
|
+
const response = mcpText(JSON.parse(redactText(JSON.stringify({
|
|
120
|
+
message: `Deployed "${args.appName}" to ${env.name} (${plan.existing ? 'updated' : 'created'})`,
|
|
121
|
+
published: result.published,
|
|
122
|
+
deploymentId: result.deployment.id,
|
|
123
|
+
...(plan.existing ? { previousRef: plan.existing.application?.ref } : {}),
|
|
124
|
+
...(result.change ? { performed: result.change.performed } : {}),
|
|
125
|
+
...(result.snapshot
|
|
126
|
+
? {
|
|
127
|
+
phase: result.snapshot.phase,
|
|
128
|
+
settled: result.snapshot.settled,
|
|
129
|
+
...(result.snapshot.reason ? { reason: result.snapshot.reason } : {}),
|
|
130
|
+
...(result.timedOut ? { timedOut: true } : {}),
|
|
131
|
+
}
|
|
132
|
+
: {
|
|
133
|
+
tip: 'Pass wait: true, or call get_app_status with wait: true, to follow the rollout.',
|
|
134
|
+
}),
|
|
135
|
+
}), secretValues)));
|
|
136
|
+
return result.snapshot?.terminal && !result.snapshot.settled
|
|
137
|
+
? { ...response, isError: true }
|
|
138
|
+
: response;
|
|
110
139
|
}
|
|
111
140
|
catch (error) {
|
|
112
|
-
return
|
|
141
|
+
return errorText(error, secretValues);
|
|
113
142
|
}
|
|
114
143
|
});
|
|
115
144
|
server.registerTool('deploy_app', {
|
|
116
145
|
title: 'Deploy Application',
|
|
117
|
-
description: 'Deploys
|
|
146
|
+
description: 'Deploys an artifact already in Exchange (groupId:artifactId:version) to CloudHub 2.0. Creates the app if it does not exist; otherwise updates it in one change, including any runtime or settings change. ' +
|
|
147
|
+
'Region, vCores, replicas and JVM arguments apply only to a new app. Previews by default; pass confirm: true to apply.',
|
|
118
148
|
inputSchema: {
|
|
119
|
-
appName: z.string().describe('Application name (
|
|
120
|
-
environment: z.string().describe('Environment name (e.g. "Sandbox"
|
|
121
|
-
groupId: z.string().describe('Maven group ID of the
|
|
122
|
-
artifactId: z.string().describe('Maven artifact ID (e.g. "
|
|
123
|
-
version: z.string().describe('Artifact version (e.g. "1.2.0"
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
.optional()
|
|
132
|
-
.describe('CloudHub 2.0 target region (default: "cloudhub-us-east-2"). Examples: "cloudhub-us-east-1", "cloudhub-eu-west-1", "cloudhub-ap-southeast-1"'),
|
|
133
|
-
vcores: z
|
|
134
|
-
.string()
|
|
135
|
-
.optional()
|
|
136
|
-
.describe('vCore size (default: "0.1"). Options: "0.1", "0.2", "0.5", "1", "1.5", "2", "2.5", "3", "4"'),
|
|
137
|
-
properties: z
|
|
138
|
-
.record(z.string())
|
|
139
|
-
.optional()
|
|
140
|
-
.describe('Application properties as key-value pairs to set on deploy'),
|
|
141
|
-
secureProperties: z
|
|
142
|
-
.record(z.string())
|
|
143
|
-
.optional()
|
|
144
|
-
.describe('Secure (encrypted) application properties as key-value pairs'),
|
|
145
|
-
jvmArgs: z.string().optional().describe('JVM arguments (e.g. "-XX:MaxMetaspaceSize=256m")'),
|
|
146
|
-
confirm: z
|
|
147
|
-
.boolean()
|
|
148
|
-
.optional()
|
|
149
|
-
.describe('Set true to apply. When omitted/false, returns a dry-run preview and changes nothing.'),
|
|
149
|
+
appName: z.string().describe('Application name (also the public URL slug)'),
|
|
150
|
+
environment: z.string().describe('Environment name (e.g. "Sandbox") or ID'),
|
|
151
|
+
groupId: z.string().describe('Maven group ID of the artifact (usually the organization ID)'),
|
|
152
|
+
artifactId: z.string().describe('Maven artifact ID (e.g. "orders-sapi")'),
|
|
153
|
+
version: z.string().describe('Artifact version (e.g. "1.2.0")'),
|
|
154
|
+
...runtimeInputs,
|
|
155
|
+
...createOnlyInputs,
|
|
156
|
+
...settingsInputs,
|
|
157
|
+
mode: modeInput,
|
|
158
|
+
updateStrategy: updateStrategyInput,
|
|
159
|
+
...waitInputs,
|
|
160
|
+
...writeInputs,
|
|
150
161
|
},
|
|
151
162
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
152
|
-
}, async (
|
|
163
|
+
}, async (args) => {
|
|
164
|
+
let secretValues = [];
|
|
153
165
|
try {
|
|
154
|
-
const { orgId, env } = await resolveEnvironment(client, environment);
|
|
155
|
-
const existing = await client.cloudHub2.findDetailByName(orgId, env.id, appName);
|
|
156
|
-
// ── Update path: existing app → SAFE artifact-ref-only redeploy ──
|
|
157
|
-
// Infra params (runtime/region/vcores/replicas/jvmArgs) are intentionally NOT
|
|
158
|
-
// restated here; doing so previously clobbered the live deployment. They are
|
|
159
|
-
// ignored on redeploy and the caller is told so.
|
|
166
|
+
const { orgId, env } = await resolveEnvironment(client, args.environment);
|
|
167
|
+
const existing = await client.cloudHub2.findDetailByName(orgId, env.id, args.appName);
|
|
160
168
|
if (existing) {
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const merged = mergeForArtifactUpdate(existing, { groupId, artifactId, version });
|
|
171
|
-
const currentVersion = existing.application?.ref?.version || null;
|
|
172
|
-
if (!confirm) {
|
|
173
|
-
return dryRunPreview({
|
|
174
|
-
action: 'redeploy (artifact ref only)',
|
|
175
|
-
app: appName,
|
|
176
|
-
environment: env.name,
|
|
177
|
-
current: {
|
|
178
|
-
version: currentVersion,
|
|
179
|
-
runtime: existing.target?.deploymentSettings?.runtime?.version,
|
|
180
|
-
targetId: existing.target?.targetId,
|
|
181
|
-
replicas: existing.target?.replicas,
|
|
182
|
-
},
|
|
183
|
-
next: { ref: merged.application.ref },
|
|
184
|
-
preserved: 'runtime, target/space, replicas, resources, settings',
|
|
185
|
-
...(ignored.length
|
|
186
|
-
? {
|
|
187
|
-
note: `Ignored on redeploy (use update_app_settings / a fresh deploy to change infra): ${ignored.join(', ')}`,
|
|
188
|
-
}
|
|
189
|
-
: {}),
|
|
190
|
-
});
|
|
169
|
+
const rejected = ['region', 'vcores', 'replicas', 'jvmArgs'].filter((key) => args[key] !== undefined);
|
|
170
|
+
if (rejected.length) {
|
|
171
|
+
return {
|
|
172
|
+
...mcpText({
|
|
173
|
+
refused: true,
|
|
174
|
+
message: `"${args.appName}" already exists in ${env.name}; ${rejected.join(', ')} apply only to a new app.`,
|
|
175
|
+
}),
|
|
176
|
+
isError: true,
|
|
177
|
+
};
|
|
191
178
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
179
|
+
return runAppChangeTool(client, args, {
|
|
180
|
+
existing,
|
|
181
|
+
ref: { groupId: args.groupId, artifactId: args.artifactId, version: args.version },
|
|
182
|
+
runtime: runtimeFromArgs(args),
|
|
183
|
+
settings: settingsFromArgs(args),
|
|
184
|
+
mode: args.mode,
|
|
185
|
+
updateStrategy: args.updateStrategy,
|
|
186
|
+
}, { done: 'Updated' });
|
|
187
|
+
}
|
|
188
|
+
const resolved = resolveSettingsInput(settingsFromArgs(args));
|
|
189
|
+
secretValues = resolved.secretValues;
|
|
190
|
+
if (resolved.change?.removeProperties ||
|
|
191
|
+
resolved.change?.removeSecureProperties ||
|
|
192
|
+
resolved.change?.moveToSecure) {
|
|
193
|
+
throw new Error('removeProperties, removeSecureProperties and moveToSecure apply only to an existing app');
|
|
203
194
|
}
|
|
204
|
-
// ── Create path: new app → full payload from the shared builder ──
|
|
205
195
|
const payload = buildCreatePayload({
|
|
206
|
-
appName,
|
|
207
|
-
groupId,
|
|
208
|
-
artifactId,
|
|
209
|
-
version,
|
|
210
|
-
runtime,
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
196
|
+
appName: args.appName,
|
|
197
|
+
groupId: args.groupId,
|
|
198
|
+
artifactId: args.artifactId,
|
|
199
|
+
version: args.version,
|
|
200
|
+
runtime: args.runtime,
|
|
201
|
+
javaVersion: args.javaVersion,
|
|
202
|
+
releaseChannel: args.releaseChannel,
|
|
203
|
+
replicas: args.replicas,
|
|
204
|
+
region: args.region,
|
|
205
|
+
vcores: args.vcores,
|
|
206
|
+
properties: resolved.change?.properties,
|
|
207
|
+
secureProperties: resolved.change?.secureProperties,
|
|
208
|
+
jvmArgs: args.jvmArgs,
|
|
209
|
+
});
|
|
210
|
+
const preview = {
|
|
211
|
+
action: 'create new deployment',
|
|
212
|
+
app: args.appName,
|
|
213
|
+
environment: env.name,
|
|
214
|
+
next: {
|
|
215
|
+
ref: payload.application.ref,
|
|
216
|
+
runtime: payload.target.deploymentSettings.runtime,
|
|
217
|
+
region: payload.target.targetId,
|
|
218
|
+
vCores: payload.application.vCores,
|
|
219
|
+
replicas: payload.target.replicas,
|
|
220
|
+
properties: Object.keys(resolved.change?.properties ?? {}),
|
|
221
|
+
secureProperties: Object.keys(resolved.change?.secureProperties ?? {}),
|
|
222
|
+
},
|
|
223
|
+
};
|
|
224
|
+
const gate = guardWrite({
|
|
225
|
+
env,
|
|
226
|
+
confirm: args.confirm,
|
|
227
|
+
confirmProduction: args.confirmProduction,
|
|
228
|
+
preview,
|
|
217
229
|
});
|
|
218
|
-
if (
|
|
219
|
-
return
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
vCores: payload.application.vCores,
|
|
228
|
-
replicas: payload.target.replicas,
|
|
229
|
-
},
|
|
230
|
+
if (gate)
|
|
231
|
+
return gate;
|
|
232
|
+
const sentAt = Date.now();
|
|
233
|
+
const deployment = await client.cloudHub2.createDeployment(orgId, env.id, payload);
|
|
234
|
+
if (!args.wait) {
|
|
235
|
+
return mcpText({
|
|
236
|
+
message: `Created "${args.appName}" in ${env.name}`,
|
|
237
|
+
deploymentId: deployment.id,
|
|
238
|
+
...preview.next,
|
|
230
239
|
});
|
|
231
240
|
}
|
|
232
|
-
const
|
|
233
|
-
|
|
234
|
-
|
|
241
|
+
const result = await waitForAppPhase(client.cloudHub2, orgId, env.id, deployment.id, {
|
|
242
|
+
sinceChange: sentAt,
|
|
243
|
+
timeoutMs: args.waitTimeoutSeconds ? args.waitTimeoutSeconds * 1000 : undefined,
|
|
244
|
+
});
|
|
245
|
+
const response = mcpText({
|
|
246
|
+
message: `Created "${args.appName}" in ${env.name}`,
|
|
235
247
|
deploymentId: deployment.id,
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
replicas: payload.target.replicas,
|
|
241
|
-
region: payload.target.targetId,
|
|
242
|
-
tip: 'Use get_app_status to monitor deployment progress.',
|
|
248
|
+
phase: result.snapshot.phase,
|
|
249
|
+
settled: result.snapshot.settled,
|
|
250
|
+
...(result.snapshot.reason ? { reason: result.snapshot.reason } : {}),
|
|
251
|
+
...(result.timedOut ? { timedOut: true } : {}),
|
|
243
252
|
});
|
|
253
|
+
return result.snapshot.terminal && !result.snapshot.settled
|
|
254
|
+
? { ...response, isError: true }
|
|
255
|
+
: response;
|
|
244
256
|
}
|
|
245
257
|
catch (error) {
|
|
246
|
-
return
|
|
258
|
+
return errorText(error, secretValues);
|
|
247
259
|
}
|
|
248
260
|
});
|
|
261
|
+
server.registerTool('update_app', {
|
|
262
|
+
title: 'Update Application',
|
|
263
|
+
description: 'Changes an existing CloudHub 2.0 application in one call: artifact version, Mule runtime, properties and update strategy together, as one new spec. ' +
|
|
264
|
+
'mode stopStart stops the app, applies the change and starts it, so old and new replicas never process events together; use it for apps with streaming, subscription or polling listeners. ' +
|
|
265
|
+
'The runtime is checked against what the target offers before anything is written; a retired runtime is refused with the nearest supported versions. ' +
|
|
266
|
+
'Waits for the rollout by default. Previews by default; pass confirm: true to apply.',
|
|
267
|
+
inputSchema: {
|
|
268
|
+
appName: z.string().describe('Application name exactly as deployed (case-insensitive match)'),
|
|
269
|
+
environment: z.string().describe('Environment name or ID'),
|
|
270
|
+
version: z.string().optional().describe('New artifact version. Default: keep the current one'),
|
|
271
|
+
...refInputs,
|
|
272
|
+
...runtimeInputs,
|
|
273
|
+
...settingsInputs,
|
|
274
|
+
mode: modeInput,
|
|
275
|
+
updateStrategy: updateStrategyInput,
|
|
276
|
+
wait: z.boolean().optional().describe('Wait until every replica runs the new spec (default: true)'),
|
|
277
|
+
waitTimeoutSeconds: waitInputs.waitTimeoutSeconds,
|
|
278
|
+
...writeInputs,
|
|
279
|
+
},
|
|
280
|
+
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
281
|
+
}, async (args) => runAppChangeTool(client, { ...args, wait: args.wait ?? true }, {
|
|
282
|
+
ref: {
|
|
283
|
+
version: args.version,
|
|
284
|
+
artifactId: args.artifactId,
|
|
285
|
+
groupId: args.groupId,
|
|
286
|
+
packaging: args.packaging,
|
|
287
|
+
},
|
|
288
|
+
runtime: runtimeFromArgs(args),
|
|
289
|
+
settings: settingsFromArgs(args),
|
|
290
|
+
mode: args.mode,
|
|
291
|
+
updateStrategy: args.updateStrategy,
|
|
292
|
+
}, { done: 'Updated' }));
|
|
249
293
|
server.registerTool('update_app_artifact', {
|
|
250
|
-
title: 'Update Application Artifact
|
|
251
|
-
description: '
|
|
294
|
+
title: 'Update Application Artifact',
|
|
295
|
+
description: 'Moves an existing CloudHub 2.0 application to another artifact version, optionally with a runtime change in the same update. Target, replicas, resources and settings are preserved. ' +
|
|
296
|
+
'Use runtime when the current runtime has been retired; the preview names supported versions. For settings changes in the same call use update_app. Previews by default; pass confirm: true to apply.',
|
|
252
297
|
inputSchema: {
|
|
253
298
|
appName: z.string().describe('Application name exactly as deployed (case-insensitive match)'),
|
|
254
|
-
environment: z.string().describe('Environment name
|
|
255
|
-
version: z.string().describe('New artifact version
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
.describe('Artifact packaging. Default: keep existing (usually "jar").'),
|
|
262
|
-
wait: z
|
|
263
|
-
.boolean()
|
|
264
|
-
.optional()
|
|
265
|
-
.describe('Wait for the redeploy to reach a running state before returning (default: false).'),
|
|
266
|
-
confirm: z
|
|
267
|
-
.boolean()
|
|
268
|
-
.optional()
|
|
269
|
-
.describe('Set true to apply. When omitted/false, returns a dry-run preview and changes nothing.'),
|
|
299
|
+
environment: z.string().describe('Environment name or ID'),
|
|
300
|
+
version: z.string().describe('New artifact version (e.g. "1.4.12")'),
|
|
301
|
+
...refInputs,
|
|
302
|
+
...runtimeInputs,
|
|
303
|
+
mode: modeInput,
|
|
304
|
+
...waitInputs,
|
|
305
|
+
...writeInputs,
|
|
270
306
|
},
|
|
271
307
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
272
|
-
}, async (
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
return dryRunPreview({
|
|
283
|
-
action: 'update artifact ref (safe redeploy)',
|
|
284
|
-
app: appName,
|
|
285
|
-
environment: env.name,
|
|
286
|
-
current: { ref: oldRef },
|
|
287
|
-
next: { ref: merged.application.ref },
|
|
288
|
-
preserved: 'runtime, target/space, replicas, resources, settings',
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
let deployment = await client.cloudHub2.updateArtifactRef(orgId, env.id, existing.id, merged.application.ref);
|
|
292
|
-
let waitResult;
|
|
293
|
-
if (wait) {
|
|
294
|
-
try {
|
|
295
|
-
deployment = await client.cloudHub2.waitForDeployment(orgId, env.id, deployment.id);
|
|
296
|
-
waitResult = deployment.status;
|
|
297
|
-
}
|
|
298
|
-
catch (waitErr) {
|
|
299
|
-
waitResult = `did not settle: ${errorMessage(waitErr)}`;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
return mcpText({
|
|
303
|
-
message: `✅ Updated "${appName}" in ${env.name} to v${version}`,
|
|
304
|
-
deploymentId: deployment.id,
|
|
305
|
-
status: deployment.status,
|
|
306
|
-
from: oldRef,
|
|
307
|
-
to: merged.application.ref,
|
|
308
|
-
preserved: 'runtime, target/space, replicas, resources, settings',
|
|
309
|
-
...(wait ? { waitResult } : { tip: 'Pass wait:true or use get_app_status to monitor progress.' }),
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
catch (error) {
|
|
313
|
-
return mcpError(error);
|
|
314
|
-
}
|
|
315
|
-
});
|
|
308
|
+
}, async (args) => runAppChangeTool(client, args, {
|
|
309
|
+
ref: {
|
|
310
|
+
version: args.version,
|
|
311
|
+
artifactId: args.artifactId,
|
|
312
|
+
groupId: args.groupId,
|
|
313
|
+
packaging: args.packaging,
|
|
314
|
+
},
|
|
315
|
+
runtime: runtimeFromArgs(args),
|
|
316
|
+
mode: args.mode,
|
|
317
|
+
}, { done: 'Updated artifact of' }));
|
|
316
318
|
server.registerTool('rollback_app', {
|
|
317
319
|
title: 'Roll Back Application',
|
|
318
|
-
description: 'Rolls an existing CloudHub 2.0 application back to a previous artifact
|
|
320
|
+
description: 'Rolls an existing CloudHub 2.0 application back to a previous artifact; runtime, target, replicas and settings are preserved. By default it picks the last successful or newest distinct earlier artifact; toVersion selects one. Previews by default; pass confirm: true to apply.',
|
|
319
321
|
inputSchema: {
|
|
320
322
|
appName: z.string().describe('Application name exactly as deployed (case-insensitive match)'),
|
|
321
|
-
environment: z.string().describe('Environment name
|
|
323
|
+
environment: z.string().describe('Environment name or ID'),
|
|
322
324
|
toVersion: z
|
|
323
325
|
.string()
|
|
324
326
|
.optional()
|
|
325
|
-
.describe('Artifact version to roll back to. Default: newest distinct
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
.describe('Wait for the rollback to reach a running state (default: false).'),
|
|
330
|
-
confirm: z
|
|
331
|
-
.boolean()
|
|
332
|
-
.optional()
|
|
333
|
-
.describe('Set true to apply. When omitted/false, returns a dry-run preview and changes nothing.'),
|
|
327
|
+
.describe('Artifact version to roll back to. Default: newest distinct earlier artifact'),
|
|
328
|
+
mode: modeInput,
|
|
329
|
+
...waitInputs,
|
|
330
|
+
...writeInputs,
|
|
334
331
|
},
|
|
335
332
|
annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false },
|
|
336
|
-
}, async (
|
|
333
|
+
}, async (args) => {
|
|
337
334
|
try {
|
|
338
|
-
const { orgId, env } = await resolveEnvironment(client, environment);
|
|
339
|
-
const existing = await client.cloudHub2.findDetailByName(orgId, env.id, appName);
|
|
335
|
+
const { orgId, env } = await resolveEnvironment(client, args.environment);
|
|
336
|
+
const existing = await client.cloudHub2.findDetailByName(orgId, env.id, args.appName);
|
|
340
337
|
if (!existing) {
|
|
341
|
-
return
|
|
338
|
+
return {
|
|
339
|
+
...mcpText({ message: `Application "${args.appName}" not found in ${env.name}` }),
|
|
340
|
+
isError: true,
|
|
341
|
+
};
|
|
342
342
|
}
|
|
343
343
|
const specs = await client.cloudHub2.getDeploymentSpecs(orgId, env.id, existing.id);
|
|
344
|
-
const target = resolveRollbackTarget(existing, specs, toVersion);
|
|
344
|
+
const target = resolveRollbackTarget(existing, specs, args.toVersion);
|
|
345
345
|
if (!target) {
|
|
346
|
-
return mcpText(
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
if (!confirm) {
|
|
350
|
-
return dryRunPreview({
|
|
351
|
-
action: 'rollback (artifact ref only)',
|
|
352
|
-
app: appName,
|
|
353
|
-
environment: env.name,
|
|
354
|
-
current: { ref: existing.application.ref, specId: existing.desiredVersion },
|
|
355
|
-
next: { ref: target.ref, sourceSpecId: target.sourceSpecId },
|
|
356
|
-
preserved: 'runtime, target/space, replicas, resources, settings',
|
|
346
|
+
return mcpText({
|
|
347
|
+
noop: true,
|
|
348
|
+
message: `No distinct rollback target for "${args.appName}" in ${env.name}. Pass toVersion to select one.`,
|
|
357
349
|
});
|
|
358
350
|
}
|
|
359
|
-
|
|
360
|
-
let waitResult;
|
|
361
|
-
if (wait) {
|
|
362
|
-
try {
|
|
363
|
-
deployment = await client.cloudHub2.waitForDeployment(orgId, env.id, deployment.id);
|
|
364
|
-
waitResult = deployment.status;
|
|
365
|
-
}
|
|
366
|
-
catch (waitErr) {
|
|
367
|
-
waitResult = `did not settle: ${errorMessage(waitErr)}`;
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
return mcpText({
|
|
371
|
-
message: `✅ Rolled back "${appName}" in ${env.name}: ${existing.application.ref.version} → ${target.ref.version}`,
|
|
372
|
-
deploymentId: deployment.id,
|
|
373
|
-
status: deployment.status,
|
|
374
|
-
rolledBackFrom: existing.application.ref,
|
|
375
|
-
rolledBackTo: target.ref,
|
|
376
|
-
sourceSpecId: target.sourceSpecId,
|
|
377
|
-
preserved: 'runtime, target/space, replicas, resources, settings',
|
|
378
|
-
...(wait ? { waitResult } : {}),
|
|
379
|
-
});
|
|
351
|
+
return runAppChangeTool(client, args, { existing, ref: target.ref, mode: args.mode }, { done: 'Rolled back' });
|
|
380
352
|
}
|
|
381
353
|
catch (error) {
|
|
382
|
-
return
|
|
354
|
+
return errorText(error, []);
|
|
383
355
|
}
|
|
384
356
|
});
|
|
385
357
|
}
|