lua-cli 3.1.0-alpha.4 → 3.1.0
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/dist/api/cdn.api.service.d.ts +18 -0
- package/dist/api/cdn.api.service.js +43 -0
- package/dist/api/custom.data.api.service.d.ts +4 -3
- package/dist/api/custom.data.api.service.js +4 -3
- package/dist/api/developer.api.service.d.ts +54 -1
- package/dist/api/developer.api.service.js +89 -0
- package/dist/api/job.api.service.d.ts +10 -0
- package/dist/api/job.api.service.js +14 -0
- package/dist/api/lazy-instances.d.ts +8 -0
- package/dist/api/lazy-instances.js +16 -0
- package/dist/api/postprocessor.api.service.d.ts +3 -6
- package/dist/api/postprocessor.api.service.js +2 -3
- package/dist/api-exports.d.ts +74 -6
- package/dist/api-exports.js +87 -7
- package/dist/cli/command-definitions.js +34 -7
- package/dist/commands/admin.js +1 -1
- package/dist/commands/channels.js +1 -1
- package/dist/commands/compile.js +23 -4
- package/dist/commands/evals.d.ts +8 -0
- package/dist/commands/evals.js +41 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/init.d.ts +10 -1
- package/dist/commands/init.js +13 -3
- package/dist/commands/mcp.d.ts +18 -0
- package/dist/commands/mcp.js +393 -0
- package/dist/commands/push.js +172 -14
- package/dist/common/data.entry.instance.d.ts +1 -1
- package/dist/common/data.entry.instance.js +4 -4
- package/dist/common/job.instance.d.ts +24 -0
- package/dist/common/job.instance.js +38 -0
- package/dist/config/constants.d.ts +1 -0
- package/dist/config/constants.js +1 -0
- package/dist/index.js +1 -0
- package/dist/interfaces/cdn.d.ts +24 -0
- package/dist/interfaces/cdn.js +5 -0
- package/dist/interfaces/compile.d.ts +1 -0
- package/dist/interfaces/custom.data.d.ts +3 -3
- package/dist/interfaces/index.d.ts +1 -0
- package/dist/interfaces/mcp.d.ts +64 -0
- package/dist/interfaces/mcp.js +5 -0
- package/dist/types/api-contracts.d.ts +36 -14
- package/dist/types/compile.types.d.ts +5 -0
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +3 -1
- package/dist/types/skill.d.ts +120 -13
- package/dist/types/skill.js +95 -5
- package/dist/utils/bundling.d.ts +4 -11
- package/dist/utils/bundling.js +19 -27
- package/dist/utils/compile.d.ts +17 -8
- package/dist/utils/compile.js +71 -37
- package/dist/utils/deployment.js +13 -6
- package/dist/utils/dev-api.js +1 -2
- package/dist/utils/dev-server.js +1 -1
- package/dist/utils/files.d.ts +8 -1
- package/dist/utils/files.js +13 -2
- package/dist/utils/init-helpers.d.ts +3 -1
- package/dist/utils/init-helpers.js +7 -2
- package/dist/utils/mcp-server-management.d.ts +23 -0
- package/dist/utils/mcp-server-management.js +212 -0
- package/dist/utils/sandbox.d.ts +4 -2
- package/dist/utils/sandbox.js +22 -3
- package/dist/web/app.css +1505 -14
- package/dist/web/app.js +79 -64
- package/package.json +2 -6
- package/template/QUICKSTART.md +57 -761
- package/template/README.md +80 -906
- package/template/examples/README.md +106 -0
- package/template/{src → examples}/jobs/AbandonedBasketProcessorJob.ts +67 -11
- package/template/{src → examples}/postprocessors/modifyResponse.ts +3 -3
- package/template/{src → examples}/skills/tools/GameScoreTrackerTool.ts +11 -15
- package/template/{src → examples}/skills/tools/OrderTool.ts +25 -0
- package/template/examples/skills/tools/PremiumFeatureTool.ts +98 -0
- package/template/{src → examples}/skills/tools/UserDataTool.ts +34 -0
- package/template/examples/webhooks/FileUploadWebhook.ts +86 -0
- package/template/package-lock.json +7895 -0
- package/template/package.json +1 -1
- package/template/src/index.ts +40 -22
- /package/template/{src → examples}/jobs/DailyCleanupJob.ts +0 -0
- /package/template/{src → examples}/jobs/DataMigrationJob.ts +0 -0
- /package/template/{src → examples}/jobs/HealthCheckJob.ts +0 -0
- /package/template/{src → examples}/preprocessors/messageMatching.ts +0 -0
- /package/template/{src → examples}/services/ApiService.ts +0 -0
- /package/template/{src → examples}/services/GetWeather.ts +0 -0
- /package/template/{src → examples}/skills/basket.skill.ts +0 -0
- /package/template/{src → examples}/skills/product.skill.ts +0 -0
- /package/template/{src → examples}/skills/tools/BasketTool.ts +0 -0
- /package/template/{src → examples}/skills/tools/CreateInlineJob.ts +0 -0
- /package/template/{src → examples}/skills/tools/CreatePostTool.ts +0 -0
- /package/template/{src → examples}/skills/tools/CustomDataTool.ts +0 -0
- /package/template/{src → examples}/skills/tools/GetWeatherTool.ts +0 -0
- /package/template/{src → examples}/skills/tools/PaymentTool.ts +0 -0
- /package/template/{src → examples}/skills/tools/ProductsTool.ts +0 -0
- /package/template/{src → examples}/skills/tools/SmartBasketTool.ts +0 -0
- /package/template/{src → examples}/skills/user.skill.ts +0 -0
- /package/template/{src → examples}/webhooks/PaymentWebhook.ts +0 -0
- /package/template/{src → examples}/webhooks/UserEventWebhook.ts +0 -0
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Command
|
|
3
|
+
* Manages Model Context Protocol (MCP) servers for agents
|
|
4
|
+
*/
|
|
5
|
+
import { loadApiKey, checkApiKey } from '../services/auth.js';
|
|
6
|
+
import { readSkillConfig } from '../utils/files.js';
|
|
7
|
+
import { withErrorHandling, writeProgress, writeSuccess, writeInfo } from '../utils/cli.js';
|
|
8
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
9
|
+
import { safePrompt } from '../utils/prompt-handler.js';
|
|
10
|
+
import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
|
|
11
|
+
import DeveloperApi from '../api/developer.api.service.js';
|
|
12
|
+
/**
|
|
13
|
+
* Main MCP command - manages MCP servers
|
|
14
|
+
*
|
|
15
|
+
* Subcommands:
|
|
16
|
+
* - lua mcp list - List all MCP servers
|
|
17
|
+
* - lua mcp activate - Activate an MCP server
|
|
18
|
+
* - lua mcp deactivate - Deactivate an MCP server
|
|
19
|
+
* - lua mcp delete - Delete an MCP server
|
|
20
|
+
*
|
|
21
|
+
* @param action - Optional action ('list', 'activate', 'deactivate', 'delete')
|
|
22
|
+
* @param serverName - Optional server name for actions
|
|
23
|
+
* @returns Promise that resolves when command completes
|
|
24
|
+
*/
|
|
25
|
+
export async function mcpCommand(action, serverName) {
|
|
26
|
+
return withErrorHandling(async () => {
|
|
27
|
+
// Step 1: Load configuration
|
|
28
|
+
const config = readSkillConfig();
|
|
29
|
+
validateConfig(config);
|
|
30
|
+
validateAgentConfig(config);
|
|
31
|
+
const agentId = config.agent.agentId;
|
|
32
|
+
// Step 2: Authenticate
|
|
33
|
+
const apiKey = await loadApiKey();
|
|
34
|
+
if (!apiKey) {
|
|
35
|
+
console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
await checkApiKey(apiKey);
|
|
39
|
+
writeProgress("✅ Authenticated");
|
|
40
|
+
const developerApi = new DeveloperApi(BASE_URLS.API, apiKey, agentId);
|
|
41
|
+
const context = {
|
|
42
|
+
agentId,
|
|
43
|
+
apiKey,
|
|
44
|
+
developerApi,
|
|
45
|
+
};
|
|
46
|
+
// Step 3: Handle action or show interactive menu
|
|
47
|
+
if (action) {
|
|
48
|
+
const normalizedAction = action.toLowerCase();
|
|
49
|
+
switch (normalizedAction) {
|
|
50
|
+
case 'list':
|
|
51
|
+
case 'ls':
|
|
52
|
+
await listMCPServers(context);
|
|
53
|
+
break;
|
|
54
|
+
case 'activate':
|
|
55
|
+
case 'enable':
|
|
56
|
+
await activateMCPServer(context, serverName);
|
|
57
|
+
break;
|
|
58
|
+
case 'deactivate':
|
|
59
|
+
case 'disable':
|
|
60
|
+
await deactivateMCPServer(context, serverName);
|
|
61
|
+
break;
|
|
62
|
+
case 'delete':
|
|
63
|
+
case 'rm':
|
|
64
|
+
await deleteMCPServer(context, serverName);
|
|
65
|
+
break;
|
|
66
|
+
default:
|
|
67
|
+
console.error(`❌ Unknown action: "${action}"`);
|
|
68
|
+
showUsage();
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// Interactive mode
|
|
74
|
+
await interactiveMCPManagement(context);
|
|
75
|
+
}
|
|
76
|
+
}, "mcp");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Show usage information
|
|
80
|
+
*/
|
|
81
|
+
function showUsage() {
|
|
82
|
+
console.log('\nUsage:');
|
|
83
|
+
console.log(' lua mcp - Interactive MCP server management');
|
|
84
|
+
console.log(' lua mcp list - List all MCP servers');
|
|
85
|
+
console.log(' lua mcp activate [name] - Activate an MCP server');
|
|
86
|
+
console.log(' lua mcp deactivate [name] - Deactivate an MCP server');
|
|
87
|
+
console.log(' lua mcp delete [name] - Delete an MCP server');
|
|
88
|
+
console.log('\nAliases:');
|
|
89
|
+
console.log(' list → ls');
|
|
90
|
+
console.log(' activate → enable');
|
|
91
|
+
console.log(' deactivate → disable');
|
|
92
|
+
console.log(' delete → rm');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Interactive MCP management
|
|
96
|
+
*/
|
|
97
|
+
async function interactiveMCPManagement(context) {
|
|
98
|
+
let continueManaging = true;
|
|
99
|
+
while (continueManaging) {
|
|
100
|
+
console.log("\n" + "=".repeat(60));
|
|
101
|
+
console.log("🔌 MCP Server Management");
|
|
102
|
+
console.log("=".repeat(60) + "\n");
|
|
103
|
+
const actionAnswer = await safePrompt([
|
|
104
|
+
{
|
|
105
|
+
type: 'list',
|
|
106
|
+
name: 'action',
|
|
107
|
+
message: 'What would you like to do?',
|
|
108
|
+
choices: [
|
|
109
|
+
{ name: '📋 List MCP servers', value: 'list' },
|
|
110
|
+
{ name: '✅ Activate a server', value: 'activate' },
|
|
111
|
+
{ name: '⏸️ Deactivate a server', value: 'deactivate' },
|
|
112
|
+
{ name: '🗑️ Delete a server', value: 'delete' },
|
|
113
|
+
{ name: '❌ Exit', value: 'exit' }
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
if (!actionAnswer)
|
|
118
|
+
return;
|
|
119
|
+
const { action } = actionAnswer;
|
|
120
|
+
switch (action) {
|
|
121
|
+
case 'list':
|
|
122
|
+
await listMCPServers(context);
|
|
123
|
+
break;
|
|
124
|
+
case 'activate':
|
|
125
|
+
await activateMCPServer(context);
|
|
126
|
+
break;
|
|
127
|
+
case 'deactivate':
|
|
128
|
+
await deactivateMCPServer(context);
|
|
129
|
+
break;
|
|
130
|
+
case 'delete':
|
|
131
|
+
await deleteMCPServer(context);
|
|
132
|
+
break;
|
|
133
|
+
case 'exit':
|
|
134
|
+
continueManaging = false;
|
|
135
|
+
console.log("\n👋 Goodbye!\n");
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* List all MCP servers
|
|
142
|
+
*/
|
|
143
|
+
async function listMCPServers(context) {
|
|
144
|
+
writeProgress("🔄 Loading MCP servers...");
|
|
145
|
+
try {
|
|
146
|
+
const result = await context.developerApi.getMCPServers();
|
|
147
|
+
if (!result.success) {
|
|
148
|
+
console.error(`\n❌ Failed to load MCP servers: ${result.error?.message}\n`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const servers = result.data || [];
|
|
152
|
+
console.log("\n" + "=".repeat(60));
|
|
153
|
+
console.log("🔌 MCP Servers");
|
|
154
|
+
console.log("=".repeat(60) + "\n");
|
|
155
|
+
if (servers.length === 0) {
|
|
156
|
+
console.log("ℹ️ No MCP servers found.");
|
|
157
|
+
console.log("💡 Define MCP servers in your LuaAgent configuration and run 'lua push all'.\n");
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Separate active and inactive servers
|
|
161
|
+
const activeServers = servers.filter((s) => s.active);
|
|
162
|
+
const inactiveServers = servers.filter((s) => !s.active);
|
|
163
|
+
if (activeServers.length > 0) {
|
|
164
|
+
console.log("✅ Active Servers:\n");
|
|
165
|
+
activeServers.forEach((server) => {
|
|
166
|
+
printServerInfo(server);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (inactiveServers.length > 0) {
|
|
170
|
+
if (activeServers.length > 0)
|
|
171
|
+
console.log("─".repeat(40) + "\n");
|
|
172
|
+
console.log("⏸️ Inactive Servers:\n");
|
|
173
|
+
inactiveServers.forEach((server) => {
|
|
174
|
+
printServerInfo(server);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
console.log("=".repeat(60) + "\n");
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.error('\n❌ Error loading MCP servers:', error.message);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Print server information
|
|
185
|
+
*/
|
|
186
|
+
function printServerInfo(server) {
|
|
187
|
+
const statusIcon = server.active ? '🟢' : '⚪';
|
|
188
|
+
console.log(`${statusIcon} ${server.name}`);
|
|
189
|
+
console.log(` Transport: ${server.transport}`);
|
|
190
|
+
if (server.transport === 'stdio') {
|
|
191
|
+
console.log(` Command: ${server.command} ${(server.args || []).join(' ')}`);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
console.log(` URL: ${server.url}`);
|
|
195
|
+
}
|
|
196
|
+
console.log(` ID: ${server.id}`);
|
|
197
|
+
console.log();
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Activate an MCP server
|
|
201
|
+
*/
|
|
202
|
+
async function activateMCPServer(context, serverName) {
|
|
203
|
+
try {
|
|
204
|
+
// Get all servers
|
|
205
|
+
const result = await context.developerApi.getMCPServers();
|
|
206
|
+
if (!result.success) {
|
|
207
|
+
console.error(`\n❌ Failed to load MCP servers: ${result.error?.message}\n`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const servers = result.data || [];
|
|
211
|
+
const inactiveServers = servers.filter((s) => !s.active);
|
|
212
|
+
if (inactiveServers.length === 0) {
|
|
213
|
+
console.log("\nℹ️ All MCP servers are already active.\n");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
let serverToActivate;
|
|
217
|
+
if (serverName) {
|
|
218
|
+
// Find by name
|
|
219
|
+
const server = inactiveServers.find((s) => s.name.toLowerCase() === serverName.toLowerCase());
|
|
220
|
+
if (!server) {
|
|
221
|
+
console.error(`\n❌ Inactive MCP server "${serverName}" not found.\n`);
|
|
222
|
+
console.log("Available inactive servers:");
|
|
223
|
+
inactiveServers.forEach((s) => console.log(` - ${s.name}`));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
serverToActivate = server;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// Prompt for selection
|
|
230
|
+
const answer = await safePrompt([
|
|
231
|
+
{
|
|
232
|
+
type: 'list',
|
|
233
|
+
name: 'server',
|
|
234
|
+
message: 'Select an MCP server to activate:',
|
|
235
|
+
choices: inactiveServers.map((s) => ({
|
|
236
|
+
name: `${s.name} (${s.transport})`,
|
|
237
|
+
value: s
|
|
238
|
+
}))
|
|
239
|
+
}
|
|
240
|
+
]);
|
|
241
|
+
if (!answer)
|
|
242
|
+
return;
|
|
243
|
+
serverToActivate = answer.server;
|
|
244
|
+
}
|
|
245
|
+
writeProgress(`🔄 Activating ${serverToActivate.name}...`);
|
|
246
|
+
const activateResult = await context.developerApi.activateMCPServer(serverToActivate.id);
|
|
247
|
+
if (activateResult.success) {
|
|
248
|
+
writeSuccess(`\n✅ MCP server "${serverToActivate.name}" activated successfully!\n`);
|
|
249
|
+
writeInfo("💡 The server's tools are now available to your agent.");
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.error(`\n❌ Failed to activate: ${activateResult.error?.message}\n`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
console.error('\n❌ Error activating MCP server:', error.message);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Deactivate an MCP server
|
|
261
|
+
*/
|
|
262
|
+
async function deactivateMCPServer(context, serverName) {
|
|
263
|
+
try {
|
|
264
|
+
// Get all servers
|
|
265
|
+
const result = await context.developerApi.getMCPServers();
|
|
266
|
+
if (!result.success) {
|
|
267
|
+
console.error(`\n❌ Failed to load MCP servers: ${result.error?.message}\n`);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const servers = result.data || [];
|
|
271
|
+
const activeServers = servers.filter((s) => s.active);
|
|
272
|
+
if (activeServers.length === 0) {
|
|
273
|
+
console.log("\nℹ️ No active MCP servers to deactivate.\n");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
let serverToDeactivate;
|
|
277
|
+
if (serverName) {
|
|
278
|
+
// Find by name
|
|
279
|
+
const server = activeServers.find((s) => s.name.toLowerCase() === serverName.toLowerCase());
|
|
280
|
+
if (!server) {
|
|
281
|
+
console.error(`\n❌ Active MCP server "${serverName}" not found.\n`);
|
|
282
|
+
console.log("Available active servers:");
|
|
283
|
+
activeServers.forEach((s) => console.log(` - ${s.name}`));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
serverToDeactivate = server;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Prompt for selection
|
|
290
|
+
const answer = await safePrompt([
|
|
291
|
+
{
|
|
292
|
+
type: 'list',
|
|
293
|
+
name: 'server',
|
|
294
|
+
message: 'Select an MCP server to deactivate:',
|
|
295
|
+
choices: activeServers.map((s) => ({
|
|
296
|
+
name: `${s.name} (${s.transport})`,
|
|
297
|
+
value: s
|
|
298
|
+
}))
|
|
299
|
+
}
|
|
300
|
+
]);
|
|
301
|
+
if (!answer)
|
|
302
|
+
return;
|
|
303
|
+
serverToDeactivate = answer.server;
|
|
304
|
+
}
|
|
305
|
+
writeProgress(`🔄 Deactivating ${serverToDeactivate.name}...`);
|
|
306
|
+
const deactivateResult = await context.developerApi.deactivateMCPServer(serverToDeactivate.id);
|
|
307
|
+
if (deactivateResult.success) {
|
|
308
|
+
writeSuccess(`\n✅ MCP server "${serverToDeactivate.name}" deactivated successfully!\n`);
|
|
309
|
+
writeInfo("💡 The server's tools are no longer available to your agent.");
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
console.error(`\n❌ Failed to deactivate: ${deactivateResult.error?.message}\n`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
console.error('\n❌ Error deactivating MCP server:', error.message);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Delete an MCP server
|
|
321
|
+
*/
|
|
322
|
+
async function deleteMCPServer(context, serverName) {
|
|
323
|
+
try {
|
|
324
|
+
// Get all servers
|
|
325
|
+
const result = await context.developerApi.getMCPServers();
|
|
326
|
+
if (!result.success) {
|
|
327
|
+
console.error(`\n❌ Failed to load MCP servers: ${result.error?.message}\n`);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const servers = result.data || [];
|
|
331
|
+
if (servers.length === 0) {
|
|
332
|
+
console.log("\nℹ️ No MCP servers to delete.\n");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
let serverToDelete;
|
|
336
|
+
if (serverName) {
|
|
337
|
+
// Find by name
|
|
338
|
+
const server = servers.find((s) => s.name.toLowerCase() === serverName.toLowerCase());
|
|
339
|
+
if (!server) {
|
|
340
|
+
console.error(`\n❌ MCP server "${serverName}" not found.\n`);
|
|
341
|
+
console.log("Available servers:");
|
|
342
|
+
servers.forEach((s) => console.log(` - ${s.name}`));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
serverToDelete = server;
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// Prompt for selection
|
|
349
|
+
const answer = await safePrompt([
|
|
350
|
+
{
|
|
351
|
+
type: 'list',
|
|
352
|
+
name: 'server',
|
|
353
|
+
message: 'Select an MCP server to delete:',
|
|
354
|
+
choices: servers.map((s) => ({
|
|
355
|
+
name: `${s.name} (${s.transport}) ${s.active ? '🟢' : '⚪'}`,
|
|
356
|
+
value: s
|
|
357
|
+
}))
|
|
358
|
+
}
|
|
359
|
+
]);
|
|
360
|
+
if (!answer)
|
|
361
|
+
return;
|
|
362
|
+
serverToDelete = answer.server;
|
|
363
|
+
}
|
|
364
|
+
// Confirm deletion
|
|
365
|
+
console.log(`\n⚠️ You are about to delete MCP server: ${serverToDelete.name}`);
|
|
366
|
+
if (serverToDelete.active) {
|
|
367
|
+
console.log("⚠️ WARNING: This server is currently ACTIVE!");
|
|
368
|
+
}
|
|
369
|
+
const confirmAnswer = await safePrompt([
|
|
370
|
+
{
|
|
371
|
+
type: 'confirm',
|
|
372
|
+
name: 'confirm',
|
|
373
|
+
message: 'Are you sure you want to delete this MCP server?',
|
|
374
|
+
default: false
|
|
375
|
+
}
|
|
376
|
+
]);
|
|
377
|
+
if (!confirmAnswer || !confirmAnswer.confirm) {
|
|
378
|
+
console.log("\n❌ Deletion cancelled.\n");
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
writeProgress(`🔄 Deleting ${serverToDelete.name}...`);
|
|
382
|
+
const deleteResult = await context.developerApi.deleteMCPServer(serverToDelete.id);
|
|
383
|
+
if (deleteResult.success) {
|
|
384
|
+
writeSuccess(`\n✅ MCP server "${serverToDelete.name}" deleted successfully!\n`);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
console.error(`\n❌ Failed to delete: ${deleteResult.error?.message}\n`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
console.error('\n❌ Error deleting MCP server:', error.message);
|
|
392
|
+
}
|
|
393
|
+
}
|
package/dist/commands/push.js
CHANGED
|
@@ -16,6 +16,7 @@ import { fetchVersions, publishVersion, } from '../utils/deploy-api.js';
|
|
|
16
16
|
import { BASE_URLS } from '../config/constants.js';
|
|
17
17
|
import PreProcessorApi from '../api/preprocessor.api.service.js';
|
|
18
18
|
import PostProcessorApi from '../api/postprocessor.api.service.js';
|
|
19
|
+
import DeveloperApi from '../api/developer.api.service.js';
|
|
19
20
|
/**
|
|
20
21
|
* Main push command - pushes a skill or persona version to the server.
|
|
21
22
|
*
|
|
@@ -57,8 +58,8 @@ export async function pushCommand(type, cmdObj) {
|
|
|
57
58
|
// Step 1: Check if type was provided as argument
|
|
58
59
|
if (type) {
|
|
59
60
|
// Validate the provided type
|
|
60
|
-
if (type !== 'skill' && type !== 'persona' && type !== 'webhook' && type !== 'job' && type !== 'preprocessor' && type !== 'postprocessor') {
|
|
61
|
-
console.error(`❌ Invalid type: "${type}". Must be "skill", "persona", "webhook", "job", "preprocessor", "postprocessor", or "all".`);
|
|
61
|
+
if (type !== 'skill' && type !== 'persona' && type !== 'webhook' && type !== 'job' && type !== 'preprocessor' && type !== 'postprocessor' && type !== 'mcp') {
|
|
62
|
+
console.error(`❌ Invalid type: "${type}". Must be "skill", "persona", "webhook", "job", "preprocessor", "postprocessor", "mcp", or "all".`);
|
|
62
63
|
console.log('\nUsage:');
|
|
63
64
|
console.log(' lua push - Interactive selection');
|
|
64
65
|
console.log(' lua push skill - Push a skill directly');
|
|
@@ -67,6 +68,7 @@ export async function pushCommand(type, cmdObj) {
|
|
|
67
68
|
console.log(' lua push job - Push a job directly');
|
|
68
69
|
console.log(' lua push preprocessor - Push a preprocessor directly');
|
|
69
70
|
console.log(' lua push postprocessor - Push a postprocessor directly');
|
|
71
|
+
console.log(' lua push mcp - Push an MCP server directly');
|
|
70
72
|
console.log(' lua push all --force - Push all components without prompts');
|
|
71
73
|
process.exit(1);
|
|
72
74
|
}
|
|
@@ -85,6 +87,7 @@ export async function pushCommand(type, cmdObj) {
|
|
|
85
87
|
{ name: '⏰ Job', value: 'job' },
|
|
86
88
|
{ name: '📥 PreProcessor', value: 'preprocessor' },
|
|
87
89
|
{ name: '📤 PostProcessor', value: 'postprocessor' },
|
|
90
|
+
{ name: '🔌 MCP Server', value: 'mcp' },
|
|
88
91
|
{ name: '🌙 Persona', value: 'persona' }
|
|
89
92
|
]
|
|
90
93
|
}
|
|
@@ -111,6 +114,9 @@ export async function pushCommand(type, cmdObj) {
|
|
|
111
114
|
else if (selectedType === 'postprocessor') {
|
|
112
115
|
await pushPostProcessorVersion();
|
|
113
116
|
}
|
|
117
|
+
else if (selectedType === 'mcp') {
|
|
118
|
+
await pushMCPServerVersion();
|
|
119
|
+
}
|
|
114
120
|
else {
|
|
115
121
|
await pushPersonaVersion();
|
|
116
122
|
}
|
|
@@ -133,8 +139,9 @@ export async function pushCommand(type, cmdObj) {
|
|
|
133
139
|
*/
|
|
134
140
|
async function pushSkillVersion() {
|
|
135
141
|
// Step 1: Validate configuration
|
|
136
|
-
const
|
|
137
|
-
validatePushConfig(
|
|
142
|
+
const yamlConfig = readSkillConfig();
|
|
143
|
+
validatePushConfig(yamlConfig);
|
|
144
|
+
const config = yamlConfig;
|
|
138
145
|
// Step 2: Get available skills and prompt for selection
|
|
139
146
|
const availableSkills = getAvailableSkills(config);
|
|
140
147
|
if (availableSkills.length === 0) {
|
|
@@ -912,8 +919,7 @@ async function pushPostProcessorVersion() {
|
|
|
912
919
|
description: bundledData.description || selected.description,
|
|
913
920
|
postprocessorId: selected.postprocessorId,
|
|
914
921
|
code: bundledData.code,
|
|
915
|
-
executeFunction: bundledData.executeFunction
|
|
916
|
-
async: Boolean(bundledData.async ?? false) // Ensure boolean type
|
|
922
|
+
executeFunction: bundledData.executeFunction
|
|
917
923
|
};
|
|
918
924
|
writeProgress(`\n🚀 Pushing ${selected.name} v${confirmedVersion}...`);
|
|
919
925
|
const api = new PostProcessorApi(BASE_URLS.API, apiKey, config.agent.agentId);
|
|
@@ -1001,6 +1007,120 @@ function updateProcessorVersionInYaml(processorType, processorName, newVersion)
|
|
|
1001
1007
|
console.warn('⚠️ Could not update processor version in YAML:', error);
|
|
1002
1008
|
}
|
|
1003
1009
|
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Push MCP Server to the server
|
|
1012
|
+
*/
|
|
1013
|
+
async function pushMCPServerVersion() {
|
|
1014
|
+
try {
|
|
1015
|
+
// Step 1: Run compilation
|
|
1016
|
+
writeProgress("📦 Compiling project...");
|
|
1017
|
+
await compileCommand();
|
|
1018
|
+
writeSuccess("✅ Compilation complete");
|
|
1019
|
+
// Step 2: Authenticate
|
|
1020
|
+
const apiKey = await loadApiKey();
|
|
1021
|
+
if (!apiKey) {
|
|
1022
|
+
console.error("❌ No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
1023
|
+
process.exit(1);
|
|
1024
|
+
}
|
|
1025
|
+
await checkApiKey(apiKey);
|
|
1026
|
+
writeSuccess("✅ Authentication verified");
|
|
1027
|
+
// Step 3: Read configuration
|
|
1028
|
+
const config = readSkillConfig();
|
|
1029
|
+
if (!config?.agent?.agentId) {
|
|
1030
|
+
console.error("❌ No agent ID found in lua.skill.yaml. Please run 'lua init' first.");
|
|
1031
|
+
process.exit(1);
|
|
1032
|
+
}
|
|
1033
|
+
const mcpServers = config.mcpServers || [];
|
|
1034
|
+
if (mcpServers.length === 0) {
|
|
1035
|
+
console.error("❌ No MCP servers found in lua.skill.yaml.");
|
|
1036
|
+
console.log("💡 Make sure you have defined MCP servers in your LuaAgent configuration.");
|
|
1037
|
+
process.exit(1);
|
|
1038
|
+
}
|
|
1039
|
+
// Step 4: Load bundled MCP server data first (has full config)
|
|
1040
|
+
const bundledServersPath = path.join(process.cwd(), 'dist', 'mcp-servers.json');
|
|
1041
|
+
let bundledServers = [];
|
|
1042
|
+
if (fs.existsSync(bundledServersPath)) {
|
|
1043
|
+
bundledServers = JSON.parse(fs.readFileSync(bundledServersPath, 'utf8'));
|
|
1044
|
+
}
|
|
1045
|
+
else {
|
|
1046
|
+
console.error('❌ Bundled MCP server data not found.');
|
|
1047
|
+
console.log("💡 Please ensure your MCP servers are properly compiled.");
|
|
1048
|
+
process.exit(1);
|
|
1049
|
+
}
|
|
1050
|
+
// Step 5: Select MCP server to push (use bundled data for display, YAML for ID tracking)
|
|
1051
|
+
const serverAnswer = await safePrompt([
|
|
1052
|
+
{
|
|
1053
|
+
type: 'list',
|
|
1054
|
+
name: 'selectedServer',
|
|
1055
|
+
message: 'Select an MCP server to push:',
|
|
1056
|
+
choices: bundledServers.map((server) => {
|
|
1057
|
+
const yamlEntry = mcpServers.find((s) => s.name === server.name);
|
|
1058
|
+
return {
|
|
1059
|
+
name: `${server.name} (${server.transport})`,
|
|
1060
|
+
value: { ...server, mcpServerId: yamlEntry?.mcpServerId }
|
|
1061
|
+
};
|
|
1062
|
+
})
|
|
1063
|
+
}
|
|
1064
|
+
]);
|
|
1065
|
+
if (!serverAnswer) {
|
|
1066
|
+
console.log("Push cancelled.");
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
const selectedServer = serverAnswer.selectedServer;
|
|
1070
|
+
const bundledServerData = selectedServer;
|
|
1071
|
+
// Step 6: Prepare server data for push
|
|
1072
|
+
const serverData = {
|
|
1073
|
+
name: bundledServerData.name,
|
|
1074
|
+
transport: bundledServerData.transport,
|
|
1075
|
+
timeout: bundledServerData.timeout,
|
|
1076
|
+
...(bundledServerData.transport === 'stdio' ? {
|
|
1077
|
+
command: bundledServerData.command,
|
|
1078
|
+
args: bundledServerData.args,
|
|
1079
|
+
env: bundledServerData.env
|
|
1080
|
+
} : {
|
|
1081
|
+
url: bundledServerData.url,
|
|
1082
|
+
headers: bundledServerData.headers
|
|
1083
|
+
})
|
|
1084
|
+
};
|
|
1085
|
+
// Step 7: Push to server (upsert)
|
|
1086
|
+
writeProgress(`\n🚀 Pushing MCP server "${selectedServer.name}" to server...`);
|
|
1087
|
+
const developerApi = new DeveloperApi(BASE_URLS.API, apiKey, config.agent.agentId);
|
|
1088
|
+
const result = await developerApi.upsertMCPServer(serverData);
|
|
1089
|
+
if (result.success && result.data) {
|
|
1090
|
+
writeSuccess(`\n✅ MCP server "${selectedServer.name}" pushed successfully\n`);
|
|
1091
|
+
// Ask if user wants to activate now
|
|
1092
|
+
const activateAnswer = await safePrompt([
|
|
1093
|
+
{
|
|
1094
|
+
type: 'confirm',
|
|
1095
|
+
name: 'activateNow',
|
|
1096
|
+
message: 'Would you like to activate this MCP server now?',
|
|
1097
|
+
default: false
|
|
1098
|
+
}
|
|
1099
|
+
]);
|
|
1100
|
+
if (activateAnswer && activateAnswer.activateNow) {
|
|
1101
|
+
writeProgress("🔄 Activating MCP server...");
|
|
1102
|
+
const activateResult = await developerApi.activateMCPServer(result.data.id);
|
|
1103
|
+
if (activateResult.success) {
|
|
1104
|
+
writeSuccess(`\n✅ MCP server "${selectedServer.name}" activated successfully\n`);
|
|
1105
|
+
writeInfo("💡 The server's tools are now available to your agent.");
|
|
1106
|
+
}
|
|
1107
|
+
else {
|
|
1108
|
+
console.error(`❌ Failed to activate: ${activateResult.error?.message}`);
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
else {
|
|
1112
|
+
writeInfo("💡 You can activate this server later using: lua mcp activate");
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
else {
|
|
1116
|
+
console.error(`❌ Failed to push: ${result.error?.message}`);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
catch (error) {
|
|
1120
|
+
console.error('❌ Error pushing MCP server:', error);
|
|
1121
|
+
process.exit(1);
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1004
1124
|
/**
|
|
1005
1125
|
* Deploy a version immediately after pushing
|
|
1006
1126
|
*/
|
|
@@ -1189,7 +1309,7 @@ async function pushAllCommand(options) {
|
|
|
1189
1309
|
const pushData = {
|
|
1190
1310
|
name: webhookConfig.name,
|
|
1191
1311
|
version: newVersion,
|
|
1192
|
-
description: webhookData.description ||
|
|
1312
|
+
description: webhookData.description || '',
|
|
1193
1313
|
webhookId: webhookConfig.webhookId,
|
|
1194
1314
|
querySchema: webhookData.querySchema,
|
|
1195
1315
|
headerSchema: webhookData.headerSchema,
|
|
@@ -1249,14 +1369,14 @@ async function pushAllCommand(options) {
|
|
|
1249
1369
|
const pushData = {
|
|
1250
1370
|
name: jobConfig.name,
|
|
1251
1371
|
version: newVersion,
|
|
1252
|
-
description: jobData.description ||
|
|
1372
|
+
description: jobData.description || '',
|
|
1253
1373
|
jobId: jobConfig.jobId,
|
|
1254
1374
|
schedule: jobData.schedule || jobConfig.schedule,
|
|
1255
1375
|
timeout: jobData.timeout,
|
|
1256
1376
|
retry: jobData.retry,
|
|
1257
1377
|
code: jobData.code,
|
|
1258
1378
|
executeFunction: jobData.executeFunction,
|
|
1259
|
-
metadata: jobData.metadata
|
|
1379
|
+
metadata: jobData.metadata
|
|
1260
1380
|
};
|
|
1261
1381
|
// Push version using fetch
|
|
1262
1382
|
const response = await fetch(`${BASE_URLS.API}/developer/jobs/${agentId}/${jobConfig.jobId}/version`, {
|
|
@@ -1313,7 +1433,7 @@ async function pushAllCommand(options) {
|
|
|
1313
1433
|
const versionData = {
|
|
1314
1434
|
name: processorConfig.name,
|
|
1315
1435
|
version: newVersion,
|
|
1316
|
-
description: processorData.description ||
|
|
1436
|
+
description: processorData.description || '',
|
|
1317
1437
|
preprocessorId: preprocessorId,
|
|
1318
1438
|
code: processorData.code,
|
|
1319
1439
|
executeFunction: processorData.executeFunction,
|
|
@@ -1367,11 +1487,10 @@ async function pushAllCommand(options) {
|
|
|
1367
1487
|
const versionData = {
|
|
1368
1488
|
name: processorConfig.name,
|
|
1369
1489
|
version: newVersion,
|
|
1370
|
-
description: processorData.description ||
|
|
1490
|
+
description: processorData.description || '',
|
|
1371
1491
|
postprocessorId: postprocessorId,
|
|
1372
1492
|
code: processorData.code,
|
|
1373
|
-
executeFunction: processorData.executeFunction
|
|
1374
|
-
async: Boolean(processorData.async ?? false)
|
|
1493
|
+
executeFunction: processorData.executeFunction
|
|
1375
1494
|
};
|
|
1376
1495
|
// Push version
|
|
1377
1496
|
const result = await postprocessorService.pushPostProcessor(postprocessorId, versionData);
|
|
@@ -1392,7 +1511,46 @@ async function pushAllCommand(options) {
|
|
|
1392
1511
|
}
|
|
1393
1512
|
}
|
|
1394
1513
|
}
|
|
1395
|
-
// Step 9:
|
|
1514
|
+
// Step 9: Push MCP server configurations
|
|
1515
|
+
const mcpServersJsonPath = path.join(process.cwd(), 'dist', 'mcp-servers.json');
|
|
1516
|
+
if (fs.existsSync(mcpServersJsonPath)) {
|
|
1517
|
+
const mcpServers = JSON.parse(fs.readFileSync(mcpServersJsonPath, 'utf8'));
|
|
1518
|
+
if (mcpServers.length > 0) {
|
|
1519
|
+
writeProgress(`\n🔌 Pushing ${mcpServers.length} MCP server(s)...`);
|
|
1520
|
+
try {
|
|
1521
|
+
const DeveloperApi = (await import('../api/developer.api.service.js')).default;
|
|
1522
|
+
const developerApi = new DeveloperApi(BASE_URLS.API, apiKey, agentId);
|
|
1523
|
+
for (const serverConfig of mcpServers) {
|
|
1524
|
+
try {
|
|
1525
|
+
// Upsert the MCP server (create or update by name)
|
|
1526
|
+
const result = await developerApi.upsertMCPServer(serverConfig);
|
|
1527
|
+
if (result.success && result.data) {
|
|
1528
|
+
const mcpServerId = result.data.id;
|
|
1529
|
+
const isActive = result.data.active;
|
|
1530
|
+
writeSuccess(` ✅ ${serverConfig.name} (${serverConfig.transport}) - ${isActive ? 'active' : 'inactive'}`);
|
|
1531
|
+
// Auto-activate if autoDeploy is enabled
|
|
1532
|
+
if (options.autoDeploy && !isActive) {
|
|
1533
|
+
const activateResult = await developerApi.activateMCPServer(mcpServerId);
|
|
1534
|
+
if (activateResult.success) {
|
|
1535
|
+
writeSuccess(` 🔌 Auto-activated`);
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
}
|
|
1539
|
+
else {
|
|
1540
|
+
console.error(` ❌ Failed to push ${serverConfig.name}:`, result.error?.message);
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
catch (error) {
|
|
1544
|
+
console.error(` ❌ Failed to push ${serverConfig.name}:`, error.message);
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
catch (error) {
|
|
1549
|
+
console.error(` ❌ Failed to push MCP servers:`, error.message);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
// Step 10: Deploy all components if autoDeploy is enabled
|
|
1396
1554
|
if (options.autoDeploy && (toDeploySkills.length > 0 || toDeployWebhooks.length > 0 || toDeployJobs.length > 0 || toDeployPreprocessors.length > 0 || toDeployPostprocessors.length > 0)) {
|
|
1397
1555
|
writeProgress('\n🚀 Deploying all pushed versions to production...');
|
|
1398
1556
|
writeInfo('⏱️ Waiting for server to process versions (5 seconds)...\n');
|
|
@@ -32,7 +32,7 @@ export default class DataEntryInstance {
|
|
|
32
32
|
* @returns Promise resolving to the updated data
|
|
33
33
|
* @throws Error if the update fails
|
|
34
34
|
*/
|
|
35
|
-
update(data: Record<string, any>, searchText?: string): Promise<any
|
|
35
|
+
update(data: Record<string, any>, searchText?: string): Promise<Record<string, any>>;
|
|
36
36
|
/**
|
|
37
37
|
* Deletes the custom data entry
|
|
38
38
|
* @returns Promise resolving to true if deletion was successful
|