@miosa/cli 1.0.8 → 1.0.10
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/databases.d.ts.map +1 -1
- package/dist/commands/databases.js +69 -20
- package/dist/commands/databases.js.map +1 -1
- package/dist/commands/db.d.ts.map +1 -1
- package/dist/commands/db.js +160 -7
- package/dist/commands/db.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 +277 -1445
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +1084 -23
- 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
|
-
},
|
|
1489
|
-
},
|
|
1490
|
-
{
|
|
1491
|
-
name: "storage_bucket_delete",
|
|
1492
|
-
description: "Delete a storage bucket.",
|
|
1493
|
-
inputSchema: {
|
|
1494
|
-
type: "object",
|
|
1495
|
-
properties: {
|
|
1496
|
-
bucket_id: {
|
|
1497
|
-
type: "string",
|
|
1498
|
-
description: "Bucket ID or name to delete",
|
|
1499
|
-
},
|
|
1500
|
-
},
|
|
1501
|
-
required: ["bucket_id"],
|
|
1502
|
-
},
|
|
1503
|
-
},
|
|
1504
|
-
{
|
|
1505
|
-
name: "storage_object_list",
|
|
1506
|
-
description: "List objects in a storage bucket, optionally filtered by prefix.",
|
|
1507
|
-
inputSchema: {
|
|
1508
|
-
type: "object",
|
|
1509
|
-
properties: {
|
|
1510
|
-
bucket_id: { type: "string", description: "Bucket ID or name" },
|
|
1511
|
-
prefix: {
|
|
1512
|
-
type: "string",
|
|
1513
|
-
description: "Key prefix to filter by (optional)",
|
|
1514
|
-
},
|
|
1515
|
-
},
|
|
1516
|
-
required: ["bucket_id"],
|
|
1517
|
-
},
|
|
1518
|
-
},
|
|
1519
|
-
{
|
|
1520
|
-
name: "storage_object_upload",
|
|
1521
|
-
description: "Upload an object to a storage bucket.",
|
|
1522
|
-
inputSchema: {
|
|
1523
|
-
type: "object",
|
|
1524
|
-
properties: {
|
|
1525
|
-
bucket_id: { type: "string", description: "Bucket ID or name" },
|
|
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
|
-
},
|
|
1535
|
-
},
|
|
1536
|
-
required: ["bucket_id", "key", "content"],
|
|
1537
|
-
},
|
|
1538
|
-
},
|
|
1539
|
-
{
|
|
1540
|
-
name: "storage_object_download",
|
|
1541
|
-
description: "Download an object from a storage bucket.",
|
|
1542
|
-
inputSchema: {
|
|
1543
|
-
type: "object",
|
|
1544
|
-
properties: {
|
|
1545
|
-
bucket_id: { type: "string", description: "Bucket ID or name" },
|
|
1546
|
-
key: { type: "string", description: "Object key to download" },
|
|
1547
|
-
},
|
|
1548
|
-
required: ["bucket_id", "key"],
|
|
1549
|
-
},
|
|
1550
|
-
},
|
|
1551
|
-
{
|
|
1552
|
-
name: "storage_object_delete",
|
|
1553
|
-
description: "Delete an object from a storage bucket.",
|
|
1554
|
-
inputSchema: {
|
|
1555
|
-
type: "object",
|
|
1556
|
-
properties: {
|
|
1557
|
-
bucket_id: { type: "string", description: "Bucket ID or name" },
|
|
1558
|
-
key: { type: "string", description: "Object key to delete" },
|
|
1559
|
-
},
|
|
1560
|
-
required: ["bucket_id", "key"],
|
|
1561
|
-
},
|
|
1562
|
-
},
|
|
1563
|
-
{
|
|
1564
|
-
name: "storage_presign",
|
|
1565
|
-
description: "Get a presigned URL for temporary access to a storage object.",
|
|
1566
|
-
inputSchema: {
|
|
1567
|
-
type: "object",
|
|
1568
|
-
properties: {
|
|
1569
|
-
bucket_id: { type: "string", description: "Bucket ID or name" },
|
|
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
|
-
},
|
|
1582
|
-
},
|
|
1583
|
-
required: ["bucket_id", "key"],
|
|
1584
|
-
},
|
|
1585
|
-
},
|
|
1586
|
-
// Databases
|
|
1587
|
-
{
|
|
1588
|
-
name: "database_list",
|
|
1589
|
-
description: "List all managed databases in the tenant.",
|
|
1590
|
-
inputSchema: { type: "object", properties: {} },
|
|
1591
|
-
},
|
|
1592
|
-
{
|
|
1593
|
-
name: "database_create",
|
|
1594
|
-
description: "Create a new managed database.",
|
|
1595
|
-
inputSchema: {
|
|
1596
|
-
type: "object",
|
|
1597
|
-
properties: {
|
|
1598
|
-
name: { type: "string", description: "Database name" },
|
|
1599
|
-
engine: {
|
|
1600
|
-
type: "string",
|
|
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)" },
|
|
1607
|
-
},
|
|
1608
|
-
required: ["name", "engine"],
|
|
1609
|
-
},
|
|
1610
|
-
},
|
|
1611
|
-
{
|
|
1612
|
-
name: "database_get",
|
|
1613
|
-
description: "Get details of a specific database.",
|
|
1614
|
-
inputSchema: {
|
|
1615
|
-
type: "object",
|
|
1616
|
-
properties: {
|
|
1617
|
-
database_id: { type: "string", description: "Database ID" },
|
|
1618
|
-
},
|
|
1619
|
-
required: ["database_id"],
|
|
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
|
-
},
|
|
1310
|
+
name: 'deployment_list',
|
|
1311
|
+
description: 'List all deployments in the tenant.',
|
|
1312
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1684
1313
|
},
|
|
1685
1314
|
{
|
|
1686
|
-
name:
|
|
1687
|
-
description:
|
|
1315
|
+
name: 'deployment_get',
|
|
1316
|
+
description: 'Get details of a specific deployment.',
|
|
1688
1317
|
inputSchema: {
|
|
1689
|
-
type:
|
|
1318
|
+
type: 'object',
|
|
1690
1319
|
properties: {
|
|
1691
|
-
|
|
1320
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1692
1321
|
},
|
|
1693
|
-
required: [
|
|
1322
|
+
required: ['deployment_id'],
|
|
1694
1323
|
},
|
|
1695
1324
|
},
|
|
1696
1325
|
{
|
|
1697
|
-
name:
|
|
1698
|
-
description:
|
|
1326
|
+
name: 'deployment_create',
|
|
1327
|
+
description: 'Create a new deployment.',
|
|
1699
1328
|
inputSchema: {
|
|
1700
|
-
type:
|
|
1329
|
+
type: 'object',
|
|
1701
1330
|
properties: {
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
description:
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
},
|
|
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)' },
|
|
1708
1336
|
},
|
|
1709
|
-
required: [
|
|
1337
|
+
required: ['name'],
|
|
1710
1338
|
},
|
|
1711
1339
|
},
|
|
1712
1340
|
{
|
|
1713
|
-
name:
|
|
1714
|
-
description:
|
|
1341
|
+
name: 'deployment_delete',
|
|
1342
|
+
description: 'Delete a deployment permanently.',
|
|
1715
1343
|
inputSchema: {
|
|
1716
|
-
type:
|
|
1344
|
+
type: 'object',
|
|
1717
1345
|
properties: {
|
|
1718
|
-
|
|
1346
|
+
deployment_id: { type: 'string', description: 'Deployment ID to delete' },
|
|
1719
1347
|
},
|
|
1720
|
-
required: [
|
|
1348
|
+
required: ['deployment_id'],
|
|
1721
1349
|
},
|
|
1722
1350
|
},
|
|
1723
1351
|
{
|
|
1724
|
-
name:
|
|
1725
|
-
description:
|
|
1352
|
+
name: 'deployment_publish',
|
|
1353
|
+
description: 'Publish a new version of a deployment.',
|
|
1726
1354
|
inputSchema: {
|
|
1727
|
-
type:
|
|
1355
|
+
type: 'object',
|
|
1728
1356
|
properties: {
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
type: "string",
|
|
1732
|
-
description: "Billing period (e.g. '2026-05'). Defaults to current month.",
|
|
1733
|
-
},
|
|
1357
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1358
|
+
source: { type: 'object', description: 'Source configuration for the new version' },
|
|
1734
1359
|
},
|
|
1735
|
-
required: [
|
|
1360
|
+
required: ['deployment_id'],
|
|
1736
1361
|
},
|
|
1737
1362
|
},
|
|
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
1363
|
{
|
|
1751
|
-
name:
|
|
1752
|
-
description:
|
|
1364
|
+
name: 'deployment_rollback',
|
|
1365
|
+
description: 'Rollback a deployment to a previous version.',
|
|
1753
1366
|
inputSchema: {
|
|
1754
|
-
type:
|
|
1367
|
+
type: 'object',
|
|
1755
1368
|
properties: {
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
protocol: {
|
|
1759
|
-
type: "string",
|
|
1760
|
-
enum: ["http", "https", "tcp"],
|
|
1761
|
-
description: "Protocol (default: http)",
|
|
1762
|
-
},
|
|
1369
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1370
|
+
version_id: { type: 'string', description: 'Version ID to roll back to' },
|
|
1763
1371
|
},
|
|
1764
|
-
required: [
|
|
1372
|
+
required: ['deployment_id', 'version_id'],
|
|
1765
1373
|
},
|
|
1766
1374
|
},
|
|
1767
1375
|
{
|
|
1768
|
-
name:
|
|
1769
|
-
description:
|
|
1376
|
+
name: 'deployment_env_list',
|
|
1377
|
+
description: 'List environment variables for a deployment.',
|
|
1770
1378
|
inputSchema: {
|
|
1771
|
-
type:
|
|
1379
|
+
type: 'object',
|
|
1772
1380
|
properties: {
|
|
1773
|
-
|
|
1381
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1774
1382
|
},
|
|
1775
|
-
required: [
|
|
1383
|
+
required: ['deployment_id'],
|
|
1776
1384
|
},
|
|
1777
1385
|
},
|
|
1778
1386
|
{
|
|
1779
|
-
name:
|
|
1780
|
-
description:
|
|
1387
|
+
name: 'deployment_env_set',
|
|
1388
|
+
description: 'Set (create or update) an environment variable for a deployment.',
|
|
1781
1389
|
inputSchema: {
|
|
1782
|
-
type:
|
|
1783
|
-
properties: {
|
|
1784
|
-
|
|
1785
|
-
|
|
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
|
-
},
|
|
1990
|
-
},
|
|
1991
|
-
required: ["workspace_id"],
|
|
1992
|
-
},
|
|
1993
|
-
},
|
|
1994
|
-
{
|
|
1995
|
-
name: "computer_template_create",
|
|
1996
|
-
description: "Create a new computer template in a workspace.",
|
|
1997
|
-
inputSchema: {
|
|
1998
|
-
type: "object",
|
|
1999
|
-
properties: {
|
|
2000
|
-
workspace_id: {
|
|
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
|
-
},
|
|
1390
|
+
type: 'object',
|
|
1391
|
+
properties: {
|
|
1392
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1393
|
+
key: { type: 'string', description: 'Environment variable name' },
|
|
1394
|
+
value: { type: 'string', description: 'Environment variable value' },
|
|
2026
1395
|
},
|
|
2027
|
-
required: [
|
|
1396
|
+
required: ['deployment_id', 'key', 'value'],
|
|
2028
1397
|
},
|
|
2029
1398
|
},
|
|
2030
|
-
// Settings
|
|
2031
1399
|
{
|
|
2032
|
-
name:
|
|
2033
|
-
description:
|
|
2034
|
-
inputSchema: {
|
|
1400
|
+
name: 'deployment_logs',
|
|
1401
|
+
description: 'Get logs for a deployment.',
|
|
1402
|
+
inputSchema: {
|
|
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)' },
|
|
1408
|
+
},
|
|
1409
|
+
required: ['deployment_id'],
|
|
1410
|
+
},
|
|
2035
1411
|
},
|
|
2036
1412
|
{
|
|
2037
|
-
name:
|
|
2038
|
-
description:
|
|
2039
|
-
inputSchema: {
|
|
1413
|
+
name: 'deployment_version_list',
|
|
1414
|
+
description: 'List all versions of a deployment.',
|
|
1415
|
+
inputSchema: {
|
|
1416
|
+
type: 'object',
|
|
1417
|
+
properties: {
|
|
1418
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1419
|
+
},
|
|
1420
|
+
required: ['deployment_id'],
|
|
1421
|
+
},
|
|
2040
1422
|
},
|
|
2041
1423
|
{
|
|
2042
|
-
name:
|
|
2043
|
-
description:
|
|
1424
|
+
name: 'deployment_version_promote',
|
|
1425
|
+
description: 'Promote a specific version to be the active deployment.',
|
|
2044
1426
|
inputSchema: {
|
|
2045
|
-
type:
|
|
1427
|
+
type: 'object',
|
|
2046
1428
|
properties: {
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
description: "HTTPS URL for the default desktop wallpaper (optional)",
|
|
2050
|
-
},
|
|
2051
|
-
logo_url: {
|
|
2052
|
-
type: "string",
|
|
2053
|
-
description: "HTTPS URL for the tenant logo (optional)",
|
|
2054
|
-
},
|
|
1429
|
+
deployment_id: { type: 'string', description: 'Deployment ID' },
|
|
1430
|
+
version_id: { type: 'string', description: 'Version ID to promote' },
|
|
2055
1431
|
},
|
|
1432
|
+
required: ['deployment_id', 'version_id'],
|
|
2056
1433
|
},
|
|
2057
1434
|
},
|
|
1435
|
+
// Storage
|
|
2058
1436
|
{
|
|
2059
|
-
name:
|
|
2060
|
-
description:
|
|
2061
|
-
inputSchema: { type:
|
|
1437
|
+
name: 'storage_bucket_list',
|
|
1438
|
+
description: 'List all storage buckets in the tenant.',
|
|
1439
|
+
inputSchema: { type: 'object', properties: {} },
|
|
2062
1440
|
},
|
|
2063
|
-
// Sandbox template extensions
|
|
2064
1441
|
{
|
|
2065
|
-
name:
|
|
2066
|
-
description:
|
|
1442
|
+
name: 'storage_bucket_create',
|
|
1443
|
+
description: 'Create a new storage bucket.',
|
|
2067
1444
|
inputSchema: {
|
|
2068
|
-
type:
|
|
1445
|
+
type: 'object',
|
|
2069
1446
|
properties: {
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
},
|
|
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 },
|
|
2074
1450
|
},
|
|
2075
|
-
required: [
|
|
1451
|
+
required: ['name'],
|
|
2076
1452
|
},
|
|
2077
1453
|
},
|
|
2078
1454
|
{
|
|
2079
|
-
name:
|
|
2080
|
-
description:
|
|
1455
|
+
name: 'storage_bucket_delete',
|
|
1456
|
+
description: 'Delete a storage bucket.',
|
|
2081
1457
|
inputSchema: {
|
|
2082
|
-
type:
|
|
1458
|
+
type: 'object',
|
|
2083
1459
|
properties: {
|
|
2084
|
-
|
|
2085
|
-
type: "string",
|
|
2086
|
-
description: "Sandbox template ID or slug",
|
|
2087
|
-
},
|
|
1460
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name to delete' },
|
|
2088
1461
|
},
|
|
2089
|
-
required: [
|
|
1462
|
+
required: ['bucket_id'],
|
|
2090
1463
|
},
|
|
2091
1464
|
},
|
|
2092
|
-
// Cron jobs
|
|
2093
1465
|
{
|
|
2094
|
-
name:
|
|
2095
|
-
description:
|
|
1466
|
+
name: 'storage_object_list',
|
|
1467
|
+
description: 'List objects in a storage bucket, optionally filtered by prefix.',
|
|
2096
1468
|
inputSchema: {
|
|
2097
|
-
type:
|
|
1469
|
+
type: 'object',
|
|
2098
1470
|
properties: {
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
description: "Filter cron jobs by computer ID (optional)",
|
|
2102
|
-
},
|
|
1471
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1472
|
+
prefix: { type: 'string', description: 'Key prefix to filter by (optional)' },
|
|
2103
1473
|
},
|
|
1474
|
+
required: ['bucket_id'],
|
|
2104
1475
|
},
|
|
2105
1476
|
},
|
|
2106
1477
|
{
|
|
2107
|
-
name:
|
|
2108
|
-
description:
|
|
1478
|
+
name: 'storage_object_upload',
|
|
1479
|
+
description: 'Upload an object to a storage bucket.',
|
|
2109
1480
|
inputSchema: {
|
|
2110
|
-
type:
|
|
1481
|
+
type: 'object',
|
|
2111
1482
|
properties: {
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
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
|
-
},
|
|
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)' },
|
|
2128
1487
|
},
|
|
2129
|
-
required: [
|
|
1488
|
+
required: ['bucket_id', 'key', 'content'],
|
|
2130
1489
|
},
|
|
2131
1490
|
},
|
|
2132
1491
|
{
|
|
2133
|
-
name:
|
|
2134
|
-
description:
|
|
1492
|
+
name: 'storage_object_download',
|
|
1493
|
+
description: 'Download an object from a storage bucket.',
|
|
2135
1494
|
inputSchema: {
|
|
2136
|
-
type:
|
|
1495
|
+
type: 'object',
|
|
2137
1496
|
properties: {
|
|
2138
|
-
|
|
1497
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1498
|
+
key: { type: 'string', description: 'Object key to download' },
|
|
2139
1499
|
},
|
|
2140
|
-
required: [
|
|
1500
|
+
required: ['bucket_id', 'key'],
|
|
2141
1501
|
},
|
|
2142
1502
|
},
|
|
2143
1503
|
{
|
|
2144
|
-
name:
|
|
2145
|
-
description:
|
|
1504
|
+
name: 'storage_object_delete',
|
|
1505
|
+
description: 'Delete an object from a storage bucket.',
|
|
2146
1506
|
inputSchema: {
|
|
2147
|
-
type:
|
|
1507
|
+
type: 'object',
|
|
2148
1508
|
properties: {
|
|
2149
|
-
|
|
1509
|
+
bucket_id: { type: 'string', description: 'Bucket ID or name' },
|
|
1510
|
+
key: { type: 'string', description: 'Object key to delete' },
|
|
2150
1511
|
},
|
|
2151
|
-
required: [
|
|
1512
|
+
required: ['bucket_id', 'key'],
|
|
2152
1513
|
},
|
|
2153
1514
|
},
|
|
2154
1515
|
{
|
|
2155
|
-
name:
|
|
2156
|
-
description:
|
|
1516
|
+
name: 'storage_presign',
|
|
1517
|
+
description: 'Get a presigned URL for temporary access to a storage object.',
|
|
2157
1518
|
inputSchema: {
|
|
2158
|
-
type:
|
|
1519
|
+
type: 'object',
|
|
2159
1520
|
properties: {
|
|
2160
|
-
|
|
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' },
|
|
2161
1525
|
},
|
|
2162
|
-
required: [
|
|
1526
|
+
required: ['bucket_id', 'key'],
|
|
2163
1527
|
},
|
|
2164
1528
|
},
|
|
1529
|
+
// Databases
|
|
1530
|
+
{
|
|
1531
|
+
name: 'database_list',
|
|
1532
|
+
description: 'List all managed databases in the tenant.',
|
|
1533
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1534
|
+
},
|
|
2165
1535
|
{
|
|
2166
|
-
name:
|
|
2167
|
-
description:
|
|
1536
|
+
name: 'database_create',
|
|
1537
|
+
description: 'Create a new managed database.',
|
|
2168
1538
|
inputSchema: {
|
|
2169
|
-
type:
|
|
1539
|
+
type: 'object',
|
|
2170
1540
|
properties: {
|
|
2171
|
-
|
|
1541
|
+
name: { type: 'string', description: 'Database name' },
|
|
1542
|
+
engine: { type: 'string', enum: ['postgres', 'postgresql', '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)' },
|
|
2172
1546
|
},
|
|
2173
|
-
required: [
|
|
1547
|
+
required: ['name', 'engine'],
|
|
2174
1548
|
},
|
|
2175
1549
|
},
|
|
2176
1550
|
{
|
|
2177
|
-
name:
|
|
2178
|
-
description:
|
|
1551
|
+
name: 'database_get',
|
|
1552
|
+
description: 'Get details of a specific database.',
|
|
2179
1553
|
inputSchema: {
|
|
2180
|
-
type:
|
|
1554
|
+
type: 'object',
|
|
2181
1555
|
properties: {
|
|
2182
|
-
|
|
2183
|
-
type: "string",
|
|
2184
|
-
description: "Cron job ID to run immediately",
|
|
2185
|
-
},
|
|
1556
|
+
database_id: { type: 'string', description: 'Database ID' },
|
|
2186
1557
|
},
|
|
2187
|
-
required: [
|
|
1558
|
+
required: ['database_id'],
|
|
2188
1559
|
},
|
|
2189
1560
|
},
|
|
2190
1561
|
{
|
|
2191
|
-
name:
|
|
2192
|
-
description:
|
|
1562
|
+
name: 'database_delete',
|
|
1563
|
+
description: 'Delete a managed database permanently.',
|
|
2193
1564
|
inputSchema: {
|
|
2194
|
-
type:
|
|
1565
|
+
type: 'object',
|
|
2195
1566
|
properties: {
|
|
2196
|
-
|
|
1567
|
+
database_id: { type: 'string', description: 'Database ID to delete' },
|
|
2197
1568
|
},
|
|
2198
|
-
required: [
|
|
1569
|
+
required: ['database_id'],
|
|
2199
1570
|
},
|
|
2200
1571
|
},
|
|
2201
|
-
// Volumes
|
|
2202
1572
|
{
|
|
2203
|
-
name:
|
|
2204
|
-
description:
|
|
2205
|
-
inputSchema: {
|
|
1573
|
+
name: 'database_credentials',
|
|
1574
|
+
description: 'Get the connection string and credentials for a database.',
|
|
1575
|
+
inputSchema: {
|
|
1576
|
+
type: 'object',
|
|
1577
|
+
properties: {
|
|
1578
|
+
database_id: { type: 'string', description: 'Database ID' },
|
|
1579
|
+
},
|
|
1580
|
+
required: ['database_id'],
|
|
1581
|
+
},
|
|
2206
1582
|
},
|
|
2207
1583
|
{
|
|
2208
|
-
name:
|
|
2209
|
-
description:
|
|
1584
|
+
name: 'database_logs',
|
|
1585
|
+
description: 'Get logs for a managed database.',
|
|
2210
1586
|
inputSchema: {
|
|
2211
|
-
type:
|
|
1587
|
+
type: 'object',
|
|
2212
1588
|
properties: {
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
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
|
-
},
|
|
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)' },
|
|
2225
1592
|
},
|
|
2226
|
-
required: [
|
|
1593
|
+
required: ['database_id'],
|
|
2227
1594
|
},
|
|
2228
1595
|
},
|
|
1596
|
+
// Workspaces
|
|
1597
|
+
{
|
|
1598
|
+
name: 'workspace_list',
|
|
1599
|
+
description: 'List all workspaces in the tenant.',
|
|
1600
|
+
inputSchema: { type: 'object', properties: {} },
|
|
1601
|
+
},
|
|
2229
1602
|
{
|
|
2230
|
-
name:
|
|
2231
|
-
description:
|
|
1603
|
+
name: 'workspace_create',
|
|
1604
|
+
description: 'Create a new workspace.',
|
|
2232
1605
|
inputSchema: {
|
|
2233
|
-
type:
|
|
1606
|
+
type: 'object',
|
|
2234
1607
|
properties: {
|
|
2235
|
-
|
|
1608
|
+
name: { type: 'string', description: 'Workspace name' },
|
|
1609
|
+
description: { type: 'string', description: 'Workspace description (optional)' },
|
|
2236
1610
|
},
|
|
2237
|
-
required: [
|
|
1611
|
+
required: ['name'],
|
|
2238
1612
|
},
|
|
2239
1613
|
},
|
|
2240
1614
|
{
|
|
2241
|
-
name:
|
|
2242
|
-
description:
|
|
1615
|
+
name: 'workspace_get',
|
|
1616
|
+
description: 'Get details of a specific workspace.',
|
|
2243
1617
|
inputSchema: {
|
|
2244
|
-
type:
|
|
1618
|
+
type: 'object',
|
|
2245
1619
|
properties: {
|
|
2246
|
-
|
|
1620
|
+
workspace_id: { type: 'string', description: 'Workspace ID' },
|
|
2247
1621
|
},
|
|
2248
|
-
required: [
|
|
1622
|
+
required: ['workspace_id'],
|
|
2249
1623
|
},
|
|
2250
1624
|
},
|
|
2251
1625
|
{
|
|
2252
|
-
name:
|
|
2253
|
-
description: "
|
|
1626
|
+
name: 'workspace_update',
|
|
1627
|
+
description: "Update a workspace's name or description.",
|
|
2254
1628
|
inputSchema: {
|
|
2255
|
-
type:
|
|
1629
|
+
type: 'object',
|
|
2256
1630
|
properties: {
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
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
|
-
},
|
|
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)' },
|
|
2266
1634
|
},
|
|
2267
|
-
required: [
|
|
1635
|
+
required: ['workspace_id'],
|
|
2268
1636
|
},
|
|
2269
1637
|
},
|
|
2270
1638
|
{
|
|
2271
|
-
name:
|
|
2272
|
-
description:
|
|
1639
|
+
name: 'workspace_stats',
|
|
1640
|
+
description: 'Get resource statistics for a workspace (computers, sandboxes, databases, etc.).',
|
|
2273
1641
|
inputSchema: {
|
|
2274
|
-
type:
|
|
1642
|
+
type: 'object',
|
|
2275
1643
|
properties: {
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
1644
|
+
workspace_id: { type: 'string', description: 'Workspace ID' },
|
|
1645
|
+
},
|
|
1646
|
+
required: ['workspace_id'],
|
|
1647
|
+
},
|
|
1648
|
+
},
|
|
1649
|
+
{
|
|
1650
|
+
name: 'workspace_usage',
|
|
1651
|
+
description: 'Get usage data (compute hours, storage, bandwidth) for a workspace.',
|
|
1652
|
+
inputSchema: {
|
|
1653
|
+
type: 'object',
|
|
1654
|
+
properties: {
|
|
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) {
|
|
@@ -2290,6 +1677,16 @@ function ok(text) {
|
|
|
2290
1677
|
function err(msg) {
|
|
2291
1678
|
return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
|
|
2292
1679
|
}
|
|
1680
|
+
function shellQuote(value) {
|
|
1681
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
1682
|
+
}
|
|
1683
|
+
function commandInCwd(command, cwd) {
|
|
1684
|
+
return cwd ? `cd ${shellQuote(cwd)} && ${command}` : command;
|
|
1685
|
+
}
|
|
1686
|
+
function normalizeDatabaseEngine(engine) {
|
|
1687
|
+
const value = String(engine ?? "postgresql").trim().toLowerCase();
|
|
1688
|
+
return value === "postgres" ? "postgresql" : value;
|
|
1689
|
+
}
|
|
2293
1690
|
function image(pngBytes) {
|
|
2294
1691
|
return {
|
|
2295
1692
|
content: [
|
|
@@ -2321,10 +1718,6 @@ async function dispatchTool(client, name, args) {
|
|
|
2321
1718
|
body["external_workspace_id"] = args["external_workspace_id"];
|
|
2322
1719
|
if (args["external_project_id"])
|
|
2323
1720
|
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
1721
|
const computer = await client.apiPost("/api/v1/computers", body);
|
|
2329
1722
|
const data = unwrapData(computer);
|
|
2330
1723
|
const id = String(data["id"] ?? "");
|
|
@@ -3057,9 +2450,14 @@ async function dispatchTool(client, name, args) {
|
|
|
3057
2450
|
const sid = String(args["sandbox_id"] ?? "");
|
|
3058
2451
|
if (!sid)
|
|
3059
2452
|
return err("sandbox_id is required");
|
|
3060
|
-
const
|
|
3061
|
-
|
|
3062
|
-
|
|
2453
|
+
const cwd = args["cwd"] ? String(args["cwd"]) : undefined;
|
|
2454
|
+
const body = {
|
|
2455
|
+
command: commandInCwd(String(args["command"] ?? ""), cwd),
|
|
2456
|
+
};
|
|
2457
|
+
if (cwd) {
|
|
2458
|
+
body["cwd"] = cwd;
|
|
2459
|
+
body["dir"] = cwd;
|
|
2460
|
+
}
|
|
3063
2461
|
if (args["timeout"] !== undefined)
|
|
3064
2462
|
body["timeout"] = args["timeout"];
|
|
3065
2463
|
const result = await client.apiPost(`/api/v1/sandboxes/${encodeURIComponent(sid)}/exec`, body);
|
|
@@ -3355,12 +2753,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3355
2753
|
const lines = ["Deployments:"];
|
|
3356
2754
|
for (const d of items) {
|
|
3357
2755
|
const r = d;
|
|
3358
|
-
lines.push(" " +
|
|
3359
|
-
r["id"] +
|
|
3360
|
-
" " +
|
|
3361
|
-
r["name"] +
|
|
3362
|
-
" " +
|
|
3363
|
-
(r["status"] ?? r["state"] ?? ""));
|
|
2756
|
+
lines.push(" " + r["id"] + " " + r["name"] + " " + (r["status"] ?? r["state"] ?? ""));
|
|
3364
2757
|
}
|
|
3365
2758
|
return ok(lines.join("\n"));
|
|
3366
2759
|
}
|
|
@@ -3383,11 +2776,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3383
2776
|
body["region"] = args["region"];
|
|
3384
2777
|
const result = await client.apiPost("/api/v1/deployments", body);
|
|
3385
2778
|
const data = unwrapData(result);
|
|
3386
|
-
return ok("Created deployment '" +
|
|
3387
|
-
String(data["name"] ?? args["name"]) +
|
|
3388
|
-
"' (id=" +
|
|
3389
|
-
data["id"] +
|
|
3390
|
-
")");
|
|
2779
|
+
return ok("Created deployment '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3391
2780
|
}
|
|
3392
2781
|
if (name === "deployment_delete") {
|
|
3393
2782
|
const did = String(args["deployment_id"] ?? "");
|
|
@@ -3405,11 +2794,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3405
2794
|
body["source"] = args["source"];
|
|
3406
2795
|
const result = await client.apiPost("/api/v1/deployments/" + encodeURIComponent(did) + "/publish", body);
|
|
3407
2796
|
const data = unwrapData(result);
|
|
3408
|
-
return ok("Published deployment " +
|
|
3409
|
-
did +
|
|
3410
|
-
" (version id=" +
|
|
3411
|
-
(data["id"] ?? "unknown") +
|
|
3412
|
-
")");
|
|
2797
|
+
return ok("Published deployment " + did + " (version id=" + (data["id"] ?? "unknown") + ")");
|
|
3413
2798
|
}
|
|
3414
2799
|
if (name === "deployment_rollback") {
|
|
3415
2800
|
const did = String(args["deployment_id"] ?? "");
|
|
@@ -3427,8 +2812,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3427
2812
|
return err("deployment_id is required");
|
|
3428
2813
|
const result = await client.apiGet("/api/v1/deployments/" + encodeURIComponent(did) + "/env");
|
|
3429
2814
|
const envVars = unwrapData(result);
|
|
3430
|
-
if (!envVars ||
|
|
3431
|
-
(Array.isArray(envVars) && envVars.length === 0))
|
|
2815
|
+
if (!envVars || (Array.isArray(envVars) && envVars.length === 0))
|
|
3432
2816
|
return ok("No environment variables set.");
|
|
3433
2817
|
const lines = ["Environment variables:"];
|
|
3434
2818
|
if (typeof envVars === "object" && !Array.isArray(envVars)) {
|
|
@@ -3454,20 +2838,13 @@ async function dispatchTool(client, name, args) {
|
|
|
3454
2838
|
const did = String(args["deployment_id"] ?? "");
|
|
3455
2839
|
if (!did)
|
|
3456
2840
|
return err("deployment_id is required");
|
|
3457
|
-
const params = new URLSearchParams({
|
|
3458
|
-
lines: String(args["lines"] ?? 100),
|
|
3459
|
-
});
|
|
2841
|
+
const params = new URLSearchParams({ lines: String(args["lines"] ?? 100) });
|
|
3460
2842
|
if (args["since"])
|
|
3461
2843
|
params.set("since", String(args["since"]));
|
|
3462
|
-
const result = await client.apiGet("/api/v1/deployments/" +
|
|
3463
|
-
encodeURIComponent(did) +
|
|
3464
|
-
"/logs?" +
|
|
3465
|
-
params.toString());
|
|
2844
|
+
const result = await client.apiGet("/api/v1/deployments/" + encodeURIComponent(did) + "/logs?" + params.toString());
|
|
3466
2845
|
const logs = unwrapData(result);
|
|
3467
2846
|
if (Array.isArray(logs))
|
|
3468
|
-
return ok(logs.length
|
|
3469
|
-
? logs.map(String).join("\n")
|
|
3470
|
-
: "No logs.");
|
|
2847
|
+
return ok(logs.length ? logs.map(String).join("\n") : "No logs.");
|
|
3471
2848
|
return ok(String(logs));
|
|
3472
2849
|
}
|
|
3473
2850
|
if (name === "deployment_version_list") {
|
|
@@ -3481,12 +2858,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3481
2858
|
const lines = ["Versions:"];
|
|
3482
2859
|
for (const v of versions) {
|
|
3483
2860
|
const r = v;
|
|
3484
|
-
lines.push(" " +
|
|
3485
|
-
r["id"] +
|
|
3486
|
-
" " +
|
|
3487
|
-
(r["created_at"] ?? "") +
|
|
3488
|
-
" " +
|
|
3489
|
-
(r["status"] ?? ""));
|
|
2861
|
+
lines.push(" " + r["id"] + " " + (r["created_at"] ?? "") + " " + (r["status"] ?? ""));
|
|
3490
2862
|
}
|
|
3491
2863
|
return ok(lines.join("\n"));
|
|
3492
2864
|
}
|
|
@@ -3497,11 +2869,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3497
2869
|
return err("deployment_id is required");
|
|
3498
2870
|
if (!vid)
|
|
3499
2871
|
return err("version_id is required");
|
|
3500
|
-
await client.apiPost("/api/v1/deployments/" +
|
|
3501
|
-
encodeURIComponent(did) +
|
|
3502
|
-
"/versions/" +
|
|
3503
|
-
encodeURIComponent(vid) +
|
|
3504
|
-
"/promote", {});
|
|
2872
|
+
await client.apiPost("/api/v1/deployments/" + encodeURIComponent(did) + "/versions/" + encodeURIComponent(vid) + "/promote", {});
|
|
3505
2873
|
return ok("Version " + vid + " promoted on deployment " + did + ".");
|
|
3506
2874
|
}
|
|
3507
2875
|
// ── Storage ───────────────────────────────────────────────────────────
|
|
@@ -3525,11 +2893,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3525
2893
|
body["public"] = args["public"];
|
|
3526
2894
|
const result = await client.apiPost("/api/v1/storage/buckets", body);
|
|
3527
2895
|
const data = unwrapData(result);
|
|
3528
|
-
return ok("Created bucket '" +
|
|
3529
|
-
String(data["name"] ?? args["name"]) +
|
|
3530
|
-
"' (id=" +
|
|
3531
|
-
data["id"] +
|
|
3532
|
-
")");
|
|
2896
|
+
return ok("Created bucket '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3533
2897
|
}
|
|
3534
2898
|
if (name === "storage_bucket_delete") {
|
|
3535
2899
|
const bid = String(args["bucket_id"] ?? "");
|
|
@@ -3553,12 +2917,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3553
2917
|
const lines = ["Objects:"];
|
|
3554
2918
|
for (const o of items) {
|
|
3555
2919
|
const r = o;
|
|
3556
|
-
lines.push(" " +
|
|
3557
|
-
r["key"] +
|
|
3558
|
-
" " +
|
|
3559
|
-
(r["size"] ?? "") +
|
|
3560
|
-
" " +
|
|
3561
|
-
(r["last_modified"] ?? ""));
|
|
2920
|
+
lines.push(" " + r["key"] + " " + (r["size"] ?? "") + " " + (r["last_modified"] ?? ""));
|
|
3562
2921
|
}
|
|
3563
2922
|
return ok(lines.join("\n"));
|
|
3564
2923
|
}
|
|
@@ -3577,10 +2936,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3577
2936
|
const bid = String(args["bucket_id"] ?? "");
|
|
3578
2937
|
if (!bid)
|
|
3579
2938
|
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"] ?? "")));
|
|
2939
|
+
const result = await client.apiGet("/api/v1/storage/buckets/" + encodeURIComponent(bid) + "/objects/" + encodeURIComponent(String(args["key"] ?? "")));
|
|
3584
2940
|
const data = unwrapData(result);
|
|
3585
2941
|
const content = typeof data["content"] === "string"
|
|
3586
2942
|
? Buffer.from(data["content"], "base64").toString("utf8")
|
|
@@ -3593,10 +2949,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3593
2949
|
const bid = String(args["bucket_id"] ?? "");
|
|
3594
2950
|
if (!bid)
|
|
3595
2951
|
return err("bucket_id is required");
|
|
3596
|
-
await client.apiDelete("/api/v1/storage/buckets/" +
|
|
3597
|
-
encodeURIComponent(bid) +
|
|
3598
|
-
"/objects/" +
|
|
3599
|
-
encodeURIComponent(String(args["key"] ?? "")));
|
|
2952
|
+
await client.apiDelete("/api/v1/storage/buckets/" + encodeURIComponent(bid) + "/objects/" + encodeURIComponent(String(args["key"] ?? "")));
|
|
3600
2953
|
return ok("Deleted " + String(args["key"]) + " from bucket " + bid + ".");
|
|
3601
2954
|
}
|
|
3602
2955
|
if (name === "storage_presign") {
|
|
@@ -3620,33 +2973,24 @@ async function dispatchTool(client, name, args) {
|
|
|
3620
2973
|
const lines = ["Databases:"];
|
|
3621
2974
|
for (const d of items) {
|
|
3622
2975
|
const r = d;
|
|
3623
|
-
lines.push(" " +
|
|
3624
|
-
r["id"] +
|
|
3625
|
-
" " +
|
|
3626
|
-
r["name"] +
|
|
3627
|
-
" " +
|
|
3628
|
-
(r["engine"] ?? "") +
|
|
3629
|
-
" " +
|
|
3630
|
-
(r["status"] ?? ""));
|
|
2976
|
+
lines.push(" " + r["id"] + " " + r["name"] + " " + (r["engine"] ?? "") + " " + (r["status"] ?? ""));
|
|
3631
2977
|
}
|
|
3632
2978
|
return ok(lines.join("\n"));
|
|
3633
2979
|
}
|
|
3634
2980
|
if (name === "database_create") {
|
|
3635
|
-
const
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
for (const key of ["
|
|
2981
|
+
const engine = normalizeDatabaseEngine(args["engine"]);
|
|
2982
|
+
const body = { name: args["name"], engine };
|
|
2983
|
+
if (engine === "postgresql" && !args["version"])
|
|
2984
|
+
body["engine_version"] = "15";
|
|
2985
|
+
for (const key of ["size", "region"]) {
|
|
3640
2986
|
if (args[key])
|
|
3641
2987
|
body[key] = args[key];
|
|
3642
2988
|
}
|
|
2989
|
+
if (args["version"])
|
|
2990
|
+
body["engine_version"] = args["version"];
|
|
3643
2991
|
const result = await client.apiPost("/api/v1/databases", body);
|
|
3644
2992
|
const data = unwrapData(result);
|
|
3645
|
-
return ok("Created database '" +
|
|
3646
|
-
String(data["name"] ?? args["name"]) +
|
|
3647
|
-
"' (id=" +
|
|
3648
|
-
data["id"] +
|
|
3649
|
-
")");
|
|
2993
|
+
return ok("Created database '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3650
2994
|
}
|
|
3651
2995
|
if (name === "database_get") {
|
|
3652
2996
|
const dbid = String(args["database_id"] ?? "");
|
|
@@ -3669,14 +3013,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3669
3013
|
const result = await client.apiGet("/api/v1/databases/" + encodeURIComponent(dbid) + "/credentials");
|
|
3670
3014
|
const data = unwrapData(result);
|
|
3671
3015
|
const lines = ["Database credentials:"];
|
|
3672
|
-
for (const field of [
|
|
3673
|
-
"connection_string",
|
|
3674
|
-
"host",
|
|
3675
|
-
"port",
|
|
3676
|
-
"database",
|
|
3677
|
-
"username",
|
|
3678
|
-
"password",
|
|
3679
|
-
]) {
|
|
3016
|
+
for (const field of ["connection_string", "host", "port", "database", "username", "password"]) {
|
|
3680
3017
|
if (data[field])
|
|
3681
3018
|
lines.push(" " + field + ": " + data[field]);
|
|
3682
3019
|
}
|
|
@@ -3686,20 +3023,13 @@ async function dispatchTool(client, name, args) {
|
|
|
3686
3023
|
const dbid = String(args["database_id"] ?? "");
|
|
3687
3024
|
if (!dbid)
|
|
3688
3025
|
return err("database_id is required");
|
|
3689
|
-
const params = new URLSearchParams({
|
|
3690
|
-
lines: String(args["lines"] ?? 100),
|
|
3691
|
-
});
|
|
3026
|
+
const params = new URLSearchParams({ lines: String(args["lines"] ?? 100) });
|
|
3692
3027
|
if (args["since"])
|
|
3693
3028
|
params.set("since", String(args["since"]));
|
|
3694
|
-
const result = await client.apiGet("/api/v1/databases/" +
|
|
3695
|
-
encodeURIComponent(dbid) +
|
|
3696
|
-
"/logs?" +
|
|
3697
|
-
params.toString());
|
|
3029
|
+
const result = await client.apiGet("/api/v1/databases/" + encodeURIComponent(dbid) + "/logs?" + params.toString());
|
|
3698
3030
|
const logs = unwrapData(result);
|
|
3699
3031
|
if (Array.isArray(logs))
|
|
3700
|
-
return ok(logs.length
|
|
3701
|
-
? logs.map(String).join("\n")
|
|
3702
|
-
: "No logs.");
|
|
3032
|
+
return ok(logs.length ? logs.map(String).join("\n") : "No logs.");
|
|
3703
3033
|
return ok(String(logs));
|
|
3704
3034
|
}
|
|
3705
3035
|
// ── Workspaces ────────────────────────────────────────────────────────
|
|
@@ -3721,11 +3051,7 @@ async function dispatchTool(client, name, args) {
|
|
|
3721
3051
|
body["description"] = args["description"];
|
|
3722
3052
|
const result = await client.apiPost("/api/v1/workspaces", body);
|
|
3723
3053
|
const data = unwrapData(result);
|
|
3724
|
-
return ok("Created workspace '" +
|
|
3725
|
-
String(data["name"] ?? args["name"]) +
|
|
3726
|
-
"' (id=" +
|
|
3727
|
-
data["id"] +
|
|
3728
|
-
")");
|
|
3054
|
+
return ok("Created workspace '" + String(data["name"] ?? args["name"]) + "' (id=" + data["id"] + ")");
|
|
3729
3055
|
}
|
|
3730
3056
|
if (name === "workspace_get") {
|
|
3731
3057
|
const wid = String(args["workspace_id"] ?? "");
|
|
@@ -3773,425 +3099,6 @@ async function dispatchTool(client, name, args) {
|
|
|
3773
3099
|
const result = await client.apiGet("/api/v1/billing/plan");
|
|
3774
3100
|
return ok(JSON.stringify(unwrapData(result), null, 2));
|
|
3775
3101
|
}
|
|
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
3102
|
return err(`Unknown tool: ${name}`);
|
|
4196
3103
|
}
|
|
4197
3104
|
catch (e) {
|
|
@@ -4256,47 +3163,7 @@ async function runServer() {
|
|
|
4256
3163
|
result: {
|
|
4257
3164
|
protocolVersion: "2024-11-05",
|
|
4258
3165
|
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"),
|
|
3166
|
+
serverInfo: { name: "miosa-mcp", version: "0.1.1" },
|
|
4300
3167
|
},
|
|
4301
3168
|
});
|
|
4302
3169
|
break;
|
|
@@ -4368,19 +3235,17 @@ async function runDeviceFlow(endpoint, clientName) {
|
|
|
4368
3235
|
}
|
|
4369
3236
|
const flow = start.body;
|
|
4370
3237
|
console.log();
|
|
4371
|
-
console.log(
|
|
3238
|
+
console.log(chalk.bold("Authorize MIOSA MCP for this device"));
|
|
4372
3239
|
console.log();
|
|
4373
|
-
console.log(
|
|
4374
|
-
|
|
4375
|
-
{ label: "Code", value: chalk.bold(flow.user_code) },
|
|
4376
|
-
]));
|
|
3240
|
+
console.log(` Open: ${chalk.cyan(flow.verification_uri_complete)}`);
|
|
3241
|
+
console.log(` Code: ${chalk.bold(flow.user_code)}`);
|
|
4377
3242
|
console.log();
|
|
4378
3243
|
try {
|
|
4379
3244
|
openUrl(flow.verification_uri_complete);
|
|
4380
|
-
console.log(
|
|
3245
|
+
console.log(chalk.dim(" Browser opened. Waiting for approval..."));
|
|
4381
3246
|
}
|
|
4382
3247
|
catch {
|
|
4383
|
-
console.log(
|
|
3248
|
+
console.log(chalk.dim(" Could not open a browser automatically."));
|
|
4384
3249
|
}
|
|
4385
3250
|
const deadline = Date.now() + flow.expires_in * 1000;
|
|
4386
3251
|
const intervalMs = Math.max(flow.interval || 3, 1) * 1000;
|
|
@@ -4467,50 +3332,26 @@ function printManualSnippet(client, apiKey, remoteUrl) {
|
|
|
4467
3332
|
console.log(` ${chalk.cyan(`--header "Authorization: Bearer ${apiKey}"`)}`);
|
|
4468
3333
|
}
|
|
4469
3334
|
async function runInstall(opts) {
|
|
4470
|
-
const startTime = Date.now();
|
|
4471
3335
|
const config = loadConfig();
|
|
4472
3336
|
const clientName = `MIOSA MCP (${opts.client === "manual" ? "manual" : opts.client})`;
|
|
3337
|
+
console.log(chalk.bold("MIOSA MCP installer"), chalk.dim(`— wiring ${opts.client} → ${opts.remoteUrl}`));
|
|
4473
3338
|
const apiKey = await runDeviceFlow(config.endpoint, clientName);
|
|
4474
3339
|
if (opts.client === "claude") {
|
|
4475
3340
|
const wired = wireClaudeCode(apiKey, opts.remoteUrl, opts.scope);
|
|
4476
3341
|
if (wired.ok) {
|
|
4477
3342
|
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
|
-
]));
|
|
3343
|
+
console.log(chalk.green("✓"), `MCP server '${MCP_SERVER_NAME}' added to Claude Code (${opts.scope} scope).`);
|
|
3344
|
+
console.log();
|
|
3345
|
+
console.log(chalk.dim("Verify:"));
|
|
3346
|
+
console.log(` ${chalk.cyan("claude mcp list")}`);
|
|
4495
3347
|
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));
|
|
3348
|
+
console.log(chalk.dim("Try in a fresh Claude Code session:"));
|
|
3349
|
+
console.log(chalk.dim(` "Create a MIOSA sandbox, run \`python -c 'print(2+2)'\`, then destroy it."`));
|
|
4501
3350
|
return;
|
|
4502
3351
|
}
|
|
4503
3352
|
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();
|
|
3353
|
+
console.log(chalk.yellow("!"), `Could not auto-wire Claude Code: ${wired.reason}`);
|
|
3354
|
+
console.log(chalk.yellow(" Falling back to manual snippet:"));
|
|
4514
3355
|
printManualSnippet("claude", apiKey, opts.remoteUrl);
|
|
4515
3356
|
return;
|
|
4516
3357
|
}
|
|
@@ -4548,16 +3389,7 @@ export function register(program) {
|
|
|
4548
3389
|
}
|
|
4549
3390
|
catch (e) {
|
|
4550
3391
|
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
|
-
}));
|
|
3392
|
+
console.error(chalk.red(`Error: ${msg}`));
|
|
4561
3393
|
process.exit(3);
|
|
4562
3394
|
}
|
|
4563
3395
|
});
|