tmpa-cli 1.0.17 → 1.0.18

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/bin/index.js +106 -41
  2. package/package.json +6 -2
package/bin/index.js CHANGED
@@ -90,13 +90,12 @@ ${C.c3} ██║ ██║╚██╔╝██║██╔═══╝ █
90
90
  ${C.c4} ██║ ██║ ╚═╝ ██║██║ ██║ ██║${C.reset}
91
91
  ${C.c4} ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${C.reset}
92
92
  ${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
93
- ${C.reset}The Multi Platform AI ${C.green}[Isolated Tool Execution Engine]${C.reset}
94
- ${C.gray}/config | /models | /skill | /mcp | /connect | /scan | /exit${C.reset}
93
+ ${C.reset}The Multi Platform AI ${C.green}[MCP Hub & Tool Engine]${C.reset}
94
+ ${C.gray}/config | /models | /skill | /mcp | /new-mcp | /scan | /exit${C.reset}
95
95
  ${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
96
96
  `);
97
97
  }
98
98
 
99
- // Helper untuk membaca isi file skill/MCP secara otomatis
100
99
  function readResourceContent(targetPath) {
101
100
  if (!fs.existsSync(targetPath)) return "[Resource file/directory not found on local system]";
102
101
 
@@ -108,7 +107,6 @@ function readResourceContent(targetPath) {
108
107
  return `[Error reading file: ${e.message}]`;
109
108
  }
110
109
  } else if (stat.isDirectory()) {
111
- // Cari file instruksi utama seperti SKILL.md, README.md, index.js, prompt.txt
112
110
  const candidateFiles = ['SKILL.md', 'skill.md', 'PROMPT.md', 'README.md', 'index.js', 'index.ts', 'main.py'];
113
111
  for (const file of candidateFiles) {
114
112
  const full = path.join(targetPath, file);
@@ -119,7 +117,6 @@ function readResourceContent(targetPath) {
119
117
  }
120
118
  }
121
119
 
122
- // Jika tidak ada file markdown/skrip khusus, baca beberapa file pertama
123
120
  try {
124
121
  const files = fs.readdirSync(targetPath);
125
122
  let combinedText = `Directory Contents for ${path.basename(targetPath)}:\n`;
@@ -137,11 +134,18 @@ function readResourceContent(targetPath) {
137
134
  return "[Unknown resource format]";
138
135
  }
139
136
 
140
- // System Context Builder dengan ISOLASI KETAT
141
137
  function getActiveToolsContext(forcedTool = null) {
142
- // 1. Jika User Memanggil Tool Khusus (Misal: /skill-remotion-video)
143
138
  if (forcedTool) {
144
- const rawContent = readResourceContent(forcedTool.target);
139
+ let rawContent = "";
140
+ if (forcedTool.type === 'mcp') {
141
+ rawContent = `MCP Server Info:
142
+ Name: ${forcedTool.name}
143
+ Target/Endpoint: ${forcedTool.target}
144
+ Type: ${forcedTool.mcpType || 'HTTP/SSE'}
145
+ Auth Token: ${forcedTool.authToken ? 'Provided' : 'None'}`;
146
+ } else {
147
+ rawContent = readResourceContent(forcedTool.target);
148
+ }
145
149
 
146
150
  return `\n\n[STRICT TOOL EXECUTION SYSTEM DIRECTIVE]
147
151
  YOU ARE NOW STRICTLY ACTING AS THE FOLLOWING ${forcedTool.type.toUpperCase()} TOOL: "${forcedTool.name}".
@@ -154,17 +158,16 @@ ${rawContent}
154
158
  Executing User Prompt under this tool context only:\n`;
155
159
  }
156
160
 
157
- // 2. Jika Chat Biasa (Tanpa Slash Specific Tool), tampilkan ringkasan umum
158
161
  let contextParts = [];
159
162
  const activeSkills = Object.keys(registry.skills || {});
160
163
  if (activeSkills.length > 0) {
161
- contextParts.push("AVAILABLE SKILLS (Use /skill-<name> to invoke directly):");
164
+ contextParts.push("AVAILABLE SKILLS:");
162
165
  activeSkills.forEach(name => contextParts.push(`- /skill-${name}`));
163
166
  }
164
167
 
165
168
  const activeMCP = Object.keys(registry.mcp || {});
166
169
  if (activeMCP.length > 0) {
167
- contextParts.push("AVAILABLE MCP SERVERS (Use /mcp-<name> to invoke directly):");
170
+ contextParts.push("AVAILABLE MCP SERVERS:");
168
171
  activeMCP.forEach(name => contextParts.push(`- /mcp-${name}`));
169
172
  }
170
173
 
@@ -172,59 +175,113 @@ Executing User Prompt under this tool context only:\n`;
172
175
  return "\n\n[SYSTEM ENVIRONMENT SUMMARY]\n" + contextParts.join("\n") + "\n";
173
176
  }
174
177
 
175
- function listSkills() {
176
- console.log(`\n${C.cyan}=== Registered Skills ===${C.reset}`);
177
- const keys = Object.keys(registry.skills || {});
178
-
178
+ // RUANGAN KHUSUS MCP CENTER
179
+ function showMCPHub() {
180
+ console.log(`\n${C.c4}============================================================${C.reset}`);
181
+ console.log(`${C.c4} 🔌 MCP (MODEL CONTEXT PROTOCOL) CENTER ${C.reset}`);
182
+ console.log(`${C.c4}============================================================${C.reset}\n`);
183
+
184
+ const keys = Object.keys(registry.mcp || {});
185
+
179
186
  if (keys.length === 0) {
180
- console.log(`${C.gray}Belum ada skill terhubung. Ketik ${C.yellow}/scan${C.gray} atau ${C.yellow}/connect skill <path>${C.reset}\n`);
181
- return;
187
+ console.log(`${C.yellow} [!] Belum ada MCP Server yang terhubung saat ini.${C.reset}`);
188
+ console.log(`${C.gray} Gunakan perintah ${C.green}/new-mcp${C.gray} untuk mendaftarkan MCP baru.${C.reset}\n`);
189
+ } else {
190
+ console.log(`${C.bold}Daftar MCP Server Aktif:${C.reset}`);
191
+ keys.forEach((name, i) => {
192
+ const m = registry.mcp[name];
193
+ const typeBadge = m.type === 'remote' ? `${C.cyan}[Remote SSE/HTTP]${C.reset}` : `${C.green}[Local Stdio]${C.reset}`;
194
+ console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.bold}${name}${C.reset} ${typeBadge}`);
195
+ console.log(` ↳ Target: ${C.gray}${m.target}${C.reset}`);
196
+ if (m.authToken) console.log(` ↳ Auth : ${C.green}Encrypted/Token set${C.reset}`);
197
+ });
198
+ console.log('');
182
199
  }
183
200
 
184
- keys.forEach((name, i) => {
185
- const item = registry.skills[name];
186
- console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.green}${name}${C.reset} -> ${C.gray}${item.path}${C.reset}`);
187
- });
188
- console.log('');
189
-
190
201
  const lines = [
191
- `${C.bold}Perintah Instan (Fokus 100% Khusus Tool Tersebut):${C.reset}`,
192
- ``
202
+ `${C.bold}Command Instan MCP:${C.reset}`,
203
+ `${C.yellow}/new-mcp${C.reset} 👉 Tambah MCP Server Baru (Wizard)`,
204
+ `${C.yellow}/mcp-<nama>${C.reset} <prompt> 👉 Eksekusi MCP secara spesifik`,
205
+ `${C.yellow}/scan${C.reset} 👉 Pindai folder .mcp otomatis`
193
206
  ];
194
207
 
195
- keys.forEach(name => {
196
- lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt kamu>`);
197
- });
198
-
199
- drawBox("⚡ COMMAND INSTAN SKILL TERSEDIA", lines, C.c1);
208
+ drawBox("💡 PETUNJUK RUANG MCP", lines, C.c4);
200
209
  console.log('');
201
210
  }
202
211
 
203
- function listMCP() {
204
- console.log(`\n${C.cyan}=== Registered MCP Servers ===${C.reset}`);
205
- const keys = Object.keys(registry.mcp || {});
212
+ // WIZARD KONFIGURASI MCP BARU (/new-mcp)
213
+ function createNewMCPWizard(callback) {
214
+ console.log(`\n${C.cyan}=== 🛠️ SETUP MCP (MODEL CONTEXT PROTOCOL) BARU ===${C.reset}\n`);
206
215
 
216
+ rl.question(`${C.yellow}[1/4] Masukkan Nama MCP Server (misal: stitch, github, filesystem):${C.reset} `, (nameInput) => {
217
+ const mcpName = nameInput.trim().toLowerCase().replace(/\s+/g, '-');
218
+ if (!mcpName) {
219
+ console.log(`${C.red}[x] Nama MCP tidak boleh kosong.${C.reset}\n`);
220
+ return callback();
221
+ }
222
+
223
+ console.log(`\n${C.cyan}Pilih Tipe Koneksi MCP:${C.reset}`);
224
+ console.log(` ${C.yellow}1.${C.reset} Remote URL / SSE Endpoint (misal: https://mcp.example.com/sse)`);
225
+ console.log(` ${C.yellow}2.${C.reset} Local Command / File Path (misal: npx -y @modelcontextprotocol/server-filesystem)`);
226
+
227
+ rl.question(`\n${C.yellow}[2/4] Pilih Tipe (1/2):${C.reset} `, (typeChoice) => {
228
+ const isRemote = typeChoice.trim() === '1';
229
+
230
+ rl.question(`${C.yellow}[3/4] Masukkan Target URL / Command Path:${C.reset} `, (targetInput) => {
231
+ const target = targetInput.trim();
232
+ if (!target) {
233
+ console.log(`${C.red}[x] Target tidak boleh kosong.${C.reset}\n`);
234
+ return callback();
235
+ }
236
+
237
+ rl.question(`${C.yellow}[4/4] Masukkan Auth Token / API Key (Tekan Enter jika tidak ada):${C.reset} `, (tokenInput) => {
238
+ const authToken = tokenInput.trim();
239
+
240
+ registry.mcp = registry.mcp || {};
241
+ registry.mcp[mcpName] = {
242
+ target: target,
243
+ type: isRemote ? 'remote' : 'local',
244
+ authToken: authToken || null,
245
+ connectedAt: new Date().toISOString(),
246
+ status: 'Connected'
247
+ };
248
+
249
+ saveRegistry(registry);
250
+
251
+ console.log(`\n${C.green}[✔] MCP Server "${mcpName}" berhasil ditambahkan!${C.reset}`);
252
+ console.log(`${C.gray}Gunakan perintah instan: ${C.yellow}/mcp-${mcpName} <prompt kamu>${C.reset}\n`);
253
+ callback();
254
+ });
255
+ });
256
+ });
257
+ });
258
+ }
259
+
260
+ function listSkills() {
261
+ console.log(`\n${C.cyan}=== Registered Skills ===${C.reset}`);
262
+ const keys = Object.keys(registry.skills || {});
263
+
207
264
  if (keys.length === 0) {
208
- console.log(`${C.gray}Belum ada MCP server terhubung. Ketik ${C.yellow}/scan${C.gray} atau ${C.yellow}/connect mcp <target>${C.reset}\n`);
265
+ console.log(`${C.gray}Belum ada skill terhubung. Ketik ${C.yellow}/scan${C.gray} atau ${C.yellow}/connect skill <path>${C.reset}\n`);
209
266
  return;
210
267
  }
211
268
 
212
269
  keys.forEach((name, i) => {
213
- const item = registry.mcp[name];
214
- console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.green}${name}${C.reset} -> ${C.gray}${item.target}${C.reset} [${item.type}]`);
270
+ const item = registry.skills[name];
271
+ console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.green}${name}${C.reset} -> ${C.gray}${item.path}${C.reset}`);
215
272
  });
216
273
  console.log('');
217
274
 
218
275
  const lines = [
219
- `${C.bold}Perintah Instan MCP (Fokus Khusus Tool MCP):${C.reset}`,
276
+ `${C.bold}Perintah Instan Skill:${C.reset}`,
220
277
  ``
221
278
  ];
222
279
 
223
280
  keys.forEach(name => {
224
- lines.push(` ${C.yellow}/mcp-${name}${C.reset} <prompt kamu>`);
281
+ lines.push(` ${C.yellow}/skill-${name}${C.reset} <prompt kamu>`);
225
282
  });
226
283
 
227
- drawBox("🔌 COMMAND INSTAN MCP TERSEDIA", lines, C.c4);
284
+ drawBox(" COMMAND INSTAN SKILL TERSEDIA", lines, C.c1);
228
285
  console.log('');
229
286
  }
