alora-mcp 0.7.1 → 0.9.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.
Files changed (2) hide show
  1. package/package.json +3 -3
  2. package/src/index.js +20 -7
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "alora-mcp",
3
- "version": "0.7.1",
4
- "description": "MCP server for Alora, the cloud where your agent works \u2014 deploy, preview, share and run the apps your agent writes. Claude Code, Codex, Cursor and any MCP client.",
3
+ "version": "0.9.0",
4
+ "description": "MCP server for Alora, the cloud where your agent works deploy, preview, share and run the apps your agent writes. Claude Code, Codex, Cursor and any MCP client.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "alora-mcp": "src/index.js"
8
8
  },
9
9
  "dependencies": {
10
- "alora-sdk": "^0.7.0",
10
+ "alora-sdk": "^0.9.0",
11
11
  "@modelcontextprotocol/sdk": "^1.12.0",
12
12
  "tar": "^7.4.3",
13
13
  "zod": "^3.24.0"
package/src/index.js CHANGED
@@ -18,7 +18,7 @@ function client() {
18
18
  return new AloraClient({ api: cfg.api || 'https://api.alora.build', token: cfg.token });
19
19
  }
20
20
 
21
- const server = new McpServer({ name: 'alora', version: '0.7.0' });
21
+ const server = new McpServer({ name: 'alora', version: '0.9.0' });
22
22
 
23
23
  const ok = (data) => ({ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] });
24
24
  const asError = (e) => ({
@@ -50,7 +50,11 @@ server.registerTool('account_create_and_connect', {
50
50
  email: z.string().describe('El email que el usuario te dio en el chat'),
51
51
  agent_name: z.string().optional().describe('Cómo se llama este agente, ej: "Claude de Ana"'),
52
52
  },
53
- }, wrap(({ email, agent_name }) => client().signupStart(email, agent_name || 'agente MCP')));
53
+ }, wrap(({ email, agent_name }) => {
54
+ let old;
55
+ try { old = JSON.parse(readFileSync(CONFIG_FILE, 'utf8')).token; } catch {}
56
+ return client().signupStart(email, agent_name || 'agente MCP', old);
57
+ }));
54
58
 
55
59
  server.registerTool('account_connect_poll', {
56
60
  description: 'Después de account_create_and_connect: llamá esto cada ~5s con el device_code. Cuando el usuario toque el email devuelve approved y GUARDA el token automáticamente — desde ahí todas las demás tools funcionan. expired = el link venció sin click: pedile al usuario que revise el inbox y volvé a empezar.',
@@ -151,9 +155,14 @@ server.registerTool('logs', {
151
155
  }, wrap(({ project, lines, since }) => client().logs(project, { lines, since })));
152
156
 
153
157
  server.registerTool('exec', {
154
- description: 'Ejecuta un comando dentro de la microVM del proyecto (despierta la máquina si duerme). Devuelve stdout, stderr y exit_code. Para inspeccionar el filesystem, ver archivos en /data, debuggear. Ej: "ls -la /data", "cat /data/bitacora/hoy.log".',
155
- inputSchema: { project: z.string(), command: z.string() },
156
- }, wrap(({ project, command }) => client().exec(project, command)));
158
+ description: 'Ejecuta dentro de la MISMA microVM donde corre la app (cwd /app; despierta la máquina si duerme). Devuelve stdout/stderr/exit_code. Dos modos: command (string, pasa por sh) o argv (array LITERAL sin shell — usalo para comandos con quoting complejo o multilínea; nada se re-parsea). stdin_b64 se pipea al proceso (ideal para escribir archivos: argv ["tee","/data/x.py"] + stdin_b64 del contenido). Claves: solo $DATA_DIR sobrevive reinicios (/app se reconstruye del bundle en cada boot); tu app escucha en 127.0.0.1:8081; el guard en 8080 exige el header x-alora-proxy-auth con $ALORA_PROXY_SECRET (está en el env de la VM) — para pegarle a un endpoint propio: curl -H "x-alora-proxy-auth: $ALORA_PROXY_SECRET" http://127.0.0.1:8080/ruta.',
159
+ inputSchema: {
160
+ project: z.string(),
161
+ command: z.string().optional().describe('Comando via sh (modo simple)'),
162
+ argv: z.array(z.string()).optional().describe('Comando como array literal, sin shell (modo seguro para quoting)'),
163
+ stdin_b64: z.string().optional().describe('Contenido en base64 para pipear al stdin del proceso'),
164
+ },
165
+ }, wrap(({ project, command, argv, stdin_b64 }) => client().exec(project, { command, argv, stdin_b64 })));
157
166
 
158
167
  server.registerTool('restart', {
159
168
  description: 'Reinicia la app sin redesplegar (útil para aplicar un cambio de estado o salir de un cuelgue).',
@@ -182,8 +191,12 @@ server.registerTool('egress_ip_release', {
182
191
 
183
192
  server.registerTool('token_create', {
184
193
  description: 'Crea un token de acceso por proyecto que BYPASSEA el login: un script/webhook/backup externo puede pegarle a la URL de la app con Authorization: Bearer <token> sin SSO. Scoped a este proyecto y revocable. La app lo ve con x-alora-user-role: service. El token se muestra una sola vez.',
185
- inputSchema: { project: z.string(), name: z.string().optional() },
186
- }, wrap(({ project, name }) => client().tokenCreate(project, name)));
194
+ inputSchema: {
195
+ project: z.string(),
196
+ name: z.string().optional(),
197
+ paths: z.array(z.string()).optional().describe('Scoping: prefijos de ruta que el token puede tocar, ej ["/export","/api/hook"]. Sin paths vale para toda la app.'),
198
+ },
199
+ }, wrap(({ project, name, paths }) => client().tokenCreate(project, name, paths)));
187
200
 
188
201
  server.registerTool('list_versions', {
189
202
  description: 'Historial de versiones del proyecto, con autor y mensaje.',