@miosa/cli 1.0.8 → 1.0.9
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/bin/miosa.js +0 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +7 -1
- package/dist/client.js.map +1 -1
- package/dist/commands/login.d.ts.map +1 -1
- package/dist/commands/login.js +10 -2
- package/dist/commands/login.js.map +1 -1
- package/dist/commands/mcp.d.ts.map +1 -1
- package/dist/commands/mcp.js +241 -1429
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +366 -14
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/whoami.js +2 -2
- package/dist/commands/whoami.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/miosa-linux-x64 +0 -0
- package/dist/tui/dashboard.d.ts.map +1 -1
- package/dist/tui/dashboard.js +1 -1
- package/dist/tui/dashboard.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
package/dist/commands/mcp.js
CHANGED
|
@@ -22,7 +22,6 @@ import { request } from "undici";
|
|
|
22
22
|
import chalk from "chalk";
|
|
23
23
|
import { loadConfig } from "../config.js";
|
|
24
24
|
import { MiosaClient } from "../client.js";
|
|
25
|
-
import { banner, errorEnvelope, hintBlock, icon, kvPanel, printElapsed, formatDuration, } from "../ui/render.js";
|
|
26
25
|
// ── Tool definitions — mirror the Python MCP server exactly ─────────────────
|
|
27
26
|
const TOOL_LIST = [
|
|
28
27
|
// Lifecycle
|
|
@@ -59,15 +58,6 @@ const TOOL_LIST = [
|
|
|
59
58
|
type: "string",
|
|
60
59
|
description: "Your internal project ID for attribution (optional)",
|
|
61
60
|
},
|
|
62
|
-
gpu_model: {
|
|
63
|
-
type: "string",
|
|
64
|
-
description: "GPU model to attach (e.g. 'nvidia-a10g', 'nvidia-t4'). Omit for CPU-only.",
|
|
65
|
-
},
|
|
66
|
-
gpu_count: {
|
|
67
|
-
type: "integer",
|
|
68
|
-
description: "Number of GPUs to attach (default: 1 when gpu_model is set).",
|
|
69
|
-
default: 1,
|
|
70
|
-
},
|
|
71
61
|
},
|
|
72
62
|
required: ["name"],
|
|
73
63
|
},
|
|
@@ -1317,971 +1307,368 @@ const TOOL_LIST = [
|
|
|
1317
1307
|
},
|
|
1318
1308
|
// Deployments
|
|
1319
1309
|
{
|
|
1320
|
-
name:
|
|
1321
|
-
description:
|
|
1322
|
-
inputSchema: { type:
|
|
1323
|
-
},
|
|
1324
|
-
{
|
|
1325
|
-
name: "deployment_get",
|
|
1326
|
-
description: "Get details of a specific deployment.",
|
|
1327
|
-
inputSchema: {
|
|
1328
|
-
type: "object",
|
|
1329
|
-
properties: {
|
|
1330
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1331
|
-
},
|
|
1332
|
-
required: ["deployment_id"],
|
|
1333
|
-
},
|
|
1334
|
-
},
|
|
1335
|
-
{
|
|
1336
|
-
name: "deployment_create",
|
|
1337
|
-
description: "Create a new deployment.",
|
|
1338
|
-
inputSchema: {
|
|
1339
|
-
type: "object",
|
|
1340
|
-
properties: {
|
|
1341
|
-
name: { type: "string", description: "Deployment name" },
|
|
1342
|
-
type: {
|
|
1343
|
-
type: "string",
|
|
1344
|
-
description: "Deployment type (e.g. web, worker)",
|
|
1345
|
-
},
|
|
1346
|
-
source: { type: "object", description: "Source configuration" },
|
|
1347
|
-
env_vars: {
|
|
1348
|
-
type: "object",
|
|
1349
|
-
description: "Environment variables as key-value pairs",
|
|
1350
|
-
},
|
|
1351
|
-
region: { type: "string", description: "Deployment region (optional)" },
|
|
1352
|
-
},
|
|
1353
|
-
required: ["name"],
|
|
1354
|
-
},
|
|
1355
|
-
},
|
|
1356
|
-
{
|
|
1357
|
-
name: "deployment_delete",
|
|
1358
|
-
description: "Delete a deployment permanently.",
|
|
1359
|
-
inputSchema: {
|
|
1360
|
-
type: "object",
|
|
1361
|
-
properties: {
|
|
1362
|
-
deployment_id: {
|
|
1363
|
-
type: "string",
|
|
1364
|
-
description: "Deployment ID to delete",
|
|
1365
|
-
},
|
|
1366
|
-
},
|
|
1367
|
-
required: ["deployment_id"],
|
|
1368
|
-
},
|
|
1369
|
-
},
|
|
1370
|
-
{
|
|
1371
|
-
name: "deployment_publish",
|
|
1372
|
-
description: "Publish a new version of a deployment.",
|
|
1373
|
-
inputSchema: {
|
|
1374
|
-
type: "object",
|
|
1375
|
-
properties: {
|
|
1376
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1377
|
-
source: {
|
|
1378
|
-
type: "object",
|
|
1379
|
-
description: "Source configuration for the new version",
|
|
1380
|
-
},
|
|
1381
|
-
},
|
|
1382
|
-
required: ["deployment_id"],
|
|
1383
|
-
},
|
|
1384
|
-
},
|
|
1385
|
-
{
|
|
1386
|
-
name: "deployment_rollback",
|
|
1387
|
-
description: "Rollback a deployment to a previous version.",
|
|
1388
|
-
inputSchema: {
|
|
1389
|
-
type: "object",
|
|
1390
|
-
properties: {
|
|
1391
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1392
|
-
version_id: {
|
|
1393
|
-
type: "string",
|
|
1394
|
-
description: "Version ID to roll back to",
|
|
1395
|
-
},
|
|
1396
|
-
},
|
|
1397
|
-
required: ["deployment_id", "version_id"],
|
|
1398
|
-
},
|
|
1399
|
-
},
|
|
1400
|
-
{
|
|
1401
|
-
name: "deployment_env_list",
|
|
1402
|
-
description: "List environment variables for a deployment.",
|
|
1403
|
-
inputSchema: {
|
|
1404
|
-
type: "object",
|
|
1405
|
-
properties: {
|
|
1406
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1407
|
-
},
|
|
1408
|
-
required: ["deployment_id"],
|
|
1409
|
-
},
|
|
1410
|
-
},
|
|
1411
|
-
{
|
|
1412
|
-
name: "deployment_env_set",
|
|
1413
|
-
description: "Set (create or update) an environment variable for a deployment.",
|
|
1414
|
-
inputSchema: {
|
|
1415
|
-
type: "object",
|
|
1416
|
-
properties: {
|
|
1417
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1418
|
-
key: { type: "string", description: "Environment variable name" },
|
|
1419
|
-
value: { type: "string", description: "Environment variable value" },
|
|
1420
|
-
},
|
|
1421
|
-
required: ["deployment_id", "key", "value"],
|
|
1422
|
-
},
|
|
1423
|
-
},
|
|
1424
|
-
{
|
|
1425
|
-
name: "deployment_logs",
|
|
1426
|
-
description: "Get logs for a deployment.",
|
|
1427
|
-
inputSchema: {
|
|
1428
|
-
type: "object",
|
|
1429
|
-
properties: {
|
|
1430
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1431
|
-
lines: {
|
|
1432
|
-
type: "integer",
|
|
1433
|
-
description: "Number of log lines to return (default: 100)",
|
|
1434
|
-
default: 100,
|
|
1435
|
-
},
|
|
1436
|
-
since: {
|
|
1437
|
-
type: "string",
|
|
1438
|
-
description: "ISO 8601 timestamp to fetch logs from (optional)",
|
|
1439
|
-
},
|
|
1440
|
-
},
|
|
1441
|
-
required: ["deployment_id"],
|
|
1442
|
-
},
|
|
1443
|
-
},
|
|
1444
|
-
{
|
|
1445
|
-
name: "deployment_version_list",
|
|
1446
|
-
description: "List all versions of a deployment.",
|
|
1447
|
-
inputSchema: {
|
|
1448
|
-
type: "object",
|
|
1449
|
-
properties: {
|
|
1450
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1451
|
-
},
|
|
1452
|
-
required: ["deployment_id"],
|
|
1453
|
-
},
|
|
1454
|
-
},
|
|
1455
|
-
{
|
|
1456
|
-
name: "deployment_version_promote",
|
|
1457
|
-
description: "Promote a specific version to be the active deployment.",
|
|
1458
|
-
inputSchema: {
|
|
1459
|
-
type: "object",
|
|
1460
|
-
properties: {
|
|
1461
|
-
deployment_id: { type: "string", description: "Deployment ID" },
|
|
1462
|
-
version_id: { type: "string", description: "Version ID to promote" },
|
|
1463
|
-
},
|
|
1464
|
-
required: ["deployment_id", "version_id"],
|
|
1465
|
-
},
|
|
1466
|
-
},
|
|
1467
|
-
// Storage
|
|
1468
|
-
{
|
|
1469
|
-
name: "storage_bucket_list",
|
|
1470
|
-
description: "List all storage buckets in the tenant.",
|
|
1471
|
-
inputSchema: { type: "object", properties: {} },
|
|
1472
|
-
},
|
|
1473
|
-
{
|
|
1474
|
-
name: "storage_bucket_create",
|
|
1475
|
-
description: "Create a new storage bucket.",
|
|
1476
|
-
inputSchema: {
|
|
1477
|
-
type: "object",
|
|
1478
|
-
properties: {
|
|
1479
|
-
name: { type: "string", description: "Bucket name" },
|
|
1480
|
-
region: { type: "string", description: "Bucket region (optional)" },
|
|
1481
|
-
public: {
|
|
1482
|
-
type: "boolean",
|
|
1483
|
-
description: "Whether the bucket is publicly readable (default: false)",
|
|
1484
|
-
default: false,
|
|
1485
|
-
},
|
|
1486
|
-
},
|
|
1487
|
-
required: ["name"],
|
|
1488
|
-
},
|
|
1310
|
+
name: 'deployment_list',
|
|
1311
|
+
description: 'List all deployments in the tenant.',
|
|
1312
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1489
1313
|
},
|
|
1490
1314
|
{
|
|
1491
|
-
name:
|
|
1492
|
-
description:
|
|
1315
|
+
name: 'deployment_get',
|
|
1316
|
+
description: 'Get details of a specific deployment.',
|
|
1493
1317
|
inputSchema: {
|
|
1494
|
-
type:
|
|
1318
|
+
type: 'object',
|
|
1495
1319
|
properties: {
|
|
1496
|
-
|
|
1497
|
-
type: "string",
|
|
1498
|
-
description: "Bucket ID or name to delete",
|
|
1499
|
-
},
|
|
1320
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1500
1321
|
},
|
|
1501
|
-
required: [
|
|
1322
|
+
required: ['deployment_id'],
|
|
1502
1323
|
},
|
|
1503
1324
|
},
|
|
1504
1325
|
{
|
|
1505
|
-
name:
|
|
1506
|
-
description:
|
|
1326
|
+
name: 'deployment_create',
|
|
1327
|
+
description: 'Create a new deployment.',
|
|
1507
1328
|
inputSchema: {
|
|
1508
|
-
type:
|
|
1329
|
+
type: 'object',
|
|
1509
1330
|
properties: {
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
},
|
|
1331
|
+
name: { type: 'string', description: 'Deployment name' },
|
|
1332
|
+
type: { type: 'string', description: 'Deployment type (e.g. web, worker)' },
|
|
1333
|
+
source: { type: 'object', description: 'Source configuration' },
|
|
1334
|
+
env_vars: { type: 'object', description: 'Environment variables as key-value pairs' },
|
|
1335
|
+
region: { type: 'string', description: 'Deployment region (optional)' },
|
|
1515
1336
|
},
|
|
1516
|
-
required: [
|
|
1337
|
+
required: ['name'],
|
|
1517
1338
|
},
|
|
1518
1339
|
},
|
|
1519
1340
|
{
|
|
1520
|
-
name:
|
|
1521
|
-
description:
|
|
1341
|
+
name: 'deployment_delete',
|
|
1342
|
+
description: 'Delete a deployment permanently.',
|
|
1522
1343
|
inputSchema: {
|
|
1523
|
-
type:
|
|
1344
|
+
type: 'object',
|
|
1524
1345
|
properties: {
|
|
1525
|
-
|
|
1526
|
-
key: { type: "string", description: "Object key (path within bucket)" },
|
|
1527
|
-
content: {
|
|
1528
|
-
type: "string",
|
|
1529
|
-
description: "Object content (text or base64-encoded binary)",
|
|
1530
|
-
},
|
|
1531
|
-
content_type: {
|
|
1532
|
-
type: "string",
|
|
1533
|
-
description: "MIME type of the object (optional)",
|
|
1534
|
-
},
|
|
1346
|
+
deployment_id: { type: 'string', description: 'Deployment ID to delete' },
|
|
1535
1347
|
},
|
|
1536
|
-
required: [
|
|
1348
|
+
required: ['deployment_id'],
|
|
1537
1349
|
},
|
|
1538
1350
|
},
|
|
1539
1351
|
{
|
|
1540
|
-
name:
|
|
1541
|
-
description:
|
|
1352
|
+
name: 'deployment_publish',
|
|
1353
|
+
description: 'Publish a new version of a deployment.',
|
|
1542
1354
|
inputSchema: {
|
|
1543
|
-
type:
|
|
1355
|
+
type: 'object',
|
|
1544
1356
|
properties: {
|
|
1545
|
-
|
|
1546
|
-
|
|
1357
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1358
|
+
source: { type: 'object', description: 'Source configuration for the new version' },
|
|
1547
1359
|
},
|
|
1548
|
-
required: [
|
|
1360
|
+
required: ['deployment_id'],
|
|
1549
1361
|
},
|
|
1550
1362
|
},
|
|
1551
1363
|
{
|
|
1552
|
-
name:
|
|
1553
|
-
description:
|
|
1364
|
+
name: 'deployment_rollback',
|
|
1365
|
+
description: 'Rollback a deployment to a previous version.',
|
|
1554
1366
|
inputSchema: {
|
|
1555
|
-
type:
|
|
1367
|
+
type: 'object',
|
|
1556
1368
|
properties: {
|
|
1557
|
-
|
|
1558
|
-
|
|
1369
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1370
|
+
version_id: { type: 'string', description: 'Version ID to roll back to' },
|
|
1559
1371
|
},
|
|
1560
|
-
required: [
|
|
1372
|
+
required: ['deployment_id', 'version_id'],
|
|
1561
1373
|
},
|
|
1562
1374
|
},
|
|
1563
1375
|
{
|
|
1564
|
-
name:
|
|
1565
|
-
description:
|
|
1376
|
+
name: 'deployment_env_list',
|
|
1377
|
+
description: 'List environment variables for a deployment.',
|
|
1566
1378
|
inputSchema: {
|
|
1567
|
-
type:
|
|
1379
|
+
type: 'object',
|
|
1568
1380
|
properties: {
|
|
1569
|
-
|
|
1570
|
-
key: { type: "string", description: "Object key" },
|
|
1571
|
-
expires_in: {
|
|
1572
|
-
type: "integer",
|
|
1573
|
-
description: "URL expiry in seconds (default: 3600)",
|
|
1574
|
-
default: 3600,
|
|
1575
|
-
},
|
|
1576
|
-
method: {
|
|
1577
|
-
type: "string",
|
|
1578
|
-
enum: ["GET", "PUT"],
|
|
1579
|
-
description: "HTTP method (default: GET)",
|
|
1580
|
-
default: "GET",
|
|
1581
|
-
},
|
|
1381
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1582
1382
|
},
|
|
1583
|
-
required: [
|
|
1383
|
+
required: ['deployment_id'],
|
|
1584
1384
|
},
|
|
1585
1385
|
},
|
|
1586
|
-
// Databases
|
|
1587
|
-
{
|
|
1588
|
-
name: "database_list",
|
|
1589
|
-
description: "List all managed databases in the tenant.",
|
|
1590
|
-
inputSchema: { type: "object", properties: {} },
|
|
1591
|
-
},
|
|
1592
1386
|
{
|
|
1593
|
-
name:
|
|
1594
|
-
description:
|
|
1387
|
+
name: 'deployment_env_set',
|
|
1388
|
+
description: 'Set (create or update) an environment variable for a deployment.',
|
|
1595
1389
|
inputSchema: {
|
|
1596
|
-
type:
|
|
1390
|
+
type: 'object',
|
|
1597
1391
|
properties: {
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
enum: ["postgres", "mysql", "redis"],
|
|
1602
|
-
description: "Database engine",
|
|
1603
|
-
},
|
|
1604
|
-
version: { type: "string", description: "Engine version (optional)" },
|
|
1605
|
-
size: { type: "string", description: "Database size/tier (optional)" },
|
|
1606
|
-
region: { type: "string", description: "Region (optional)" },
|
|
1392
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1393
|
+
key: { type: 'string', description: 'Environment variable name' },
|
|
1394
|
+
value: { type: 'string', description: 'Environment variable value' },
|
|
1607
1395
|
},
|
|
1608
|
-
required: [
|
|
1396
|
+
required: ['deployment_id', 'key', 'value'],
|
|
1609
1397
|
},
|
|
1610
1398
|
},
|
|
1611
1399
|
{
|
|
1612
|
-
name:
|
|
1613
|
-
description:
|
|
1400
|
+
name: 'deployment_logs',
|
|
1401
|
+
description: 'Get logs for a deployment.',
|
|
1614
1402
|
inputSchema: {
|
|
1615
|
-
type:
|
|
1616
|
-
properties: {
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
},
|
|
1621
|
-
},
|
|
1622
|
-
{
|
|
1623
|
-
name: "database_delete",
|
|
1624
|
-
description: "Delete a managed database permanently.",
|
|
1625
|
-
inputSchema: {
|
|
1626
|
-
type: "object",
|
|
1627
|
-
properties: {
|
|
1628
|
-
database_id: { type: "string", description: "Database ID to delete" },
|
|
1629
|
-
},
|
|
1630
|
-
required: ["database_id"],
|
|
1631
|
-
},
|
|
1632
|
-
},
|
|
1633
|
-
{
|
|
1634
|
-
name: "database_credentials",
|
|
1635
|
-
description: "Get the connection string and credentials for a database.",
|
|
1636
|
-
inputSchema: {
|
|
1637
|
-
type: "object",
|
|
1638
|
-
properties: {
|
|
1639
|
-
database_id: { type: "string", description: "Database ID" },
|
|
1640
|
-
},
|
|
1641
|
-
required: ["database_id"],
|
|
1642
|
-
},
|
|
1643
|
-
},
|
|
1644
|
-
{
|
|
1645
|
-
name: "database_logs",
|
|
1646
|
-
description: "Get logs for a managed database.",
|
|
1647
|
-
inputSchema: {
|
|
1648
|
-
type: "object",
|
|
1649
|
-
properties: {
|
|
1650
|
-
database_id: { type: "string", description: "Database ID" },
|
|
1651
|
-
lines: {
|
|
1652
|
-
type: "integer",
|
|
1653
|
-
description: "Number of log lines to return (default: 100)",
|
|
1654
|
-
default: 100,
|
|
1655
|
-
},
|
|
1656
|
-
since: {
|
|
1657
|
-
type: "string",
|
|
1658
|
-
description: "ISO 8601 timestamp to fetch logs from (optional)",
|
|
1659
|
-
},
|
|
1660
|
-
},
|
|
1661
|
-
required: ["database_id"],
|
|
1662
|
-
},
|
|
1663
|
-
},
|
|
1664
|
-
// Workspaces
|
|
1665
|
-
{
|
|
1666
|
-
name: "workspace_list",
|
|
1667
|
-
description: "List all workspaces in the tenant.",
|
|
1668
|
-
inputSchema: { type: "object", properties: {} },
|
|
1669
|
-
},
|
|
1670
|
-
{
|
|
1671
|
-
name: "workspace_create",
|
|
1672
|
-
description: "Create a new workspace.",
|
|
1673
|
-
inputSchema: {
|
|
1674
|
-
type: "object",
|
|
1675
|
-
properties: {
|
|
1676
|
-
name: { type: "string", description: "Workspace name" },
|
|
1677
|
-
description: {
|
|
1678
|
-
type: "string",
|
|
1679
|
-
description: "Workspace description (optional)",
|
|
1680
|
-
},
|
|
1681
|
-
},
|
|
1682
|
-
required: ["name"],
|
|
1683
|
-
},
|
|
1684
|
-
},
|
|
1685
|
-
{
|
|
1686
|
-
name: "workspace_get",
|
|
1687
|
-
description: "Get details of a specific workspace.",
|
|
1688
|
-
inputSchema: {
|
|
1689
|
-
type: "object",
|
|
1690
|
-
properties: {
|
|
1691
|
-
workspace_id: { type: "string", description: "Workspace ID" },
|
|
1692
|
-
},
|
|
1693
|
-
required: ["workspace_id"],
|
|
1694
|
-
},
|
|
1695
|
-
},
|
|
1696
|
-
{
|
|
1697
|
-
name: "workspace_update",
|
|
1698
|
-
description: "Update a workspace's name or description.",
|
|
1699
|
-
inputSchema: {
|
|
1700
|
-
type: "object",
|
|
1701
|
-
properties: {
|
|
1702
|
-
workspace_id: { type: "string", description: "Workspace ID" },
|
|
1703
|
-
name: { type: "string", description: "New workspace name (optional)" },
|
|
1704
|
-
description: {
|
|
1705
|
-
type: "string",
|
|
1706
|
-
description: "New description (optional)",
|
|
1707
|
-
},
|
|
1708
|
-
},
|
|
1709
|
-
required: ["workspace_id"],
|
|
1710
|
-
},
|
|
1711
|
-
},
|
|
1712
|
-
{
|
|
1713
|
-
name: "workspace_stats",
|
|
1714
|
-
description: "Get resource statistics for a workspace (computers, sandboxes, databases, etc.).",
|
|
1715
|
-
inputSchema: {
|
|
1716
|
-
type: "object",
|
|
1717
|
-
properties: {
|
|
1718
|
-
workspace_id: { type: "string", description: "Workspace ID" },
|
|
1719
|
-
},
|
|
1720
|
-
required: ["workspace_id"],
|
|
1721
|
-
},
|
|
1722
|
-
},
|
|
1723
|
-
{
|
|
1724
|
-
name: "workspace_usage",
|
|
1725
|
-
description: "Get usage data (compute hours, storage, bandwidth) for a workspace.",
|
|
1726
|
-
inputSchema: {
|
|
1727
|
-
type: "object",
|
|
1728
|
-
properties: {
|
|
1729
|
-
workspace_id: { type: "string", description: "Workspace ID" },
|
|
1730
|
-
period: {
|
|
1731
|
-
type: "string",
|
|
1732
|
-
description: "Billing period (e.g. '2026-05'). Defaults to current month.",
|
|
1733
|
-
},
|
|
1734
|
-
},
|
|
1735
|
-
required: ["workspace_id"],
|
|
1736
|
-
},
|
|
1737
|
-
},
|
|
1738
|
-
// Billing
|
|
1739
|
-
{
|
|
1740
|
-
name: "billing_usage",
|
|
1741
|
-
description: "Get current billing period usage for the tenant.",
|
|
1742
|
-
inputSchema: { type: "object", properties: {} },
|
|
1743
|
-
},
|
|
1744
|
-
{
|
|
1745
|
-
name: "billing_plan",
|
|
1746
|
-
description: "Get the current billing plan details for the tenant.",
|
|
1747
|
-
inputSchema: { type: "object", properties: {} },
|
|
1748
|
-
},
|
|
1749
|
-
// Tunnels / Port forwarding
|
|
1750
|
-
{
|
|
1751
|
-
name: "computer_expose_port",
|
|
1752
|
-
description: "Expose a port on the computer and return the public URL. The URL follows the pattern https://{port}-{slug}.computer.miosa.ai.",
|
|
1753
|
-
inputSchema: {
|
|
1754
|
-
type: "object",
|
|
1755
|
-
properties: {
|
|
1756
|
-
computer_id: { type: "string", description: "Computer ID." },
|
|
1757
|
-
port: { type: "integer", description: "Port number to expose" },
|
|
1758
|
-
protocol: {
|
|
1759
|
-
type: "string",
|
|
1760
|
-
enum: ["http", "https", "tcp"],
|
|
1761
|
-
description: "Protocol (default: http)",
|
|
1762
|
-
},
|
|
1763
|
-
},
|
|
1764
|
-
required: ["computer_id", "port"],
|
|
1765
|
-
},
|
|
1766
|
-
},
|
|
1767
|
-
{
|
|
1768
|
-
name: "computer_list_ports",
|
|
1769
|
-
description: "List all currently exposed ports on the computer.",
|
|
1770
|
-
inputSchema: {
|
|
1771
|
-
type: "object",
|
|
1772
|
-
properties: {
|
|
1773
|
-
computer_id: { type: "string", description: "Computer ID." },
|
|
1774
|
-
},
|
|
1775
|
-
required: ["computer_id"],
|
|
1776
|
-
},
|
|
1777
|
-
},
|
|
1778
|
-
{
|
|
1779
|
-
name: "computer_preview_url",
|
|
1780
|
-
description: "Return the public preview URL for a given port on the computer. Format: https://{port}-{slug}.computer.miosa.ai",
|
|
1781
|
-
inputSchema: {
|
|
1782
|
-
type: "object",
|
|
1783
|
-
properties: {
|
|
1784
|
-
computer_id: { type: "string", description: "Computer ID." },
|
|
1785
|
-
port: { type: "integer", description: "Port number" },
|
|
1786
|
-
},
|
|
1787
|
-
required: ["computer_id", "port"],
|
|
1788
|
-
},
|
|
1789
|
-
},
|
|
1790
|
-
// Network policy
|
|
1791
|
-
{
|
|
1792
|
-
name: "computer_network_policy_get",
|
|
1793
|
-
description: "Get the current network policy (firewall rules) for the computer.",
|
|
1794
|
-
inputSchema: {
|
|
1795
|
-
type: "object",
|
|
1796
|
-
properties: {
|
|
1797
|
-
computer_id: { type: "string", description: "Computer ID." },
|
|
1798
|
-
},
|
|
1799
|
-
required: ["computer_id"],
|
|
1800
|
-
},
|
|
1801
|
-
},
|
|
1802
|
-
{
|
|
1803
|
-
name: "computer_network_policy_set",
|
|
1804
|
-
description: "Set the network policy (firewall rules) for the computer.",
|
|
1805
|
-
inputSchema: {
|
|
1806
|
-
type: "object",
|
|
1807
|
-
properties: {
|
|
1808
|
-
computer_id: { type: "string", description: "Computer ID." },
|
|
1809
|
-
rules: {
|
|
1810
|
-
type: "array",
|
|
1811
|
-
items: { type: "object" },
|
|
1812
|
-
description: "List of firewall rule objects (e.g. {direction, protocol, port, action})",
|
|
1813
|
-
},
|
|
1814
|
-
default_effect: {
|
|
1815
|
-
type: "string",
|
|
1816
|
-
enum: ["allow", "deny"],
|
|
1817
|
-
description: "Default action when no rule matches (default: allow)",
|
|
1818
|
-
},
|
|
1819
|
-
},
|
|
1820
|
-
required: ["computer_id", "rules"],
|
|
1821
|
-
},
|
|
1822
|
-
},
|
|
1823
|
-
{
|
|
1824
|
-
name: "computer_network_policy_reset",
|
|
1825
|
-
description: "Reset the network policy for the computer to the platform default (allow all).",
|
|
1826
|
-
inputSchema: {
|
|
1827
|
-
type: "object",
|
|
1828
|
-
properties: {
|
|
1829
|
-
computer_id: { type: "string", description: "Computer ID." },
|
|
1830
|
-
},
|
|
1831
|
-
required: ["computer_id"],
|
|
1832
|
-
},
|
|
1833
|
-
},
|
|
1834
|
-
// Webhooks
|
|
1835
|
-
{
|
|
1836
|
-
name: "webhook_list",
|
|
1837
|
-
description: "List all webhooks registered in the tenant.",
|
|
1838
|
-
inputSchema: { type: "object", properties: {} },
|
|
1839
|
-
},
|
|
1840
|
-
{
|
|
1841
|
-
name: "webhook_create",
|
|
1842
|
-
description: "Create a new webhook endpoint.",
|
|
1843
|
-
inputSchema: {
|
|
1844
|
-
type: "object",
|
|
1845
|
-
properties: {
|
|
1846
|
-
url: {
|
|
1847
|
-
type: "string",
|
|
1848
|
-
description: "HTTPS URL to deliver webhook events to",
|
|
1849
|
-
},
|
|
1850
|
-
events: {
|
|
1851
|
-
type: "array",
|
|
1852
|
-
items: { type: "string" },
|
|
1853
|
-
description: "List of event types to subscribe to (e.g. ['computer.started', 'computer.stopped'])",
|
|
1854
|
-
},
|
|
1855
|
-
},
|
|
1856
|
-
required: ["url", "events"],
|
|
1857
|
-
},
|
|
1858
|
-
},
|
|
1859
|
-
{
|
|
1860
|
-
name: "webhook_delete",
|
|
1861
|
-
description: "Delete a webhook.",
|
|
1862
|
-
inputSchema: {
|
|
1863
|
-
type: "object",
|
|
1864
|
-
properties: {
|
|
1865
|
-
webhook_id: { type: "string", description: "Webhook ID to delete" },
|
|
1866
|
-
},
|
|
1867
|
-
required: ["webhook_id"],
|
|
1868
|
-
},
|
|
1869
|
-
},
|
|
1870
|
-
{
|
|
1871
|
-
name: "webhook_test",
|
|
1872
|
-
description: "Send a test event delivery to a webhook endpoint.",
|
|
1873
|
-
inputSchema: {
|
|
1874
|
-
type: "object",
|
|
1875
|
-
properties: {
|
|
1876
|
-
webhook_id: { type: "string", description: "Webhook ID to test" },
|
|
1877
|
-
},
|
|
1878
|
-
required: ["webhook_id"],
|
|
1879
|
-
},
|
|
1880
|
-
},
|
|
1881
|
-
// Functions
|
|
1882
|
-
{
|
|
1883
|
-
name: "function_list",
|
|
1884
|
-
description: "List all serverless functions in the tenant.",
|
|
1885
|
-
inputSchema: { type: "object", properties: {} },
|
|
1886
|
-
},
|
|
1887
|
-
{
|
|
1888
|
-
name: "function_create",
|
|
1889
|
-
description: "Create a new serverless function.",
|
|
1890
|
-
inputSchema: {
|
|
1891
|
-
type: "object",
|
|
1892
|
-
properties: {
|
|
1893
|
-
name: { type: "string", description: "Function name" },
|
|
1894
|
-
runtime: {
|
|
1895
|
-
type: "string",
|
|
1896
|
-
description: "Runtime identifier (e.g. 'node20', 'python311', 'go122')",
|
|
1897
|
-
},
|
|
1898
|
-
code: {
|
|
1899
|
-
type: "string",
|
|
1900
|
-
description: "Inline function source code (optional)",
|
|
1901
|
-
},
|
|
1902
|
-
},
|
|
1903
|
-
required: ["name", "runtime"],
|
|
1904
|
-
},
|
|
1905
|
-
},
|
|
1906
|
-
{
|
|
1907
|
-
name: "function_invoke",
|
|
1908
|
-
description: "Invoke a serverless function and return its response.",
|
|
1909
|
-
inputSchema: {
|
|
1910
|
-
type: "object",
|
|
1911
|
-
properties: {
|
|
1912
|
-
function_id: { type: "string", description: "Function ID to invoke" },
|
|
1913
|
-
payload: {
|
|
1914
|
-
type: "object",
|
|
1915
|
-
description: "JSON payload to pass to the function (optional)",
|
|
1916
|
-
},
|
|
1917
|
-
},
|
|
1918
|
-
required: ["function_id"],
|
|
1919
|
-
},
|
|
1920
|
-
},
|
|
1921
|
-
{
|
|
1922
|
-
name: "function_delete",
|
|
1923
|
-
description: "Delete a serverless function permanently.",
|
|
1924
|
-
inputSchema: {
|
|
1925
|
-
type: "object",
|
|
1926
|
-
properties: {
|
|
1927
|
-
function_id: { type: "string", description: "Function ID to delete" },
|
|
1928
|
-
},
|
|
1929
|
-
required: ["function_id"],
|
|
1930
|
-
},
|
|
1931
|
-
},
|
|
1932
|
-
// API Keys
|
|
1933
|
-
{
|
|
1934
|
-
name: "api_key_list",
|
|
1935
|
-
description: "List all API keys for the tenant.",
|
|
1936
|
-
inputSchema: { type: "object", properties: {} },
|
|
1937
|
-
},
|
|
1938
|
-
{
|
|
1939
|
-
name: "api_key_create",
|
|
1940
|
-
description: "Create a new API key.",
|
|
1941
|
-
inputSchema: {
|
|
1942
|
-
type: "object",
|
|
1943
|
-
properties: {
|
|
1944
|
-
name: {
|
|
1945
|
-
type: "string",
|
|
1946
|
-
description: "Human-readable label for the key",
|
|
1947
|
-
},
|
|
1948
|
-
scopes: {
|
|
1949
|
-
type: "array",
|
|
1950
|
-
items: { type: "string" },
|
|
1951
|
-
description: "Permission scopes for the key (optional; defaults to full access)",
|
|
1952
|
-
},
|
|
1953
|
-
},
|
|
1954
|
-
required: ["name"],
|
|
1955
|
-
},
|
|
1956
|
-
},
|
|
1957
|
-
{
|
|
1958
|
-
name: "api_key_delete",
|
|
1959
|
-
description: "Revoke and delete an API key.",
|
|
1960
|
-
inputSchema: {
|
|
1961
|
-
type: "object",
|
|
1962
|
-
properties: {
|
|
1963
|
-
key_id: { type: "string", description: "API key ID to delete" },
|
|
1964
|
-
},
|
|
1965
|
-
required: ["key_id"],
|
|
1966
|
-
},
|
|
1967
|
-
},
|
|
1968
|
-
// Regions
|
|
1969
|
-
{
|
|
1970
|
-
name: "region_list",
|
|
1971
|
-
description: "List available regions and their GPU availability.",
|
|
1972
|
-
inputSchema: { type: "object", properties: {} },
|
|
1973
|
-
},
|
|
1974
|
-
{
|
|
1975
|
-
name: "computer_list_regions",
|
|
1976
|
-
description: "List available compute regions with GPU availability details.",
|
|
1977
|
-
inputSchema: { type: "object", properties: {} },
|
|
1978
|
-
},
|
|
1979
|
-
// Computer templates
|
|
1980
|
-
{
|
|
1981
|
-
name: "computer_template_list",
|
|
1982
|
-
description: "List computer templates available in a workspace.",
|
|
1983
|
-
inputSchema: {
|
|
1984
|
-
type: "object",
|
|
1985
|
-
properties: {
|
|
1986
|
-
workspace_id: {
|
|
1987
|
-
type: "string",
|
|
1988
|
-
description: "Workspace ID to list templates for",
|
|
1989
|
-
},
|
|
1403
|
+
type: 'object',
|
|
1404
|
+
properties: {
|
|
1405
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1406
|
+
lines: { type: 'integer', description: 'Number of log lines to return (default: 100)', default: 100 },
|
|
1407
|
+
since: { type: 'string', description: 'ISO 8601 timestamp to fetch logs from (optional)' },
|
|
1990
1408
|
},
|
|
1991
|
-
required: [
|
|
1409
|
+
required: ['deployment_id'],
|
|
1992
1410
|
},
|
|
1993
1411
|
},
|
|
1994
1412
|
{
|
|
1995
|
-
name:
|
|
1996
|
-
description:
|
|
1413
|
+
name: 'deployment_version_list',
|
|
1414
|
+
description: 'List all versions of a deployment.',
|
|
1997
1415
|
inputSchema: {
|
|
1998
|
-
type:
|
|
1416
|
+
type: 'object',
|
|
1999
1417
|
properties: {
|
|
2000
|
-
|
|
2001
|
-
type: "string",
|
|
2002
|
-
description: "Workspace ID to create the template in",
|
|
2003
|
-
},
|
|
2004
|
-
name: {
|
|
2005
|
-
type: "string",
|
|
2006
|
-
description: "Human-readable name for the template",
|
|
2007
|
-
},
|
|
2008
|
-
template_type: {
|
|
2009
|
-
type: "string",
|
|
2010
|
-
description: "Base template type (e.g. miosa-desktop)",
|
|
2011
|
-
},
|
|
2012
|
-
size: {
|
|
2013
|
-
type: "string",
|
|
2014
|
-
enum: ["small", "medium", "large", "xl"],
|
|
2015
|
-
description: "VM size for the template",
|
|
2016
|
-
},
|
|
2017
|
-
selected_apps: {
|
|
2018
|
-
type: "array",
|
|
2019
|
-
items: { type: "string" },
|
|
2020
|
-
description: "List of app identifiers to pre-install",
|
|
2021
|
-
},
|
|
2022
|
-
settings: {
|
|
2023
|
-
type: "object",
|
|
2024
|
-
description: "Additional template settings (key-value pairs)",
|
|
2025
|
-
},
|
|
1418
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
2026
1419
|
},
|
|
2027
|
-
required: [
|
|
1420
|
+
required: ['deployment_id'],
|
|
2028
1421
|
},
|
|
2029
1422
|
},
|
|
2030
|
-
// Settings
|
|
2031
1423
|
{
|
|
2032
|
-
name:
|
|
2033
|
-
description:
|
|
2034
|
-
inputSchema: {
|
|
1424
|
+
name: 'deployment_version_promote',
|
|
1425
|
+
description: 'Promote a specific version to be the active deployment.',
|
|
1426
|
+
inputSchema: {
|
|
1427
|
+
type: 'object',
|
|
1428
|
+
properties: {
|
|
1429
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1430
|
+
version_id: { type: 'string', description: 'Version ID to promote' },
|
|
1431
|
+
},
|
|
1432
|
+
required: ['deployment_id', 'version_id'],
|
|
1433
|
+
},
|
|
2035
1434
|
},
|
|
1435
|
+
// Storage
|
|
2036
1436
|
{
|
|
2037
|
-
name:
|
|
2038
|
-
description:
|
|
2039
|
-
inputSchema: { type:
|
|
1437
|
+
name: 'storage_bucket_list',
|
|
1438
|
+
description: 'List all storage buckets in the tenant.',
|
|
1439
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2040
1440
|
},
|
|
2041
1441
|
{
|
|
2042
|
-
name:
|
|
2043
|
-
description:
|
|
1442
|
+
name: 'storage_bucket_create',
|
|
1443
|
+
description: 'Create a new storage bucket.',
|
|
2044
1444
|
inputSchema: {
|
|
2045
|
-
type:
|
|
1445
|
+
type: 'object',
|
|
2046
1446
|
properties: {
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
},
|
|
2051
|
-
logo_url: {
|
|
2052
|
-
type: "string",
|
|
2053
|
-
description: "HTTPS URL for the tenant logo (optional)",
|
|
2054
|
-
},
|
|
1447
|
+
name: { type: 'string', description: 'Bucket name' },
|
|
1448
|
+
region: { type: 'string', description: 'Bucket region (optional)' },
|
|
1449
|
+
public: { type: 'boolean', description: 'Whether the bucket is publicly readable (default: false)', default: false },
|
|
2055
1450
|
},
|
|
1451
|
+
required: ['name'],
|
|
2056
1452
|
},
|
|
2057
1453
|
},
|
|
2058
1454
|
{
|
|
2059
|
-
name:
|
|
2060
|
-
description:
|
|
2061
|
-
inputSchema: {
|
|
1455
|
+
name: 'storage_bucket_delete',
|
|
1456
|
+
description: 'Delete a storage bucket.',
|
|
1457
|
+
inputSchema: {
|
|
1458
|
+
type: 'object',
|
|
1459
|
+
properties: {
|
|
1460
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name to delete' },
|
|
1461
|
+
},
|
|
1462
|
+
required: ['bucket_id'],
|
|
1463
|
+
},
|
|
2062
1464
|
},
|
|
2063
|
-
// Sandbox template extensions
|
|
2064
1465
|
{
|
|
2065
|
-
name:
|
|
2066
|
-
description:
|
|
1466
|
+
name: 'storage_object_list',
|
|
1467
|
+
description: 'List objects in a storage bucket, optionally filtered by prefix.',
|
|
2067
1468
|
inputSchema: {
|
|
2068
|
-
type:
|
|
1469
|
+
type: 'object',
|
|
2069
1470
|
properties: {
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
description: "Sandbox template ID or slug",
|
|
2073
|
-
},
|
|
1471
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1472
|
+
prefix: { type: 'string', description: 'Key prefix to filter by (optional)' },
|
|
2074
1473
|
},
|
|
2075
|
-
required: [
|
|
1474
|
+
required: ['bucket_id'],
|
|
2076
1475
|
},
|
|
2077
1476
|
},
|
|
2078
1477
|
{
|
|
2079
|
-
name:
|
|
2080
|
-
description:
|
|
1478
|
+
name: 'storage_object_upload',
|
|
1479
|
+
description: 'Upload an object to a storage bucket.',
|
|
2081
1480
|
inputSchema: {
|
|
2082
|
-
type:
|
|
1481
|
+
type: 'object',
|
|
2083
1482
|
properties: {
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
},
|
|
1483
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1484
|
+
key: { type: 'string', description: 'Object key (path within bucket)' },
|
|
1485
|
+
content: { type: 'string', description: 'Object content (text or base64-encoded binary)' },
|
|
1486
|
+
content_type: { type: 'string', description: 'MIME type of the object (optional)' },
|
|
2088
1487
|
},
|
|
2089
|
-
required: [
|
|
1488
|
+
required: ['bucket_id', 'key', 'content'],
|
|
2090
1489
|
},
|
|
2091
1490
|
},
|
|
2092
|
-
// Cron jobs
|
|
2093
1491
|
{
|
|
2094
|
-
name:
|
|
2095
|
-
description:
|
|
1492
|
+
name: 'storage_object_download',
|
|
1493
|
+
description: 'Download an object from a storage bucket.',
|
|
2096
1494
|
inputSchema: {
|
|
2097
|
-
type:
|
|
1495
|
+
type: 'object',
|
|
2098
1496
|
properties: {
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
description: "Filter cron jobs by computer ID (optional)",
|
|
2102
|
-
},
|
|
1497
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1498
|
+
key: { type: 'string', description: 'Object key to download' },
|
|
2103
1499
|
},
|
|
1500
|
+
required: ['bucket_id', 'key'],
|
|
2104
1501
|
},
|
|
2105
1502
|
},
|
|
2106
1503
|
{
|
|
2107
|
-
name:
|
|
2108
|
-
description:
|
|
1504
|
+
name: 'storage_object_delete',
|
|
1505
|
+
description: 'Delete an object from a storage bucket.',
|
|
2109
1506
|
inputSchema: {
|
|
2110
|
-
type:
|
|
1507
|
+
type: 'object',
|
|
2111
1508
|
properties: {
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
description: "ID of the computer to run the cron job on",
|
|
2115
|
-
},
|
|
2116
|
-
schedule: {
|
|
2117
|
-
type: "string",
|
|
2118
|
-
description: "Cron schedule expression (e.g. '0 * * * *' for hourly)",
|
|
2119
|
-
},
|
|
2120
|
-
command: {
|
|
2121
|
-
type: "string",
|
|
2122
|
-
description: "Shell command to execute",
|
|
2123
|
-
},
|
|
2124
|
-
name: {
|
|
2125
|
-
type: "string",
|
|
2126
|
-
description: "Human-readable name for the cron job (optional)",
|
|
2127
|
-
},
|
|
1509
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1510
|
+
key: { type: 'string', description: 'Object key to delete' },
|
|
2128
1511
|
},
|
|
2129
|
-
required: [
|
|
1512
|
+
required: ['bucket_id', 'key'],
|
|
2130
1513
|
},
|
|
2131
1514
|
},
|
|
2132
1515
|
{
|
|
2133
|
-
name:
|
|
2134
|
-
description:
|
|
1516
|
+
name: 'storage_presign',
|
|
1517
|
+
description: 'Get a presigned URL for temporary access to a storage object.',
|
|
2135
1518
|
inputSchema: {
|
|
2136
|
-
type:
|
|
1519
|
+
type: 'object',
|
|
2137
1520
|
properties: {
|
|
2138
|
-
|
|
1521
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1522
|
+
key: { type: 'string', description: 'Object key' },
|
|
1523
|
+
expires_in: { type: 'integer', description: 'URL expiry in seconds (default: 3600)', default: 3600 },
|
|
1524
|
+
method: { type: 'string', enum: ['GET', 'PUT'], description: 'HTTP method (default: GET)', default: 'GET' },
|
|
2139
1525
|
},
|
|
2140
|
-
required: [
|
|
1526
|
+
required: ['bucket_id', 'key'],
|
|
2141
1527
|
},
|
|
2142
1528
|
},
|
|
1529
|
+
// Databases
|
|
1530
|
+
{
|
|
1531
|
+
name: 'database_list',
|
|
1532
|
+
description: 'List all managed databases in the tenant.',
|
|
1533
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1534
|
+
},
|
|
2143
1535
|
{
|
|
2144
|
-
name:
|
|
2145
|
-
description:
|
|
1536
|
+
name: 'database_create',
|
|
1537
|
+
description: 'Create a new managed database.',
|
|
2146
1538
|
inputSchema: {
|
|
2147
|
-
type:
|
|
1539
|
+
type: 'object',
|
|
2148
1540
|
properties: {
|
|
2149
|
-
|
|
1541
|
+
name: { type: 'string', description: 'Database name' },
|
|
1542
|
+
engine: { type: 'string', enum: ['postgres', 'mysql', 'redis'], description: 'Database engine' },
|
|
1543
|
+
version: { type: 'string', description: 'Engine version (optional)' },
|
|
1544
|
+
size: { type: 'string', description: 'Database size/tier (optional)' },
|
|
1545
|
+
region: { type: 'string', description: 'Region (optional)' },
|
|
2150
1546
|
},
|
|
2151
|
-
required: [
|
|
1547
|
+
required: ['name', 'engine'],
|
|
2152
1548
|
},
|
|
2153
1549
|
},
|
|
2154
1550
|
{
|
|
2155
|
-
name:
|
|
2156
|
-
description:
|
|
1551
|
+
name: 'database_get',
|
|
1552
|
+
description: 'Get details of a specific database.',
|
|
2157
1553
|
inputSchema: {
|
|
2158
|
-
type:
|
|
1554
|
+
type: 'object',
|
|
2159
1555
|
properties: {
|
|
2160
|
-
|
|
1556
|
+
database_id: { type: 'string', description: 'Database ID' },
|
|
2161
1557
|
},
|
|
2162
|
-
required: [
|
|
1558
|
+
required: ['database_id'],
|
|
2163
1559
|
},
|
|
2164
1560
|
},
|
|
2165
1561
|
{
|
|
2166
|
-
name:
|
|
2167
|
-
description:
|
|
1562
|
+
name: 'database_delete',
|
|
1563
|
+
description: 'Delete a managed database permanently.',
|
|
2168
1564
|
inputSchema: {
|
|
2169
|
-
type:
|
|
1565
|
+
type: 'object',
|
|
2170
1566
|
properties: {
|
|
2171
|
-
|
|
1567
|
+
database_id: { type: 'string', description: 'Database ID to delete' },
|
|
2172
1568
|
},
|
|
2173
|
-
required: [
|
|
1569
|
+
required: ['database_id'],
|
|
2174
1570
|
},
|
|
2175
1571
|
},
|
|
2176
1572
|
{
|
|
2177
|
-
name:
|
|
2178
|
-
description:
|
|
1573
|
+
name: 'database_credentials',
|
|
1574
|
+
description: 'Get the connection string and credentials for a database.',
|
|
2179
1575
|
inputSchema: {
|
|
2180
|
-
type:
|
|
1576
|
+
type: 'object',
|
|
2181
1577
|
properties: {
|
|
2182
|
-
|
|
2183
|
-
type: "string",
|
|
2184
|
-
description: "Cron job ID to run immediately",
|
|
2185
|
-
},
|
|
1578
|
+
database_id: { type: 'string', description: 'Database ID' },
|
|
2186
1579
|
},
|
|
2187
|
-
required: [
|
|
1580
|
+
required: ['database_id'],
|
|
2188
1581
|
},
|
|
2189
1582
|
},
|
|
2190
1583
|
{
|
|
2191
|
-
name:
|
|
2192
|
-
description:
|
|
1584
|
+
name: 'database_logs',
|
|
1585
|
+
description: 'Get logs for a managed database.',
|
|
2193
1586
|
inputSchema: {
|
|
2194
|
-
type:
|
|
1587
|
+
type: 'object',
|
|
2195
1588
|
properties: {
|
|
2196
|
-
|
|
1589
|
+
database_id: { type: 'string', description: 'Database ID' },
|
|
1590
|
+
lines: { type: 'integer', description: 'Number of log lines to return (default: 100)', default: 100 },
|
|
1591
|
+
since: { type: 'string', description: 'ISO 8601 timestamp to fetch logs from (optional)' },
|
|
2197
1592
|
},
|
|
2198
|
-
required: [
|
|
1593
|
+
required: ['database_id'],
|
|
2199
1594
|
},
|
|
2200
1595
|
},
|
|
2201
|
-
//
|
|
1596
|
+
// Workspaces
|
|
2202
1597
|
{
|
|
2203
|
-
name:
|
|
2204
|
-
description:
|
|
2205
|
-
inputSchema: { type:
|
|
1598
|
+
name: 'workspace_list',
|
|
1599
|
+
description: 'List all workspaces in the tenant.',
|
|
1600
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2206
1601
|
},
|
|
2207
1602
|
{
|
|
2208
|
-
name:
|
|
2209
|
-
description:
|
|
1603
|
+
name: 'workspace_create',
|
|
1604
|
+
description: 'Create a new workspace.',
|
|
2210
1605
|
inputSchema: {
|
|
2211
|
-
type:
|
|
1606
|
+
type: 'object',
|
|
2212
1607
|
properties: {
|
|
2213
|
-
name: {
|
|
2214
|
-
|
|
2215
|
-
description: "Human-readable name for the volume",
|
|
2216
|
-
},
|
|
2217
|
-
size_gb: {
|
|
2218
|
-
type: "integer",
|
|
2219
|
-
description: "Size of the volume in GB (optional)",
|
|
2220
|
-
},
|
|
2221
|
-
region: {
|
|
2222
|
-
type: "string",
|
|
2223
|
-
description: "Region to create the volume in (optional)",
|
|
2224
|
-
},
|
|
1608
|
+
name: { type: 'string', description: 'Workspace name' },
|
|
1609
|
+
description: { type: 'string', description: 'Workspace description (optional)' },
|
|
2225
1610
|
},
|
|
2226
|
-
required: [
|
|
1611
|
+
required: ['name'],
|
|
2227
1612
|
},
|
|
2228
1613
|
},
|
|
2229
1614
|
{
|
|
2230
|
-
name:
|
|
2231
|
-
description:
|
|
1615
|
+
name: 'workspace_get',
|
|
1616
|
+
description: 'Get details of a specific workspace.',
|
|
2232
1617
|
inputSchema: {
|
|
2233
|
-
type:
|
|
1618
|
+
type: 'object',
|
|
2234
1619
|
properties: {
|
|
2235
|
-
|
|
1620
|
+
workspace_id: { type: 'string', description: 'Workspace ID' },
|
|
2236
1621
|
},
|
|
2237
|
-
required: [
|
|
1622
|
+
required: ['workspace_id'],
|
|
2238
1623
|
},
|
|
2239
1624
|
},
|
|
2240
1625
|
{
|
|
2241
|
-
name:
|
|
2242
|
-
description: "
|
|
1626
|
+
name: 'workspace_update',
|
|
1627
|
+
description: "Update a workspace's name or description.",
|
|
2243
1628
|
inputSchema: {
|
|
2244
|
-
type:
|
|
1629
|
+
type: 'object',
|
|
2245
1630
|
properties: {
|
|
2246
|
-
|
|
1631
|
+
workspace_id: { type: 'string', description: 'Workspace ID' },
|
|
1632
|
+
name: { type: 'string', description: 'New workspace name (optional)' },
|
|
1633
|
+
description: { type: 'string', description: 'New description (optional)' },
|
|
2247
1634
|
},
|
|
2248
|
-
required: [
|
|
1635
|
+
required: ['workspace_id'],
|
|
2249
1636
|
},
|
|
2250
1637
|
},
|
|
2251
1638
|
{
|
|
2252
|
-
name:
|
|
2253
|
-
description:
|
|
1639
|
+
name: 'workspace_stats',
|
|
1640
|
+
description: 'Get resource statistics for a workspace (computers, sandboxes, databases, etc.).',
|
|
2254
1641
|
inputSchema: {
|
|
2255
|
-
type:
|
|
1642
|
+
type: 'object',
|
|
2256
1643
|
properties: {
|
|
2257
|
-
|
|
2258
|
-
type: "string",
|
|
2259
|
-
description: "Computer ID to attach the volume to",
|
|
2260
|
-
},
|
|
2261
|
-
volume_id: { type: "string", description: "Volume ID to attach" },
|
|
2262
|
-
mount_path: {
|
|
2263
|
-
type: "string",
|
|
2264
|
-
description: "Path inside the VM to mount the volume (optional)",
|
|
2265
|
-
},
|
|
1644
|
+
workspace_id: { type: 'string', description: 'Workspace ID' },
|
|
2266
1645
|
},
|
|
2267
|
-
required: [
|
|
1646
|
+
required: ['workspace_id'],
|
|
2268
1647
|
},
|
|
2269
1648
|
},
|
|
2270
1649
|
{
|
|
2271
|
-
name:
|
|
2272
|
-
description:
|
|
1650
|
+
name: 'workspace_usage',
|
|
1651
|
+
description: 'Get usage data (compute hours, storage, bandwidth) for a workspace.',
|
|
2273
1652
|
inputSchema: {
|
|
2274
|
-
type:
|
|
1653
|
+
type: 'object',
|
|
2275
1654
|
properties: {
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
type: "string",
|
|
2279
|
-
description: "Attachment ID to remove",
|
|
2280
|
-
},
|
|
1655
|
+
workspace_id: { type: 'string', description: 'Workspace ID' },
|
|
1656
|
+
period: { type: 'string', description: "Billing period (e.g. '2026-05'). Defaults to current month." },
|
|
2281
1657
|
},
|
|
2282
|
-
required: [
|
|
1658
|
+
required: ['workspace_id'],
|
|
2283
1659
|
},
|
|
2284
1660
|
},
|
|
1661
|
+
// Billing
|
|
1662
|
+
{
|
|
1663
|
+
name: 'billing_usage',
|
|
1664
|
+
description: 'Get current billing period usage for the tenant.',
|
|
1665
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1666
|
+
},
|
|
1667
|
+
{
|
|
1668
|
+
name: 'billing_plan',
|
|
1669
|
+
description: 'Get the current billing plan details for the tenant.',
|
|
1670
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1671
|
+
},
|
|
2285
1672
|
];
|
|
2286
1673
|
// ── Wire helpers ─────────────────────────────────────────────────────────────
|
|
2287
1674
|
function ok(text) {
|
|
@@ -2321,10 +1708,6 @@ async function dispatchTool(client, name, args) {
|
|
|
2321
1708
|
body["external_workspace_id"] = args["external_workspace_id"];
|
|
2322
1709
|
if (args["external_project_id"])
|
|
2323
1710
|
body["external_project_id"] = args["external_project_id"];
|
|
2324
|
-
if (args["gpu_model"]) {
|
|
2325
|
-
body["gpu_model"] = args["gpu_model"];
|
|
2326
|
-
body["gpu_count"] = args["gpu_count"] ?? 1;
|
|
2327
|
-
}
|
|
2328
1711
|
const computer = await client.apiPost("/api/v1/computers", body);
|
|
2329
1712
|
const data = unwrapData(computer);
|
|
2330
1713
|
const id = String(data["id"] ?? "");
|
|
@@ -3355,12 +2738,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3355
2738
|
const lines = ["Deployments:"];
|
|
3356
2739
|
for (const d of items) {
|
|
3357
2740
|
const r = d;
|
|
3358
|
-
lines.push(" " +
|
|
3359
|
-
r["id"] +
|
|
3360
|
-
" " +
|
|
3361
|
-
r["name"] +
|
|
3362
|
-
" " +
|
|
3363
|
-
(r["status"] ?? r["state"] ?? ""));
|
|
2741
|
+
lines.push(" " + r["id"] + " " + r["name"] + " " + (r["status"] ?? r["state"] ?? ""));
|
|
3364
2742
|
}
|
|
3365
2743
|
return ok(lines.join("\n"));
|
|
3366
2744
|
}
|
|
@@ -3383,11 +2761,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3383
2761
|
body["region"] = args["region"];
|
|
3384
2762
|
const result = await client.apiPost("/api/v1/deployments", body);
|
|
3385
2763
|
const data = unwrapData(result);
|
|
3386
|
-
return ok("Created deployment '" +
|
|
3387
|
-
String(data["name"] ?? args["name"]) +
|
|
3388
|
-
"' (id=" +
|
|
3389
|
-
data["id"] +
|
|
3390
|
-
")");
|
|
2764
|
+
return ok("Created deployment '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3391
2765
|
}
|
|
3392
2766
|
if (name === "deployment_delete") {
|
|
3393
2767
|
const did = String(args["deployment_id"] ?? "");
|
|
@@ -3405,11 +2779,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3405
2779
|
body["source"] = args["source"];
|
|
3406
2780
|
const result = await client.apiPost("/api/v1/deployments/" + encodeURIComponent(did) + "/publish", body);
|
|
3407
2781
|
const data = unwrapData(result);
|
|
3408
|
-
return ok("Published deployment " +
|
|
3409
|
-
did +
|
|
3410
|
-
" (version id=" +
|
|
3411
|
-
(data["id"] ?? "unknown") +
|
|
3412
|
-
")");
|
|
2782
|
+
return ok("Published deployment " + did + " (version id=" + (data["id"] ?? "unknown") + ")");
|
|
3413
2783
|
}
|
|
3414
2784
|
if (name === "deployment_rollback") {
|
|
3415
2785
|
const did = String(args["deployment_id"] ?? "");
|
|
@@ -3427,8 +2797,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3427
2797
|
return err("deployment_id is required");
|
|
3428
2798
|
const result = await client.apiGet("/api/v1/deployments/" + encodeURIComponent(did) + "/env");
|
|
3429
2799
|
const envVars = unwrapData(result);
|
|
3430
|
-
if (!envVars ||
|
|
3431
|
-
(Array.isArray(envVars) && envVars.length === 0))
|
|
2800
|
+
if (!envVars || (Array.isArray(envVars) && envVars.length === 0))
|
|
3432
2801
|
return ok("No environment variables set.");
|
|
3433
2802
|
const lines = ["Environment variables:"];
|
|
3434
2803
|
if (typeof envVars === "object" && !Array.isArray(envVars)) {
|
|
@@ -3454,20 +2823,13 @@ async function dispatchTool(client, name, args) {
|
|
|
3454
2823
|
const did = String(args["deployment_id"] ?? "");
|
|
3455
2824
|
if (!did)
|
|
3456
2825
|
return err("deployment_id is required");
|
|
3457
|
-
const params = new URLSearchParams({
|
|
3458
|
-
lines: String(args["lines"] ?? 100),
|
|
3459
|
-
});
|
|
2826
|
+
const params = new URLSearchParams({ lines: String(args["lines"] ?? 100) });
|
|
3460
2827
|
if (args["since"])
|
|
3461
2828
|
params.set("since", String(args["since"]));
|
|
3462
|
-
const result = await client.apiGet("/api/v1/deployments/" +
|
|
3463
|
-
encodeURIComponent(did) +
|
|
3464
|
-
"/logs?" +
|
|
3465
|
-
params.toString());
|
|
2829
|
+
const result = await client.apiGet("/api/v1/deployments/" + encodeURIComponent(did) + "/logs?" + params.toString());
|
|
3466
2830
|
const logs = unwrapData(result);
|
|
3467
2831
|
if (Array.isArray(logs))
|
|
3468
|
-
return ok(logs.length
|
|
3469
|
-
? logs.map(String).join("\n")
|
|
3470
|
-
: "No logs.");
|
|
2832
|
+
return ok(logs.length ? logs.map(String).join("\n") : "No logs.");
|
|
3471
2833
|
return ok(String(logs));
|
|
3472
2834
|
}
|
|
3473
2835
|
if (name === "deployment_version_list") {
|
|
@@ -3481,12 +2843,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3481
2843
|
const lines = ["Versions:"];
|
|
3482
2844
|
for (const v of versions) {
|
|
3483
2845
|
const r = v;
|
|
3484
|
-
lines.push(" " +
|
|
3485
|
-
r["id"] +
|
|
3486
|
-
" " +
|
|
3487
|
-
(r["created_at"] ?? "") +
|
|
3488
|
-
" " +
|
|
3489
|
-
(r["status"] ?? ""));
|
|
2846
|
+
lines.push(" " + r["id"] + " " + (r["created_at"] ?? "") + " " + (r["status"] ?? ""));
|
|
3490
2847
|
}
|
|
3491
2848
|
return ok(lines.join("\n"));
|
|
3492
2849
|
}
|
|
@@ -3497,11 +2854,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3497
2854
|
return err("deployment_id is required");
|
|
3498
2855
|
if (!vid)
|
|
3499
2856
|
return err("version_id is required");
|
|
3500
|
-
await client.apiPost("/api/v1/deployments/" +
|
|
3501
|
-
encodeURIComponent(did) +
|
|
3502
|
-
"/versions/" +
|
|
3503
|
-
encodeURIComponent(vid) +
|
|
3504
|
-
"/promote", {});
|
|
2857
|
+
await client.apiPost("/api/v1/deployments/" + encodeURIComponent(did) + "/versions/" + encodeURIComponent(vid) + "/promote", {});
|
|
3505
2858
|
return ok("Version " + vid + " promoted on deployment " + did + ".");
|
|
3506
2859
|
}
|
|
3507
2860
|
// ── Storage ───────────────────────────────────────────────────────────
|
|
@@ -3525,11 +2878,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3525
2878
|
body["public"] = args["public"];
|
|
3526
2879
|
const result = await client.apiPost("/api/v1/storage/buckets", body);
|
|
3527
2880
|
const data = unwrapData(result);
|
|
3528
|
-
return ok("Created bucket '" +
|
|
3529
|
-
String(data["name"] ?? args["name"]) +
|
|
3530
|
-
"' (id=" +
|
|
3531
|
-
data["id"] +
|
|
3532
|
-
")");
|
|
2881
|
+
return ok("Created bucket '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3533
2882
|
}
|
|
3534
2883
|
if (name === "storage_bucket_delete") {
|
|
3535
2884
|
const bid = String(args["bucket_id"] ?? "");
|
|
@@ -3553,12 +2902,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3553
2902
|
const lines = ["Objects:"];
|
|
3554
2903
|
for (const o of items) {
|
|
3555
2904
|
const r = o;
|
|
3556
|
-
lines.push(" " +
|
|
3557
|
-
r["key"] +
|
|
3558
|
-
" " +
|
|
3559
|
-
(r["size"] ?? "") +
|
|
3560
|
-
" " +
|
|
3561
|
-
(r["last_modified"] ?? ""));
|
|
2905
|
+
lines.push(" " + r["key"] + " " + (r["size"] ?? "") + " " + (r["last_modified"] ?? ""));
|
|
3562
2906
|
}
|
|
3563
2907
|
return ok(lines.join("\n"));
|
|
3564
2908
|
}
|
|
@@ -3577,10 +2921,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3577
2921
|
const bid = String(args["bucket_id"] ?? "");
|
|
3578
2922
|
if (!bid)
|
|
3579
2923
|
return err("bucket_id is required");
|
|
3580
|
-
const result = await client.apiGet("/api/v1/storage/buckets/" +
|
|
3581
|
-
encodeURIComponent(bid) +
|
|
3582
|
-
"/objects/" +
|
|
3583
|
-
encodeURIComponent(String(args["key"] ?? "")));
|
|
2924
|
+
const result = await client.apiGet("/api/v1/storage/buckets/" + encodeURIComponent(bid) + "/objects/" + encodeURIComponent(String(args["key"] ?? "")));
|
|
3584
2925
|
const data = unwrapData(result);
|
|
3585
2926
|
const content = typeof data["content"] === "string"
|
|
3586
2927
|
? Buffer.from(data["content"], "base64").toString("utf8")
|
|
@@ -3593,10 +2934,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3593
2934
|
const bid = String(args["bucket_id"] ?? "");
|
|
3594
2935
|
if (!bid)
|
|
3595
2936
|
return err("bucket_id is required");
|
|
3596
|
-
await client.apiDelete("/api/v1/storage/buckets/" +
|
|
3597
|
-
encodeURIComponent(bid) +
|
|
3598
|
-
"/objects/" +
|
|
3599
|
-
encodeURIComponent(String(args["key"] ?? "")));
|
|
2937
|
+
await client.apiDelete("/api/v1/storage/buckets/" + encodeURIComponent(bid) + "/objects/" + encodeURIComponent(String(args["key"] ?? "")));
|
|
3600
2938
|
return ok("Deleted " + String(args["key"]) + " from bucket " + bid + ".");
|
|
3601
2939
|
}
|
|
3602
2940
|
if (name === "storage_presign") {
|
|
@@ -3620,33 +2958,19 @@ async function dispatchTool(client, name, args) {
|
|
|
3620
2958
|
const lines = ["Databases:"];
|
|
3621
2959
|
for (const d of items) {
|
|
3622
2960
|
const r = d;
|
|
3623
|
-
lines.push(" " +
|
|
3624
|
-
r["id"] +
|
|
3625
|
-
" " +
|
|
3626
|
-
r["name"] +
|
|
3627
|
-
" " +
|
|
3628
|
-
(r["engine"] ?? "") +
|
|
3629
|
-
" " +
|
|
3630
|
-
(r["status"] ?? ""));
|
|
2961
|
+
lines.push(" " + r["id"] + " " + r["name"] + " " + (r["engine"] ?? "") + " " + (r["status"] ?? ""));
|
|
3631
2962
|
}
|
|
3632
2963
|
return ok(lines.join("\n"));
|
|
3633
2964
|
}
|
|
3634
2965
|
if (name === "database_create") {
|
|
3635
|
-
const body = {
|
|
3636
|
-
name: args["name"],
|
|
3637
|
-
engine: args["engine"],
|
|
3638
|
-
};
|
|
2966
|
+
const body = { name: args["name"], engine: args["engine"] };
|
|
3639
2967
|
for (const key of ["version", "size", "region"]) {
|
|
3640
2968
|
if (args[key])
|
|
3641
2969
|
body[key] = args[key];
|
|
3642
2970
|
}
|
|
3643
2971
|
const result = await client.apiPost("/api/v1/databases", body);
|
|
3644
2972
|
const data = unwrapData(result);
|
|
3645
|
-
return ok("Created database '" +
|
|
3646
|
-
String(data["name"] ?? args["name"]) +
|
|
3647
|
-
"' (id=" +
|
|
3648
|
-
data["id"] +
|
|
3649
|
-
")");
|
|
2973
|
+
return ok("Created database '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3650
2974
|
}
|
|
3651
2975
|
if (name === "database_get") {
|
|
3652
2976
|
const dbid = String(args["database_id"] ?? "");
|
|
@@ -3669,14 +2993,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3669
2993
|
const result = await client.apiGet("/api/v1/databases/" + encodeURIComponent(dbid) + "/credentials");
|
|
3670
2994
|
const data = unwrapData(result);
|
|
3671
2995
|
const lines = ["Database credentials:"];
|
|
3672
|
-
for (const field of [
|
|
3673
|
-
"connection_string",
|
|
3674
|
-
"host",
|
|
3675
|
-
"port",
|
|
3676
|
-
"database",
|
|
3677
|
-
"username",
|
|
3678
|
-
"password",
|
|
3679
|
-
]) {
|
|
2996
|
+
for (const field of ["connection_string", "host", "port", "database", "username", "password"]) {
|
|
3680
2997
|
if (data[field])
|
|
3681
2998
|
lines.push(" " + field + ": " + data[field]);
|
|
3682
2999
|
}
|
|
@@ -3686,20 +3003,13 @@ async function dispatchTool(client, name, args) {
|
|
|
3686
3003
|
const dbid = String(args["database_id"] ?? "");
|
|
3687
3004
|
if (!dbid)
|
|
3688
3005
|
return err("database_id is required");
|
|
3689
|
-
const params = new URLSearchParams({
|
|
3690
|
-
lines: String(args["lines"] ?? 100),
|
|
3691
|
-
});
|
|
3006
|
+
const params = new URLSearchParams({ lines: String(args["lines"] ?? 100) });
|
|
3692
3007
|
if (args["since"])
|
|
3693
3008
|
params.set("since", String(args["since"]));
|
|
3694
|
-
const result = await client.apiGet("/api/v1/databases/" +
|
|
3695
|
-
encodeURIComponent(dbid) +
|
|
3696
|
-
"/logs?" +
|
|
3697
|
-
params.toString());
|
|
3009
|
+
const result = await client.apiGet("/api/v1/databases/" + encodeURIComponent(dbid) + "/logs?" + params.toString());
|
|
3698
3010
|
const logs = unwrapData(result);
|
|
3699
3011
|
if (Array.isArray(logs))
|
|
3700
|
-
return ok(logs.length
|
|
3701
|
-
? logs.map(String).join("\n")
|
|
3702
|
-
: "No logs.");
|
|
3012
|
+
return ok(logs.length ? logs.map(String).join("\n") : "No logs.");
|
|
3703
3013
|
return ok(String(logs));
|
|
3704
3014
|
}
|
|
3705
3015
|
// ── Workspaces ────────────────────────────────────────────────────────
|
|
@@ -3721,11 +3031,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3721
3031
|
body["description"] = args["description"];
|
|
3722
3032
|
const result = await client.apiPost("/api/v1/workspaces", body);
|
|
3723
3033
|
const data = unwrapData(result);
|
|
3724
|
-
return ok("Created workspace '" +
|
|
3725
|
-
String(data["name"] ?? args["name"]) +
|
|
3726
|
-
"' (id=" +
|
|
3727
|
-
data["id"] +
|
|
3728
|
-
")");
|
|
3034
|
+
return ok("Created workspace '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3729
3035
|
}
|
|
3730
3036
|
if (name === "workspace_get") {
|
|
3731
3037
|
const wid = String(args["workspace_id"] ?? "");
|
|
@@ -3773,425 +3079,6 @@ async function dispatchTool(client, name, args) {
|
|
|
3773
3079
|
const result = await client.apiGet("/api/v1/billing/plan");
|
|
3774
3080
|
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
3775
3081
|
}
|
|
3776
|
-
// ── Tunnels / Port forwarding ─────────────────────────────────────────
|
|
3777
|
-
if (name === "computer_expose_port") {
|
|
3778
|
-
if (!cid)
|
|
3779
|
-
return err("computer_id is required");
|
|
3780
|
-
const body = { port: args["port"] };
|
|
3781
|
-
if (args["protocol"])
|
|
3782
|
-
body["protocol"] = args["protocol"];
|
|
3783
|
-
const result = await client.apiPost(`/api/v1/computers/${encodeURIComponent(cid)}/ports`, body);
|
|
3784
|
-
const data = unwrapData(result);
|
|
3785
|
-
const url = String(data["url"] ?? data["public_url"] ?? "");
|
|
3786
|
-
return ok(`Port ${args["port"]} exposed. URL: ${url}`);
|
|
3787
|
-
}
|
|
3788
|
-
if (name === "computer_list_ports") {
|
|
3789
|
-
if (!cid)
|
|
3790
|
-
return err("computer_id is required");
|
|
3791
|
-
const result = await client.apiGet(`/api/v1/computers/${encodeURIComponent(cid)}/ports`);
|
|
3792
|
-
const items = listOf(result);
|
|
3793
|
-
if (items.length === 0)
|
|
3794
|
-
return ok("No ports currently exposed.");
|
|
3795
|
-
const lines = ["Exposed ports:"];
|
|
3796
|
-
for (const p of items) {
|
|
3797
|
-
const r = p;
|
|
3798
|
-
lines.push(` port=${r["port"]} protocol=${r["protocol"] ?? "http"} url=${r["url"] ?? r["public_url"] ?? ""}`);
|
|
3799
|
-
}
|
|
3800
|
-
return ok(lines.join("\n"));
|
|
3801
|
-
}
|
|
3802
|
-
if (name === "computer_preview_url") {
|
|
3803
|
-
if (!cid)
|
|
3804
|
-
return err("computer_id is required");
|
|
3805
|
-
const port = args["port"];
|
|
3806
|
-
const result = await client.apiGet(`/api/v1/computers/${encodeURIComponent(cid)}/ports/${encodeURIComponent(String(port))}/url`);
|
|
3807
|
-
const data = unwrapData(result);
|
|
3808
|
-
const url = String(data["url"] ?? data["public_url"] ?? "") ||
|
|
3809
|
-
`https://${port}-${cid}.computer.miosa.ai`;
|
|
3810
|
-
return ok(`Preview URL: ${url}`);
|
|
3811
|
-
}
|
|
3812
|
-
// ── Network policy ────────────────────────────────────────────────────
|
|
3813
|
-
if (name === "computer_network_policy_get") {
|
|
3814
|
-
if (!cid)
|
|
3815
|
-
return err("computer_id is required");
|
|
3816
|
-
const result = await client.apiGet(`/api/v1/computers/${encodeURIComponent(cid)}/network-policy`);
|
|
3817
|
-
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
3818
|
-
}
|
|
3819
|
-
if (name === "computer_network_policy_set") {
|
|
3820
|
-
if (!cid)
|
|
3821
|
-
return err("computer_id is required");
|
|
3822
|
-
const body = { rules: args["rules"] };
|
|
3823
|
-
if (args["default_effect"])
|
|
3824
|
-
body["default_effect"] = args["default_effect"];
|
|
3825
|
-
await client.apiPut(`/api/v1/computers/${encodeURIComponent(cid)}/network-policy`, body);
|
|
3826
|
-
return ok(`Network policy updated for computer ${cid}.`);
|
|
3827
|
-
}
|
|
3828
|
-
if (name === "computer_network_policy_reset") {
|
|
3829
|
-
if (!cid)
|
|
3830
|
-
return err("computer_id is required");
|
|
3831
|
-
await client.apiDelete(`/api/v1/computers/${encodeURIComponent(cid)}/network-policy`);
|
|
3832
|
-
return ok(`Network policy reset to default for computer ${cid}.`);
|
|
3833
|
-
}
|
|
3834
|
-
// ── Webhooks ──────────────────────────────────────────────────────────
|
|
3835
|
-
if (name === "webhook_list") {
|
|
3836
|
-
const result = await client.apiGet("/api/v1/webhooks");
|
|
3837
|
-
const items = listOf(result);
|
|
3838
|
-
if (items.length === 0)
|
|
3839
|
-
return ok("No webhooks found.");
|
|
3840
|
-
const lines = ["Webhooks:"];
|
|
3841
|
-
for (const w of items) {
|
|
3842
|
-
const r = w;
|
|
3843
|
-
lines.push(` ${r["id"]} ${r["url"]} events=${JSON.stringify(r["events"] ?? [])}`);
|
|
3844
|
-
}
|
|
3845
|
-
return ok(lines.join("\n"));
|
|
3846
|
-
}
|
|
3847
|
-
if (name === "webhook_create") {
|
|
3848
|
-
const result = await client.apiPost("/api/v1/webhooks", {
|
|
3849
|
-
url: args["url"],
|
|
3850
|
-
events: args["events"],
|
|
3851
|
-
});
|
|
3852
|
-
const data = unwrapData(result);
|
|
3853
|
-
return ok(`Created webhook (id=${data["id"] ?? "?"}).`);
|
|
3854
|
-
}
|
|
3855
|
-
if (name === "webhook_delete") {
|
|
3856
|
-
const whId = String(args["webhook_id"] ?? "");
|
|
3857
|
-
if (!whId)
|
|
3858
|
-
return err("webhook_id is required");
|
|
3859
|
-
await client.apiDelete(`/api/v1/webhooks/${encodeURIComponent(whId)}`);
|
|
3860
|
-
return ok(`Webhook ${whId} deleted.`);
|
|
3861
|
-
}
|
|
3862
|
-
if (name === "webhook_test") {
|
|
3863
|
-
const whId = String(args["webhook_id"] ?? "");
|
|
3864
|
-
if (!whId)
|
|
3865
|
-
return err("webhook_id is required");
|
|
3866
|
-
const result = await client.apiPost(`/api/v1/webhooks/${encodeURIComponent(whId)}/test`, {});
|
|
3867
|
-
const data = unwrapData(result);
|
|
3868
|
-
const status = String(data["status"] ?? "delivered");
|
|
3869
|
-
return ok(`Test event sent to webhook ${whId} (status=${status}).`);
|
|
3870
|
-
}
|
|
3871
|
-
// ── Functions ─────────────────────────────────────────────────────────
|
|
3872
|
-
if (name === "function_list") {
|
|
3873
|
-
const result = await client.apiGet("/api/v1/functions");
|
|
3874
|
-
const items = listOf(result);
|
|
3875
|
-
if (items.length === 0)
|
|
3876
|
-
return ok("No functions found.");
|
|
3877
|
-
const lines = ["Functions:"];
|
|
3878
|
-
for (const f of items) {
|
|
3879
|
-
const r = f;
|
|
3880
|
-
lines.push(` ${r["id"]} ${r["name"]} runtime=${r["runtime"] ?? ""}`);
|
|
3881
|
-
}
|
|
3882
|
-
return ok(lines.join("\n"));
|
|
3883
|
-
}
|
|
3884
|
-
if (name === "function_create") {
|
|
3885
|
-
const body = {
|
|
3886
|
-
name: args["name"],
|
|
3887
|
-
runtime: args["runtime"],
|
|
3888
|
-
};
|
|
3889
|
-
if (args["code"])
|
|
3890
|
-
body["code"] = args["code"];
|
|
3891
|
-
const result = await client.apiPost("/api/v1/functions", body);
|
|
3892
|
-
const data = unwrapData(result);
|
|
3893
|
-
return ok(`Created function '${data["name"] ?? args["name"]}' (id=${data["id"]}).`);
|
|
3894
|
-
}
|
|
3895
|
-
if (name === "function_invoke") {
|
|
3896
|
-
const fnId = String(args["function_id"] ?? "");
|
|
3897
|
-
if (!fnId)
|
|
3898
|
-
return err("function_id is required");
|
|
3899
|
-
const body = {};
|
|
3900
|
-
if (args["payload"] !== undefined)
|
|
3901
|
-
body["payload"] = args["payload"];
|
|
3902
|
-
const result = await client.apiPost(`/api/v1/functions/${encodeURIComponent(fnId)}/invoke`, body);
|
|
3903
|
-
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
3904
|
-
}
|
|
3905
|
-
if (name === "function_delete") {
|
|
3906
|
-
const fnId = String(args["function_id"] ?? "");
|
|
3907
|
-
if (!fnId)
|
|
3908
|
-
return err("function_id is required");
|
|
3909
|
-
await client.apiDelete(`/api/v1/functions/${encodeURIComponent(fnId)}`);
|
|
3910
|
-
return ok(`Function ${fnId} deleted.`);
|
|
3911
|
-
}
|
|
3912
|
-
// ── API Keys ──────────────────────────────────────────────────────────
|
|
3913
|
-
if (name === "api_key_list") {
|
|
3914
|
-
const result = await client.apiGet("/api/v1/api-keys");
|
|
3915
|
-
const items = listOf(result);
|
|
3916
|
-
if (items.length === 0)
|
|
3917
|
-
return ok("No API keys found.");
|
|
3918
|
-
const lines = ["API keys:"];
|
|
3919
|
-
for (const k of items) {
|
|
3920
|
-
const r = k;
|
|
3921
|
-
const scopes = Array.isArray(r["scopes"])
|
|
3922
|
-
? r["scopes"].join(", ")
|
|
3923
|
-
: String(r["scopes"] ?? "");
|
|
3924
|
-
lines.push(` ${r["id"]} ${r["name"]} scopes=[${scopes}]`);
|
|
3925
|
-
}
|
|
3926
|
-
return ok(lines.join("\n"));
|
|
3927
|
-
}
|
|
3928
|
-
if (name === "api_key_create") {
|
|
3929
|
-
const body = { name: args["name"] };
|
|
3930
|
-
if (args["scopes"])
|
|
3931
|
-
body["scopes"] = args["scopes"];
|
|
3932
|
-
const result = await client.apiPost("/api/v1/api-keys", body);
|
|
3933
|
-
const data = unwrapData(result);
|
|
3934
|
-
const keyId = String(data["id"] ?? "?");
|
|
3935
|
-
const keyValue = String(data["key"] ?? data["token"] ?? data["secret"] ?? "");
|
|
3936
|
-
let msg = `Created API key '${args["name"]}' (id=${keyId}).`;
|
|
3937
|
-
if (keyValue)
|
|
3938
|
-
msg += `\nKey value (shown once): ${keyValue}`;
|
|
3939
|
-
return ok(msg);
|
|
3940
|
-
}
|
|
3941
|
-
if (name === "api_key_delete") {
|
|
3942
|
-
const keyId = String(args["key_id"] ?? "");
|
|
3943
|
-
if (!keyId)
|
|
3944
|
-
return err("key_id is required");
|
|
3945
|
-
await client.apiDelete(`/api/v1/api-keys/${encodeURIComponent(keyId)}`);
|
|
3946
|
-
return ok(`API key ${keyId} deleted.`);
|
|
3947
|
-
}
|
|
3948
|
-
// ── Cron jobs ─────────────────────────────────────────────────────────
|
|
3949
|
-
if (name === "cron_list") {
|
|
3950
|
-
const params = new URLSearchParams();
|
|
3951
|
-
if (args["computer_id"])
|
|
3952
|
-
params.set("computer_id", String(args["computer_id"]));
|
|
3953
|
-
const qs = params.toString() ? `?${params.toString()}` : "";
|
|
3954
|
-
const result = await client.apiGet(`/api/v1/cron-jobs${qs}`);
|
|
3955
|
-
const items = listOf(result);
|
|
3956
|
-
if (items.length === 0)
|
|
3957
|
-
return ok("No cron jobs found.");
|
|
3958
|
-
const lines = ["Cron jobs:"];
|
|
3959
|
-
for (const j of items) {
|
|
3960
|
-
const r = j;
|
|
3961
|
-
lines.push(` ${r["id"]} ${r["name"] ?? ""} ${r["schedule"] ?? ""} status=${r["status"] ?? r["state"] ?? ""}`);
|
|
3962
|
-
}
|
|
3963
|
-
return ok(lines.join("\n"));
|
|
3964
|
-
}
|
|
3965
|
-
if (name === "cron_create") {
|
|
3966
|
-
const body = {
|
|
3967
|
-
computer_id: args["computer_id"],
|
|
3968
|
-
schedule: args["schedule"],
|
|
3969
|
-
command: args["command"],
|
|
3970
|
-
};
|
|
3971
|
-
if (args["name"])
|
|
3972
|
-
body["name"] = args["name"];
|
|
3973
|
-
const result = await client.apiPost("/api/v1/cron-jobs", body);
|
|
3974
|
-
const data = unwrapData(result);
|
|
3975
|
-
return ok(`Created cron job '${data["name"] ?? args["name"] ?? ""}' (id=${data["id"]}).`);
|
|
3976
|
-
}
|
|
3977
|
-
if (name === "cron_get") {
|
|
3978
|
-
const cronId = String(args["cron_id"] ?? "");
|
|
3979
|
-
if (!cronId)
|
|
3980
|
-
return err("cron_id is required");
|
|
3981
|
-
const result = await client.apiGet(`/api/v1/cron-jobs/${encodeURIComponent(cronId)}`);
|
|
3982
|
-
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
3983
|
-
}
|
|
3984
|
-
if (name === "cron_delete") {
|
|
3985
|
-
const cronId = String(args["cron_id"] ?? "");
|
|
3986
|
-
if (!cronId)
|
|
3987
|
-
return err("cron_id is required");
|
|
3988
|
-
await client.apiDelete(`/api/v1/cron-jobs/${encodeURIComponent(cronId)}`);
|
|
3989
|
-
return ok(`Cron job ${cronId} deleted.`);
|
|
3990
|
-
}
|
|
3991
|
-
if (name === "cron_pause") {
|
|
3992
|
-
const cronId = String(args["cron_id"] ?? "");
|
|
3993
|
-
if (!cronId)
|
|
3994
|
-
return err("cron_id is required");
|
|
3995
|
-
await client.apiPost(`/api/v1/cron-jobs/${encodeURIComponent(cronId)}/pause`, {});
|
|
3996
|
-
return ok(`Cron job ${cronId} paused.`);
|
|
3997
|
-
}
|
|
3998
|
-
if (name === "cron_resume") {
|
|
3999
|
-
const cronId = String(args["cron_id"] ?? "");
|
|
4000
|
-
if (!cronId)
|
|
4001
|
-
return err("cron_id is required");
|
|
4002
|
-
await client.apiPost(`/api/v1/cron-jobs/${encodeURIComponent(cronId)}/resume`, {});
|
|
4003
|
-
return ok(`Cron job ${cronId} resumed.`);
|
|
4004
|
-
}
|
|
4005
|
-
if (name === "cron_run_now") {
|
|
4006
|
-
const cronId = String(args["cron_id"] ?? "");
|
|
4007
|
-
if (!cronId)
|
|
4008
|
-
return err("cron_id is required");
|
|
4009
|
-
const result = await client.apiPost(`/api/v1/cron-jobs/${encodeURIComponent(cronId)}/run-now`, {});
|
|
4010
|
-
const data = unwrapData(result);
|
|
4011
|
-
const execId = data["id"] ?? data["execution_id"];
|
|
4012
|
-
return ok(`Cron job ${cronId} triggered.${execId ? ` Execution id=${execId}.` : ""}`);
|
|
4013
|
-
}
|
|
4014
|
-
if (name === "cron_executions") {
|
|
4015
|
-
const cronId = String(args["cron_id"] ?? "");
|
|
4016
|
-
if (!cronId)
|
|
4017
|
-
return err("cron_id is required");
|
|
4018
|
-
const result = await client.apiGet(`/api/v1/cron-jobs/${encodeURIComponent(cronId)}/executions`);
|
|
4019
|
-
const items = listOf(result);
|
|
4020
|
-
if (items.length === 0)
|
|
4021
|
-
return ok("No executions found.");
|
|
4022
|
-
const lines = ["Executions:"];
|
|
4023
|
-
for (const e of items) {
|
|
4024
|
-
const r = e;
|
|
4025
|
-
lines.push(` ${r["id"]} ${r["started_at"] ?? r["created_at"] ?? ""} status=${r["status"] ?? ""} exit_code=${r["exit_code"] ?? ""}`);
|
|
4026
|
-
}
|
|
4027
|
-
return ok(lines.join("\n"));
|
|
4028
|
-
}
|
|
4029
|
-
// ── Regions ────────────────────────────────────────────────────────────
|
|
4030
|
-
if (name === "region_list" || name === "computer_list_regions") {
|
|
4031
|
-
const result = await client.apiGet("/api/v1/regions");
|
|
4032
|
-
const regions = (() => {
|
|
4033
|
-
const d = unwrapData(result);
|
|
4034
|
-
if (Array.isArray(d))
|
|
4035
|
-
return d;
|
|
4036
|
-
const r = d;
|
|
4037
|
-
for (const key of ["regions", "data", "items"]) {
|
|
4038
|
-
if (Array.isArray(r[key]))
|
|
4039
|
-
return r[key];
|
|
4040
|
-
}
|
|
4041
|
-
return Object.values(r);
|
|
4042
|
-
})();
|
|
4043
|
-
if (regions.length === 0)
|
|
4044
|
-
return ok("No regions found.");
|
|
4045
|
-
const lines = ["Regions:"];
|
|
4046
|
-
for (const region of regions) {
|
|
4047
|
-
const r = region;
|
|
4048
|
-
const gpuTypes = r["gpu_types"] ?? r["gpus"] ?? [];
|
|
4049
|
-
const gpuInfo = Array.isArray(gpuTypes) && gpuTypes.length > 0
|
|
4050
|
-
? ` gpus=${JSON.stringify(gpuTypes)}`
|
|
4051
|
-
: "";
|
|
4052
|
-
lines.push(` ${r["id"] ?? r["slug"] ?? ""} ${r["name"] ?? ""} status=${r["status"] ?? "available"}${gpuInfo}`);
|
|
4053
|
-
}
|
|
4054
|
-
return ok(lines.join("\n"));
|
|
4055
|
-
}
|
|
4056
|
-
// ── Computer templates ─────────────────────────────────────────────────
|
|
4057
|
-
if (name === "computer_template_list") {
|
|
4058
|
-
const wid = String(args["workspace_id"] ?? "");
|
|
4059
|
-
if (!wid)
|
|
4060
|
-
return err("workspace_id is required");
|
|
4061
|
-
const result = await client.apiGet(`/api/v1/workspaces/${encodeURIComponent(wid)}/computer-templates`);
|
|
4062
|
-
const items = listOf(result);
|
|
4063
|
-
if (items.length === 0)
|
|
4064
|
-
return ok("No computer templates found.");
|
|
4065
|
-
const lines = ["Computer templates:"];
|
|
4066
|
-
for (const t of items) {
|
|
4067
|
-
const r = t;
|
|
4068
|
-
lines.push(` ${r["id"]} ${r["name"]} type=${r["template_type"] ?? ""} size=${r["size"] ?? ""}`);
|
|
4069
|
-
}
|
|
4070
|
-
return ok(lines.join("\n"));
|
|
4071
|
-
}
|
|
4072
|
-
if (name === "computer_template_create") {
|
|
4073
|
-
const wid = String(args["workspace_id"] ?? "");
|
|
4074
|
-
if (!wid)
|
|
4075
|
-
return err("workspace_id is required");
|
|
4076
|
-
const body = { name: args["name"] };
|
|
4077
|
-
if (args["template_type"])
|
|
4078
|
-
body["template_type"] = args["template_type"];
|
|
4079
|
-
if (args["size"])
|
|
4080
|
-
body["size"] = args["size"];
|
|
4081
|
-
if (args["selected_apps"])
|
|
4082
|
-
body["selected_apps"] = args["selected_apps"];
|
|
4083
|
-
if (args["settings"])
|
|
4084
|
-
body["settings"] = args["settings"];
|
|
4085
|
-
const result = await client.apiPost(`/api/v1/workspaces/${encodeURIComponent(wid)}/computer-templates`, body);
|
|
4086
|
-
const data = unwrapData(result);
|
|
4087
|
-
return ok(`Created computer template '${data["name"] ?? args["name"]}' (id=${data["id"]}).`);
|
|
4088
|
-
}
|
|
4089
|
-
// ── Settings ───────────────────────────────────────────────────────────
|
|
4090
|
-
if (name === "settings_get") {
|
|
4091
|
-
const result = await client.apiGet("/api/v1/settings");
|
|
4092
|
-
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
4093
|
-
}
|
|
4094
|
-
if (name === "settings_get_branding") {
|
|
4095
|
-
const result = await client.apiGet("/api/v1/settings/branding");
|
|
4096
|
-
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
4097
|
-
}
|
|
4098
|
-
if (name === "settings_update_branding") {
|
|
4099
|
-
const body = {};
|
|
4100
|
-
if (args["desktop_wallpaper_url"])
|
|
4101
|
-
body["desktop_wallpaper_url"] = args["desktop_wallpaper_url"];
|
|
4102
|
-
if (args["logo_url"])
|
|
4103
|
-
body["logo_url"] = args["logo_url"];
|
|
4104
|
-
const result = await client.apiPut("/api/v1/settings/branding", body);
|
|
4105
|
-
return ok(`Branding updated: ${JSON.stringify(unwrapData(result), null, 2)}`);
|
|
4106
|
-
}
|
|
4107
|
-
if (name === "settings_compute_pricing") {
|
|
4108
|
-
const result = await client.apiGet("/api/v1/settings/compute-pricing");
|
|
4109
|
-
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
4110
|
-
}
|
|
4111
|
-
// ── Sandbox template extensions ────────────────────────────────────────
|
|
4112
|
-
if (name === "sandbox_template_get") {
|
|
4113
|
-
const tid = String(args["template_id"] ?? "");
|
|
4114
|
-
if (!tid)
|
|
4115
|
-
return err("template_id is required");
|
|
4116
|
-
const result = await client.apiGet(`/api/v1/sandbox-templates/${encodeURIComponent(tid)}`);
|
|
4117
|
-
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
4118
|
-
}
|
|
4119
|
-
if (name === "sandbox_template_builds") {
|
|
4120
|
-
const tid = String(args["template_id"] ?? "");
|
|
4121
|
-
if (!tid)
|
|
4122
|
-
return err("template_id is required");
|
|
4123
|
-
const result = await client.apiGet(`/api/v1/sandbox-templates/${encodeURIComponent(tid)}/builds`);
|
|
4124
|
-
const items = listOf(result);
|
|
4125
|
-
if (items.length === 0)
|
|
4126
|
-
return ok("No builds found.");
|
|
4127
|
-
const lines = ["Builds:"];
|
|
4128
|
-
for (const b of items) {
|
|
4129
|
-
const r = b;
|
|
4130
|
-
lines.push(` ${r["id"]} ${r["status"] ?? ""} created_at=${r["created_at"] ?? ""}`);
|
|
4131
|
-
}
|
|
4132
|
-
return ok(lines.join("\n"));
|
|
4133
|
-
}
|
|
4134
|
-
// ── Volumes ───────────────────────────────────────────────────────────
|
|
4135
|
-
if (name === "volume_list") {
|
|
4136
|
-
const result = await client.apiGet("/api/v1/volumes");
|
|
4137
|
-
const items = listOf(result);
|
|
4138
|
-
if (items.length === 0)
|
|
4139
|
-
return ok("No volumes found.");
|
|
4140
|
-
const lines = ["Volumes:"];
|
|
4141
|
-
for (const v of items) {
|
|
4142
|
-
const r = v;
|
|
4143
|
-
lines.push(` ${r["id"]} ${r["name"]} size_gb=${r["size_gb"] ?? ""} region=${r["region"] ?? ""} status=${r["status"] ?? ""}`);
|
|
4144
|
-
}
|
|
4145
|
-
return ok(lines.join("\n"));
|
|
4146
|
-
}
|
|
4147
|
-
if (name === "volume_create") {
|
|
4148
|
-
const body = { name: args["name"] };
|
|
4149
|
-
if (args["size_gb"] !== undefined)
|
|
4150
|
-
body["size_gb"] = args["size_gb"];
|
|
4151
|
-
if (args["region"])
|
|
4152
|
-
body["region"] = args["region"];
|
|
4153
|
-
const result = await client.apiPost("/api/v1/volumes", body);
|
|
4154
|
-
const data = unwrapData(result);
|
|
4155
|
-
return ok(`Created volume '${data["name"] ?? args["name"]}' (id=${data["id"]}).`);
|
|
4156
|
-
}
|
|
4157
|
-
if (name === "volume_get") {
|
|
4158
|
-
const vid = String(args["volume_id"] ?? "");
|
|
4159
|
-
if (!vid)
|
|
4160
|
-
return err("volume_id is required");
|
|
4161
|
-
const result = await client.apiGet(`/api/v1/volumes/${encodeURIComponent(vid)}`);
|
|
4162
|
-
const data = unwrapData(result);
|
|
4163
|
-
return ok(`id=${data["id"]} name=${JSON.stringify(data["name"])} size_gb=${data["size_gb"] ?? ""} region=${data["region"] ?? ""} status=${data["status"] ?? ""}`);
|
|
4164
|
-
}
|
|
4165
|
-
if (name === "volume_delete") {
|
|
4166
|
-
const vid = String(args["volume_id"] ?? "");
|
|
4167
|
-
if (!vid)
|
|
4168
|
-
return err("volume_id is required");
|
|
4169
|
-
await client.apiDelete(`/api/v1/volumes/${encodeURIComponent(vid)}`);
|
|
4170
|
-
return ok(`Volume ${vid} deleted.`);
|
|
4171
|
-
}
|
|
4172
|
-
if (name === "volume_attach") {
|
|
4173
|
-
const attachCid = String(args["computer_id"] ?? "");
|
|
4174
|
-
if (!attachCid)
|
|
4175
|
-
return err("computer_id is required");
|
|
4176
|
-
const attachBody = {
|
|
4177
|
-
volume_id: args["volume_id"],
|
|
4178
|
-
};
|
|
4179
|
-
if (args["mount_path"])
|
|
4180
|
-
attachBody["mount_path"] = args["mount_path"];
|
|
4181
|
-
const result = await client.apiPost(`/api/v1/computers/${encodeURIComponent(attachCid)}/volumes`, attachBody);
|
|
4182
|
-
const data = unwrapData(result);
|
|
4183
|
-
return ok(`Volume ${args["volume_id"]} attached to computer ${attachCid} (attachment id=${data["id"] ?? "?"}).`);
|
|
4184
|
-
}
|
|
4185
|
-
if (name === "volume_detach") {
|
|
4186
|
-
const detachCid = String(args["computer_id"] ?? "");
|
|
4187
|
-
if (!detachCid)
|
|
4188
|
-
return err("computer_id is required");
|
|
4189
|
-
const attId = String(args["attachment_id"] ?? "");
|
|
4190
|
-
if (!attId)
|
|
4191
|
-
return err("attachment_id is required");
|
|
4192
|
-
await client.apiDelete(`/api/v1/computers/${encodeURIComponent(detachCid)}/volumes/${encodeURIComponent(attId)}`);
|
|
4193
|
-
return ok(`Attachment ${attId} removed from computer ${detachCid}.`);
|
|
4194
|
-
}
|
|
4195
3082
|
return err(`Unknown tool: ${name}`);
|
|
4196
3083
|
}
|
|
4197
3084
|
catch (e) {
|
|
@@ -4256,47 +3143,7 @@ async function runServer() {
|
|
|
4256
3143
|
result: {
|
|
4257
3144
|
protocolVersion: "2024-11-05",
|
|
4258
3145
|
capabilities: { tools: {} },
|
|
4259
|
-
serverInfo: { name: "miosa-mcp", version: "0.1.
|
|
4260
|
-
instructions: [
|
|
4261
|
-
"MIOSA cloud infrastructure — Firecracker microVMs you control via API.",
|
|
4262
|
-
"",
|
|
4263
|
-
"## Concepts",
|
|
4264
|
-
"- **Computer**: full Linux desktop VM (GUI, browser, apps). Use for visual tasks, browser automation, desktop control.",
|
|
4265
|
-
"- **Sandbox**: headless Linux VM. Use for code execution, builds, CI, scripts. No desktop.",
|
|
4266
|
-
"- **Deployment**: git-based app hosting with builds, releases, domains.",
|
|
4267
|
-
"- **Storage**: S3-compatible object storage (buckets + objects).",
|
|
4268
|
-
"- **Database**: managed Postgres, MySQL, or Redis.",
|
|
4269
|
-
"- **Volume**: persistent block storage, attachable to computers.",
|
|
4270
|
-
"",
|
|
4271
|
-
"## Core workflows",
|
|
4272
|
-
"",
|
|
4273
|
-
"### Run code (sandbox)",
|
|
4274
|
-
"create_sandbox → exec (or exec_python) → read output → destroy_sandbox",
|
|
4275
|
-
"",
|
|
4276
|
-
"### Desktop automation (computer)",
|
|
4277
|
-
"computer_create → computer_screenshot → computer_click/type/key → computer_screenshot → repeat",
|
|
4278
|
-
"",
|
|
4279
|
-
"### Deploy an app",
|
|
4280
|
-
"deployment_create(repo_url) → deployment_publish → custom_domain_add (optional)",
|
|
4281
|
-
"",
|
|
4282
|
-
"### Store files",
|
|
4283
|
-
"storage_bucket_create → storage_object_upload → storage_object_presign (for public URL)",
|
|
4284
|
-
"",
|
|
4285
|
-
"### Provision a database",
|
|
4286
|
-
'database_create(engine="postgres") → database_credentials → use connection string',
|
|
4287
|
-
"",
|
|
4288
|
-
"## Conventions",
|
|
4289
|
-
"- IDs: pass computer_id or sandbox_id to every tool that operates on a resource.",
|
|
4290
|
-
"- Sizes: xs (1cpu/2GB), small (2cpu/4GB), medium (4cpu/8GB), large (8cpu/16GB), xl (16cpu/32GB).",
|
|
4291
|
-
'- Status: "running" = ready. Poll with get/list until status is "running".',
|
|
4292
|
-
"- File paths inside VMs: /workspace is the default working directory. /home/user also writable.",
|
|
4293
|
-
"- exec timeout: default 30s. For installs (npm/pip), set timeout_ms=120000.",
|
|
4294
|
-
"- Screenshots: PNG bytes, 1024x768 default. Coordinates are absolute pixels from top-left (0,0).",
|
|
4295
|
-
"",
|
|
4296
|
-
"## Tool naming",
|
|
4297
|
-
"{resource}_{action} — e.g. computer_create, sandbox_exec, storage_bucket_list.",
|
|
4298
|
-
"Desktop tools: computer_screenshot, computer_click, computer_type, computer_key, computer_scroll.",
|
|
4299
|
-
].join("\n"),
|
|
3146
|
+
serverInfo: { name: "miosa-mcp", version: "0.1.1" },
|
|
4300
3147
|
},
|
|
4301
3148
|
});
|
|
4302
3149
|
break;
|
|
@@ -4368,19 +3215,17 @@ async function runDeviceFlow(endpoint, clientName) {
|
|
|
4368
3215
|
}
|
|
4369
3216
|
const flow = start.body;
|
|
4370
3217
|
console.log();
|
|
4371
|
-
console.log(
|
|
3218
|
+
console.log(chalk.bold("Authorize MIOSA MCP for this device"));
|
|
4372
3219
|
console.log();
|
|
4373
|
-
console.log(
|
|
4374
|
-
|
|
4375
|
-
{ label: "Code", value: chalk.bold(flow.user_code) },
|
|
4376
|
-
]));
|
|
3220
|
+
console.log(` Open: ${chalk.cyan(flow.verification_uri_complete)}`);
|
|
3221
|
+
console.log(` Code: ${chalk.bold(flow.user_code)}`);
|
|
4377
3222
|
console.log();
|
|
4378
3223
|
try {
|
|
4379
3224
|
openUrl(flow.verification_uri_complete);
|
|
4380
|
-
console.log(
|
|
3225
|
+
console.log(chalk.dim(" Browser opened. Waiting for approval..."));
|
|
4381
3226
|
}
|
|
4382
3227
|
catch {
|
|
4383
|
-
console.log(
|
|
3228
|
+
console.log(chalk.dim(" Could not open a browser automatically."));
|
|
4384
3229
|
}
|
|
4385
3230
|
const deadline = Date.now() + flow.expires_in * 1000;
|
|
4386
3231
|
const intervalMs = Math.max(flow.interval || 3, 1) * 1000;
|
|
@@ -4467,50 +3312,26 @@ function printManualSnippet(client, apiKey, remoteUrl) {
|
|
|
4467
3312
|
console.log(` ${chalk.cyan(`--header "Authorization: Bearer ${apiKey}"`)}`);
|
|
4468
3313
|
}
|
|
4469
3314
|
async function runInstall(opts) {
|
|
4470
|
-
const startTime = Date.now();
|
|
4471
3315
|
const config = loadConfig();
|
|
4472
3316
|
const clientName = `MIOSA MCP (${opts.client === "manual" ? "manual" : opts.client})`;
|
|
3317
|
+
console.log(chalk.bold("MIOSA MCP installer"), chalk.dim(`— wiring ${opts.client} → ${opts.remoteUrl}`));
|
|
4473
3318
|
const apiKey = await runDeviceFlow(config.endpoint, clientName);
|
|
4474
3319
|
if (opts.client === "claude") {
|
|
4475
3320
|
const wired = wireClaudeCode(apiKey, opts.remoteUrl, opts.scope);
|
|
4476
3321
|
if (wired.ok) {
|
|
4477
3322
|
console.log();
|
|
4478
|
-
console.log(
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
value: chalk.bold(MCP_SERVER_NAME),
|
|
4483
|
-
},
|
|
4484
|
-
{
|
|
4485
|
-
icon: icon.ok,
|
|
4486
|
-
label: "Client",
|
|
4487
|
-
value: chalk.bold("Claude Code") + chalk.dim(` · ${opts.scope} scope`),
|
|
4488
|
-
},
|
|
4489
|
-
{
|
|
4490
|
-
icon: icon.ok,
|
|
4491
|
-
label: "Endpoint",
|
|
4492
|
-
value: chalk.dim(opts.remoteUrl),
|
|
4493
|
-
},
|
|
4494
|
-
]));
|
|
3323
|
+
console.log(chalk.green("✓"), `MCP server '${MCP_SERVER_NAME}' added to Claude Code (${opts.scope} scope).`);
|
|
3324
|
+
console.log();
|
|
3325
|
+
console.log(chalk.dim("Verify:"));
|
|
3326
|
+
console.log(` ${chalk.cyan("claude mcp list")}`);
|
|
4495
3327
|
console.log();
|
|
4496
|
-
console.log(
|
|
4497
|
-
|
|
4498
|
-
"Try in Claude Code: 'Create a MIOSA sandbox and run python -c print(2+2)'",
|
|
4499
|
-
]));
|
|
4500
|
-
printElapsed(formatDuration(Date.now() - startTime));
|
|
3328
|
+
console.log(chalk.dim("Try in a fresh Claude Code session:"));
|
|
3329
|
+
console.log(chalk.dim(` "Create a MIOSA sandbox, run \`python -c 'print(2+2)'\`, then destroy it."`));
|
|
4501
3330
|
return;
|
|
4502
3331
|
}
|
|
4503
3332
|
console.log();
|
|
4504
|
-
console.log(
|
|
4505
|
-
|
|
4506
|
-
body: wired.reason,
|
|
4507
|
-
suggest: [
|
|
4508
|
-
"miosa mcp install # try again",
|
|
4509
|
-
"miosa mcp install --client manual # get the snippet instead",
|
|
4510
|
-
],
|
|
4511
|
-
withDebugHint: true,
|
|
4512
|
-
}));
|
|
4513
|
-
console.log();
|
|
3333
|
+
console.log(chalk.yellow("!"), `Could not auto-wire Claude Code: ${wired.reason}`);
|
|
3334
|
+
console.log(chalk.yellow(" Falling back to manual snippet:"));
|
|
4514
3335
|
printManualSnippet("claude", apiKey, opts.remoteUrl);
|
|
4515
3336
|
return;
|
|
4516
3337
|
}
|
|
@@ -4548,16 +3369,7 @@ export function register(program) {
|
|
|
4548
3369
|
}
|
|
4549
3370
|
catch (e) {
|
|
4550
3371
|
const msg = e instanceof Error ? e.message : String(e);
|
|
4551
|
-
console.
|
|
4552
|
-
console.log(errorEnvelope({
|
|
4553
|
-
title: "MCP install failed",
|
|
4554
|
-
body: msg,
|
|
4555
|
-
suggest: [
|
|
4556
|
-
"miosa mcp install # try again",
|
|
4557
|
-
"miosa login # re-authenticate first",
|
|
4558
|
-
],
|
|
4559
|
-
withDebugHint: true,
|
|
4560
|
-
}));
|
|
3372
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
4561
3373
|
process.exit(3);
|
|
4562
3374
|
}
|
|
4563
3375
|
});
|