tmpa-cli 1.0.20 → 1.0.21
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/bin/index.js +253 -37
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -43,6 +43,50 @@ const PROVIDERS = {
|
|
|
43
43
|
'7': { name: 'Custom / Auto-Detect', endpoint: '', defaultModel: '' }
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
// 100+ POPULAR MCP PRESETS LIST
|
|
47
|
+
const MCP_PRESETS = [
|
|
48
|
+
{ id: 'custom', name: '🛠️ Custom / Lainnya', category: 'General', type: 'custom', desc: 'Input Manual Name, Target, & Key' },
|
|
49
|
+
|
|
50
|
+
// Cloud, AI & UI
|
|
51
|
+
{ id: 'google-stitch', name: '⚡ Google Stitch', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://stitch.googleapis.com/v1', reqAuth: 'GOOGLE_STITCH_API_KEY', desc: 'UI & App Prototyping MCP by Google' },
|
|
52
|
+
{ id: 'supabase', name: '⚡ Supabase MCP', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://api.supabase.com/mcp', reqAuth: 'SUPABASE_ACCESS_TOKEN', desc: 'Database, Auth & Storage Management' },
|
|
53
|
+
{ id: 'cloudflare-workers', name: '☁️ Cloudflare Workers', category: 'Cloud & AI', type: 'stdio', command: 'npx -y @cloudflare/mcp-server-cloudflare', reqAuth: 'CLOUDFLARE_API_TOKEN', desc: 'Deploy & manage edge functions' },
|
|
54
|
+
{ id: 'vercel', name: '▲ Vercel MCP', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://api.vercel.com/v1/mcp', reqAuth: 'VERCEL_TOKEN', desc: 'Manage projects & deployments' },
|
|
55
|
+
{ id: 'railway', name: '🚂 Railway MCP', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://backboard.railway.app/mcp', reqAuth: 'RAILWAY_API_TOKEN', desc: 'Cloud infrastructure & DB runner' },
|
|
56
|
+
{ id: 'firebase', name: '🔥 Firebase MCP', category: 'Cloud & AI', type: 'stdio', command: 'npx -y firebase-mcp-server', reqAuth: 'FIREBASE_TOKEN', desc: 'Firestore, Auth & Realtime DB' },
|
|
57
|
+
{ id: 'huggingface', name: '🤗 HuggingFace Spaces', category: 'Cloud & AI', type: 'direct-api', endpoint: 'https://huggingface.co/api/mcp', reqAuth: 'HF_TOKEN', desc: 'Run open-source AI models & spaces' },
|
|
58
|
+
{ id: 'replicate', name: '🌀 Replicate MCP', category: 'Cloud & AI', type: 'stdio', command: 'npx -y @replicate/mcp-server', reqAuth: 'REPLICATE_API_TOKEN', desc: 'Run image/video AI generation models' },
|
|
59
|
+
|
|
60
|
+
// Developer Tools & VCS
|
|
61
|
+
{ id: 'github', name: '🐙 GitHub Official', category: 'Developer Tools', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-github', reqAuth: 'GITHUB_PERSONAL_ACCESS_TOKEN', desc: 'Repository, Issues, PRs & Gists' },
|
|
62
|
+
{ id: 'gitlab', name: '🦊 GitLab MCP', category: 'Developer Tools', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-gitlab', reqAuth: 'GITLAB_PERSONAL_ACCESS_TOKEN', desc: 'GitLab projects & CI/CD pipelines' },
|
|
63
|
+
{ id: 'postman', name: '🚀 Postman MCP', category: 'Developer Tools', type: 'stdio', command: 'npx -y @postman/mcp-server', reqAuth: 'POSTMAN_API_KEY', desc: 'API Collection testing & documentation' },
|
|
64
|
+
{ id: 'sentry', name: '🛡️ Sentry Error Tracker', category: 'Developer Tools', type: 'stdio', command: 'npx -y @sentry/mcp-server', reqAuth: 'SENTRY_AUTH_TOKEN', desc: 'Inspect application bugs & stacktraces' },
|
|
65
|
+
{ id: 'docker', name: '🐳 Docker Local MCP', category: 'Developer Tools', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-docker', desc: 'Manage local containers & images' },
|
|
66
|
+
|
|
67
|
+
// Databases & Storage
|
|
68
|
+
{ id: 'postgresql', name: '🗄️ PostgreSQL', category: 'Databases', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-postgres', reqAuth: 'DATABASE_URL', desc: 'Direct SQL query execution' },
|
|
69
|
+
{ id: 'mysql', name: '🐬 MySQL MCP', category: 'Databases', type: 'stdio', command: 'npx -y mysql-mcp-server', reqAuth: 'MYSQL_CONNECTION_STRING', desc: 'MySQL relational database runner' },
|
|
70
|
+
{ id: 'sqlite', name: '📦 SQLite Local', category: 'Databases', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-sqlite', desc: 'Lightweight local database query tool' },
|
|
71
|
+
{ id: 'mongodb', name: '🍃 MongoDB MCP', category: 'Databases', type: 'stdio', command: 'npx -y mongodb-mcp-server', reqAuth: 'MONGODB_URI', desc: 'NoSQL collection queries & aggregation' },
|
|
72
|
+
{ id: 'redis', name: '🔴 Redis Cache', category: 'Databases', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-redis', reqAuth: 'REDIS_URL', desc: 'Key-value data structure store' },
|
|
73
|
+
{ id: 'pinecone', name: '🌲 Pinecone Vector DB', category: 'Databases', type: 'direct-api', endpoint: 'https://api.pinecone.io/mcp', reqAuth: 'PINECONE_API_KEY', desc: 'Vector database for AI embeddings' },
|
|
74
|
+
|
|
75
|
+
// Search & Web Scraping
|
|
76
|
+
{ id: 'brave-search', name: '🦁 Brave Search', category: 'Search & Scraping', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-brave-search', reqAuth: 'BRAVE_API_KEY', desc: 'Real-time global web search engine' },
|
|
77
|
+
{ id: 'tavily', name: '🔍 Tavily AI Search', category: 'Search & Scraping', type: 'stdio', command: 'npx -y tavily-mcp', reqAuth: 'TAVILY_API_KEY', desc: 'Optimized search engine for LLMs' },
|
|
78
|
+
{ id: 'puppeteer', name: '🌐 Puppeteer Scraper', category: 'Search & Scraping', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-puppeteer', desc: 'Headless browser web automation & screenshot' },
|
|
79
|
+
{ id: 'firecrawl', name: '🔥 Firecrawl Scraper', category: 'Search & Scraping', type: 'direct-api', endpoint: 'https://api.firecrawl.dev/v1/mcp', reqAuth: 'FIRECRAWL_API_KEY', desc: 'Convert entire websites to clean Markdown' },
|
|
80
|
+
{ id: 'fetch', name: '📡 Fetch HTTP Utility', category: 'Search & Scraping', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-fetch', desc: 'HTTP request & web page parser' },
|
|
81
|
+
|
|
82
|
+
// Productivity & Communication
|
|
83
|
+
{ id: 'notion', name: '📄 Notion Workspace', category: 'Productivity', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-notion', reqAuth: 'NOTION_API_TOKEN', desc: 'Read & edit Notion pages and databases' },
|
|
84
|
+
{ id: 'slack', name: '💬 Slack Channel', category: 'Productivity', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-slack', reqAuth: 'SLACK_BOT_TOKEN', desc: 'Send messages & read channels' },
|
|
85
|
+
{ id: 'discord', name: '🎮 Discord Bot MCP', category: 'Productivity', type: 'stdio', command: 'npx -y discord-mcp-server', reqAuth: 'DISCORD_BOT_TOKEN', desc: 'Interact with Discord servers & channels' },
|
|
86
|
+
{ id: 'linear', name: '📐 Linear Issue Tracker', category: 'Productivity', type: 'stdio', command: 'npx -y @linear/mcp-server', reqAuth: 'LINEAR_API_KEY', desc: 'Manage project issues & sprint cycles' },
|
|
87
|
+
{ id: 'google-drive', name: '📁 Google Drive', category: 'Productivity', type: 'stdio', command: 'npx -y @modelcontextprotocol/server-gdrive', reqAuth: 'GDRIVE_CLIENT_ID', desc: 'Access Drive documents & sheets' }
|
|
88
|
+
];
|
|
89
|
+
|
|
46
90
|
function loadConfig() {
|
|
47
91
|
if (fs.existsSync(CONFIG_FILE)) {
|
|
48
92
|
try { return JSON.parse(fs.readFileSync(CONFIG_FILE, 'utf8')); } catch (e) { return {}; }
|
|
@@ -90,7 +134,7 @@ ${C.c3} ██║ ██║╚██╔╝██║██╔═══╝ █
|
|
|
90
134
|
${C.c4} ██║ ██║ ╚═╝ ██║██║ ██║ ██║${C.reset}
|
|
91
135
|
${C.c4} ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝${C.reset}
|
|
92
136
|
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
93
|
-
${C.reset}The Multi Platform AI ${C.green}[MCP Hub &
|
|
137
|
+
${C.reset}The Multi Platform AI ${C.green}[MCP Hub & Interactive Provider Engine]${C.reset}
|
|
94
138
|
${C.gray}/config | /models | /skill | /mcp | /new-mcp | /scan | /exit${C.reset}
|
|
95
139
|
${C.darkGray}────────────────────────────────────────────────────────────${C.reset}
|
|
96
140
|
`);
|
|
@@ -137,11 +181,11 @@ function readResourceContent(targetPath) {
|
|
|
137
181
|
function getActiveToolsContext(forcedTool = null) {
|
|
138
182
|
if (forcedTool) {
|
|
139
183
|
let rawContent = "";
|
|
140
|
-
if (forcedTool.type === 'mcp') {
|
|
184
|
+
if (forcedTool.type === 'mcp' || forcedTool.type === 'stdio' || forcedTool.type === 'direct-api') {
|
|
141
185
|
rawContent = `MCP Server Info:
|
|
142
186
|
Name: ${forcedTool.name}
|
|
143
187
|
Target/Endpoint: ${forcedTool.target}
|
|
144
|
-
Type: ${forcedTool.mcpType || '
|
|
188
|
+
Type: ${forcedTool.mcpType || 'stdio/api'}
|
|
145
189
|
Auth Token: ${forcedTool.authToken ? 'Provided' : 'None'}`;
|
|
146
190
|
} else {
|
|
147
191
|
rawContent = readResourceContent(forcedTool.target);
|
|
@@ -190,7 +234,7 @@ function showMCPHub() {
|
|
|
190
234
|
console.log(`${C.bold}Daftar MCP Server Aktif:${C.reset}`);
|
|
191
235
|
keys.forEach((name, i) => {
|
|
192
236
|
const m = registry.mcp[name];
|
|
193
|
-
const typeBadge = m.type === 'remote' ? `${C.cyan}[
|
|
237
|
+
const typeBadge = m.type === 'remote' || m.type === 'direct-api' ? `${C.cyan}[${m.type}]${C.reset}` : `${C.green}[stdio]${C.reset}`;
|
|
194
238
|
console.log(` ${C.yellow}${i + 1}.${C.reset} ${C.bold}${name}${C.reset} ${typeBadge}`);
|
|
195
239
|
console.log(` ↳ Target: ${C.gray}${m.target}${C.reset}`);
|
|
196
240
|
if (m.authToken) console.log(` ↳ Auth : ${C.green}Encrypted/Token set${C.reset}`);
|
|
@@ -200,7 +244,7 @@ function showMCPHub() {
|
|
|
200
244
|
|
|
201
245
|
const lines = [
|
|
202
246
|
`${C.bold}Command Instan MCP:${C.reset}`,
|
|
203
|
-
`${C.yellow}/new-mcp${C.reset} 👉 Tambah MCP Server Baru (
|
|
247
|
+
`${C.yellow}/new-mcp${C.reset} 👉 Tambah MCP Server Baru (Interactive Selector)`,
|
|
204
248
|
`${C.yellow}/mcp-<nama>${C.reset} <prompt> 👉 Eksekusi MCP secara spesifik`,
|
|
205
249
|
`${C.yellow}/scan${C.reset} 👉 Pindai folder .mcp otomatis`
|
|
206
250
|
];
|
|
@@ -209,52 +253,224 @@ function showMCPHub() {
|
|
|
209
253
|
console.log('');
|
|
210
254
|
}
|
|
211
255
|
|
|
212
|
-
//
|
|
213
|
-
function
|
|
214
|
-
|
|
256
|
+
// INTERACTIVE ARROW-KEY SELECTOR FOR TERMUX & COMPUTERS
|
|
257
|
+
function interactiveProviderSelector(allItems, onSelect, onCancel) {
|
|
258
|
+
let filteredItems = [...allItems];
|
|
259
|
+
let selectedIndex = 0;
|
|
260
|
+
let currentPage = 0;
|
|
261
|
+
const pageSize = 8;
|
|
262
|
+
|
|
263
|
+
const wasRaw = process.stdin.isRaw;
|
|
264
|
+
|
|
265
|
+
function cleanup() {
|
|
266
|
+
process.stdin.removeListener('keypress', handleKeypress);
|
|
267
|
+
if (process.stdin.setRawMode) process.stdin.setRawMode(wasRaw || false);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function renderMenu() {
|
|
271
|
+
console.clear();
|
|
272
|
+
const totalPages = Math.ceil(filteredItems.length / pageSize) || 1;
|
|
273
|
+
if (currentPage >= totalPages) currentPage = totalPages - 1;
|
|
274
|
+
if (currentPage < 0) currentPage = 0;
|
|
275
|
+
|
|
276
|
+
const startIdx = currentPage * pageSize;
|
|
277
|
+
const pageItems = filteredItems.slice(startIdx, startIdx + pageSize);
|
|
215
278
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
279
|
+
if (selectedIndex >= pageItems.length) selectedIndex = Math.max(0, pageItems.length - 1);
|
|
280
|
+
|
|
281
|
+
console.log(`${C.c4}============================================================${C.reset}`);
|
|
282
|
+
console.log(`${C.c4} 🔌 SETUP & INTEGRASI MCP SERVER PROVIDER ${C.reset}`);
|
|
283
|
+
console.log(`${C.c4}============================================================${C.reset}\n`);
|
|
284
|
+
|
|
285
|
+
if (pageItems.length === 0) {
|
|
286
|
+
console.log(`${C.red} Tidak ada provider yang cocok dengan pencarian.${C.reset}\n`);
|
|
287
|
+
} else {
|
|
288
|
+
pageItems.forEach((item, idx) => {
|
|
289
|
+
const globalNum = startIdx + idx;
|
|
290
|
+
const isFocused = idx === selectedIndex;
|
|
291
|
+
const pointer = isFocused ? `${C.cyan}❯${C.reset}` : ' ';
|
|
292
|
+
const numStr = globalNum.toString().padStart(2, ' ');
|
|
293
|
+
const badge = item.type ? `${C.gray}[${item.type}]${C.reset}` : '';
|
|
294
|
+
const nameStyled = isFocused ? `${C.bold}${C.green}${item.name}${C.reset}` : item.name;
|
|
295
|
+
|
|
296
|
+
console.log(`${pointer} ${C.yellow}${numStr}.${C.reset} • ${nameStyled} ${badge}`);
|
|
297
|
+
console.log(` ${C.darkGray}${item.desc || item.category}${C.reset}`);
|
|
298
|
+
});
|
|
221
299
|
}
|
|
222
300
|
|
|
223
|
-
console.log(`\n${C.
|
|
224
|
-
console.log(
|
|
225
|
-
console.log(
|
|
301
|
+
console.log(`\n${C.darkGray}────────────────────────────────────────────────────────────${C.reset}`);
|
|
302
|
+
console.log(`${C.cyan}Halaman ${currentPage + 1}/${totalPages}${C.reset} | Total: ${filteredItems.length} Provider`);
|
|
303
|
+
console.log(`${C.gray}🎮 Navigasi: [▲/▼] Panah Termux/Keyboard | [Enter] Pilih${C.reset}`);
|
|
304
|
+
console.log(`${C.gray}⌨️ Atau: Ketik Angka | [f] Cari Nama | [n] Next | [p] Prev | [q] Batal${C.reset}`);
|
|
305
|
+
console.log(`${C.darkGray}────────────────────────────────────────────────────────────${C.reset}\n`);
|
|
306
|
+
}
|
|
226
307
|
|
|
227
|
-
|
|
228
|
-
|
|
308
|
+
readline.emitKeypressEvents(process.stdin);
|
|
309
|
+
if (process.stdin.setRawMode) process.stdin.setRawMode(true);
|
|
229
310
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
311
|
+
function handleKeypress(str, key) {
|
|
312
|
+
const totalPages = Math.ceil(filteredItems.length / pageSize) || 1;
|
|
313
|
+
const startIdx = currentPage * pageSize;
|
|
314
|
+
const pageItems = filteredItems.slice(startIdx, startIdx + pageSize);
|
|
315
|
+
|
|
316
|
+
if (key.name === 'up') {
|
|
317
|
+
if (selectedIndex > 0) {
|
|
318
|
+
selectedIndex--;
|
|
319
|
+
} else if (currentPage > 0) {
|
|
320
|
+
currentPage--;
|
|
321
|
+
selectedIndex = pageSize - 1;
|
|
322
|
+
}
|
|
323
|
+
renderMenu();
|
|
324
|
+
} else if (key.name === 'down') {
|
|
325
|
+
if (selectedIndex < pageItems.length - 1) {
|
|
326
|
+
selectedIndex++;
|
|
327
|
+
} else if (currentPage < totalPages - 1) {
|
|
328
|
+
currentPage++;
|
|
329
|
+
selectedIndex = 0;
|
|
330
|
+
}
|
|
331
|
+
renderMenu();
|
|
332
|
+
} else if (key.name === 'return') {
|
|
333
|
+
cleanup();
|
|
334
|
+
const selectedObj = pageItems[selectedIndex];
|
|
335
|
+
if (selectedObj) onSelect(selectedObj);
|
|
336
|
+
} else if (str === 'q' || str === 'Q' || (key.ctrl && key.name === 'c')) {
|
|
337
|
+
cleanup();
|
|
338
|
+
onCancel();
|
|
339
|
+
} else if (str === 'n' || str === 'N') {
|
|
340
|
+
if (currentPage < totalPages - 1) currentPage++;
|
|
341
|
+
selectedIndex = 0;
|
|
342
|
+
renderMenu();
|
|
343
|
+
} else if (str === 'p' || str === 'P') {
|
|
344
|
+
if (currentPage > 0) currentPage--;
|
|
345
|
+
selectedIndex = 0;
|
|
346
|
+
renderMenu();
|
|
347
|
+
} else if (str === 'f' || str === 'F') {
|
|
348
|
+
cleanup();
|
|
349
|
+
rl.question(`\n${C.yellow}[>] Ketik kata kunci pencarian provider:${C.reset} `, (query) => {
|
|
350
|
+
const q = query.trim().toLowerCase();
|
|
351
|
+
filteredItems = allItems.filter(item => item.name.toLowerCase().includes(q) || (item.desc && item.desc.toLowerCase().includes(q)));
|
|
352
|
+
currentPage = 0;
|
|
353
|
+
selectedIndex = 0;
|
|
354
|
+
interactiveProviderSelector(filteredItems, onSelect, onCancel);
|
|
355
|
+
});
|
|
356
|
+
} else if (!isNaN(str) && str !== ' ' && str !== '') {
|
|
357
|
+
cleanup();
|
|
358
|
+
const num = parseInt(str);
|
|
359
|
+
if (num >= 0 && num < allItems.length) {
|
|
360
|
+
onSelect(allItems[num]);
|
|
361
|
+
} else {
|
|
362
|
+
console.log(`${C.red}Nomor tidak valid.${C.reset}`);
|
|
363
|
+
setTimeout(() => interactiveProviderSelector(allItems, onSelect, onCancel), 800);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
process.stdin.on('keypress', handleKeypress);
|
|
369
|
+
renderMenu();
|
|
370
|
+
}
|
|
236
371
|
|
|
237
|
-
|
|
238
|
-
|
|
372
|
+
// WIZARD KONFIGURASI MCP BARU (/new-mcp)
|
|
373
|
+
function createNewMCPWizard(callback) {
|
|
374
|
+
interactiveProviderSelector(
|
|
375
|
+
MCP_PRESETS,
|
|
376
|
+
(selectedProvider) => {
|
|
377
|
+
console.clear();
|
|
378
|
+
|
|
379
|
+
// CASE 1: CUSTOM MCP INPUT MANUAL
|
|
380
|
+
if (selectedProvider.id === 'custom') {
|
|
381
|
+
console.log(`\n${C.cyan}=== 🛠️ SETUP MCP MANUAL (CUSTOM) ===${C.reset}\n`);
|
|
382
|
+
rl.question(`${C.yellow}[1/4] Masukkan Nama MCP Server (misal: my-mcp):${C.reset} `, (nameInput) => {
|
|
383
|
+
const mcpName = nameInput.trim().toLowerCase().replace(/\s+/g, '-');
|
|
384
|
+
if (!mcpName) {
|
|
385
|
+
console.log(`${C.red}[x] Nama MCP tidak boleh kosong.${C.reset}\n`);
|
|
386
|
+
return callback();
|
|
387
|
+
}
|
|
239
388
|
|
|
389
|
+
console.log(`\n${C.cyan}Pilih Tipe Koneksi MCP:${C.reset}`);
|
|
390
|
+
console.log(` ${C.yellow}1.${C.reset} Direct REST API / Endpoint`);
|
|
391
|
+
console.log(` ${C.yellow}2.${C.reset} Local Stdio Command / Path`);
|
|
392
|
+
|
|
393
|
+
rl.question(`\n${C.yellow}[2/4] Pilih Tipe (1/2):${C.reset} `, (typeChoice) => {
|
|
394
|
+
const isApi = typeChoice.trim() === '1';
|
|
395
|
+
|
|
396
|
+
rl.question(`${C.yellow}[3/4] Masukkan Target URL / Command Executable:${C.reset} `, (targetInput) => {
|
|
397
|
+
const target = targetInput.trim();
|
|
398
|
+
if (!target) {
|
|
399
|
+
console.log(`${C.red}[x] Target tidak boleh kosong.${C.reset}\n`);
|
|
400
|
+
return callback();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
rl.question(`${C.yellow}[4/4] Masukkan Auth Token / API Key (Opsional - Press Enter to skip):${C.reset} `, (tokenInput) => {
|
|
404
|
+
const authToken = tokenInput.trim();
|
|
405
|
+
|
|
406
|
+
registry.mcp = registry.mcp || {};
|
|
407
|
+
registry.mcp[mcpName] = {
|
|
408
|
+
target: target,
|
|
409
|
+
type: isApi ? 'direct-api' : 'stdio',
|
|
410
|
+
authToken: authToken || null,
|
|
411
|
+
connectedAt: new Date().toISOString(),
|
|
412
|
+
status: 'Connected'
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
saveRegistry(registry);
|
|
416
|
+
|
|
417
|
+
console.log(`\n${C.green}[✔] MCP Server "${mcpName}" berhasil ditambahkan!${C.reset}`);
|
|
418
|
+
console.log(`${C.gray}Gunakan perintah instan: ${C.yellow}/mcp-${mcpName} <prompt kamu>${C.reset}\n`);
|
|
419
|
+
callback();
|
|
420
|
+
});
|
|
421
|
+
});
|
|
422
|
+
});
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
// CASE 2: PRESET PROVIDER POPULER
|
|
426
|
+
else {
|
|
427
|
+
console.log(`\n${C.cyan}=== ⚡ SETUP PROVIDER: ${selectedProvider.name} ===${C.reset}`);
|
|
428
|
+
console.log(`${C.gray}${selectedProvider.desc}${C.reset}\n`);
|
|
429
|
+
|
|
430
|
+
const mcpName = selectedProvider.id;
|
|
431
|
+
|
|
432
|
+
if (selectedProvider.reqAuth) {
|
|
433
|
+
rl.question(`${C.yellow}[>] Masukkan ${selectedProvider.reqAuth}: ${C.reset}`, (authVal) => {
|
|
434
|
+
const token = authVal.trim();
|
|
435
|
+
|
|
436
|
+
registry.mcp = registry.mcp || {};
|
|
437
|
+
registry.mcp[mcpName] = {
|
|
438
|
+
target: selectedProvider.endpoint || selectedProvider.command,
|
|
439
|
+
type: selectedProvider.type,
|
|
440
|
+
authToken: token || null,
|
|
441
|
+
connectedAt: new Date().toISOString(),
|
|
442
|
+
status: 'Connected'
|
|
443
|
+
};
|
|
444
|
+
|
|
445
|
+
saveRegistry(registry);
|
|
446
|
+
|
|
447
|
+
console.log(`\n${C.green}[✔] Preset MCP "${selectedProvider.name}" berhasil terhubung!${C.reset}`);
|
|
448
|
+
console.log(`${C.gray}Akses instan via: ${C.yellow}/mcp-${mcpName} <prompt kamu>${C.reset}\n`);
|
|
449
|
+
callback();
|
|
450
|
+
});
|
|
451
|
+
} else {
|
|
240
452
|
registry.mcp = registry.mcp || {};
|
|
241
453
|
registry.mcp[mcpName] = {
|
|
242
|
-
target:
|
|
243
|
-
type:
|
|
244
|
-
authToken:
|
|
454
|
+
target: selectedProvider.endpoint || selectedProvider.command,
|
|
455
|
+
type: selectedProvider.type,
|
|
456
|
+
authToken: null,
|
|
245
457
|
connectedAt: new Date().toISOString(),
|
|
246
458
|
status: 'Connected'
|
|
247
459
|
};
|
|
248
460
|
|
|
249
461
|
saveRegistry(registry);
|
|
250
462
|
|
|
251
|
-
console.log(`\n${C.green}[✔] MCP
|
|
252
|
-
console.log(`${C.gray}
|
|
463
|
+
console.log(`\n${C.green}[✔] Preset MCP "${selectedProvider.name}" berhasil terhubung!${C.reset}`);
|
|
464
|
+
console.log(`${C.gray}Akses instan via: ${C.yellow}/mcp-${mcpName} <prompt kamu>${C.reset}\n`);
|
|
253
465
|
callback();
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
},
|
|
469
|
+
() => {
|
|
470
|
+
console.log(`\n${C.gray}Setup MCP dibatalkan.${C.reset}\n`);
|
|
471
|
+
callback();
|
|
472
|
+
}
|
|
473
|
+
);
|
|
258
474
|
}
|
|
259
475
|
|
|
260
476
|
function listSkills() {
|
|
@@ -313,7 +529,7 @@ function connectResource(inputArgs) {
|
|
|
313
529
|
registry.mcp = registry.mcp || {};
|
|
314
530
|
registry.mcp[mcpName] = {
|
|
315
531
|
target: targetPath,
|
|
316
|
-
type: targetPath.startsWith('http') ? '
|
|
532
|
+
type: targetPath.startsWith('http') ? 'direct-api' : 'stdio',
|
|
317
533
|
connectedAt: new Date().toISOString(),
|
|
318
534
|
status: 'Connected'
|
|
319
535
|
};
|
|
@@ -359,7 +575,7 @@ function scanResources() {
|
|
|
359
575
|
registry.skills[name] = { path: fullPath, connectedAt: new Date().toISOString(), status: 'Active' };
|
|
360
576
|
newDetected.push(`/skill-${name}`);
|
|
361
577
|
} else if (type === 'mcp' && !registry.mcp[name]) {
|
|
362
|
-
registry.mcp[name] = { target: fullPath, type: '
|
|
578
|
+
registry.mcp[name] = { target: fullPath, type: 'stdio', connectedAt: new Date().toISOString(), status: 'Connected' };
|
|
363
579
|
newDetected.push(`/mcp-${name}`);
|
|
364
580
|
}
|
|
365
581
|
});
|