@botuyo/mcp 0.1.0 → 0.2.1
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/client.d.ts +9 -14
- package/dist/client.js +34 -29
- package/dist/client.js.map +1 -1
- package/dist/commands/auth.d.ts +18 -0
- package/dist/commands/auth.js +151 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/credentials.d.ts +28 -0
- package/dist/commands/credentials.js +59 -0
- package/dist/commands/credentials.js.map +1 -0
- package/dist/commands/login.d.ts +15 -0
- package/dist/commands/login.js +202 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/setup.d.ts +8 -0
- package/dist/commands/setup.js +95 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/switch_tenant.d.ts +10 -0
- package/dist/commands/switch_tenant.js +117 -0
- package/dist/commands/switch_tenant.js.map +1 -0
- package/dist/commands/tenants.d.ts +9 -0
- package/dist/commands/tenants.js +48 -0
- package/dist/commands/tenants.js.map +1 -0
- package/dist/index.d.ts +13 -14
- package/dist/index.js +120 -57
- package/dist/index.js.map +1 -1
- package/package.json +12 -3
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @botuyo/mcp login command
|
|
4
|
+
*
|
|
5
|
+
* Usage: npx @botuyo/mcp login
|
|
6
|
+
*
|
|
7
|
+
* Flow:
|
|
8
|
+
* 1. Prompts for email and password in the terminal
|
|
9
|
+
* 2. Calls POST /api/auth/login to get a JWT
|
|
10
|
+
* 3. Calls GET /api/auth/me to get the user's tenants
|
|
11
|
+
* 4. If multiple tenants, asks the user to pick one
|
|
12
|
+
* 5. If needed, calls POST /api/auth/switch-tenant
|
|
13
|
+
* 6. Saves the credentials to ~/.botuyo/credentials.json
|
|
14
|
+
*/
|
|
15
|
+
import * as readline from 'readline';
|
|
16
|
+
import { readCredentials, saveCredentials } from './credentials.js';
|
|
17
|
+
const API_URL = process.env.BOTUYO_API_URL || 'https://api.botuyo.com';
|
|
18
|
+
export async function runLogin(args) {
|
|
19
|
+
console.log('\n🤖 BotUyo MCP — Login\n');
|
|
20
|
+
const existing = await readCredentials();
|
|
21
|
+
if (existing && !args.includes('--force')) {
|
|
22
|
+
const expired = existing.expiresAt && new Date(existing.expiresAt) < new Date();
|
|
23
|
+
if (!expired) {
|
|
24
|
+
console.log(`✅ Ya estás autenticado como: ${existing.email}`);
|
|
25
|
+
console.log(` Tenant: ${existing.tenantName} (${existing.role})`);
|
|
26
|
+
console.log('\n Usá --force para re-autenticarte.\n');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log('⚠️ Tu sesión expiró. Vamos a re-autenticarte.\n');
|
|
30
|
+
}
|
|
31
|
+
// Prompt for email and password
|
|
32
|
+
const email = await prompt('📧 Email: ');
|
|
33
|
+
const password = await promptPassword('🔑 Password: ');
|
|
34
|
+
if (!email || !password) {
|
|
35
|
+
console.error('❌ Email y password son requeridos.');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
console.log('\n⏳ Autenticando...');
|
|
39
|
+
// 1. Login
|
|
40
|
+
const loginRes = await fetch(`${API_URL}/api/auth/login`, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: { 'Content-Type': 'application/json' },
|
|
43
|
+
body: JSON.stringify({ email: email.trim(), password })
|
|
44
|
+
});
|
|
45
|
+
const loginData = (await loginRes.json());
|
|
46
|
+
if (!loginData.success) {
|
|
47
|
+
console.error(`❌ Login fallido: ${loginData.error || 'Credenciales inválidas'}`);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
let token = loginData.data.token;
|
|
51
|
+
let tenantId = loginData.data.tenantId;
|
|
52
|
+
// 2. Get user info and tenants
|
|
53
|
+
const meRes = await fetch(`${API_URL}/api/auth/me`, {
|
|
54
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
55
|
+
});
|
|
56
|
+
const meData = (await meRes.json());
|
|
57
|
+
if (!meData.success) {
|
|
58
|
+
console.error(`❌ Error al obtener info del usuario: ${meData.error}`);
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
const user = meData.data.user;
|
|
62
|
+
const tenantIds = user.tenantIds || [];
|
|
63
|
+
const roles = user.roles || [];
|
|
64
|
+
// 3. If multiple tenants, ask user to pick
|
|
65
|
+
if (tenantIds.length > 1) {
|
|
66
|
+
console.log(`\n📋 Tenés ${tenantIds.length} tenants disponibles:\n`);
|
|
67
|
+
// Fetch tenant names for display
|
|
68
|
+
const tenantInfos = await Promise.all(tenantIds.map(async (tid, i) => {
|
|
69
|
+
const role = roles.find((r) => r.tenantId === tid)?.role || 'member';
|
|
70
|
+
const isActive = tid === tenantId;
|
|
71
|
+
return { id: tid, role, isActive, index: i + 1 };
|
|
72
|
+
}));
|
|
73
|
+
for (const t of tenantInfos) {
|
|
74
|
+
const marker = t.isActive ? ' ← actual' : '';
|
|
75
|
+
console.log(` ${t.index}. ${t.id} (${t.role})${marker}`);
|
|
76
|
+
}
|
|
77
|
+
const choice = await prompt('\n¿Qué tenant querés usar? (número, Enter para el actual): ');
|
|
78
|
+
const choiceNum = parseInt(choice, 10);
|
|
79
|
+
if (choice.trim() && choiceNum >= 1 && choiceNum <= tenantInfos.length) {
|
|
80
|
+
const selectedTenant = tenantInfos[choiceNum - 1];
|
|
81
|
+
if (selectedTenant.id !== tenantId) {
|
|
82
|
+
// Switch tenant
|
|
83
|
+
console.log(`\n⏳ Cambiando a tenant ${selectedTenant.id}...`);
|
|
84
|
+
const switchRes = await fetch(`${API_URL}/api/auth/switch-tenant`, {
|
|
85
|
+
method: 'POST',
|
|
86
|
+
headers: {
|
|
87
|
+
Authorization: `Bearer ${token}`,
|
|
88
|
+
'Content-Type': 'application/json'
|
|
89
|
+
},
|
|
90
|
+
body: JSON.stringify({ tenantId: selectedTenant.id })
|
|
91
|
+
});
|
|
92
|
+
const switchData = (await switchRes.json());
|
|
93
|
+
if (!switchData.success) {
|
|
94
|
+
console.error(`❌ Error al cambiar de tenant: ${switchData.error}`);
|
|
95
|
+
process.exit(1);
|
|
96
|
+
}
|
|
97
|
+
token = switchData.data.token;
|
|
98
|
+
tenantId = selectedTenant.id;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 4. Get the role for the active tenant
|
|
103
|
+
const activeRole = roles.find((r) => r.tenantId === tenantId)?.role || 'member';
|
|
104
|
+
// 5. Save credentials
|
|
105
|
+
// JWT from AuthService expires in 7 days
|
|
106
|
+
const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
107
|
+
const creds = {
|
|
108
|
+
token,
|
|
109
|
+
tenantId,
|
|
110
|
+
tenantName: tenantId, // We'll update this with actual name below
|
|
111
|
+
role: activeRole,
|
|
112
|
+
email: email.trim(),
|
|
113
|
+
savedAt: new Date().toISOString(),
|
|
114
|
+
expiresAt
|
|
115
|
+
};
|
|
116
|
+
// Try to get the tenant name
|
|
117
|
+
try {
|
|
118
|
+
const tenantRes = await fetch(`${API_URL}/api/v1/tenants/${tenantId}`, {
|
|
119
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
120
|
+
});
|
|
121
|
+
const tenantData = (await tenantRes.json());
|
|
122
|
+
if (tenantData.success && tenantData.data?.name) {
|
|
123
|
+
creds.tenantName = tenantData.data.name;
|
|
124
|
+
}
|
|
125
|
+
else if (tenantData.data?.tenant?.name) {
|
|
126
|
+
creds.tenantName = tenantData.data.tenant.name;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// If we can't get the name, tenantId is fine
|
|
131
|
+
}
|
|
132
|
+
await saveCredentials(creds);
|
|
133
|
+
console.log(`\n✅ ¡Autenticado exitosamente!`);
|
|
134
|
+
console.log(` Email: ${creds.email}`);
|
|
135
|
+
console.log(` Tenant: ${creds.tenantName}`);
|
|
136
|
+
console.log(` Role: ${creds.role}`);
|
|
137
|
+
console.log(` Expira: ${new Date(creds.expiresAt).toLocaleDateString()}`);
|
|
138
|
+
console.log(`\n🚀 Ya podés usar el servidor MCP de BotUyo.\n`);
|
|
139
|
+
}
|
|
140
|
+
// ── Prompts ───────────────────────────────────────────────────────────────────
|
|
141
|
+
function prompt(question) {
|
|
142
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
143
|
+
return new Promise((resolve) => {
|
|
144
|
+
rl.question(question, (answer) => {
|
|
145
|
+
rl.close();
|
|
146
|
+
resolve(answer);
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function promptPassword(question) {
|
|
151
|
+
return new Promise((resolve) => {
|
|
152
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
153
|
+
// Attempt to hide input on supported terminals
|
|
154
|
+
if (process.stdin.isTTY) {
|
|
155
|
+
process.stdout.write(question);
|
|
156
|
+
const stdin = process.stdin;
|
|
157
|
+
stdin.setRawMode(true);
|
|
158
|
+
stdin.resume();
|
|
159
|
+
stdin.setEncoding('utf8');
|
|
160
|
+
let password = '';
|
|
161
|
+
const onData = (ch) => {
|
|
162
|
+
const c = ch.toString();
|
|
163
|
+
switch (c) {
|
|
164
|
+
case '\n':
|
|
165
|
+
case '\r':
|
|
166
|
+
case '\u0004': // Ctrl+D
|
|
167
|
+
stdin.setRawMode(false);
|
|
168
|
+
stdin.pause();
|
|
169
|
+
stdin.removeListener('data', onData);
|
|
170
|
+
rl.close();
|
|
171
|
+
process.stdout.write('\n');
|
|
172
|
+
resolve(password);
|
|
173
|
+
break;
|
|
174
|
+
case '\u0003': // Ctrl+C
|
|
175
|
+
process.exit();
|
|
176
|
+
break;
|
|
177
|
+
case '\u007F': // Backspace
|
|
178
|
+
if (password.length > 0) {
|
|
179
|
+
password = password.slice(0, -1);
|
|
180
|
+
process.stdout.clearLine(0);
|
|
181
|
+
process.stdout.cursorTo(0);
|
|
182
|
+
process.stdout.write(question + '*'.repeat(password.length));
|
|
183
|
+
}
|
|
184
|
+
break;
|
|
185
|
+
default:
|
|
186
|
+
password += c;
|
|
187
|
+
process.stdout.write('*');
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
stdin.on('data', onData);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
// Non-TTY fallback (piped input)
|
|
195
|
+
rl.question(question, (answer) => {
|
|
196
|
+
rl.close();
|
|
197
|
+
resolve(answer);
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npx @botuyo/mcp setup
|
|
3
|
+
*
|
|
4
|
+
* Generates the mcp.json snippet for the current MCP client.
|
|
5
|
+
* Since auth uses ~/.botuyo/credentials.json (saved by login),
|
|
6
|
+
* the server block only needs command + args, no env vars.
|
|
7
|
+
*/
|
|
8
|
+
export declare function runSetup(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npx @botuyo/mcp setup
|
|
3
|
+
*
|
|
4
|
+
* Generates the mcp.json snippet for the current MCP client.
|
|
5
|
+
* Since auth uses ~/.botuyo/credentials.json (saved by login),
|
|
6
|
+
* the server block only needs command + args, no env vars.
|
|
7
|
+
*/
|
|
8
|
+
import { readCredentials } from './credentials.js';
|
|
9
|
+
import { writeFile, readFile } from 'fs/promises';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import { existsSync } from 'fs';
|
|
12
|
+
const CLIENTS = {
|
|
13
|
+
cursor: {
|
|
14
|
+
name: 'Cursor',
|
|
15
|
+
configPath: '.cursor/mcp.json'
|
|
16
|
+
},
|
|
17
|
+
vscode: {
|
|
18
|
+
name: 'VS Code / Antigravity',
|
|
19
|
+
configPath: '.vscode/mcp.json'
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
function buildServerBlock() {
|
|
23
|
+
return {
|
|
24
|
+
servers: {
|
|
25
|
+
botuyo: {
|
|
26
|
+
command: 'npx',
|
|
27
|
+
args: ['-y', '@botuyo/mcp']
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export async function runSetup(args) {
|
|
33
|
+
console.log('\n🔧 BotUyo MCP — Setup\n');
|
|
34
|
+
const creds = await readCredentials();
|
|
35
|
+
if (!creds?.token) {
|
|
36
|
+
console.log('⚠️ No estás autenticado. Ejecutá `npx @botuyo/mcp login` primero.\n');
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log(`✅ Autenticado como: ${creds.email} (${creds.tenantName})\n`);
|
|
40
|
+
}
|
|
41
|
+
const target = args[0] || autoDetectClient();
|
|
42
|
+
if (target && CLIENTS[target]) {
|
|
43
|
+
await writeConfigFile(target);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
// Print all snippets
|
|
47
|
+
console.log('Copiá el snippet para tu herramienta:\n');
|
|
48
|
+
const block = buildServerBlock();
|
|
49
|
+
for (const [_id, client] of Object.entries(CLIENTS)) {
|
|
50
|
+
console.log(`── ${client.name} (${client.configPath}) ──`);
|
|
51
|
+
console.log(JSON.stringify(block, null, 2));
|
|
52
|
+
console.log();
|
|
53
|
+
}
|
|
54
|
+
printClaudeSnippet();
|
|
55
|
+
}
|
|
56
|
+
console.log('💡 El servidor lee las credenciales de ~/.botuyo/credentials.json automáticamente.');
|
|
57
|
+
console.log(' No necesitás configurar variables de entorno.\n');
|
|
58
|
+
}
|
|
59
|
+
async function writeConfigFile(clientId) {
|
|
60
|
+
const client = CLIENTS[clientId];
|
|
61
|
+
const configPath = join(process.cwd(), client.configPath);
|
|
62
|
+
const config = buildServerBlock();
|
|
63
|
+
try {
|
|
64
|
+
// Merge with existing config if present
|
|
65
|
+
let merged = config;
|
|
66
|
+
if (existsSync(configPath)) {
|
|
67
|
+
const existing = JSON.parse(await readFile(configPath, 'utf8'));
|
|
68
|
+
merged = { ...existing, servers: { ...existing.servers, ...config.servers } };
|
|
69
|
+
}
|
|
70
|
+
const dir = configPath.split(/[/\\]/).slice(0, -1).join('/');
|
|
71
|
+
if (dir) {
|
|
72
|
+
const { mkdir } = await import('fs/promises');
|
|
73
|
+
await mkdir(dir, { recursive: true });
|
|
74
|
+
}
|
|
75
|
+
await writeFile(configPath, JSON.stringify(merged, null, 2));
|
|
76
|
+
console.log(`✅ Escrito en ${configPath}`);
|
|
77
|
+
console.log(` Reiniciá tu editor para que tome los cambios.\n`);
|
|
78
|
+
}
|
|
79
|
+
catch (err) {
|
|
80
|
+
console.error(`❌ Error al escribir config: ${err.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function autoDetectClient() {
|
|
84
|
+
if (existsSync('.cursor'))
|
|
85
|
+
return 'cursor';
|
|
86
|
+
if (existsSync('.vscode'))
|
|
87
|
+
return 'vscode';
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
function printClaudeSnippet() {
|
|
91
|
+
console.log(`── Claude Desktop (~/.config/claude/claude_desktop_config.json) ──`);
|
|
92
|
+
console.log(JSON.stringify(buildServerBlock(), null, 2));
|
|
93
|
+
console.log();
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../../src/commands/setup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @botuyo/mcp switch-tenant command
|
|
4
|
+
*
|
|
5
|
+
* Usage: npx @botuyo/mcp switch-tenant
|
|
6
|
+
*
|
|
7
|
+
* Lists the user's tenants and lets them pick a different one.
|
|
8
|
+
* Calls POST /api/auth/switch-tenant and saves the new JWT.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runSwitchTenant(): Promise<void>;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @botuyo/mcp switch-tenant command
|
|
4
|
+
*
|
|
5
|
+
* Usage: npx @botuyo/mcp switch-tenant
|
|
6
|
+
*
|
|
7
|
+
* Lists the user's tenants and lets them pick a different one.
|
|
8
|
+
* Calls POST /api/auth/switch-tenant and saves the new JWT.
|
|
9
|
+
*/
|
|
10
|
+
import * as readline from 'readline';
|
|
11
|
+
import { readCredentials, saveCredentials, resolveToken } from './credentials.js';
|
|
12
|
+
const API_URL = process.env.BOTUYO_API_URL || 'https://api.botuyo.com';
|
|
13
|
+
export async function runSwitchTenant() {
|
|
14
|
+
console.log('\n🔄 BotUyo MCP — Switch Tenant\n');
|
|
15
|
+
const token = await resolveToken();
|
|
16
|
+
const creds = await readCredentials();
|
|
17
|
+
if (!token || !creds) {
|
|
18
|
+
console.error('❌ No estás autenticado. Ejecutá: npx @botuyo/mcp login');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
// Get user's tenants
|
|
22
|
+
const meRes = await fetch(`${API_URL}/api/auth/me`, {
|
|
23
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
24
|
+
});
|
|
25
|
+
const meData = (await meRes.json());
|
|
26
|
+
if (!meData.success) {
|
|
27
|
+
console.error(`❌ Sesión inválida: ${meData.error || 'Token expirado'}`);
|
|
28
|
+
console.error(' Ejecutá: npx @botuyo/mcp login');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const user = meData.data.user;
|
|
32
|
+
const tenantIds = user.tenantIds || [];
|
|
33
|
+
const roles = user.roles || [];
|
|
34
|
+
if (tenantIds.length === 0) {
|
|
35
|
+
console.log('No tenés tenants disponibles.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (tenantIds.length === 1) {
|
|
39
|
+
console.log(`Solo tenés un tenant: ${creds.tenantName} (${creds.role})`);
|
|
40
|
+
console.log('No hay nada para cambiar.\n');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.log(`Tenés ${tenantIds.length} tenants disponibles:\n`);
|
|
44
|
+
for (let i = 0; i < tenantIds.length; i++) {
|
|
45
|
+
const tid = tenantIds[i];
|
|
46
|
+
const role = roles.find((r) => r.tenantId === tid)?.role || 'member';
|
|
47
|
+
const isActive = tid === creds.tenantId;
|
|
48
|
+
const marker = isActive ? ' ← actual' : '';
|
|
49
|
+
console.log(` ${i + 1}. ${tid} (${role})${marker}`);
|
|
50
|
+
}
|
|
51
|
+
const choice = await prompt('\n¿A qué tenant querés cambiar? (número): ');
|
|
52
|
+
const choiceNum = parseInt(choice, 10);
|
|
53
|
+
if (!choiceNum || choiceNum < 1 || choiceNum > tenantIds.length) {
|
|
54
|
+
console.log('Operación cancelada.');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const selectedTenantId = tenantIds[choiceNum - 1];
|
|
58
|
+
if (selectedTenantId === creds.tenantId) {
|
|
59
|
+
console.log('\nYa estás en ese tenant. No hubo cambios.\n');
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
console.log(`\n⏳ Cambiando a tenant ${selectedTenantId}...`);
|
|
63
|
+
const switchRes = await fetch(`${API_URL}/api/auth/switch-tenant`, {
|
|
64
|
+
method: 'POST',
|
|
65
|
+
headers: {
|
|
66
|
+
Authorization: `Bearer ${token}`,
|
|
67
|
+
'Content-Type': 'application/json'
|
|
68
|
+
},
|
|
69
|
+
body: JSON.stringify({ tenantId: selectedTenantId })
|
|
70
|
+
});
|
|
71
|
+
const switchData = (await switchRes.json());
|
|
72
|
+
if (!switchData.success) {
|
|
73
|
+
console.error(`❌ Error al cambiar de tenant: ${switchData.error}`);
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
const newToken = switchData.data.token;
|
|
77
|
+
const newRole = switchData.data.user?.role || roles.find((r) => r.tenantId === selectedTenantId)?.role || 'member';
|
|
78
|
+
// Try to get tenant name
|
|
79
|
+
let tenantName = selectedTenantId;
|
|
80
|
+
try {
|
|
81
|
+
const tenantRes = await fetch(`${API_URL}/api/v1/tenants/${selectedTenantId}`, {
|
|
82
|
+
headers: { Authorization: `Bearer ${newToken}` }
|
|
83
|
+
});
|
|
84
|
+
const tenantData = (await tenantRes.json());
|
|
85
|
+
if (tenantData.success && tenantData.data?.name) {
|
|
86
|
+
tenantName = tenantData.data.name;
|
|
87
|
+
}
|
|
88
|
+
else if (tenantData.data?.tenant?.name) {
|
|
89
|
+
tenantName = tenantData.data.tenant.name;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
// use tenantId
|
|
94
|
+
}
|
|
95
|
+
await saveCredentials({
|
|
96
|
+
...creds,
|
|
97
|
+
token: newToken,
|
|
98
|
+
tenantId: selectedTenantId,
|
|
99
|
+
tenantName,
|
|
100
|
+
role: newRole,
|
|
101
|
+
savedAt: new Date().toISOString(),
|
|
102
|
+
expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString()
|
|
103
|
+
});
|
|
104
|
+
console.log(`\n✅ Cambiado exitosamente`);
|
|
105
|
+
console.log(` Tenant: ${tenantName}`);
|
|
106
|
+
console.log(` Role: ${newRole}\n`);
|
|
107
|
+
}
|
|
108
|
+
function prompt(question) {
|
|
109
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
110
|
+
return new Promise((resolve) => {
|
|
111
|
+
rl.question(question, (answer) => {
|
|
112
|
+
rl.close();
|
|
113
|
+
resolve(answer);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=switch_tenant.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"switch_tenant.js","sourceRoot":"","sources":["../../src/commands/switch_tenant.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,QAAQ,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEjF,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,wBAAwB,CAAA;AAEtE,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAA;IAEhD,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAA;IAClC,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAA;IAErC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAA;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,qBAAqB;IACrB,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,cAAc,EAAE;QAClD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;KAC9C,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAQ,CAAA;IAE1C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,IAAI,gBAAgB,EAAE,CAAC,CAAA;QACvE,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;IAC7B,MAAM,SAAS,GAAa,IAAI,CAAC,SAAS,IAAI,EAAE,CAAA;IAChD,MAAM,KAAK,GAA8C,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;IAEzE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAA;QAC5C,OAAM;IACR,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,CAAC,UAAU,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,CAAA;QACxE,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;QAC1C,OAAM;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,SAAS,SAAS,CAAC,MAAM,yBAAyB,CAAC,CAAA;IAE/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,EAAE,IAAI,IAAI,QAAQ,CAAA;QACzE,MAAM,QAAQ,GAAG,GAAG,KAAK,KAAK,CAAC,QAAQ,CAAA;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;QAC1C,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,KAAK,IAAI,IAAI,MAAM,EAAE,CAAC,CAAA;IACvD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,4CAA4C,CAAC,CAAA;IACzE,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;IAEtC,IAAI,CAAC,SAAS,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC;QAChE,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;QACnC,OAAM;IACR,CAAC;IAED,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;IACjD,IAAI,gBAAgB,KAAK,KAAK,CAAC,QAAQ,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAA;QAC3D,OAAM;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,0BAA0B,gBAAgB,KAAK,CAAC,CAAA;IAE5D,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,yBAAyB,EAAE;QACjE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,KAAK,EAAE;YAChC,cAAc,EAAE,kBAAkB;SACnC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC;KACrD,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,CAAQ,CAAA;IAElD,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,iCAAiC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAA;QAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC,KAAK,CAAA;IACtC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,gBAAgB,CAAC,EAAE,IAAI,IAAI,QAAQ,CAAA;IAEvH,yBAAyB;IACzB,IAAI,UAAU,GAAG,gBAAgB,CAAA;IACjC,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,mBAAmB,gBAAgB,EAAE,EAAE;YAC7E,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,EAAE,EAAE;SACjD,CAAC,CAAA;QACF,MAAM,UAAU,GAAG,CAAC,MAAM,SAAS,CAAC,IAAI,EAAE,CAAQ,CAAA;QAClD,IAAI,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;YAChD,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAA;QACnC,CAAC;aAAM,IAAI,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;YACzC,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;QAC1C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IAED,MAAM,eAAe,CAAC;QACpB,GAAG,KAAK;QACR,KAAK,EAAE,QAAQ;QACf,QAAQ,EAAE,gBAAgB;QAC1B,UAAU;QACV,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACjC,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;KACxE,CAAC,CAAA;IAEF,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;IACxC,OAAO,CAAC,GAAG,CAAC,eAAe,UAAU,EAAE,CAAC,CAAA;IACxC,OAAO,CAAC,GAAG,CAAC,eAAe,OAAO,IAAI,CAAC,CAAA;AACzC,CAAC;AAED,SAAS,MAAM,CAAC,QAAgB;IAC9B,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACrF,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,EAAE;YAC/B,EAAE,CAAC,KAAK,EAAE,CAAA;YACV,OAAO,CAAC,MAAM,CAAC,CAAA;QACjB,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @botuyo/mcp tenants command
|
|
4
|
+
*
|
|
5
|
+
* Usage: npx @botuyo/mcp tenants
|
|
6
|
+
*
|
|
7
|
+
* Lists all tenants the current user belongs to with their roles.
|
|
8
|
+
*/
|
|
9
|
+
import { readCredentials, resolveToken } from './credentials.js';
|
|
10
|
+
const API_URL = process.env.BOTUYO_API_URL || 'https://api.botuyo.com';
|
|
11
|
+
export async function runTenants() {
|
|
12
|
+
console.log('\n📋 BotUyo MCP — Mis Tenants\n');
|
|
13
|
+
const token = await resolveToken();
|
|
14
|
+
const creds = await readCredentials();
|
|
15
|
+
if (!token || !creds) {
|
|
16
|
+
console.error('❌ No estás autenticado. Ejecutá: npx @botuyo/mcp login');
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
const meRes = await fetch(`${API_URL}/api/auth/me`, {
|
|
20
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
21
|
+
});
|
|
22
|
+
const meData = (await meRes.json());
|
|
23
|
+
if (!meData.success) {
|
|
24
|
+
console.error(`❌ Sesión inválida: ${meData.error || 'Token expirado'}`);
|
|
25
|
+
console.error(' Ejecutá: npx @botuyo/mcp login');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const user = meData.data.user;
|
|
29
|
+
const tenantIds = user.tenantIds || [];
|
|
30
|
+
const roles = user.roles || [];
|
|
31
|
+
if (tenantIds.length === 0) {
|
|
32
|
+
console.log('No tenés tenants disponibles.\n');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.log(`Email: ${creds.email}`);
|
|
36
|
+
console.log(`Tenants: ${tenantIds.length}\n`);
|
|
37
|
+
console.log(' # Tenant ID Rol Estado');
|
|
38
|
+
console.log(' ─ ───────────────────────────────── ───────── ──────');
|
|
39
|
+
for (let i = 0; i < tenantIds.length; i++) {
|
|
40
|
+
const tid = tenantIds[i];
|
|
41
|
+
const role = roles.find((r) => r.tenantId === tid)?.role || 'member';
|
|
42
|
+
const isActive = tid === creds.tenantId;
|
|
43
|
+
const status = isActive ? '✓ activo' : '';
|
|
44
|
+
console.log(` ${i + 1} ${tid.padEnd(37)} ${role.padEnd(10)} ${status}`);
|
|
45
|
+
}
|
|
46
|
+
console.log(`\nPara cambiar de tenant: npx @botuyo/mcp switch-tenant\n`);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=tenants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenants.js","sourceRoot":"","sources":["../../src/commands/tenants.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAEhE,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,wBAAwB,CAAA;AAEtE,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAA;IAE9C,MAAM,KAAK,GAAG,MAAM,YAAY,EAAE,CAAA;IAClC,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAA;IAErC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAA;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,GAAG,OAAO,cAAc,EAAE;QAClD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE;KAC9C,CAAC,CAAA;IACF,MAAM,MAAM,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,EAAE,CAAQ,CAAA;IAE1C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,IAAI,gBAAgB,EAAE,CAAC,CAAA;QACvE,OAAO,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;QAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAA;IAC7B,MAAM,SAAS,GAAa,IAAI,CAAC,SAAS,IAAI,EAAE,CAAA;IAChD,MAAM,KAAK,GAA8C,IAAI,CAAC,KAAK,IAAI,EAAE,CAAA;IAEzE,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAA;QAC9C,OAAM;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;IACpC,OAAO,CAAC,GAAG,CAAC,YAAY,SAAS,CAAC,MAAM,IAAI,CAAC,CAAA;IAC7C,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAA;IAC1E,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAA;IAE1E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,CAAA;QACxB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,EAAE,IAAI,IAAI,QAAQ,CAAA;QACzE,MAAM,QAAQ,GAAG,GAAG,KAAK,KAAK,CAAC,QAAQ,CAAA;QACvC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAA;QACzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,EAAE,CAAC,CAAA;IAC5E,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAA;AAC1E,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* @botuyo/mcp — Entry Point
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* }
|
|
5
|
+
* Sub-commands:
|
|
6
|
+
* npx @botuyo/mcp login — Login with email/password
|
|
7
|
+
* npx @botuyo/mcp tenants — List your tenants
|
|
8
|
+
* npx @botuyo/mcp switch-tenant — Switch active tenant
|
|
9
|
+
* npx @botuyo/mcp setup — Generate mcp.json for your editor
|
|
10
|
+
* npx @botuyo/mcp whoami — Show current credentials
|
|
11
|
+
* npx @botuyo/mcp logout — Clear stored credentials
|
|
12
|
+
* npx @botuyo/mcp — Start the MCP server (default)
|
|
13
|
+
*
|
|
14
|
+
* Token resolution (in priority order):
|
|
15
|
+
* 1. BOTUYO_TOKEN env var
|
|
16
|
+
* 2. ~/.botuyo/credentials.json (saved by `npx @botuyo/mcp login`)
|
|
18
17
|
*/
|
|
19
18
|
export {};
|