230
287
 
@@ -589,8 +646,10 @@ function startPrompt() {
589
646
  listSkills();
590
647
  startPrompt();
591
648
  } else if (cmd === '/mcp') {
592
- listMCP();
649
+ showMCPHub();
593
650
  startPrompt();
651
+ } else if (cmd === '/new-mcp') {
652
+ createNewMCPWizard(() => startPrompt());
594
653
  } else if (cmd.startsWith('/connect')) {
595
654
  connectResource(cmd.replace('/connect', ''));
596
655
  startPrompt();
@@ -628,7 +687,13 @@ function startPrompt() {
628
687
  }
629
688
 
630
689
  if (registry.mcp && registry.mcp[mcpName]) {
631
- handleChat(userPrompt, { type: 'mcp', name: mcpName, target: registry.mcp[mcpName].target });
690
+ handleChat(userPrompt, {
691
+ type: 'mcp',
692
+ name: mcpName,
693
+ target: registry.mcp[mcpName].target,
694
+ mcpType: registry.mcp[mcpName].type,
695
+ authToken: registry.mcp[mcpName].authToken
696
+ });
632
697
  } else {
633
698
  console.log(`${C.red}[x] MCP "${mcpName}" tidak ditemukan di registry. Ketik /mcp untuk melihat daftar.${C.reset}\n`);
634
699
  startPrompt();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tmpa-cli",
3
- "version": "1.0.17",
3
+ "version": "1.0.18",
4
4
  "description": "",
5
5
  "main": "bin/index.js",
6
6
  "bin": {
@@ -14,8 +14,12 @@
14
14
  "author": "",
15
15
  "license": "ISC",
16
16
  "dependencies": {
17
+ "@remotion/cli": "^4.0.506",
17
18
  "chalk": "^4.1.2",
18
19
  "commander": "^11.0.0",
19
- "ora": "^5.4.1"
20
+ "ora": "^5.4.1",
21
+ "react": "^19.2.8",
22
+ "react-dom": "^19.2.8",
23
+ "remotion": "^4.0.506"
20
24
  }
21
25
  }