@roxyon/mcp 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -690,9 +690,6 @@ async function resolveApp(args) {
690
690
  function accountContext(session) {
691
691
  return session.roxyon.account.context();
692
692
  }
693
- function hideUntilLive(tool) {
694
- if (process.env.ROXYON_MCP_PROVISIONING !== "1") tool.disable();
695
- }
696
693
  function registerTools(server) {
697
694
  server.registerTool(
698
695
  "roxyon_whoami",
@@ -1228,270 +1225,260 @@ ${f.content.slice(0, 4096)}`,
1228
1225
  return text(f.content, { path: f.path, size: f.size, encoding: "utf8" });
1229
1226
  })
1230
1227
  );
1231
- hideUntilLive(
1232
- server.registerTool(
1233
- "roxyon_database_create",
1234
- {
1235
- title: "Roxyon: create a database",
1236
- description: `Provision a MySQL/MariaDB database + user. The name is prefixed with the account's own username (globally unique across the shared cluster) \u2014 pass just the suffix, e.g. "wordpress". The password is shown once in the result; there is no way to retrieve it later. Needs confirm:true.`,
1237
- inputSchema: {
1238
- name: z4.string().describe("DB name suffix: lowercase letters, digits, underscore."),
1239
- subscription: z4.string().optional(),
1240
- password: z4.string().optional().describe("Omit to have Roxyon generate one."),
1241
- confirm: z4.boolean().optional()
1242
- }
1243
- },
1244
- (args) => guard(async () => {
1245
- const session = await getSession();
1246
- if (!args.confirm) {
1247
- return text(`Would create database "${args.name}". Pass confirm:true.`, {
1248
- dryRun: true
1249
- });
1250
- }
1251
- const r = await session.roxyon.databases.create({
1252
- name: args.name,
1253
- subscription: args.subscription ?? session.preferredSubscription,
1254
- password: args.password
1228
+ server.registerTool(
1229
+ "roxyon_database_create",
1230
+ {
1231
+ title: "Roxyon: create a database",
1232
+ description: `Provision a database + user on a Roxyon hosting account: engine "mysql" (MySQL/MariaDB, default) or "postgres" (PostgreSQL 15 inside the account, localhost:5432; the first one installs it in a few minutes). Every hosting account has both: no VPS is needed for PostgreSQL. The name is prefixed with the account's own username \u2014 pass just the suffix, e.g. "wordpress". The password is shown once in the result; there is no way to retrieve it later. Needs confirm:true.`,
1233
+ inputSchema: {
1234
+ name: z4.string().describe("DB name suffix: lowercase letters, digits, underscore."),
1235
+ subscription: z4.string().optional(),
1236
+ password: z4.string().optional().describe("Omit to have Roxyon generate one."),
1237
+ engine: z4.enum(["mysql", "postgres"]).optional().describe("mysql (default) or postgres."),
1238
+ confirm: z4.boolean().optional()
1239
+ }
1240
+ },
1241
+ (args) => guard(async () => {
1242
+ const session = await getSession();
1243
+ if (!args.confirm) {
1244
+ return text(`Would create ${args.engine === "postgres" ? "PostgreSQL" : "MySQL"} database "${args.name}". Pass confirm:true.`, {
1245
+ dryRun: true
1255
1246
  });
1256
- const body = [
1257
- `${r.status === "active" ? "\u2713" : "\xBB"} Database ${r.name} (user ${r.username}) \u2014 ${r.status}.`,
1258
- r.password ? `
1247
+ }
1248
+ const r = await session.roxyon.databases.create({
1249
+ name: args.name,
1250
+ subscription: args.subscription ?? session.preferredSubscription,
1251
+ password: args.password,
1252
+ ...args.engine ? { engine: args.engine } : {}
1253
+ });
1254
+ const pg = r.engine === "postgres";
1255
+ const body = [
1256
+ `${r.status === "active" ? "\u2713" : "\xBB"} ${pg ? "PostgreSQL" : "MySQL"} database ${r.name} (user ${r.username}) \u2014 ${r.status}.`,
1257
+ r.password ? `
1259
1258
  Password (save this now \u2014 shown once):
1260
1259
  ${r.password}` : "",
1261
- r.host ? `Host: ${r.host}` : ""
1262
- ].filter(Boolean).join("\n");
1263
- return text(body, {
1264
- ok: true,
1265
- objectId: r.objectId,
1266
- name: r.name,
1267
- username: r.username,
1268
- host: r.host,
1269
- status: r.status
1270
- });
1271
- })
1272
- )
1273
- );
1274
- hideUntilLive(
1275
- server.registerTool(
1276
- "roxyon_list_databases",
1277
- {
1278
- title: "Roxyon: list databases",
1279
- description: "Databases on the active subscription.",
1280
- inputSchema: { subscription: z4.string().optional() }
1281
- },
1282
- (args) => guard(async () => {
1283
- const session = await getSession();
1284
- const subscription = args.subscription ?? session.preferredSubscription;
1285
- if (!subscription) return errorResult('No subscription \u2014 pass "subscription".');
1286
- const rows = await session.roxyon.databases.list(subscription);
1287
- const body = rows.length ? rows.map((d) => `- ${d.Name} [${d.objectId}] \u2014 ${d.Status} (user ${d.Username})`).join("\n") : "(no databases)";
1288
- return text(body, { databases: rows });
1289
- })
1290
- )
1260
+ r.host ? `Host: ${r.host}${r.port ? `:${r.port}` : ""}` : "",
1261
+ r.note ?? ""
1262
+ ].filter(Boolean).join("\n");
1263
+ return text(body, {
1264
+ ok: true,
1265
+ objectId: r.objectId,
1266
+ name: r.name,
1267
+ username: r.username,
1268
+ engine: r.engine ?? "mysql",
1269
+ host: r.host,
1270
+ port: r.port,
1271
+ status: r.status
1272
+ });
1273
+ })
1291
1274
  );
1292
- hideUntilLive(
1293
- server.registerTool(
1294
- "roxyon_database_delete",
1295
- {
1296
- title: "Roxyon: delete a database",
1297
- description: "Delete a database by its objectId (from roxyon_database_create/roxyon_list_databases). Needs confirm:true.",
1298
- inputSchema: { database: z4.string(), confirm: z4.boolean().optional() }
1299
- },
1300
- (args) => guard(async () => {
1301
- const session = await getSession();
1302
- if (!args.confirm) {
1303
- return text(`Would delete database ${args.database}. Pass confirm:true.`, {
1304
- dryRun: true
1305
- });
1306
- }
1307
- const r = await session.roxyon.databases.delete(args.database);
1308
- return text(`Database ${args.database} \u2014 ${r.status}.`, { ok: true, status: r.status });
1309
- })
1310
- )
1275
+ server.registerTool(
1276
+ "roxyon_list_databases",
1277
+ {
1278
+ title: "Roxyon: list databases",
1279
+ description: "Databases on the active subscription.",
1280
+ inputSchema: { subscription: z4.string().optional() }
1281
+ },
1282
+ (args) => guard(async () => {
1283
+ const session = await getSession();
1284
+ const subscription = args.subscription ?? session.preferredSubscription;
1285
+ if (!subscription) return errorResult('No subscription \u2014 pass "subscription".');
1286
+ const rows = await session.roxyon.databases.list(subscription);
1287
+ const body = rows.length ? rows.map((d) => `- ${d.Name} [${d.objectId}] \u2014 ${d.Engine === "postgres" ? "PostgreSQL" : "MySQL"}, ${d.Status} (user ${d.Username})`).join("\n") : "(no databases)";
1288
+ return text(body, { databases: rows });
1289
+ })
1311
1290
  );
1312
- hideUntilLive(
1313
- server.registerTool(
1314
- "roxyon_email_create",
1315
- {
1316
- title: "Roxyon: create a mailbox",
1317
- description: "Provision a mailbox on a host already on the account. The password is shown once in the result; there is no way to retrieve it later. Needs confirm:true.",
1318
- inputSchema: {
1319
- localPart: z4.string().describe('The part before @, e.g. "info".'),
1320
- domain: z4.string().describe("A hostname already on the account."),
1321
- password: z4.string().optional().describe("Omit to have Roxyon generate one."),
1322
- quota: z4.number().int().positive().optional().describe("Quota in MB (default 1024)."),
1323
- forwardTo: z4.string().optional(),
1324
- saveCopy: z4.boolean().optional(),
1325
- confirm: z4.boolean().optional()
1326
- }
1327
- },
1328
- (args) => guard(async () => {
1329
- const session = await getSession();
1330
- const email = `${args.localPart}@${args.domain}`;
1331
- if (!args.confirm) {
1332
- return text(`Would create mailbox ${email}. Pass confirm:true.`, { dryRun: true });
1333
- }
1334
- const r = await session.roxyon.email.create({
1335
- localPart: args.localPart,
1336
- domain: args.domain,
1337
- password: args.password,
1338
- quota: args.quota,
1339
- forwardTo: args.forwardTo,
1340
- saveCopy: args.saveCopy
1291
+ server.registerTool(
1292
+ "roxyon_database_delete",
1293
+ {
1294
+ title: "Roxyon: delete a database",
1295
+ description: "Delete a database by its objectId (from roxyon_database_create/roxyon_list_databases). Needs confirm:true.",
1296
+ inputSchema: { database: z4.string(), confirm: z4.boolean().optional() }
1297
+ },
1298
+ (args) => guard(async () => {
1299
+ const session = await getSession();
1300
+ if (!args.confirm) {
1301
+ return text(`Would delete database ${args.database}. Pass confirm:true.`, {
1302
+ dryRun: true
1341
1303
  });
1342
- const body = [
1343
- `${r.status === "active" ? "\u2713" : "\xBB"} Mailbox ${r.email} \u2014 ${r.status}.`,
1344
- r.password ? `
1304
+ }
1305
+ const r = await session.roxyon.databases.delete(args.database);
1306
+ return text(`Database ${args.database} \u2014 ${r.status}.`, { ok: true, status: r.status });
1307
+ })
1308
+ );
1309
+ server.registerTool(
1310
+ "roxyon_email_create",
1311
+ {
1312
+ title: "Roxyon: create a mailbox",
1313
+ description: "Provision a mailbox on a host already on the account. The password is shown once in the result; there is no way to retrieve it later. Needs confirm:true.",
1314
+ inputSchema: {
1315
+ localPart: z4.string().describe('The part before @, e.g. "info".'),
1316
+ domain: z4.string().describe("A hostname already on the account."),
1317
+ password: z4.string().optional().describe("Omit to have Roxyon generate one."),
1318
+ quota: z4.number().int().positive().optional().describe("Quota in MB (default 1024)."),
1319
+ forwardTo: z4.string().optional(),
1320
+ saveCopy: z4.boolean().optional(),
1321
+ confirm: z4.boolean().optional()
1322
+ }
1323
+ },
1324
+ (args) => guard(async () => {
1325
+ const session = await getSession();
1326
+ const email = `${args.localPart}@${args.domain}`;
1327
+ if (!args.confirm) {
1328
+ return text(`Would create mailbox ${email}. Pass confirm:true.`, { dryRun: true });
1329
+ }
1330
+ const r = await session.roxyon.email.create({
1331
+ localPart: args.localPart,
1332
+ domain: args.domain,
1333
+ password: args.password,
1334
+ quota: args.quota,
1335
+ forwardTo: args.forwardTo,
1336
+ saveCopy: args.saveCopy
1337
+ });
1338
+ const body = [
1339
+ `${r.status === "active" ? "\u2713" : "\xBB"} Mailbox ${r.email} \u2014 ${r.status}.`,
1340
+ r.password ? `
1345
1341
  Password (save this now \u2014 shown once):
1346
1342
  ${r.password}` : ""
1347
- ].filter(Boolean).join("\n");
1348
- return text(body, { ok: true, objectId: r.objectId, email: r.email, status: r.status });
1349
- })
1350
- )
1343
+ ].filter(Boolean).join("\n");
1344
+ return text(body, { ok: true, objectId: r.objectId, email: r.email, status: r.status });
1345
+ })
1351
1346
  );
1352
- hideUntilLive(
1353
- server.registerTool(
1354
- "roxyon_list_emails",
1355
- {
1356
- title: "Roxyon: list mailboxes",
1357
- description: "Mailboxes on the active subscription.",
1358
- inputSchema: { subscription: z4.string().optional() }
1359
- },
1360
- (args) => guard(async () => {
1361
- const session = await getSession();
1362
- const subscription = args.subscription ?? session.preferredSubscription;
1363
- if (!subscription) return errorResult('No subscription \u2014 pass "subscription".');
1364
- const rows = await session.roxyon.email.list(subscription);
1365
- const body = rows.length ? rows.map((e) => `- ${e.Email} [${e.objectId}] \u2014 ${e.Status}`).join("\n") : "(no mailboxes)";
1366
- return text(body, { emails: rows });
1367
- })
1368
- )
1347
+ server.registerTool(
1348
+ "roxyon_list_emails",
1349
+ {
1350
+ title: "Roxyon: list mailboxes",
1351
+ description: "Mailboxes on the active subscription.",
1352
+ inputSchema: { subscription: z4.string().optional() }
1353
+ },
1354
+ (args) => guard(async () => {
1355
+ const session = await getSession();
1356
+ const subscription = args.subscription ?? session.preferredSubscription;
1357
+ if (!subscription) return errorResult('No subscription \u2014 pass "subscription".');
1358
+ const rows = await session.roxyon.email.list(subscription);
1359
+ const body = rows.length ? rows.map((e) => `- ${e.Email} [${e.objectId}] \u2014 ${e.Status}`).join("\n") : "(no mailboxes)";
1360
+ return text(body, { emails: rows });
1361
+ })
1369
1362
  );
1370
- hideUntilLive(
1371
- server.registerTool(
1372
- "roxyon_email_delete",
1373
- {
1374
- title: "Roxyon: delete a mailbox",
1375
- description: "Delete a mailbox by its objectId (from roxyon_email_create/roxyon_list_emails). Needs confirm:true.",
1376
- inputSchema: { email: z4.string(), confirm: z4.boolean().optional() }
1377
- },
1378
- (args) => guard(async () => {
1379
- const session = await getSession();
1380
- if (!args.confirm) {
1381
- return text(`Would delete mailbox ${args.email}. Pass confirm:true.`, { dryRun: true });
1382
- }
1383
- const r = await session.roxyon.email.delete(args.email);
1384
- return text(`Mailbox ${args.email} \u2014 ${r.status}.`, { ok: true, status: r.status });
1385
- })
1386
- )
1363
+ server.registerTool(
1364
+ "roxyon_email_delete",
1365
+ {
1366
+ title: "Roxyon: delete a mailbox",
1367
+ description: "Delete a mailbox by its objectId (from roxyon_email_create/roxyon_list_emails). Needs confirm:true.",
1368
+ inputSchema: { email: z4.string(), confirm: z4.boolean().optional() }
1369
+ },
1370
+ (args) => guard(async () => {
1371
+ const session = await getSession();
1372
+ if (!args.confirm) {
1373
+ return text(`Would delete mailbox ${args.email}. Pass confirm:true.`, { dryRun: true });
1374
+ }
1375
+ const r = await session.roxyon.email.delete(args.email);
1376
+ return text(`Mailbox ${args.email} \u2014 ${r.status}.`, { ok: true, status: r.status });
1377
+ })
1387
1378
  );
1388
- hideUntilLive(
1389
- server.registerTool(
1390
- "roxyon_ssh_reset_password",
1391
- {
1392
- title: "Roxyon: reset the SSH/SFTP password",
1393
- description: "Reset a subscription's shell password \u2014 used for SSH, SFTP, and the file manager. Changing it signs out anything using the old one. The password is shown once in the result; the platform never stores or re-shows it. Needs confirm:true.",
1394
- inputSchema: {
1395
- subscription: z4.string().optional(),
1396
- password: z4.string().optional().describe("Omit to have Roxyon generate one (12+ chars, mixed case, number, symbol)."),
1397
- confirm: z4.boolean().optional()
1398
- }
1399
- },
1400
- (args) => guard(async () => {
1401
- const session = await getSession();
1402
- if (!args.confirm) {
1403
- return text("Would reset the SSH/SFTP password. Pass confirm:true.", { dryRun: true });
1404
- }
1405
- const r = await session.roxyon.ssh.resetPassword({
1406
- subscription: args.subscription ?? session.preferredSubscription,
1407
- password: args.password
1408
- });
1409
- return text(
1410
- `${r.status === "active" ? "\u2713" : "\xBB"} SSH/SFTP password ${r.status === "active" ? "changed" : "change queued"}.
1379
+ server.registerTool(
1380
+ "roxyon_ssh_reset_password",
1381
+ {
1382
+ title: "Roxyon: reset the SSH/SFTP password",
1383
+ description: "Reset a subscription's shell password \u2014 used for SSH, SFTP, and the file manager. Changing it signs out anything using the old one. The password is shown once in the result; the platform never stores or re-shows it. Needs confirm:true.",
1384
+ inputSchema: {
1385
+ subscription: z4.string().optional(),
1386
+ password: z4.string().optional().describe("Omit to have Roxyon generate one (12+ chars, mixed case, number, symbol)."),
1387
+ confirm: z4.boolean().optional()
1388
+ }
1389
+ },
1390
+ (args) => guard(async () => {
1391
+ const session = await getSession();
1392
+ if (!args.confirm) {
1393
+ return text("Would reset the SSH/SFTP password. Pass confirm:true.", { dryRun: true });
1394
+ }
1395
+ const r = await session.roxyon.ssh.resetPassword({
1396
+ subscription: args.subscription ?? session.preferredSubscription,
1397
+ password: args.password
1398
+ });
1399
+ return text(
1400
+ `${r.status === "active" ? "\u2713" : "\xBB"} SSH/SFTP password ${r.status === "active" ? "changed" : "change queued"}.
1411
1401
 
1412
1402
  Password (save this now \u2014 shown once):
1413
1403
  ${r.password}`,
1414
- { ok: true, subscription: r.subscription, status: r.status }
1415
- );
1416
- })
1417
- )
1404
+ { ok: true, subscription: r.subscription, status: r.status }
1405
+ );
1406
+ })
1418
1407
  );
1419
- hideUntilLive(
1420
- server.registerTool(
1421
- "roxyon_install_wordpress",
1422
- {
1423
- title: "Roxyon: install WordPress",
1424
- description: [
1425
- "One-shot recipe: create a subdomain (if it does not already exist), provision a database",
1426
- "for it, download WordPress core, and deploy it. v1 scope \u2014 core only, no plugin/theme",
1427
- "selection, single site. Local-only (needs your filesystem to unpack WordPress into) \u2014 run",
1428
- "this from the CLI-backed MCP, not the hosted mcp.roxyon.com connector. Needs confirm:true."
1429
- ].join(" "),
1430
- inputSchema: {
1431
- host: z4.string().describe("The site host, e.g. blog.mycompany.com \u2014 created if it does not exist."),
1432
- folder: z4.string().optional().describe('Sub-path under the host; "" = site root (recommended).'),
1433
- subscription: z4.string().optional(),
1434
- dbName: z4.string().optional().describe(
1435
- "Database name suffix (default derived from the host). See roxyon_database_create."
1436
- ),
1437
- phpVersion: z4.string().optional().describe('Default "8.3".'),
1438
- confirm: z4.boolean().optional()
1439
- }
1440
- },
1441
- (args) => guard(async () => {
1442
- const blocked = remoteFilesystemBlock("roxyon_install_wordpress");
1443
- if (blocked) return blocked;
1444
- const session = await getSession();
1445
- const folder = args.folder ?? "";
1446
- const dbSuffix = (args.dbName ?? args.host.split(".")[0] ?? "wordpress").toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/^[^a-z]+/, "").slice(0, 20) || "wordpress";
1447
- if (!args.confirm) {
1448
- return text(
1449
- [
1450
- "DRY RUN \u2014 pass confirm:true to install.",
1451
- "",
1452
- `Host: ${args.host}${folder ? `/${folder}` : ""} (created if missing)`,
1453
- `Database: ${dbSuffix} (prefixed with your account username)`,
1454
- "Steps: add domain -> create database -> download WordPress core -> upload"
1455
- ].join("\n"),
1456
- { dryRun: true }
1457
- );
1458
- }
1459
- const subscription = args.subscription ?? session.preferredSubscription;
1460
- const domain = await session.roxyon.domains.create({
1461
- host: args.host,
1462
- subscription,
1463
- phpVersion: args.phpVersion ?? "8.3"
1464
- });
1465
- if (domain.status === "failed") {
1466
- return errorResult(
1467
- `Could not provision ${args.host}: ${domain.error ?? "unknown error"}`
1468
- );
1469
- }
1470
- const db = await session.roxyon.databases.create({ name: dbSuffix, subscription });
1471
- if (db.status === "failed" || !db.password || !db.host) {
1472
- return errorResult(`Could not provision the database: ${db.error ?? "unknown error"}`);
1473
- }
1474
- const scratchDir = await mkdtemp(join3(tmpdir(), "roxyon-wp-"));
1475
- await installWordPress({
1476
- dir: scratchDir,
1477
- db: { name: db.name, username: db.username, password: db.password, host: db.host }
1478
- });
1479
- const pack = await packDirectory(scratchDir);
1480
- const deployRes = await session.roxyon.sites.deploy(args.host, folder, pack.buffer);
1481
- const url = `https://${deployRes.host}${deployRes.path && deployRes.path !== "/" ? deployRes.path : ""}`;
1408
+ server.registerTool(
1409
+ "roxyon_install_wordpress",
1410
+ {
1411
+ title: "Roxyon: install WordPress",
1412
+ description: [
1413
+ "One-shot recipe: create a subdomain (if it does not already exist), provision a database",
1414
+ "for it, download WordPress core, and deploy it. v1 scope \u2014 core only, no plugin/theme",
1415
+ "selection, single site. Local-only (needs your filesystem to unpack WordPress into) \u2014 run",
1416
+ "this from the CLI-backed MCP, not the hosted mcp.roxyon.com connector. Needs confirm:true."
1417
+ ].join(" "),
1418
+ inputSchema: {
1419
+ host: z4.string().describe("The site host, e.g. blog.mycompany.com \u2014 created if it does not exist."),
1420
+ folder: z4.string().optional().describe('Sub-path under the host; "" = site root (recommended).'),
1421
+ subscription: z4.string().optional(),
1422
+ dbName: z4.string().optional().describe(
1423
+ "Database name suffix (default derived from the host). See roxyon_database_create."
1424
+ ),
1425
+ phpVersion: z4.string().optional().describe('Default "8.3".'),
1426
+ confirm: z4.boolean().optional()
1427
+ }
1428
+ },
1429
+ (args) => guard(async () => {
1430
+ const blocked = remoteFilesystemBlock("roxyon_install_wordpress");
1431
+ if (blocked) return blocked;
1432
+ const session = await getSession();
1433
+ const folder = args.folder ?? "";
1434
+ const dbSuffix = (args.dbName ?? args.host.split(".")[0] ?? "wordpress").toLowerCase().replace(/[^a-z0-9_]/g, "_").replace(/^[^a-z]+/, "").slice(0, 20) || "wordpress";
1435
+ if (!args.confirm) {
1482
1436
  return text(
1483
1437
  [
1484
- `\u2713 WordPress installed at ${url} (${pack.files.length} files).`,
1485
- "Visit the site to finish setup (site title, admin account) \u2014 WordPress asks for these",
1486
- "on first load.",
1438
+ "DRY RUN \u2014 pass confirm:true to install.",
1487
1439
  "",
1488
- `Database: ${db.name} / ${db.username} \u2014 password shown once, save it now:`,
1489
- db.password
1440
+ `Host: ${args.host}${folder ? `/${folder}` : ""} (created if missing)`,
1441
+ `Database: ${dbSuffix} (prefixed with your account username)`,
1442
+ "Steps: add domain -> create database -> download WordPress core -> upload"
1490
1443
  ].join("\n"),
1491
- { ok: true, url, database: { name: db.name, username: db.username } }
1444
+ { dryRun: true }
1445
+ );
1446
+ }
1447
+ const subscription = args.subscription ?? session.preferredSubscription;
1448
+ const domain = await session.roxyon.domains.create({
1449
+ host: args.host,
1450
+ subscription,
1451
+ phpVersion: args.phpVersion ?? "8.3"
1452
+ });
1453
+ if (domain.status === "failed") {
1454
+ return errorResult(
1455
+ `Could not provision ${args.host}: ${domain.error ?? "unknown error"}`
1492
1456
  );
1493
- })
1494
- )
1457
+ }
1458
+ const db = await session.roxyon.databases.create({ name: dbSuffix, subscription });
1459
+ if (db.status === "failed" || !db.password || !db.host) {
1460
+ return errorResult(`Could not provision the database: ${db.error ?? "unknown error"}`);
1461
+ }
1462
+ const scratchDir = await mkdtemp(join3(tmpdir(), "roxyon-wp-"));
1463
+ await installWordPress({
1464
+ dir: scratchDir,
1465
+ db: { name: db.name, username: db.username, password: db.password, host: db.host }
1466
+ });
1467
+ const pack = await packDirectory(scratchDir);
1468
+ const deployRes = await session.roxyon.sites.deploy(args.host, folder, pack.buffer);
1469
+ const url = `https://${deployRes.host}${deployRes.path && deployRes.path !== "/" ? deployRes.path : ""}`;
1470
+ return text(
1471
+ [
1472
+ `\u2713 WordPress installed at ${url} (${pack.files.length} files).`,
1473
+ "Visit the site to finish setup (site title, admin account) \u2014 WordPress asks for these",
1474
+ "on first load.",
1475
+ "",
1476
+ `Database: ${db.name} / ${db.username} \u2014 password shown once, save it now:`,
1477
+ db.password
1478
+ ].join("\n"),
1479
+ { ok: true, url, database: { name: db.name, username: db.username } }
1480
+ );
1481
+ })
1495
1482
  );
1496
1483
  }
1497
1484
 
@@ -1519,4 +1506,4 @@ export {
1519
1506
  SERVER_VERSION,
1520
1507
  createServer
1521
1508
  };
1522
- //# sourceMappingURL=chunk-JDSXDZB2.js.map
1509
+ //# sourceMappingURL=chunk-W6X4YMV5.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts","../src/baas-tools.ts","../src/context.ts","../src/session.ts","../src/result.ts","../src/commerce-tools.ts","../src/prompts.ts","../src/resources.ts","../src/tools.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { registerBaasTools } from './baas-tools.js';\nimport { registerCommerceTools } from './commerce-tools.js';\nimport { registerPrompts } from './prompts.js';\nimport { registerResources } from './resources.js';\nimport { registerTools } from './tools.js';\n\nexport const SERVER_NAME = 'roxyon';\nexport const SERVER_VERSION: string = (\n createRequire(import.meta.url)('../package.json') as { version: string }\n).version;\n\n/** Build the Roxyon MCP server with every tool, resource and prompt registered. */\nexport function createServer(): McpServer {\n const server = new McpServer(\n { name: SERVER_NAME, version: SERVER_VERSION },\n {\n instructions:\n 'Roxyon lets you build LumenJS SPAs, use the Roxyon BaaS, and deploy apps and web ' +\n 'projects to Roxyon infrastructure. Read the roxyon://docs/* resources before writing ' +\n 'LumenJS or calling the BaaS. To deploy: roxyon_init once per project, then roxyon_deploy ' +\n '(dry run, then confirm:true). Side-effecting tools require confirm:true.',\n },\n );\n\n registerResources(server);\n registerPrompts(server);\n registerTools(server);\n registerBaasTools(server);\n registerCommerceTools(server);\n return server;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { BAAS_MAX_BATCH, BAAS_MAX_PAGE, BaasDataApi, parseEnv } from '@roxyon/api-client';\nimport { z } from 'zod';\nimport { currentContext } from './context.js';\nimport { type ToolResult, errorResult, guard, text } from './result.js';\n\nconst MAX_TEXT = 40_000;\n\nconst dirArg = z\n .string()\n .optional()\n .describe('Project directory whose .env holds RX_SECRET_KEY. Defaults to cwd.');\n\n/**\n * These tools act on the user's OWN app on BaaS V2 with that app's secret key, read from the\n * project's local `.env`. The hosted server has no local files, and must not accept keys\n * through the conversation, so it refuses.\n */\nfunction remoteBlock(): ToolResult | null {\n if (!currentContext().remote) return null;\n return errorResult(\n 'The roxyon_baas_* tools read your app secret key from your local project .env, so they only ' +\n 'run in the local MCP server (`npx -y @roxyon/mcp`). Manage data in the hosted connector via ' +\n \"the console's Roxyon Base panel for now.\",\n );\n}\n\nasync function baasFor(dir: string | undefined): Promise<BaasDataApi> {\n const root = resolve(dir ?? process.cwd());\n let fileEnv: Record<string, string> = {};\n try {\n fileEnv = parseEnv(await readFile(join(root, '.env'), 'utf8'));\n } catch {\n // No .env — fall back to the process environment.\n }\n const secretKey = fileEnv.RX_SECRET_KEY || process.env.RX_SECRET_KEY || '';\n if (!secretKey) {\n throw new Error(\n `No BaaS V2 secret key found. Put RX_SECRET_KEY=rxsk_… in ${join(root, '.env')} (console.roxyon.com → Roxyon Base → your project → API keys). Keep it out of git and out of browser code.`,\n );\n }\n return new BaasDataApi({ secretKey });\n}\n\nfunction clip(s: string): string {\n return s.length > MAX_TEXT\n ? `${s.slice(0, MAX_TEXT)}\\n… (truncated — narrow with fields/where/limit)`\n : s;\n}\n\nfunction dryRun(what: string): ToolResult {\n return text(`Would ${what}. Pass confirm:true to do it.`, { dryRun: true });\n}\n\nconst SERVER_SCOPE =\n 'Runs as the app backend (server scope, which passes every class rule). Local MCP only.';\n\nexport function registerBaasTools(server: McpServer): void {\n server.registerTool(\n 'roxyon_baas_query',\n {\n title: 'Roxyon BaaS: query records',\n description: `Read records of a class in the project's own app on BaaS V2. \\`where\\` is an object like {\"Status\":\"active\",\"Age\":{\"gt\":18}}; for \\`in\\`, pass a comma-joined string. \\`fields\\` defaults to \"*\"; built-in meta columns must be named. Up to ${BAAS_MAX_PAGE} rows a page (use skip to page). ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n where: z.record(z.any()).optional(),\n fields: z.string().optional(),\n order: z.string().optional().describe('e.g. \"-createdAt\"'),\n limit: z.number().int().min(1).max(BAAS_MAX_PAGE).optional(),\n skip: z.number().int().min(0).optional(),\n count: z.boolean().optional().describe('Also return the total number of matches.'),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n const api = await baasFor(args.dir);\n const { rows, count } = await api.query(args.class, {\n where: args.where,\n fields: args.fields,\n order: args.order,\n limit: args.limit,\n skip: args.skip,\n count: args.count,\n });\n const head = `${rows.length} row(s)${count !== undefined ? ` of ${count}` : ''}`;\n return text(clip(`${head}\\n${JSON.stringify(rows, null, 2)}`), { rows, count });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_get',\n {\n title: 'Roxyon BaaS: read one record',\n description: `Read one record by objectId. ${SERVER_SCOPE}`,\n inputSchema: { dir: dirArg, class: z.string(), objectId: z.string() },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n const api = await baasFor(args.dir);\n const row = await api.get(args.class, args.objectId);\n return text(clip(JSON.stringify(row, null, 2)), { row });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_create',\n {\n title: 'Roxyon BaaS: create a record',\n description: `Insert one record into an existing class (V2 has no schema changes with a secret key: add classes and columns in the console). For relations store the other row's objectId in a string column. Needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n data: z.record(z.any()),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n if (!args.confirm) return dryRun(`insert into ${args.class}: ${JSON.stringify(args.data)}`);\n const api = await baasFor(args.dir);\n const row = await api.create(args.class, args.data);\n return text(`✓ Created ${args.class} ${String(row.objectId ?? '')}.`, { ok: true, row });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_update',\n {\n title: 'Roxyon BaaS: update a record',\n description: `Set fields on one record by objectId. Needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n objectId: z.string(),\n data: z.record(z.any()),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n if (!args.confirm) {\n return dryRun(`update ${args.class} ${args.objectId}: ${JSON.stringify(args.data)}`);\n }\n const api = await baasFor(args.dir);\n const row = await api.update(args.class, args.objectId, args.data);\n return text(`✓ Updated ${args.class} ${args.objectId}.`, { ok: true, row });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_delete',\n {\n title: 'Roxyon BaaS: delete a record',\n description: `Delete one record by objectId. Needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n objectId: z.string(),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n if (!args.confirm) return dryRun(`delete ${args.class} ${args.objectId}`);\n const api = await baasFor(args.dir);\n await api.delete(args.class, args.objectId);\n return text(`✓ Deleted ${args.class} ${args.objectId}.`, { ok: true });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_batch',\n {\n title: 'Roxyon BaaS: batch of record requests',\n description: `1 to ${BAAS_MAX_BATCH} record requests in one call, each answered on its own (one failing doesn't stop the others). path is /Class or /Class/<objectId>; for POST/PUT the body is {\"data\":{...}}; for GET the body holds query options (where, fields, limit…). A batch with any write needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n requests: z\n .array(\n z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'DELETE']),\n path: z.string(),\n body: z.record(z.any()).optional(),\n }),\n )\n .min(1)\n .max(BAAS_MAX_BATCH),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n const writes = args.requests.filter((r) => r.method !== 'GET');\n if (writes.length && !args.confirm) {\n return dryRun(\n `run ${args.requests.length} request(s), ${writes.length} of them writes: ${writes.map((r) => `${r.method} ${r.path}`).join(', ')}`,\n );\n }\n const api = await baasFor(args.dir);\n const results = await api.batch(args.requests);\n const failed = results.filter((r) => r.ok === false).length;\n return text(\n clip(\n `${results.length} answer(s), ${failed} failed\\n${JSON.stringify(results, null, 2)}`,\n ),\n { results },\n );\n }),\n );\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * Per-request state for the HTTP transport. The stdio entry never opens a\n * context, so {@link currentContext} returns `{}` there and everything falls\n * back to the env / stored-login behaviour.\n */\nexport interface RequestContext {\n /** Bearer token presented on this HTTP request (from the OAuth layer). */\n token?: string;\n /**\n * True when serving the remote HTTP server. Tools that need the caller's\n * local filesystem (`roxyon_init`, `roxyon_deploy`) refuse in this mode.\n */\n remote?: boolean;\n}\n\nconst storage = new AsyncLocalStorage<RequestContext>();\n\n/** Run `fn` with `ctx` visible to {@link currentContext} for its whole async tree. */\nexport function runWithContext<T>(ctx: RequestContext, fn: () => T): T {\n return storage.run(ctx, fn);\n}\n\n/** The context for the in-flight request, or `{}` on the stdio transport. */\nexport function currentContext(): RequestContext {\n return storage.getStore() ?? {};\n}\n","import { Roxyon, isAuthError } from '@roxyon/api-client';\nimport { endpointsFromEnv, loadCredentials, tokenFromEnv } from '@roxyon/deploy-core';\nimport { currentContext } from './context.js';\n\nexport interface RoxyonSession {\n roxyon: Roxyon;\n preferredSubscription?: string;\n /** how the session was authenticated, for diagnostics */\n source: 'env-token' | 'stored-login' | 'oauth';\n}\n\nexport class NotAuthenticatedError extends Error {\n constructor() {\n super(\n 'Not signed in to Roxyon. Run `roxyon login` in a terminal, or set ROXYON_TOKEN ' +\n \"in this MCP server's environment.\",\n );\n this.name = 'NotAuthenticatedError';\n }\n}\n\n/**\n * Resolve a Roxyon client for a tool call. Order: `ROXYON_TOKEN` env var, then\n * the login stored by the CLI at `~/.roxyon/config.json`.\n */\nexport async function getSession(): Promise<RoxyonSession> {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n\n // HTTP transport: the bearer token from this request wins over any ambient\n // env/stored credentials, and each request gets its own client.\n const requestToken = currentContext().token;\n if (requestToken) {\n return {\n roxyon: new Roxyon({ sessionToken: requestToken, baseUrl: apiUrl, consoleUrl }),\n source: 'oauth',\n };\n }\n\n const envToken = tokenFromEnv();\n if (envToken) {\n return {\n roxyon: new Roxyon({ sessionToken: envToken, baseUrl: apiUrl, consoleUrl }),\n source: 'env-token',\n };\n }\n const creds = await loadCredentials();\n if (!creds?.sessionToken) throw new NotAuthenticatedError();\n return {\n roxyon: new Roxyon({ sessionToken: creds.sessionToken, baseUrl: apiUrl, consoleUrl }),\n preferredSubscription: creds.subscription,\n source: 'stored-login',\n };\n}\n\nexport function isSessionGone(err: unknown): boolean {\n return err instanceof NotAuthenticatedError || isAuthError(err);\n}\n","import { isSessionGone } from './session.js';\n\nexport interface ToolResult {\n content: Array<{ type: 'text'; text: string }>;\n structuredContent?: Record<string, unknown>;\n isError?: boolean;\n /** SDK's CallToolResult carries an open index signature. */\n [k: string]: unknown;\n}\n\nexport function text(body: string, structured?: Record<string, unknown>): ToolResult {\n return {\n content: [{ type: 'text', text: body }],\n ...(structured ? { structuredContent: structured } : {}),\n };\n}\n\nexport function errorResult(message: string, structured?: Record<string, unknown>): ToolResult {\n return {\n content: [{ type: 'text', text: message }],\n ...(structured ? { structuredContent: structured } : {}),\n isError: true,\n };\n}\n\n/** Wrap a tool body so thrown errors become clean `isError` results. */\nexport async function guard(fn: () => Promise<ToolResult>): Promise<ToolResult> {\n try {\n return await fn();\n } catch (err) {\n if (isSessionGone(err)) {\n return errorResult(\n (err as Error).message ||\n 'Roxyon session expired — run `roxyon login` again, or refresh ROXYON_TOKEN.',\n );\n }\n return errorResult(err instanceof Error ? err.message : String(err));\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { BILLING_CYCLES, type CatalogProduct, Roxyon } from '@roxyon/api-client';\nimport { endpointsFromEnv } from '@roxyon/deploy-core';\nimport { z } from 'zod';\nimport { guard, text } from './result.js';\nimport { getSession } from './session.js';\n\n/** Catalog and quotes are public: no sign-in, so an agent can price before the user has an account. */\nfunction publicRoxyon(): Roxyon {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n return new Roxyon({ baseUrl: apiUrl, consoleUrl });\n}\n\nfunction money(n: number | undefined): string {\n return n === undefined ? '—' : `$${n.toFixed(2)}`;\n}\n\nfunction productLine(p: CatalogProduct): string {\n const spec =\n p.vcpu !== undefined\n ? ` — ${p.vcpu} vCPU (${p.cpuType}), ${p.ramGb} GB RAM, ${p.diskGb} GB disk${p.ipv4Included ? `, ${p.ipv4Included} IPv4` : ''}`\n : '';\n const prices = BILLING_CYCLES.filter((c) => p.pricesUSD[c] !== undefined)\n .map((c) => `${c} ${money(p.pricesUSD[c])}`)\n .join(', ');\n return `- ${p.sku || p.planId} \"${p.name}\" [${p.category}]${spec} | USD ${prices}${p.stock === 'out' ? ' | OUT OF STOCK' : ''} (planId ${p.planId})`;\n}\n\nexport function registerCommerceTools(server: McpServer): void {\n server.registerTool(\n 'roxyon_catalog',\n {\n title: 'Roxyon: product catalog',\n description:\n 'List what Roxyon sells: cloud servers (cloud.vps.launch / scale / power) and web hosting ' +\n '(cloud.hosting.solo / multiple / isolated). Each product has its planId (what roxyon_quote ' +\n 'takes), SKU, specs (vCPU, RAM GB, disk GB, IPv4 included) for servers, list prices in USD ' +\n 'per billing cycle BEFORE tax and currency conversion, and stock (\"out\" = cannot be ordered ' +\n 'now). No sign-in needed. Use roxyon_quote for the exact amount a buyer would pay. Read-only.',\n inputSchema: {\n category: z\n .string()\n .optional()\n .describe('Filter by category prefix, e.g. \"cloud.vps\" or \"cloud.hosting\".'),\n in_stock_only: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n let products = await publicRoxyon().billing.catalog();\n if (args.category) products = products.filter((p) => p.category.startsWith(args.category!));\n if (args.in_stock_only) products = products.filter((p) => p.stock === 'in');\n return text(\n products.length ? products.map(productLine).join('\\n') : '(no products match)',\n { products },\n );\n }),\n );\n\n server.registerTool(\n 'roxyon_quote',\n {\n title: 'Roxyon: price a new subscription',\n description:\n \"The exact amount Roxyon's checkout would charge for a NEW subscription to one plan, \" +\n 'computed by the platform itself (same server pricing the console checkout uses, setup fee ' +\n 'included): line items, subtotal, tax, total, in the requested currency. Pass the buyer ' +\n 'currency and country: without them the quote is in USD with no tax, while checkout uses the ' +\n \"account's own currency/country. No sign-in needed. Read-only: creates no order. Domains \" +\n 'are not priced by this tool yet.',\n inputSchema: {\n plan: z.string().describe('planId (or SKU, e.g. \"SCALE-S\") from roxyon_catalog.'),\n cycle: z.enum(BILLING_CYCLES),\n currency: z.string().length(3).optional().describe('ISO 4217, e.g. \"USD\", \"SAR\".'),\n country: z\n .string()\n .length(2)\n .optional()\n .describe('ISO 3166 alpha-2, decides tax, e.g. \"SA\".'),\n },\n },\n (args) =>\n guard(async () => {\n const roxyon = publicRoxyon();\n const want = args.plan.toLowerCase();\n const product = (await roxyon.billing.catalog()).find(\n (p) => p.planId === args.plan || p.sku.toLowerCase() === want,\n );\n if (!product)\n throw new Error(`No product \"${args.plan}\" in the catalog. See roxyon_catalog.`);\n const q = await roxyon.billing.quote({\n planId: product.planId,\n cycle: args.cycle,\n currency: args.currency,\n country: args.country,\n });\n const lines = [\n ...q.lineItems.map((l) => `${l.label}: ${l.amount} ${q.currency}`),\n `Subtotal: ${q.subtotal} ${q.currency}`,\n `${q.taxLabel || 'Tax'} (${q.taxRate}%): ${q.taxAmount} ${q.currency}`,\n `Total: ${q.total} ${q.currency}`,\n ];\n if (product?.stock === 'out') lines.push('Note: this plan is out of stock right now.');\n return text(lines.join('\\n'), { quote: q });\n }),\n );\n\n server.registerTool(\n 'roxyon_list_subscriptions',\n {\n title: 'Roxyon: my subscriptions (billing)',\n description:\n \"The signed-in user's own subscriptions with billing details: plan + SKU, status, billing \" +\n 'cycle, recurring price and currency, next billing date, auto-renew, and for servers the ' +\n 'state (building / running / stopped…) and public IP. Only subscriptions the user owns. ' +\n 'Read-only.',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const subs = await session.roxyon.billing.subscriptions();\n const body = subs.length\n ? subs\n .map(\n (s) =>\n `- ${s.name || s.id} [${s.status}] ${s.plan}${s.sku ? ` (${s.sku})` : ''} — ` +\n `${s.price} ${s.currency}/${s.cycle || '?'}, next billing ${s.nextBillingDate ?? '—'}` +\n `${s.autoRenew ? ', auto-renew' : ''}` +\n `${s.serverState ? `, server ${s.serverState}` : ''}${s.publicIp ? ` ${s.publicIp}` : ''}`,\n )\n .join('\\n')\n : '(no subscriptions on this account)';\n return text(body, { subscriptions: subs });\n }),\n );\n\n server.registerTool(\n 'roxyon_list_invoices',\n {\n title: 'Roxyon: my invoices',\n description:\n \"The signed-in user's own invoices, newest first: number, type, status (pending = unpaid, \" +\n 'paid, overdue, void, failed, cancelled), total and currency, due date, and payUrl (the ' +\n 'console page where the user pays; null when paid). Read-only: this never pays anything.',\n inputSchema: {\n status: z.enum(['pending', 'paid', 'overdue', 'void', 'failed', 'cancelled']).optional(),\n limit: z.number().int().min(1).max(100).optional().describe('Default 25.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const invoices = await session.roxyon.billing.invoices({\n status: args.status,\n limit: args.limit,\n });\n const body = invoices.length\n ? invoices\n .map(\n (i) =>\n `- #${i.number || i.id} ${i.type} [${i.status}] ${i.total} ${i.currency}, due ${i.dueDate ?? '—'}` +\n `${i.payUrl ? ` — pay at ${i.payUrl}` : ''}`,\n )\n .join('\\n')\n : '(no invoices)';\n return text(body, { invoices });\n }),\n );\n\n server.registerTool(\n 'roxyon_pay_link',\n {\n title: 'Roxyon: where to pay an invoice',\n description:\n 'The URL where the signed-in user pays one of their own open invoices (status pending, ' +\n 'overdue or failed), plus its amount and due date. Give the invoice number (e.g. ' +\n '\"INV2610055\") or id from roxyon_list_invoices. A human opens the link and pays in the ' +\n 'console; this tool never charges anything. Paid or void invoices have no link.',\n inputSchema: {\n invoice: z.string().min(1).max(40).describe('Invoice number or id.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const want = args.invoice.replace(/^#/, '').toLowerCase();\n const inv = (await session.roxyon.billing.invoices({ limit: 100 })).find(\n (i) => i.id.toLowerCase() === want || i.number.toLowerCase() === want,\n );\n if (!inv) {\n throw new Error(\n `No invoice \"${args.invoice}\" among your latest 100. See roxyon_list_invoices.`,\n );\n }\n if (!inv.payUrl) {\n return text(`Invoice #${inv.number || inv.id} is ${inv.status}: nothing to pay.`, {\n invoice: inv,\n });\n }\n return text(\n `Invoice #${inv.number || inv.id}: ${inv.total} ${inv.currency}, due ${inv.dueDate ?? '—'}.\\n` +\n `Pay at ${inv.payUrl} (sign in, open Invoices, choose this invoice).`,\n { invoice: inv, payUrl: inv.payUrl },\n );\n }),\n );\n\n const order = server.registerTool(\n 'roxyon_order',\n {\n title: 'Roxyon: place an order (a person pays)',\n description:\n 'Order a new web-hosting plan or cloud server for the signed-in user. The platform prices it ' +\n 'and creates the subscription and a pending invoice; a PERSON then pays at the returned payUrl ' +\n '(nothing is charged by this tool, and the service is set up only after payment). ' +\n 'Always call it first WITHOUT confirm: that dry run returns the exact quote and the token budget ' +\n 'and writes nothing. Show it to the user, then call again with confirm:true. ' +\n 'Rules: `sku` from roxyon_catalog (out-of-stock plans are refused); servers need `image` ' +\n '(e.g. \"ubuntu-24.04\"); `username` must be free. Needs a sign-in, or a token created with the ' +\n '\"billing:order\" scope (`roxyon token create <name> --scopes billing:order --budget <USD> ' +\n '[--skus SCALE-S,…]`): it is refused past that monthly budget (USD, before tax) or outside its SKUs.',\n inputSchema: {\n sku: z.string().describe('Plan code from roxyon_catalog, e.g. \"SCALE-S\".'),\n cycle: z.enum(BILLING_CYCLES),\n name: z.string().min(1).max(100).describe('A name for the service.'),\n username: z\n .string()\n .regex(/^[a-z0-9][a-z0-9.-]{1,62}$/)\n .describe('Account/server name: lowercase letters, digits, dots, dashes; must be free.'),\n image: z.string().optional().describe('Servers only: OS image, e.g. \"ubuntu-24.04\".'),\n ssh_key: z.string().optional().describe('Servers only: an SSH public key for root.'),\n php_version: z.string().optional().describe('Hosting only, e.g. \"8.3\".'),\n currency: z.string().length(3).optional(),\n country: z.string().length(2).optional().describe('Decides tax, e.g. \"SA\".'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const r = await session.roxyon.billing.order({\n sku: args.sku,\n cycle: args.cycle,\n name: args.name,\n username: args.username,\n image: args.image,\n sshKey: args.ssh_key,\n phpVersion: args.php_version,\n currency: args.currency,\n country: args.country,\n confirm: args.confirm === true,\n });\n const budget = r.budget\n ? `Token budget: ${r.budget.spentUSD.toFixed(2)} of ${r.budget.monthlyUSD.toFixed(2)} USD used this month, ${r.budget.remainingUSD.toFixed(2)} left.`\n : '';\n if (r.dryRun) {\n const q = (r.quote ?? {}) as {\n total?: string;\n currency?: string;\n taxAmount?: string;\n taxLabel?: string;\n };\n return text(\n [\n `Dry run, nothing ordered: ${r.plan.sku} \"${r.plan.name}\" (${r.plan.kind}), ${r.plan.cycle}.`,\n `Total ${q.total} ${q.currency} (incl. ${q.taxLabel || 'tax'} ${q.taxAmount}).`,\n budget,\n 'Call again with confirm:true to place it; a person then pays the invoice.',\n ]\n .filter(Boolean)\n .join('\\n'),\n { ...r },\n );\n }\n return text(\n [\n `Ordered ${r.plan.sku} \"${r.plan.name}\" (${r.plan.cycle}): invoice ${r.invoiceId}, ${r.total} ${r.currency}.`,\n `Not active until paid. The user pays at ${r.payUrl}.`,\n budget,\n ]\n .filter(Boolean)\n .join('\\n'),\n { ...r },\n );\n }),\n );\n // Hidden until the console's POST /account/order and the V2 user-session mint are live.\n if (process.env.ROXYON_MCP_ORDERING !== '1') order.disable();\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nexport function registerPrompts(server: McpServer): void {\n server.registerPrompt(\n 'scaffold-lumen-app',\n {\n title: 'Scaffold a LumenJS + Roxyon app',\n description:\n 'Guidance for creating a new LumenJS SPA wired to the Roxyon BaaS and ready to deploy.',\n argsSchema: {\n idea: z.string().describe('What the app should do.'),\n dir: z.string().optional().describe('Where to create it.'),\n },\n },\n ({ idea, dir }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Build a LumenJS single-page app: ${idea}\\n\\nSteps:\\n1. Read the \"roxyon://docs/lumenjs\" resource — follow V1 rules exactly (one bind per region, no nested bind, build option lists in JS not :for, check every BaaS write for an error field).\\n2. Read \"roxyon://docs/baas\" for the data/auth API.\\n3. Scaffold with the LumenJS CLI 2.5.7: \\`npx -y -p @lmjs/cli@2.5.7 lm create <name>\\`${dir ? ` in ${dir}` : ''}. Put views under src/views/, wire the BaaS in src/index.js via config.json.\\n4. When it runs locally (\\`lm serve\\`), call roxyon_init then roxyon_deploy (dry run first, then confirm:true).`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n 'build-and-ship-site',\n {\n title: 'Build a site and host it on Roxyon',\n description:\n 'Generate a static site (or no-build LumenJS SPA) in the conversation and publish it to ' +\n 'a Roxyon host — for the hosted connector, no local files.',\n argsSchema: {\n brief: z.string().describe('What the site should be.'),\n host: z.string().describe('Where to host it, e.g. promo.mycompany.com'),\n },\n },\n ({ brief, host }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Build and publish a website to ${host}.\\n\\nBrief: ${brief}\\n\\n1. Read \"roxyon://docs/recipe\" and follow it. (Read \"roxyon://docs/lumenjs\" too only if the site needs reactivity.)\\n2. If ${host} is not already on the account, roxyon_add_domain { host: \"${host}\", confirm: true } (add spa:true only for a real single-page app).\\n3. Generate the site — self-contained static files, relative paths, real .html per page or <page>/index.html, ≤60 files / 2 MB.\\n4. roxyon_deploy_content { host: \"${host}\", files: [...], clean: true, confirm: true } (dry-run first).\\n5. roxyon_list_files { host: \"${host}\" } to verify, then give me the URL. Note that HTTPS may take a couple of minutes on a brand-new host.`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n 'install-wordpress',\n {\n title: 'Install WordPress on Roxyon',\n description: 'Provision a host + database and install WordPress core — local/CLI MCP only.',\n argsSchema: {\n host: z.string().describe('Where to install it, e.g. blog.mycompany.com'),\n },\n },\n ({ host }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Install WordPress on ${host}.\\n\\n1. Read \"roxyon://docs/recipe-wordpress\" and follow it.\\n2. Call roxyon_install_wordpress { host: \"${host}\" } first without confirm to see the plan.\\n3. If it looks right, call it again with confirm:true.\\n4. Report the site URL and the database credentials (shown once — pass them on to me now), and tell me to visit the URL to finish WordPress's own setup wizard (site title, admin account).`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n 'deploy-to-roxyon',\n {\n title: 'Deploy this project to Roxyon',\n description: 'Walk through deploying the current project to Roxyon infrastructure.',\n argsSchema: { dir: z.string().describe('Absolute path to the project.') },\n },\n ({ dir }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Deploy the project at ${dir} to Roxyon.\\n\\n1. If there is no roxyon.json, call roxyon_init (it detects the runtime; ask me which host if there are several).\\n2. Call roxyon_deploy with just the dir first to see the plan.\\n3. If the plan looks right, call roxyon_deploy again with confirm:true.\\n4. For an app runtime, report the final status and, if it failed, the last error from roxyon_app_status.`,\n },\n },\n ],\n }),\n );\n}\n","import { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n\nconst RESOURCE_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', 'resources');\n\ninterface Doc {\n uri: string;\n name: string;\n file: string;\n title: string;\n description: string;\n}\n\nconst DOCS: Doc[] = [\n {\n uri: 'roxyon://docs/lumenjs',\n name: 'lumenjs-reference',\n file: 'lumenjs.md',\n title: 'LumenJS — complete reference',\n description:\n 'Full LumenJS V1 reference for building SPAs with vanilla JS/HTML/CSS (no build step), ' +\n 'contrasted with Vue/React. Read before writing .view files.',\n },\n {\n uri: 'roxyon://docs/baas',\n name: 'baas-reference',\n file: 'baas.md',\n title: 'Roxyon BaaS reference',\n description:\n 'The Roxyon Backend-as-a-Service REST API: endpoints, auth flow, query rules, and the ' +\n 'resolve-on-failure write behaviour.',\n },\n {\n uri: 'roxyon://docs/deploy',\n name: 'deploy-reference',\n file: 'deploy.md',\n title: 'Deploying to Roxyon',\n description:\n 'How roxyon_init / roxyon_deploy work, the roxyon.json schema, static vs app deploys, env ' +\n 'vars, and git push-to-deploy.',\n },\n {\n uri: 'roxyon://docs/recipe',\n name: 'web-deploy-recipe',\n file: 'recipe-web-deploy.md',\n title: 'Recipe — build a site and host it',\n description:\n 'The end-to-end flow for \"build a landing page and put it on sub.mydomain.com\" over the ' +\n 'hosted connector: roxyon_add_domain → roxyon_deploy_content → roxyon_list_files.',\n },\n {\n uri: 'roxyon://docs/recipe-wordpress',\n name: 'wordpress-recipe',\n file: 'recipe-wordpress.md',\n title: 'Recipe — install WordPress',\n description:\n 'The end-to-end flow for \"put WordPress on sub.mydomain.com\": roxyon_install_wordpress ' +\n '(host + database + WordPress core, one call). Local/CLI-backed MCP only.',\n },\n];\n\nexport function registerResources(server: McpServer): void {\n for (const doc of DOCS) {\n server.registerResource(\n doc.name,\n doc.uri,\n { title: doc.title, description: doc.description, mimeType: 'text/markdown' },\n async () => {\n const body = await readFile(join(RESOURCE_DIR, doc.file), 'utf8');\n return { contents: [{ uri: doc.uri, mimeType: 'text/markdown', text: body }] };\n },\n );\n }\n}\n","import { mkdtemp } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { type Roxyon, envFromStored, formatEnv } from '@roxyon/api-client';\nimport {\n buildIgnore,\n buildProjectConfig,\n deployProject,\n detectRuntime,\n installWordPress,\n listFiles,\n loadProjectConfig,\n packDirectory,\n packFiles,\n saveProjectConfig,\n} from '@roxyon/deploy-core';\nimport { z } from 'zod';\nimport { currentContext } from './context.js';\nimport { type ToolResult, errorResult, guard, text } from './result.js';\nimport { type RoxyonSession, getSession } from './session.js';\n\n/** `roxyon_deploy_content` budget — keeps the whole JSON-RPC body under the 4 MB cap. */\nconst MAX_FILES = 60;\nconst MAX_FILE_BYTES = 1024 * 1024;\nconst MAX_TOTAL_BYTES = 2 * 1024 * 1024;\n\n/**\n * `roxyon_init` / `roxyon_deploy` read and write the caller's local project\n * directory — impossible over the remote HTTP server. Returns an explanatory\n * result when running in that mode, `null` otherwise (proceed).\n */\nfunction remoteFilesystemBlock(\n tool: 'roxyon_init' | 'roxyon_deploy' | 'roxyon_install_wordpress',\n): ToolResult | null {\n if (!currentContext().remote) return null;\n return errorResult(\n [\n `${tool} needs access to your local project files, which the hosted Roxyon MCP`,\n 'server does not have. Either:',\n ' • run the `roxyon` CLI locally (`npm i -g @roxyon/cli`, then `roxyon deploy`), or',\n ' • use `roxyon_link_github` to connect a git repo for push-to-deploy, then',\n ' `roxyon_app_status` / `roxyon_logs` to watch it here.',\n ].join('\\n'),\n );\n}\n\n/** Resolve an application id from an explicit id or a project directory. */\nasync function resolveApp(args: { application?: string; dir?: string }): Promise<{\n applicationId: string;\n host?: string;\n}> {\n if (args.application) return { applicationId: args.application };\n if (args.dir) {\n const cfg = await loadProjectConfig(args.dir);\n if (cfg?.application) return { applicationId: cfg.application, host: cfg.host };\n throw new Error(\n `No application linked in ${args.dir}/roxyon.json. Deploy it once (roxyon_deploy) or pass \"application\".`,\n );\n }\n throw new Error('Pass either \"application\" (an id) or \"dir\" (a project directory).');\n}\n\n/** The account context (user + subscriptions + domains) — one call, PAT-safe. */\nfunction accountContext(session: RoxyonSession) {\n return session.roxyon.account.context();\n}\n\nexport function registerTools(server: McpServer): void {\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_whoami',\n {\n title: 'Roxyon: who am I',\n description: 'Show the signed-in Roxyon user and their subscriptions (which one is active).',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const ctx = await accountContext(session);\n const lines = [\n `User: ${ctx.user.email || ctx.user.id} (${ctx.user.id})`,\n `Auth: ${session.source}${ctx.scopes.length ? ` (scopes: ${ctx.scopes.join(', ')})` : ''}`,\n '',\n 'Subscriptions:',\n ...ctx.subscriptions.map((s) => ` ${s.name || s.id} — ${s.status || '?'}`),\n '',\n `Hosts: ${ctx.domains.map((d) => d.name).join(', ') || '(none)'}`,\n ];\n return text(lines.join('\\n'), {\n user: ctx.user,\n scopes: ctx.scopes,\n subscriptions: ctx.subscriptions,\n hosts: ctx.domains.map((d) => d.name),\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_domains',\n {\n title: 'Roxyon: list hosts',\n description:\n 'List the domains (hosts) on the active subscription — the possible deploy targets.',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const { domains } = await accountContext(session);\n return text(\n domains.length\n ? domains\n .map(\n (d) => `- ${d.name}${d.status && d.status !== 'active' ? ` (${d.status})` : ''}`,\n )\n .join('\\n')\n : '(no hosts on this account)',\n { hosts: domains },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_apps',\n {\n title: 'Roxyon: list applications',\n description:\n 'List the applications on the active subscription with their status and revision.',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const apps = await session.roxyon.account.apps();\n const body = apps.length\n ? apps\n .map(\n (a) =>\n `- ${a.name} [${a.id}] — ${a.status || '?'} ` +\n `(rev ${a.appliedRevision}/${a.configRevision})` +\n `${a.repo ? ` · git:${a.repo.branch}` : ''}`,\n )\n .join('\\n')\n : '(no applications)';\n return text(body, { applications: apps });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_init',\n {\n title: 'Roxyon: initialise a project',\n description:\n \"Detect a project's type and write roxyon.json. Run this once per project before roxyon_deploy. \" +\n 'Does not create anything on the platform.',\n inputSchema: {\n dir: z.string().describe('Absolute path to the project directory.'),\n runtime: z.enum(['lumen', 'node', 'python', 'php']).optional(),\n host: z.string().optional().describe('Deploy host (a domain on the subscription).'),\n folder: z.string().optional().describe('Sub-path under the host; \"\" = site root.'),\n overwrite: z.boolean().optional().describe('Replace an existing roxyon.json.'),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteFilesystemBlock('roxyon_init');\n if (blocked) return blocked;\n const session = await getSession();\n const existing = await loadProjectConfig(args.dir);\n if (existing && !args.overwrite) {\n return errorResult(\n `roxyon.json already exists in ${args.dir}. Pass overwrite:true to replace it.`,\n { config: existing },\n );\n }\n const { domains } = await accountContext(session);\n if (domains.length === 0) {\n return errorResult(\n 'This account has no hosts. Add a domain in the Roxyon console first.',\n );\n }\n const detected = await detectRuntime(args.dir);\n const runtime = args.runtime ?? detected.runtime;\n const host = args.host ?? domains[0]!.name;\n if (!domains.some((d) => d.name === host)) {\n return errorResult(\n `Host \"${host}\" is not on this account (have: ${domains.map((d) => d.name).join(', ')}).`,\n );\n }\n const config = buildProjectConfig({\n cwd: args.dir,\n runtime,\n host,\n folder: args.folder,\n start: detected.start,\n });\n const path = await saveProjectConfig(config, args.dir);\n return text(\n `Wrote ${path}\\nDetected: ${detected.runtime} (${detected.reason})\\n\\n${JSON.stringify(config, null, 2)}`,\n { path, detected: detected.runtime, config },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_deploy',\n {\n title: 'Roxyon: deploy a project',\n description:\n 'Build (if configured) and deploy the project in \"dir\" to Roxyon. Without confirm:true this ' +\n 'returns a dry-run plan (what would build, where it would go, how many files). With confirm:true ' +\n 'it runs the build, uploads, and — for app runtimes — waits for it to go live. Requires roxyon.json ' +\n '(run roxyon_init first).',\n inputSchema: {\n dir: z\n .string()\n .describe('Absolute path to the project directory (must contain roxyon.json).'),\n confirm: z.boolean().optional().describe('Actually deploy. Omit for a dry-run plan.'),\n build: z.boolean().optional().describe('Run the configured build command (default true).'),\n follow: z\n .boolean()\n .optional()\n .describe('For app runtimes, wait until running/failed (default true).'),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteFilesystemBlock('roxyon_deploy');\n if (blocked) return blocked;\n const session = await getSession();\n const config = await loadProjectConfig(args.dir);\n if (!config) {\n return errorResult(`No roxyon.json in ${args.dir}. Run roxyon_init first.`);\n }\n\n if (!args.confirm) {\n const ig = await buildIgnore(args.dir);\n const packRoot =\n config.kind === 'static' && config.outDir ? `${args.dir}/${config.outDir}` : args.dir;\n let files: string[] = [];\n try {\n files = await listFiles(packRoot, ig);\n } catch {\n /* outDir may not exist until the build runs */\n }\n const plan = [\n 'DRY RUN — pass confirm:true to deploy.',\n '',\n `Project: ${config.name} (${config.runtime}, ${config.kind})`,\n `Target: ${config.host}${config.folder ? `/${config.folder}` : ''}`,\n config.build ? `Build: ${config.build}` : 'Build: (none)',\n config.kind === 'app'\n ? `App: ${config.application ?? '(created on first deploy)'}`\n : 'Serve: static files from the host document root',\n files.length\n ? `Would pack ${files.length} file(s) from ${config.kind === 'static' && config.outDir ? config.outDir : '.'}`\n : `Would pack the build output (${config.outDir ?? 'dist'}) after building`,\n ].join('\\n');\n return text(plan, { dryRun: true, config });\n }\n\n const logLines: string[] = [];\n const outcome = await deployProject({\n cwd: args.dir,\n roxyon: session.roxyon,\n preferredSubscription: session.preferredSubscription,\n build: args.build,\n follow: args.follow ?? true,\n timeoutMs: 5 * 60 * 1000,\n reporter: {\n step: (m) => logLines.push(`» ${m}`),\n log: (l) => logLines.push(` ${l}`),\n },\n });\n\n const tail = logLines.slice(-60).join('\\n');\n if (outcome.kind === 'static' && outcome.ok) {\n return text(`${tail}\\n\\n✓ Live: ${outcome.url} (${outcome.files} files)`, {\n ok: true,\n kind: 'static',\n url: outcome.url,\n });\n }\n if (outcome.kind === 'app' && outcome.ok) {\n return text(\n `${tail}\\n\\n✓ ${outcome.status === 'running' ? `Live: ${outcome.url ?? outcome.application}` : `Build queued (revision ${outcome.revision})`}`,\n {\n ok: true,\n kind: 'app',\n application: outcome.application,\n status: outcome.status,\n url: outcome.url,\n },\n );\n }\n return errorResult(\n `${tail}\\n\\n✗ Deploy failed: ${'error' in outcome ? outcome.error : 'unknown'}`,\n { ok: false, application: 'application' in outcome ? outcome.application : undefined },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_app_status',\n {\n title: 'Roxyon: application status',\n description:\n 'Current status, revisions and last error for an application (by id or project dir).',\n inputSchema: {\n application: z.string().optional(),\n dir: z\n .string()\n .optional()\n .describe('A project directory whose roxyon.json links an application.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const app = await session.roxyon.account.getApp(applicationId);\n if (!app) return errorResult(`Application ${applicationId} not found.`);\n const settled = app.configRevision <= app.appliedRevision;\n const body = [\n `${app.name} [${app.id}]`,\n `Status: ${app.status || '?'}${settled ? '' : ' (applying)'}`,\n `Revision: ${app.appliedRevision} / ${app.configRevision}`,\n `Runtime: ${app.runtime}`.trim(),\n app.lastError ? `\\nLast error:\\n${app.lastError}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, {\n id: app.id,\n status: app.status,\n settled,\n configRevision: app.configRevision,\n appliedRevision: app.appliedRevision,\n lastError: app.lastError || undefined,\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_logs',\n {\n title: 'Roxyon: application logs',\n description: 'Recent journal lines for an application (by id or project dir).',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n lines: z\n .number()\n .int()\n .min(1)\n .max(1000)\n .optional()\n .describe('How many lines (default 100).'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const lines = await session.roxyon.applications.logs(applicationId, args.lines ?? 100);\n return text(lines.join('\\n') || '(no log lines)', { lines });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_restart',\n {\n title: 'Roxyon: restart an application',\n description: 'Bounce the application process (no rebuild). Needs confirm:true.',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n if (!args.confirm)\n return text(`Would restart ${applicationId}. Pass confirm:true.`, { dryRun: true });\n await session.roxyon.applications.restart(applicationId);\n return text(`Restart queued for ${applicationId}.`, { ok: true });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_env_get',\n {\n title: 'Roxyon: read environment variables',\n description: \"An application's environment variables as KEY=value lines.\",\n inputSchema: { application: z.string().optional(), dir: z.string().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const env = await session.roxyon.applications.getEnv(applicationId);\n return text(formatEnv(env) || '(none set)', { env });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_env_set',\n {\n title: 'Roxyon: set environment variables',\n description:\n \"Merge variables into an application's environment and bump its revision. Run roxyon_deploy \" +\n 'afterwards to apply. Needs confirm:true. PORT and HOST are platform-managed and ignored.',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n vars: z.record(z.string()).describe('{ KEY: \"value\", ... } to set.'),\n remove: z.array(z.string()).optional().describe('Keys to delete.'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const set: Record<string, string> = {};\n for (const [k, v] of Object.entries(args.vars)) {\n if (k === 'PORT' || k === 'HOST') continue;\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) return errorResult(`Invalid env key \"${k}\".`);\n set[k] = v;\n }\n const planned = [...Object.keys(set), ...(args.remove ?? []).map((k) => `-${k}`)];\n if (!args.confirm) {\n return text(`Would update: ${planned.join(', ') || '(nothing)'}. Pass confirm:true.`, {\n dryRun: true,\n changed: planned,\n });\n }\n const r = await session.roxyon.applications.setEnv(applicationId, {\n set,\n remove: args.remove ?? [],\n });\n return text(`Updated ${r.changed.join(', ') || '(nothing)'}. Run roxyon_deploy to apply.`, {\n ok: true,\n changed: r.changed,\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_link_github',\n {\n title: 'Roxyon: connect a git remote',\n description:\n 'Connect a git repository to an application for push-to-deploy. Returns the deploy key and ' +\n 'webhook URL to add to the repo. Needs confirm:true.',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n repoUrl: z.string().describe('SSH git URL, e.g. git@github.com:you/app.git'),\n branch: z.string().optional().describe('Branch to deploy (default main).'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n if (!args.confirm) {\n return text(\n `Would connect ${args.repoUrl} (${args.branch ?? 'main'}) to ${applicationId}. Pass confirm:true.`,\n { dryRun: true },\n );\n }\n const res = await session.roxyon.applications.repoConnect(\n applicationId,\n args.repoUrl,\n args.branch ?? 'main',\n );\n const body = [\n `Connected ${args.repoUrl} (${args.branch ?? 'main'}).`,\n res.deployKey ? `\\nDeploy key (add to the repo, read-only):\\n${res.deployKey}` : '',\n res.webhookUrl ? `\\nWebhook URL: ${res.webhookUrl}` : '',\n res.secret ? `Webhook secret: ${res.secret}` : '',\n res.hint ? `\\n${res.hint}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, {\n ok: true,\n deployKey: res.deployKey,\n webhookUrl: res.webhookUrl,\n secret: res.secret,\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_add_domain',\n {\n title: 'Roxyon: add a subdomain / host',\n description:\n 'Provision a host — DNS + web server + automatic HTTPS. The host must be a subdomain ' +\n 'of a domain the account already hosts (or a *.roxyon.com subdomain). Returns while it ' +\n 'is still coming up; TLS follows a minute or two later. Needs confirm:true.',\n inputSchema: {\n host: z.string().describe('The full hostname, e.g. promo.mycompany.com'),\n subscription: z\n .string()\n .optional()\n .describe('Which subscription to attach it to (omit if the account has one).'),\n spa: z.boolean().optional().describe('Single-page app: unmatched paths serve /index.html.'),\n phpVersion: z\n .string()\n .optional()\n .describe(\n 'PHP version for the vhost, e.g. \"8.3\" (needed to run PHP apps like WordPress).',\n ),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(\n `Would provision ${args.host}${args.spa ? ' (SPA routing)' : ''}. Pass confirm:true.`,\n { dryRun: true },\n );\n }\n const res = await session.roxyon.domains.create({\n host: args.host,\n subscription: args.subscription ?? session.preferredSubscription,\n siteType: args.spa ? 'spa' : undefined,\n phpVersion: args.phpVersion,\n });\n const live = res.status === 'active';\n return text(\n [\n `${res.host} — ${res.type}, ${res.status}.`,\n live\n ? 'The host is up. HTTPS may take another minute to issue.'\n : 'DNS + web server are being set up (~1–2 min), then HTTPS. ' +\n 'Check roxyon_list_domains, or just deploy now — files are kept and served once it is live.',\n ].join('\\n'),\n { ok: true, host: res.host, type: res.type, status: res.status },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_deploy_content',\n {\n title: 'Roxyon: deploy generated files',\n description: [\n 'Publish a set of files you generated (HTML/CSS/JS/assets) to a host on the account.',\n 'The host must already exist (roxyon_add_domain, or an existing site). Overlay by',\n 'default — pass clean:true to replace the whole document root. Needs confirm:true.',\n `Limits: ${MAX_FILES} files, ${(MAX_FILE_BYTES / 1024) | 0} KB per file,`,\n `${(MAX_TOTAL_BYTES / 1024 / 1024).toFixed(1)} MB total (base64-encode binaries).`,\n ].join(' '),\n inputSchema: {\n host: z.string().describe('Target host, e.g. promo.mycompany.com'),\n folder: z.string().optional().describe('Sub-path under the host; \"\" = site root.'),\n files: z\n .array(\n z.object({\n path: z.string().describe('Relative path, e.g. index.html, about/index.html'),\n content: z.string(),\n encoding: z.enum(['utf8', 'base64']).optional(),\n }),\n )\n .min(1),\n clean: z.boolean().optional().describe('Replace the whole docroot (keeps .well-known).'),\n spa: z.boolean().optional().describe('Also flip the host to SPA routing.'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (args.files.length > MAX_FILES) {\n return errorResult(`Too many files (${args.files.length}); the limit is ${MAX_FILES}.`);\n }\n let total = 0;\n for (const f of args.files) {\n const n = Buffer.byteLength(f.content, f.encoding === 'base64' ? 'base64' : 'utf8');\n if (n > MAX_FILE_BYTES) {\n return errorResult(\n `\"${f.path}\" is ${(n / 1024) | 0} KB; the per-file limit is ${(MAX_FILE_BYTES / 1024) | 0} KB.`,\n );\n }\n total += n;\n }\n if (total > MAX_TOTAL_BYTES) {\n return errorResult(\n `Total content is ${(total / 1024 / 1024).toFixed(1)} MB; the limit is ` +\n `${(MAX_TOTAL_BYTES / 1024 / 1024).toFixed(1)} MB. Deploy in parts or use the CLI.`,\n );\n }\n\n const folder = args.folder ?? '';\n if (!args.confirm) {\n return text(\n [\n 'DRY RUN — pass confirm:true to deploy.',\n '',\n `Host: ${args.host}${folder ? `/${folder}` : ''}`,\n `Files: ${args.files.length} (${(total / 1024) | 0} KB)`,\n `Mode: ${args.clean ? 'clean (replaces the document root)' : 'overlay'}${args.spa ? ' + SPA routing' : ''}`,\n ...args.files.slice(0, 20).map((f) => ` ${f.path}`),\n args.files.length > 20 ? ` … ${args.files.length - 20} more` : '',\n ]\n .filter(Boolean)\n .join('\\n'),\n { dryRun: true },\n );\n }\n\n const { buffer, files } = await packFiles(args.files, { maxBytes: MAX_TOTAL_BYTES });\n const r = await session.roxyon.sites.deploy(args.host, folder, buffer, {\n clean: args.clean,\n spa: args.spa,\n });\n const size = r.bytes ? ` (${(r.bytes / 1024) | 0} KB)` : '';\n const spaNote = args.spa ? '\\nSPA routing enabled — deep links resolve to index.html.' : '';\n return text(\n `✓ Deployed ${files.length} file(s) to https://${args.host}${folder ? `/${folder}` : ''}${size}.${spaNote}`,\n { ok: true, host: args.host, files: files.length },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_files',\n {\n title: 'Roxyon: list a site’s files',\n description: \"The files currently deployed to a host's document root.\",\n inputSchema: {\n host: z.string(),\n folder: z.string().optional(),\n path: z.string().optional().describe('List under this sub-path only.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const files = await session.roxyon.sites.listFiles(\n args.host,\n args.folder ?? '',\n args.path ?? '',\n );\n const body = files.length\n ? files\n .map(\n (f) => `${f.type === 'dir' ? 'd' : '-'} ${String(f.size).padStart(8)} ${f.path}`,\n )\n .join('\\n')\n : '(empty)';\n return text(body, { files });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_read_file',\n {\n title: 'Roxyon: read a site file',\n description: \"Read one file from a host's document root (to review or edit it).\",\n inputSchema: {\n host: z.string(),\n folder: z.string().optional(),\n path: z.string().describe('Relative path, e.g. index.html'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const f = await session.roxyon.sites.readFile(args.host, args.folder ?? '', args.path);\n if (f.encoding === 'base64') {\n return text(\n `${f.path} — ${f.size} bytes, binary (base64):\\n\\n${f.content.slice(0, 4096)}`,\n { path: f.path, size: f.size, encoding: 'base64' },\n );\n }\n return text(f.content, { path: f.path, size: f.size, encoding: 'utf8' });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_database_create',\n {\n title: 'Roxyon: create a database',\n description:\n 'Provision a database + user on a Roxyon hosting account: engine \"mysql\" (MySQL/MariaDB, default) or \"postgres\" ' +\n '(PostgreSQL 15 inside the account, localhost:5432; the first one installs it in a few minutes). Every hosting ' +\n 'account has both: no VPS is needed for PostgreSQL. The name is prefixed with the account\\'s own username — pass ' +\n 'just the suffix, e.g. \"wordpress\". The password is shown once in the result; there is no way to retrieve it later. ' +\n 'Needs confirm:true.',\n inputSchema: {\n name: z.string().describe('DB name suffix: lowercase letters, digits, underscore.'),\n subscription: z.string().optional(),\n password: z.string().optional().describe('Omit to have Roxyon generate one.'),\n engine: z.enum(['mysql', 'postgres']).optional().describe('mysql (default) or postgres.'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(`Would create ${args.engine === 'postgres' ? 'PostgreSQL' : 'MySQL'} database \"${args.name}\". Pass confirm:true.`, {\n dryRun: true,\n });\n }\n const r = await session.roxyon.databases.create({\n name: args.name,\n subscription: args.subscription ?? session.preferredSubscription,\n password: args.password,\n ...(args.engine ? { engine: args.engine } : {}),\n });\n const pg = r.engine === 'postgres';\n const body = [\n `${r.status === 'active' ? '✓' : '»'} ${pg ? 'PostgreSQL' : 'MySQL'} database ${r.name} (user ${r.username}) — ${r.status}.`,\n r.password ? `\\nPassword (save this now — shown once):\\n${r.password}` : '',\n r.host ? `Host: ${r.host}${r.port ? `:${r.port}` : ''}` : '',\n r.note ?? '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, {\n ok: true,\n objectId: r.objectId,\n name: r.name,\n username: r.username,\n engine: r.engine ?? 'mysql',\n host: r.host,\n port: r.port,\n status: r.status,\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_databases',\n {\n title: 'Roxyon: list databases',\n description: 'Databases on the active subscription.',\n inputSchema: { subscription: z.string().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const subscription = args.subscription ?? session.preferredSubscription;\n if (!subscription) return errorResult('No subscription — pass \"subscription\".');\n const rows = await session.roxyon.databases.list(subscription);\n const body = rows.length\n ? rows\n .map((d) => `- ${d.Name} [${d.objectId}] — ${d.Engine === 'postgres' ? 'PostgreSQL' : 'MySQL'}, ${d.Status} (user ${d.Username})`)\n .join('\\n')\n : '(no databases)';\n return text(body, { databases: rows });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_database_delete',\n {\n title: 'Roxyon: delete a database',\n description:\n 'Delete a database by its objectId (from roxyon_database_create/roxyon_list_databases). Needs confirm:true.',\n inputSchema: { database: z.string(), confirm: z.boolean().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(`Would delete database ${args.database}. Pass confirm:true.`, {\n dryRun: true,\n });\n }\n const r = await session.roxyon.databases.delete(args.database);\n return text(`Database ${args.database} — ${r.status}.`, { ok: true, status: r.status });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_email_create',\n {\n title: 'Roxyon: create a mailbox',\n description:\n 'Provision a mailbox on a host already on the account. The password is shown once in the ' +\n 'result; there is no way to retrieve it later. Needs confirm:true.',\n inputSchema: {\n localPart: z.string().describe('The part before @, e.g. \"info\".'),\n domain: z.string().describe('A hostname already on the account.'),\n password: z.string().optional().describe('Omit to have Roxyon generate one.'),\n quota: z.number().int().positive().optional().describe('Quota in MB (default 1024).'),\n forwardTo: z.string().optional(),\n saveCopy: z.boolean().optional(),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const email = `${args.localPart}@${args.domain}`;\n if (!args.confirm) {\n return text(`Would create mailbox ${email}. Pass confirm:true.`, { dryRun: true });\n }\n const r = await session.roxyon.email.create({\n localPart: args.localPart,\n domain: args.domain,\n password: args.password,\n quota: args.quota,\n forwardTo: args.forwardTo,\n saveCopy: args.saveCopy,\n });\n const body = [\n `${r.status === 'active' ? '✓' : '»'} Mailbox ${r.email} — ${r.status}.`,\n r.password ? `\\nPassword (save this now — shown once):\\n${r.password}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, { ok: true, objectId: r.objectId, email: r.email, status: r.status });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_emails',\n {\n title: 'Roxyon: list mailboxes',\n description: 'Mailboxes on the active subscription.',\n inputSchema: { subscription: z.string().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const subscription = args.subscription ?? session.preferredSubscription;\n if (!subscription) return errorResult('No subscription — pass \"subscription\".');\n const rows = await session.roxyon.email.list(subscription);\n const body = rows.length\n ? rows.map((e) => `- ${e.Email} [${e.objectId}] — ${e.Status}`).join('\\n')\n : '(no mailboxes)';\n return text(body, { emails: rows });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_email_delete',\n {\n title: 'Roxyon: delete a mailbox',\n description:\n 'Delete a mailbox by its objectId (from roxyon_email_create/roxyon_list_emails). Needs confirm:true.',\n inputSchema: { email: z.string(), confirm: z.boolean().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(`Would delete mailbox ${args.email}. Pass confirm:true.`, { dryRun: true });\n }\n const r = await session.roxyon.email.delete(args.email);\n return text(`Mailbox ${args.email} — ${r.status}.`, { ok: true, status: r.status });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_ssh_reset_password',\n {\n title: 'Roxyon: reset the SSH/SFTP password',\n description:\n \"Reset a subscription's shell password — used for SSH, SFTP, and the file manager. Changing \" +\n 'it signs out anything using the old one. The password is shown once in the result; the ' +\n 'platform never stores or re-shows it. Needs confirm:true.',\n inputSchema: {\n subscription: z.string().optional(),\n password: z\n .string()\n .optional()\n .describe('Omit to have Roxyon generate one (12+ chars, mixed case, number, symbol).'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text('Would reset the SSH/SFTP password. Pass confirm:true.', { dryRun: true });\n }\n const r = await session.roxyon.ssh.resetPassword({\n subscription: args.subscription ?? session.preferredSubscription,\n password: args.password,\n });\n return text(\n `${r.status === 'active' ? '✓' : '»'} SSH/SFTP password ${r.status === 'active' ? 'changed' : 'change queued'}.\\n\\n` +\n `Password (save this now — shown once):\\n${r.password}`,\n { ok: true, subscription: r.subscription, status: r.status },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_install_wordpress',\n {\n title: 'Roxyon: install WordPress',\n description: [\n 'One-shot recipe: create a subdomain (if it does not already exist), provision a database',\n 'for it, download WordPress core, and deploy it. v1 scope — core only, no plugin/theme',\n 'selection, single site. Local-only (needs your filesystem to unpack WordPress into) — run',\n 'this from the CLI-backed MCP, not the hosted mcp.roxyon.com connector. Needs confirm:true.',\n ].join(' '),\n inputSchema: {\n host: z\n .string()\n .describe('The site host, e.g. blog.mycompany.com — created if it does not exist.'),\n folder: z\n .string()\n .optional()\n .describe('Sub-path under the host; \"\" = site root (recommended).'),\n subscription: z.string().optional(),\n dbName: z\n .string()\n .optional()\n .describe(\n 'Database name suffix (default derived from the host). See roxyon_database_create.',\n ),\n phpVersion: z.string().optional().describe('Default \"8.3\".'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteFilesystemBlock('roxyon_install_wordpress');\n if (blocked) return blocked;\n const session = await getSession();\n const folder = args.folder ?? '';\n const dbSuffix =\n (args.dbName ?? args.host.split('.')[0] ?? 'wordpress')\n .toLowerCase()\n .replace(/[^a-z0-9_]/g, '_')\n .replace(/^[^a-z]+/, '')\n .slice(0, 20) || 'wordpress';\n\n if (!args.confirm) {\n return text(\n [\n 'DRY RUN — pass confirm:true to install.',\n '',\n `Host: ${args.host}${folder ? `/${folder}` : ''} (created if missing)`,\n `Database: ${dbSuffix} (prefixed with your account username)`,\n 'Steps: add domain -> create database -> download WordPress core -> upload',\n ].join('\\n'),\n { dryRun: true },\n );\n }\n\n const subscription = args.subscription ?? session.preferredSubscription;\n\n const domain = await session.roxyon.domains.create({\n host: args.host,\n subscription,\n phpVersion: args.phpVersion ?? '8.3',\n });\n if (domain.status === 'failed') {\n return errorResult(\n `Could not provision ${args.host}: ${domain.error ?? 'unknown error'}`,\n );\n }\n\n const db = await session.roxyon.databases.create({ name: dbSuffix, subscription });\n if (db.status === 'failed' || !db.password || !db.host) {\n return errorResult(`Could not provision the database: ${db.error ?? 'unknown error'}`);\n }\n\n const scratchDir = await mkdtemp(join(tmpdir(), 'roxyon-wp-'));\n await installWordPress({\n dir: scratchDir,\n db: { name: db.name, username: db.username, password: db.password, host: db.host },\n });\n\n const pack = await packDirectory(scratchDir);\n const deployRes = await session.roxyon.sites.deploy(args.host, folder, pack.buffer);\n\n const url = `https://${deployRes.host}${deployRes.path && deployRes.path !== '/' ? deployRes.path : ''}`;\n return text(\n [\n `✓ WordPress installed at ${url} (${pack.files.length} files).`,\n 'Visit the site to finish setup (site title, admin account) — WordPress asks for these',\n 'on first load.',\n '',\n `Database: ${db.name} / ${db.username} — password shown once, save it now:`,\n db.password,\n ].join('\\n'),\n { ok: true, url, database: { name: db.name, username: db.username } },\n );\n }),\n );\n}\n\n// Re-exported for tests.\nexport { resolveApp };\nexport type { Roxyon, ToolResult };\n"],"mappings":"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","names":["Roxyon","endpointsFromEnv","z","endpointsFromEnv","Roxyon","z","z","readFile","join","join","z","z","join"]}
@@ -4,7 +4,7 @@ import {
4
4
  SERVER_VERSION,
5
5
  createServer,
6
6
  runWithContext
7
- } from "./chunk-JDSXDZB2.js";
7
+ } from "./chunk-W6X4YMV5.js";
8
8
 
9
9
  // src/http.ts
10
10
  import { requireBearerAuth } from "@modelcontextprotocol/sdk/server/auth/middleware/bearerAuth.js";
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  SERVER_VERSION,
4
4
  createServer
5
- } from "./chunk-JDSXDZB2.js";
5
+ } from "./chunk-W6X4YMV5.js";
6
6
 
7
7
  // src/index.ts
8
8
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@roxyon/mcp",
3
3
  "mcpName": "io.github.bea-technology/roxyon",
4
- "version": "0.6.0",
4
+ "version": "0.8.0",
5
5
  "description": "Model Context Protocol server for Roxyon — lets any MCP-capable AI assistant build with LumenJS, use the Roxyon BaaS, and deploy to Roxyon infrastructure.",
6
6
  "license": "MIT",
7
7
  "type": "module",
@@ -35,8 +35,8 @@
35
35
  "@modelcontextprotocol/sdk": "^1.30.0",
36
36
  "express": "^5.2.1",
37
37
  "zod": "^3.25.0",
38
- "@roxyon/deploy-core": "0.3.2",
39
- "@roxyon/api-client": "0.5.0"
38
+ "@roxyon/api-client": "0.7.0",
39
+ "@roxyon/deploy-core": "0.3.4"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/express": "^5.0.0",
@@ -62,7 +62,7 @@ project you iterate on:
62
62
 
63
63
  | Tool | Does |
64
64
  |---|---|
65
- | `roxyon_database_create` / `roxyon_list_databases` / `roxyon_database_delete` | A MySQL/MariaDB database + user on the shared Galera cluster. The name you pass is a *suffix* — the platform prefixes it with the account's own username, since the DB namespace is shared platform-wide. Returns `{username, password, host}` — the password is shown **once**, capture it immediately. |
65
+ | `roxyon_database_create` / `roxyon_list_databases` / `roxyon_database_delete` | A database + user: `engine: "mysql"` (default, MySQL/MariaDB on the shared Galera cluster) or `engine: "postgres"` (PostgreSQL 15 inside the hosting account at `localhost:5432`; the first one installs it in a few minutes; nightly dumps; deleting dumps it first). **Every hosting account has PostgreSQL: never tell a user they need a VPS for it.** Connect with `postgresql://<user>:<password>@localhost:5432/<name>`, or over SSH as the account user with `psql <name>` (no password). The name you pass is a *suffix* — the platform prefixes it with the account's own username, since the DB namespace is shared platform-wide. Returns `{username, password, host}` — the password is shown **once**, capture it immediately. |
66
66
  | `roxyon_email_create` / `roxyon_list_emails` / `roxyon_email_delete` | A mailbox on a host already on the account. Password shown once, same as databases. |
67
67
  | `roxyon_ssh_reset_password` | Resets the **one shared shell password** for a subscription's container — used for SSH, SFTP, *and* the file manager. Resetting it signs out anything using the old one. Shown once; the platform never stores or re-shows it. |
68
68
  | `roxyon_install_wordpress` | Composes the above: create/reuse a host → create a database → download WordPress core → deploy it. Local-filesystem-only (needs somewhere to unpack WordPress), same restriction as `roxyon_init`/`roxyon_deploy`. See the `roxyon://docs/recipe-wordpress` resource. |
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/server.ts","../src/baas-tools.ts","../src/context.ts","../src/session.ts","../src/result.ts","../src/commerce-tools.ts","../src/prompts.ts","../src/resources.ts","../src/tools.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { registerBaasTools } from './baas-tools.js';\nimport { registerCommerceTools } from './commerce-tools.js';\nimport { registerPrompts } from './prompts.js';\nimport { registerResources } from './resources.js';\nimport { registerTools } from './tools.js';\n\nexport const SERVER_NAME = 'roxyon';\nexport const SERVER_VERSION: string = (\n createRequire(import.meta.url)('../package.json') as { version: string }\n).version;\n\n/** Build the Roxyon MCP server with every tool, resource and prompt registered. */\nexport function createServer(): McpServer {\n const server = new McpServer(\n { name: SERVER_NAME, version: SERVER_VERSION },\n {\n instructions:\n 'Roxyon lets you build LumenJS SPAs, use the Roxyon BaaS, and deploy apps and web ' +\n 'projects to Roxyon infrastructure. Read the roxyon://docs/* resources before writing ' +\n 'LumenJS or calling the BaaS. To deploy: roxyon_init once per project, then roxyon_deploy ' +\n '(dry run, then confirm:true). Side-effecting tools require confirm:true.',\n },\n );\n\n registerResources(server);\n registerPrompts(server);\n registerTools(server);\n registerBaasTools(server);\n registerCommerceTools(server);\n return server;\n}\n","import { readFile } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { BAAS_MAX_BATCH, BAAS_MAX_PAGE, BaasDataApi, parseEnv } from '@roxyon/api-client';\nimport { z } from 'zod';\nimport { currentContext } from './context.js';\nimport { type ToolResult, errorResult, guard, text } from './result.js';\n\nconst MAX_TEXT = 40_000;\n\nconst dirArg = z\n .string()\n .optional()\n .describe('Project directory whose .env holds RX_SECRET_KEY. Defaults to cwd.');\n\n/**\n * These tools act on the user's OWN app on BaaS V2 with that app's secret key, read from the\n * project's local `.env`. The hosted server has no local files, and must not accept keys\n * through the conversation, so it refuses.\n */\nfunction remoteBlock(): ToolResult | null {\n if (!currentContext().remote) return null;\n return errorResult(\n 'The roxyon_baas_* tools read your app secret key from your local project .env, so they only ' +\n 'run in the local MCP server (`npx -y @roxyon/mcp`). Manage data in the hosted connector via ' +\n \"the console's Roxyon Base panel for now.\",\n );\n}\n\nasync function baasFor(dir: string | undefined): Promise<BaasDataApi> {\n const root = resolve(dir ?? process.cwd());\n let fileEnv: Record<string, string> = {};\n try {\n fileEnv = parseEnv(await readFile(join(root, '.env'), 'utf8'));\n } catch {\n // No .env — fall back to the process environment.\n }\n const secretKey = fileEnv.RX_SECRET_KEY || process.env.RX_SECRET_KEY || '';\n if (!secretKey) {\n throw new Error(\n `No BaaS V2 secret key found. Put RX_SECRET_KEY=rxsk_… in ${join(root, '.env')} (console.roxyon.com → Roxyon Base → your project → API keys). Keep it out of git and out of browser code.`,\n );\n }\n return new BaasDataApi({ secretKey });\n}\n\nfunction clip(s: string): string {\n return s.length > MAX_TEXT\n ? `${s.slice(0, MAX_TEXT)}\\n… (truncated — narrow with fields/where/limit)`\n : s;\n}\n\nfunction dryRun(what: string): ToolResult {\n return text(`Would ${what}. Pass confirm:true to do it.`, { dryRun: true });\n}\n\nconst SERVER_SCOPE =\n 'Runs as the app backend (server scope, which passes every class rule). Local MCP only.';\n\nexport function registerBaasTools(server: McpServer): void {\n server.registerTool(\n 'roxyon_baas_query',\n {\n title: 'Roxyon BaaS: query records',\n description: `Read records of a class in the project's own app on BaaS V2. \\`where\\` is an object like {\"Status\":\"active\",\"Age\":{\"gt\":18}}; for \\`in\\`, pass a comma-joined string. \\`fields\\` defaults to \"*\"; built-in meta columns must be named. Up to ${BAAS_MAX_PAGE} rows a page (use skip to page). ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n where: z.record(z.any()).optional(),\n fields: z.string().optional(),\n order: z.string().optional().describe('e.g. \"-createdAt\"'),\n limit: z.number().int().min(1).max(BAAS_MAX_PAGE).optional(),\n skip: z.number().int().min(0).optional(),\n count: z.boolean().optional().describe('Also return the total number of matches.'),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n const api = await baasFor(args.dir);\n const { rows, count } = await api.query(args.class, {\n where: args.where,\n fields: args.fields,\n order: args.order,\n limit: args.limit,\n skip: args.skip,\n count: args.count,\n });\n const head = `${rows.length} row(s)${count !== undefined ? ` of ${count}` : ''}`;\n return text(clip(`${head}\\n${JSON.stringify(rows, null, 2)}`), { rows, count });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_get',\n {\n title: 'Roxyon BaaS: read one record',\n description: `Read one record by objectId. ${SERVER_SCOPE}`,\n inputSchema: { dir: dirArg, class: z.string(), objectId: z.string() },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n const api = await baasFor(args.dir);\n const row = await api.get(args.class, args.objectId);\n return text(clip(JSON.stringify(row, null, 2)), { row });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_create',\n {\n title: 'Roxyon BaaS: create a record',\n description: `Insert one record into an existing class (V2 has no schema changes with a secret key: add classes and columns in the console). For relations store the other row's objectId in a string column. Needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n data: z.record(z.any()),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n if (!args.confirm) return dryRun(`insert into ${args.class}: ${JSON.stringify(args.data)}`);\n const api = await baasFor(args.dir);\n const row = await api.create(args.class, args.data);\n return text(`✓ Created ${args.class} ${String(row.objectId ?? '')}.`, { ok: true, row });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_update',\n {\n title: 'Roxyon BaaS: update a record',\n description: `Set fields on one record by objectId. Needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n objectId: z.string(),\n data: z.record(z.any()),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n if (!args.confirm) {\n return dryRun(`update ${args.class} ${args.objectId}: ${JSON.stringify(args.data)}`);\n }\n const api = await baasFor(args.dir);\n const row = await api.update(args.class, args.objectId, args.data);\n return text(`✓ Updated ${args.class} ${args.objectId}.`, { ok: true, row });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_delete',\n {\n title: 'Roxyon BaaS: delete a record',\n description: `Delete one record by objectId. Needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n class: z.string(),\n objectId: z.string(),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n if (!args.confirm) return dryRun(`delete ${args.class} ${args.objectId}`);\n const api = await baasFor(args.dir);\n await api.delete(args.class, args.objectId);\n return text(`✓ Deleted ${args.class} ${args.objectId}.`, { ok: true });\n }),\n );\n\n server.registerTool(\n 'roxyon_baas_batch',\n {\n title: 'Roxyon BaaS: batch of record requests',\n description: `1 to ${BAAS_MAX_BATCH} record requests in one call, each answered on its own (one failing doesn't stop the others). path is /Class or /Class/<objectId>; for POST/PUT the body is {\"data\":{...}}; for GET the body holds query options (where, fields, limit…). A batch with any write needs confirm:true. ${SERVER_SCOPE}`,\n inputSchema: {\n dir: dirArg,\n requests: z\n .array(\n z.object({\n method: z.enum(['GET', 'POST', 'PUT', 'DELETE']),\n path: z.string(),\n body: z.record(z.any()).optional(),\n }),\n )\n .min(1)\n .max(BAAS_MAX_BATCH),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteBlock();\n if (blocked) return blocked;\n const writes = args.requests.filter((r) => r.method !== 'GET');\n if (writes.length && !args.confirm) {\n return dryRun(\n `run ${args.requests.length} request(s), ${writes.length} of them writes: ${writes.map((r) => `${r.method} ${r.path}`).join(', ')}`,\n );\n }\n const api = await baasFor(args.dir);\n const results = await api.batch(args.requests);\n const failed = results.filter((r) => r.ok === false).length;\n return text(\n clip(\n `${results.length} answer(s), ${failed} failed\\n${JSON.stringify(results, null, 2)}`,\n ),\n { results },\n );\n }),\n );\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\n/**\n * Per-request state for the HTTP transport. The stdio entry never opens a\n * context, so {@link currentContext} returns `{}` there and everything falls\n * back to the env / stored-login behaviour.\n */\nexport interface RequestContext {\n /** Bearer token presented on this HTTP request (from the OAuth layer). */\n token?: string;\n /**\n * True when serving the remote HTTP server. Tools that need the caller's\n * local filesystem (`roxyon_init`, `roxyon_deploy`) refuse in this mode.\n */\n remote?: boolean;\n}\n\nconst storage = new AsyncLocalStorage<RequestContext>();\n\n/** Run `fn` with `ctx` visible to {@link currentContext} for its whole async tree. */\nexport function runWithContext<T>(ctx: RequestContext, fn: () => T): T {\n return storage.run(ctx, fn);\n}\n\n/** The context for the in-flight request, or `{}` on the stdio transport. */\nexport function currentContext(): RequestContext {\n return storage.getStore() ?? {};\n}\n","import { Roxyon, isAuthError } from '@roxyon/api-client';\nimport { endpointsFromEnv, loadCredentials, tokenFromEnv } from '@roxyon/deploy-core';\nimport { currentContext } from './context.js';\n\nexport interface RoxyonSession {\n roxyon: Roxyon;\n preferredSubscription?: string;\n /** how the session was authenticated, for diagnostics */\n source: 'env-token' | 'stored-login' | 'oauth';\n}\n\nexport class NotAuthenticatedError extends Error {\n constructor() {\n super(\n 'Not signed in to Roxyon. Run `roxyon login` in a terminal, or set ROXYON_TOKEN ' +\n \"in this MCP server's environment.\",\n );\n this.name = 'NotAuthenticatedError';\n }\n}\n\n/**\n * Resolve a Roxyon client for a tool call. Order: `ROXYON_TOKEN` env var, then\n * the login stored by the CLI at `~/.roxyon/config.json`.\n */\nexport async function getSession(): Promise<RoxyonSession> {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n\n // HTTP transport: the bearer token from this request wins over any ambient\n // env/stored credentials, and each request gets its own client.\n const requestToken = currentContext().token;\n if (requestToken) {\n return {\n roxyon: new Roxyon({ sessionToken: requestToken, baseUrl: apiUrl, consoleUrl }),\n source: 'oauth',\n };\n }\n\n const envToken = tokenFromEnv();\n if (envToken) {\n return {\n roxyon: new Roxyon({ sessionToken: envToken, baseUrl: apiUrl, consoleUrl }),\n source: 'env-token',\n };\n }\n const creds = await loadCredentials();\n if (!creds?.sessionToken) throw new NotAuthenticatedError();\n return {\n roxyon: new Roxyon({ sessionToken: creds.sessionToken, baseUrl: apiUrl, consoleUrl }),\n preferredSubscription: creds.subscription,\n source: 'stored-login',\n };\n}\n\nexport function isSessionGone(err: unknown): boolean {\n return err instanceof NotAuthenticatedError || isAuthError(err);\n}\n","import { isSessionGone } from './session.js';\n\nexport interface ToolResult {\n content: Array<{ type: 'text'; text: string }>;\n structuredContent?: Record<string, unknown>;\n isError?: boolean;\n /** SDK's CallToolResult carries an open index signature. */\n [k: string]: unknown;\n}\n\nexport function text(body: string, structured?: Record<string, unknown>): ToolResult {\n return {\n content: [{ type: 'text', text: body }],\n ...(structured ? { structuredContent: structured } : {}),\n };\n}\n\nexport function errorResult(message: string, structured?: Record<string, unknown>): ToolResult {\n return {\n content: [{ type: 'text', text: message }],\n ...(structured ? { structuredContent: structured } : {}),\n isError: true,\n };\n}\n\n/** Wrap a tool body so thrown errors become clean `isError` results. */\nexport async function guard(fn: () => Promise<ToolResult>): Promise<ToolResult> {\n try {\n return await fn();\n } catch (err) {\n if (isSessionGone(err)) {\n return errorResult(\n (err as Error).message ||\n 'Roxyon session expired — run `roxyon login` again, or refresh ROXYON_TOKEN.',\n );\n }\n return errorResult(err instanceof Error ? err.message : String(err));\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { BILLING_CYCLES, type CatalogProduct, Roxyon } from '@roxyon/api-client';\nimport { endpointsFromEnv } from '@roxyon/deploy-core';\nimport { z } from 'zod';\nimport { guard, text } from './result.js';\nimport { getSession } from './session.js';\n\n/** Catalog and quotes are public: no sign-in, so an agent can price before the user has an account. */\nfunction publicRoxyon(): Roxyon {\n const { apiUrl, consoleUrl } = endpointsFromEnv();\n return new Roxyon({ baseUrl: apiUrl, consoleUrl });\n}\n\nfunction money(n: number | undefined): string {\n return n === undefined ? '—' : `$${n.toFixed(2)}`;\n}\n\nfunction productLine(p: CatalogProduct): string {\n const spec =\n p.vcpu !== undefined\n ? ` — ${p.vcpu} vCPU (${p.cpuType}), ${p.ramGb} GB RAM, ${p.diskGb} GB disk${p.ipv4Included ? `, ${p.ipv4Included} IPv4` : ''}`\n : '';\n const prices = BILLING_CYCLES.filter((c) => p.pricesUSD[c] !== undefined)\n .map((c) => `${c} ${money(p.pricesUSD[c])}`)\n .join(', ');\n return `- ${p.sku || p.planId} \"${p.name}\" [${p.category}]${spec} | USD ${prices}${p.stock === 'out' ? ' | OUT OF STOCK' : ''} (planId ${p.planId})`;\n}\n\nexport function registerCommerceTools(server: McpServer): void {\n server.registerTool(\n 'roxyon_catalog',\n {\n title: 'Roxyon: product catalog',\n description:\n 'List what Roxyon sells: cloud servers (cloud.vps.launch / scale / power) and web hosting ' +\n '(cloud.hosting.solo / multiple / isolated). Each product has its planId (what roxyon_quote ' +\n 'takes), SKU, specs (vCPU, RAM GB, disk GB, IPv4 included) for servers, list prices in USD ' +\n 'per billing cycle BEFORE tax and currency conversion, and stock (\"out\" = cannot be ordered ' +\n 'now). No sign-in needed. Use roxyon_quote for the exact amount a buyer would pay. Read-only.',\n inputSchema: {\n category: z\n .string()\n .optional()\n .describe('Filter by category prefix, e.g. \"cloud.vps\" or \"cloud.hosting\".'),\n in_stock_only: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n let products = await publicRoxyon().billing.catalog();\n if (args.category) products = products.filter((p) => p.category.startsWith(args.category!));\n if (args.in_stock_only) products = products.filter((p) => p.stock === 'in');\n return text(\n products.length ? products.map(productLine).join('\\n') : '(no products match)',\n { products },\n );\n }),\n );\n\n server.registerTool(\n 'roxyon_quote',\n {\n title: 'Roxyon: price a new subscription',\n description:\n \"The exact amount Roxyon's checkout would charge for a NEW subscription to one plan, \" +\n 'computed by the platform itself (same server pricing the console checkout uses, setup fee ' +\n 'included): line items, subtotal, tax, total, in the requested currency. Pass the buyer ' +\n 'currency and country: without them the quote is in USD with no tax, while checkout uses the ' +\n \"account's own currency/country. No sign-in needed. Read-only: creates no order. Domains \" +\n 'are not priced by this tool yet.',\n inputSchema: {\n plan: z.string().describe('planId (or SKU, e.g. \"SCALE-S\") from roxyon_catalog.'),\n cycle: z.enum(BILLING_CYCLES),\n currency: z.string().length(3).optional().describe('ISO 4217, e.g. \"USD\", \"SAR\".'),\n country: z\n .string()\n .length(2)\n .optional()\n .describe('ISO 3166 alpha-2, decides tax, e.g. \"SA\".'),\n },\n },\n (args) =>\n guard(async () => {\n const roxyon = publicRoxyon();\n const want = args.plan.toLowerCase();\n const product = (await roxyon.billing.catalog()).find(\n (p) => p.planId === args.plan || p.sku.toLowerCase() === want,\n );\n if (!product)\n throw new Error(`No product \"${args.plan}\" in the catalog. See roxyon_catalog.`);\n const q = await roxyon.billing.quote({\n planId: product.planId,\n cycle: args.cycle,\n currency: args.currency,\n country: args.country,\n });\n const lines = [\n ...q.lineItems.map((l) => `${l.label}: ${l.amount} ${q.currency}`),\n `Subtotal: ${q.subtotal} ${q.currency}`,\n `${q.taxLabel || 'Tax'} (${q.taxRate}%): ${q.taxAmount} ${q.currency}`,\n `Total: ${q.total} ${q.currency}`,\n ];\n if (product?.stock === 'out') lines.push('Note: this plan is out of stock right now.');\n return text(lines.join('\\n'), { quote: q });\n }),\n );\n\n server.registerTool(\n 'roxyon_list_subscriptions',\n {\n title: 'Roxyon: my subscriptions (billing)',\n description:\n \"The signed-in user's own subscriptions with billing details: plan + SKU, status, billing \" +\n 'cycle, recurring price and currency, next billing date, auto-renew, and for servers the ' +\n 'state (building / running / stopped…) and public IP. Only subscriptions the user owns. ' +\n 'Read-only.',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const subs = await session.roxyon.billing.subscriptions();\n const body = subs.length\n ? subs\n .map(\n (s) =>\n `- ${s.name || s.id} [${s.status}] ${s.plan}${s.sku ? ` (${s.sku})` : ''} — ` +\n `${s.price} ${s.currency}/${s.cycle || '?'}, next billing ${s.nextBillingDate ?? '—'}` +\n `${s.autoRenew ? ', auto-renew' : ''}` +\n `${s.serverState ? `, server ${s.serverState}` : ''}${s.publicIp ? ` ${s.publicIp}` : ''}`,\n )\n .join('\\n')\n : '(no subscriptions on this account)';\n return text(body, { subscriptions: subs });\n }),\n );\n\n server.registerTool(\n 'roxyon_list_invoices',\n {\n title: 'Roxyon: my invoices',\n description:\n \"The signed-in user's own invoices, newest first: number, type, status (pending = unpaid, \" +\n 'paid, overdue, void, failed, cancelled), total and currency, due date, and payUrl (the ' +\n 'console page where the user pays; null when paid). Read-only: this never pays anything.',\n inputSchema: {\n status: z.enum(['pending', 'paid', 'overdue', 'void', 'failed', 'cancelled']).optional(),\n limit: z.number().int().min(1).max(100).optional().describe('Default 25.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const invoices = await session.roxyon.billing.invoices({\n status: args.status,\n limit: args.limit,\n });\n const body = invoices.length\n ? invoices\n .map(\n (i) =>\n `- #${i.number || i.id} ${i.type} [${i.status}] ${i.total} ${i.currency}, due ${i.dueDate ?? '—'}` +\n `${i.payUrl ? ` — pay at ${i.payUrl}` : ''}`,\n )\n .join('\\n')\n : '(no invoices)';\n return text(body, { invoices });\n }),\n );\n\n server.registerTool(\n 'roxyon_pay_link',\n {\n title: 'Roxyon: where to pay an invoice',\n description:\n 'The URL where the signed-in user pays one of their own open invoices (status pending, ' +\n 'overdue or failed), plus its amount and due date. Give the invoice number (e.g. ' +\n '\"INV2610055\") or id from roxyon_list_invoices. A human opens the link and pays in the ' +\n 'console; this tool never charges anything. Paid or void invoices have no link.',\n inputSchema: {\n invoice: z.string().min(1).max(40).describe('Invoice number or id.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const want = args.invoice.replace(/^#/, '').toLowerCase();\n const inv = (await session.roxyon.billing.invoices({ limit: 100 })).find(\n (i) => i.id.toLowerCase() === want || i.number.toLowerCase() === want,\n );\n if (!inv) {\n throw new Error(\n `No invoice \"${args.invoice}\" among your latest 100. See roxyon_list_invoices.`,\n );\n }\n if (!inv.payUrl) {\n return text(`Invoice #${inv.number || inv.id} is ${inv.status}: nothing to pay.`, {\n invoice: inv,\n });\n }\n return text(\n `Invoice #${inv.number || inv.id}: ${inv.total} ${inv.currency}, due ${inv.dueDate ?? '—'}.\\n` +\n `Pay at ${inv.payUrl} (sign in, open Invoices, choose this invoice).`,\n { invoice: inv, payUrl: inv.payUrl },\n );\n }),\n );\n\n const order = server.registerTool(\n 'roxyon_order',\n {\n title: 'Roxyon: place an order (a person pays)',\n description:\n 'Order a new web-hosting plan or cloud server for the signed-in user. The platform prices it ' +\n 'and creates the subscription and a pending invoice; a PERSON then pays at the returned payUrl ' +\n '(nothing is charged by this tool, and the service is set up only after payment). ' +\n 'Always call it first WITHOUT confirm: that dry run returns the exact quote and the token budget ' +\n 'and writes nothing. Show it to the user, then call again with confirm:true. ' +\n 'Rules: `sku` from roxyon_catalog (out-of-stock plans are refused); servers need `image` ' +\n '(e.g. \"ubuntu-24.04\"); `username` must be free. Needs a sign-in, or a token created with the ' +\n '\"billing:order\" scope (`roxyon token create <name> --scopes billing:order --budget <USD> ' +\n '[--skus SCALE-S,…]`): it is refused past that monthly budget (USD, before tax) or outside its SKUs.',\n inputSchema: {\n sku: z.string().describe('Plan code from roxyon_catalog, e.g. \"SCALE-S\".'),\n cycle: z.enum(BILLING_CYCLES),\n name: z.string().min(1).max(100).describe('A name for the service.'),\n username: z\n .string()\n .regex(/^[a-z0-9][a-z0-9.-]{1,62}$/)\n .describe('Account/server name: lowercase letters, digits, dots, dashes; must be free.'),\n image: z.string().optional().describe('Servers only: OS image, e.g. \"ubuntu-24.04\".'),\n ssh_key: z.string().optional().describe('Servers only: an SSH public key for root.'),\n php_version: z.string().optional().describe('Hosting only, e.g. \"8.3\".'),\n currency: z.string().length(3).optional(),\n country: z.string().length(2).optional().describe('Decides tax, e.g. \"SA\".'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const r = await session.roxyon.billing.order({\n sku: args.sku,\n cycle: args.cycle,\n name: args.name,\n username: args.username,\n image: args.image,\n sshKey: args.ssh_key,\n phpVersion: args.php_version,\n currency: args.currency,\n country: args.country,\n confirm: args.confirm === true,\n });\n const budget = r.budget\n ? `Token budget: ${r.budget.spentUSD.toFixed(2)} of ${r.budget.monthlyUSD.toFixed(2)} USD used this month, ${r.budget.remainingUSD.toFixed(2)} left.`\n : '';\n if (r.dryRun) {\n const q = (r.quote ?? {}) as {\n total?: string;\n currency?: string;\n taxAmount?: string;\n taxLabel?: string;\n };\n return text(\n [\n `Dry run, nothing ordered: ${r.plan.sku} \"${r.plan.name}\" (${r.plan.kind}), ${r.plan.cycle}.`,\n `Total ${q.total} ${q.currency} (incl. ${q.taxLabel || 'tax'} ${q.taxAmount}).`,\n budget,\n 'Call again with confirm:true to place it; a person then pays the invoice.',\n ]\n .filter(Boolean)\n .join('\\n'),\n { ...r },\n );\n }\n return text(\n [\n `Ordered ${r.plan.sku} \"${r.plan.name}\" (${r.plan.cycle}): invoice ${r.invoiceId}, ${r.total} ${r.currency}.`,\n `Not active until paid. The user pays at ${r.payUrl}.`,\n budget,\n ]\n .filter(Boolean)\n .join('\\n'),\n { ...r },\n );\n }),\n );\n // Hidden until the console's POST /account/order and the V2 user-session mint are live.\n if (process.env.ROXYON_MCP_ORDERING !== '1') order.disable();\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { z } from 'zod';\n\nexport function registerPrompts(server: McpServer): void {\n server.registerPrompt(\n 'scaffold-lumen-app',\n {\n title: 'Scaffold a LumenJS + Roxyon app',\n description:\n 'Guidance for creating a new LumenJS SPA wired to the Roxyon BaaS and ready to deploy.',\n argsSchema: {\n idea: z.string().describe('What the app should do.'),\n dir: z.string().optional().describe('Where to create it.'),\n },\n },\n ({ idea, dir }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Build a LumenJS single-page app: ${idea}\\n\\nSteps:\\n1. Read the \"roxyon://docs/lumenjs\" resource — follow V1 rules exactly (one bind per region, no nested bind, build option lists in JS not :for, check every BaaS write for an error field).\\n2. Read \"roxyon://docs/baas\" for the data/auth API.\\n3. Scaffold with the LumenJS CLI 2.5.7: \\`npx -y -p @lmjs/cli@2.5.7 lm create <name>\\`${dir ? ` in ${dir}` : ''}. Put views under src/views/, wire the BaaS in src/index.js via config.json.\\n4. When it runs locally (\\`lm serve\\`), call roxyon_init then roxyon_deploy (dry run first, then confirm:true).`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n 'build-and-ship-site',\n {\n title: 'Build a site and host it on Roxyon',\n description:\n 'Generate a static site (or no-build LumenJS SPA) in the conversation and publish it to ' +\n 'a Roxyon host — for the hosted connector, no local files.',\n argsSchema: {\n brief: z.string().describe('What the site should be.'),\n host: z.string().describe('Where to host it, e.g. promo.mycompany.com'),\n },\n },\n ({ brief, host }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Build and publish a website to ${host}.\\n\\nBrief: ${brief}\\n\\n1. Read \"roxyon://docs/recipe\" and follow it. (Read \"roxyon://docs/lumenjs\" too only if the site needs reactivity.)\\n2. If ${host} is not already on the account, roxyon_add_domain { host: \"${host}\", confirm: true } (add spa:true only for a real single-page app).\\n3. Generate the site — self-contained static files, relative paths, real .html per page or <page>/index.html, ≤60 files / 2 MB.\\n4. roxyon_deploy_content { host: \"${host}\", files: [...], clean: true, confirm: true } (dry-run first).\\n5. roxyon_list_files { host: \"${host}\" } to verify, then give me the URL. Note that HTTPS may take a couple of minutes on a brand-new host.`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n 'install-wordpress',\n {\n title: 'Install WordPress on Roxyon',\n description: 'Provision a host + database and install WordPress core — local/CLI MCP only.',\n argsSchema: {\n host: z.string().describe('Where to install it, e.g. blog.mycompany.com'),\n },\n },\n ({ host }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Install WordPress on ${host}.\\n\\n1. Read \"roxyon://docs/recipe-wordpress\" and follow it.\\n2. Call roxyon_install_wordpress { host: \"${host}\" } first without confirm to see the plan.\\n3. If it looks right, call it again with confirm:true.\\n4. Report the site URL and the database credentials (shown once — pass them on to me now), and tell me to visit the URL to finish WordPress's own setup wizard (site title, admin account).`,\n },\n },\n ],\n }),\n );\n\n server.registerPrompt(\n 'deploy-to-roxyon',\n {\n title: 'Deploy this project to Roxyon',\n description: 'Walk through deploying the current project to Roxyon infrastructure.',\n argsSchema: { dir: z.string().describe('Absolute path to the project.') },\n },\n ({ dir }) => ({\n messages: [\n {\n role: 'user',\n content: {\n type: 'text',\n text: `Deploy the project at ${dir} to Roxyon.\\n\\n1. If there is no roxyon.json, call roxyon_init (it detects the runtime; ask me which host if there are several).\\n2. Call roxyon_deploy with just the dir first to see the plan.\\n3. If the plan looks right, call roxyon_deploy again with confirm:true.\\n4. For an app runtime, report the final status and, if it failed, the last error from roxyon_app_status.`,\n },\n },\n ],\n }),\n );\n}\n","import { readFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\n\nconst RESOURCE_DIR = join(dirname(fileURLToPath(import.meta.url)), '..', 'resources');\n\ninterface Doc {\n uri: string;\n name: string;\n file: string;\n title: string;\n description: string;\n}\n\nconst DOCS: Doc[] = [\n {\n uri: 'roxyon://docs/lumenjs',\n name: 'lumenjs-reference',\n file: 'lumenjs.md',\n title: 'LumenJS — complete reference',\n description:\n 'Full LumenJS V1 reference for building SPAs with vanilla JS/HTML/CSS (no build step), ' +\n 'contrasted with Vue/React. Read before writing .view files.',\n },\n {\n uri: 'roxyon://docs/baas',\n name: 'baas-reference',\n file: 'baas.md',\n title: 'Roxyon BaaS reference',\n description:\n 'The Roxyon Backend-as-a-Service REST API: endpoints, auth flow, query rules, and the ' +\n 'resolve-on-failure write behaviour.',\n },\n {\n uri: 'roxyon://docs/deploy',\n name: 'deploy-reference',\n file: 'deploy.md',\n title: 'Deploying to Roxyon',\n description:\n 'How roxyon_init / roxyon_deploy work, the roxyon.json schema, static vs app deploys, env ' +\n 'vars, and git push-to-deploy.',\n },\n {\n uri: 'roxyon://docs/recipe',\n name: 'web-deploy-recipe',\n file: 'recipe-web-deploy.md',\n title: 'Recipe — build a site and host it',\n description:\n 'The end-to-end flow for \"build a landing page and put it on sub.mydomain.com\" over the ' +\n 'hosted connector: roxyon_add_domain → roxyon_deploy_content → roxyon_list_files.',\n },\n {\n uri: 'roxyon://docs/recipe-wordpress',\n name: 'wordpress-recipe',\n file: 'recipe-wordpress.md',\n title: 'Recipe — install WordPress',\n description:\n 'The end-to-end flow for \"put WordPress on sub.mydomain.com\": roxyon_install_wordpress ' +\n '(host + database + WordPress core, one call). Local/CLI-backed MCP only.',\n },\n];\n\nexport function registerResources(server: McpServer): void {\n for (const doc of DOCS) {\n server.registerResource(\n doc.name,\n doc.uri,\n { title: doc.title, description: doc.description, mimeType: 'text/markdown' },\n async () => {\n const body = await readFile(join(RESOURCE_DIR, doc.file), 'utf8');\n return { contents: [{ uri: doc.uri, mimeType: 'text/markdown', text: body }] };\n },\n );\n }\n}\n","import { mkdtemp } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { type Roxyon, envFromStored, formatEnv } from '@roxyon/api-client';\nimport {\n buildIgnore,\n buildProjectConfig,\n deployProject,\n detectRuntime,\n installWordPress,\n listFiles,\n loadProjectConfig,\n packDirectory,\n packFiles,\n saveProjectConfig,\n} from '@roxyon/deploy-core';\nimport { z } from 'zod';\nimport { currentContext } from './context.js';\nimport { type ToolResult, errorResult, guard, text } from './result.js';\nimport { type RoxyonSession, getSession } from './session.js';\n\n/** `roxyon_deploy_content` budget — keeps the whole JSON-RPC body under the 4 MB cap. */\nconst MAX_FILES = 60;\nconst MAX_FILE_BYTES = 1024 * 1024;\nconst MAX_TOTAL_BYTES = 2 * 1024 * 1024;\n\n/**\n * `roxyon_init` / `roxyon_deploy` read and write the caller's local project\n * directory — impossible over the remote HTTP server. Returns an explanatory\n * result when running in that mode, `null` otherwise (proceed).\n */\nfunction remoteFilesystemBlock(\n tool: 'roxyon_init' | 'roxyon_deploy' | 'roxyon_install_wordpress',\n): ToolResult | null {\n if (!currentContext().remote) return null;\n return errorResult(\n [\n `${tool} needs access to your local project files, which the hosted Roxyon MCP`,\n 'server does not have. Either:',\n ' • run the `roxyon` CLI locally (`npm i -g @roxyon/cli`, then `roxyon deploy`), or',\n ' • use `roxyon_link_github` to connect a git repo for push-to-deploy, then',\n ' `roxyon_app_status` / `roxyon_logs` to watch it here.',\n ].join('\\n'),\n );\n}\n\n/** Resolve an application id from an explicit id or a project directory. */\nasync function resolveApp(args: { application?: string; dir?: string }): Promise<{\n applicationId: string;\n host?: string;\n}> {\n if (args.application) return { applicationId: args.application };\n if (args.dir) {\n const cfg = await loadProjectConfig(args.dir);\n if (cfg?.application) return { applicationId: cfg.application, host: cfg.host };\n throw new Error(\n `No application linked in ${args.dir}/roxyon.json. Deploy it once (roxyon_deploy) or pass \"application\".`,\n );\n }\n throw new Error('Pass either \"application\" (an id) or \"dir\" (a project directory).');\n}\n\n/** The account context (user + subscriptions + domains) — one call, PAT-safe. */\nfunction accountContext(session: RoxyonSession) {\n return session.roxyon.account.context();\n}\n\n/**\n * Tools whose console routes (/databases/*, /emails/*, /ssh/password) are not live yet, plus the two lists that\n * read the BaaS directly and so fail for PAT/OAuth callers. Hidden unless ROXYON_MCP_PROVISIONING=1, so agents are\n * never offered a tool whose backend doesn't answer. Remove the gate once those routes ship.\n */\nfunction hideUntilLive(tool: RegisteredTool): void {\n if (process.env.ROXYON_MCP_PROVISIONING !== '1') tool.disable();\n}\n\nexport function registerTools(server: McpServer): void {\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_whoami',\n {\n title: 'Roxyon: who am I',\n description: 'Show the signed-in Roxyon user and their subscriptions (which one is active).',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const ctx = await accountContext(session);\n const lines = [\n `User: ${ctx.user.email || ctx.user.id} (${ctx.user.id})`,\n `Auth: ${session.source}${ctx.scopes.length ? ` (scopes: ${ctx.scopes.join(', ')})` : ''}`,\n '',\n 'Subscriptions:',\n ...ctx.subscriptions.map((s) => ` ${s.name || s.id} — ${s.status || '?'}`),\n '',\n `Hosts: ${ctx.domains.map((d) => d.name).join(', ') || '(none)'}`,\n ];\n return text(lines.join('\\n'), {\n user: ctx.user,\n scopes: ctx.scopes,\n subscriptions: ctx.subscriptions,\n hosts: ctx.domains.map((d) => d.name),\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_domains',\n {\n title: 'Roxyon: list hosts',\n description:\n 'List the domains (hosts) on the active subscription — the possible deploy targets.',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const { domains } = await accountContext(session);\n return text(\n domains.length\n ? domains\n .map(\n (d) => `- ${d.name}${d.status && d.status !== 'active' ? ` (${d.status})` : ''}`,\n )\n .join('\\n')\n : '(no hosts on this account)',\n { hosts: domains },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_apps',\n {\n title: 'Roxyon: list applications',\n description:\n 'List the applications on the active subscription with their status and revision.',\n inputSchema: {},\n },\n () =>\n guard(async () => {\n const session = await getSession();\n const apps = await session.roxyon.account.apps();\n const body = apps.length\n ? apps\n .map(\n (a) =>\n `- ${a.name} [${a.id}] — ${a.status || '?'} ` +\n `(rev ${a.appliedRevision}/${a.configRevision})` +\n `${a.repo ? ` · git:${a.repo.branch}` : ''}`,\n )\n .join('\\n')\n : '(no applications)';\n return text(body, { applications: apps });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_init',\n {\n title: 'Roxyon: initialise a project',\n description:\n \"Detect a project's type and write roxyon.json. Run this once per project before roxyon_deploy. \" +\n 'Does not create anything on the platform.',\n inputSchema: {\n dir: z.string().describe('Absolute path to the project directory.'),\n runtime: z.enum(['lumen', 'node', 'python', 'php']).optional(),\n host: z.string().optional().describe('Deploy host (a domain on the subscription).'),\n folder: z.string().optional().describe('Sub-path under the host; \"\" = site root.'),\n overwrite: z.boolean().optional().describe('Replace an existing roxyon.json.'),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteFilesystemBlock('roxyon_init');\n if (blocked) return blocked;\n const session = await getSession();\n const existing = await loadProjectConfig(args.dir);\n if (existing && !args.overwrite) {\n return errorResult(\n `roxyon.json already exists in ${args.dir}. Pass overwrite:true to replace it.`,\n { config: existing },\n );\n }\n const { domains } = await accountContext(session);\n if (domains.length === 0) {\n return errorResult(\n 'This account has no hosts. Add a domain in the Roxyon console first.',\n );\n }\n const detected = await detectRuntime(args.dir);\n const runtime = args.runtime ?? detected.runtime;\n const host = args.host ?? domains[0]!.name;\n if (!domains.some((d) => d.name === host)) {\n return errorResult(\n `Host \"${host}\" is not on this account (have: ${domains.map((d) => d.name).join(', ')}).`,\n );\n }\n const config = buildProjectConfig({\n cwd: args.dir,\n runtime,\n host,\n folder: args.folder,\n start: detected.start,\n });\n const path = await saveProjectConfig(config, args.dir);\n return text(\n `Wrote ${path}\\nDetected: ${detected.runtime} (${detected.reason})\\n\\n${JSON.stringify(config, null, 2)}`,\n { path, detected: detected.runtime, config },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_deploy',\n {\n title: 'Roxyon: deploy a project',\n description:\n 'Build (if configured) and deploy the project in \"dir\" to Roxyon. Without confirm:true this ' +\n 'returns a dry-run plan (what would build, where it would go, how many files). With confirm:true ' +\n 'it runs the build, uploads, and — for app runtimes — waits for it to go live. Requires roxyon.json ' +\n '(run roxyon_init first).',\n inputSchema: {\n dir: z\n .string()\n .describe('Absolute path to the project directory (must contain roxyon.json).'),\n confirm: z.boolean().optional().describe('Actually deploy. Omit for a dry-run plan.'),\n build: z.boolean().optional().describe('Run the configured build command (default true).'),\n follow: z\n .boolean()\n .optional()\n .describe('For app runtimes, wait until running/failed (default true).'),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteFilesystemBlock('roxyon_deploy');\n if (blocked) return blocked;\n const session = await getSession();\n const config = await loadProjectConfig(args.dir);\n if (!config) {\n return errorResult(`No roxyon.json in ${args.dir}. Run roxyon_init first.`);\n }\n\n if (!args.confirm) {\n const ig = await buildIgnore(args.dir);\n const packRoot =\n config.kind === 'static' && config.outDir ? `${args.dir}/${config.outDir}` : args.dir;\n let files: string[] = [];\n try {\n files = await listFiles(packRoot, ig);\n } catch {\n /* outDir may not exist until the build runs */\n }\n const plan = [\n 'DRY RUN — pass confirm:true to deploy.',\n '',\n `Project: ${config.name} (${config.runtime}, ${config.kind})`,\n `Target: ${config.host}${config.folder ? `/${config.folder}` : ''}`,\n config.build ? `Build: ${config.build}` : 'Build: (none)',\n config.kind === 'app'\n ? `App: ${config.application ?? '(created on first deploy)'}`\n : 'Serve: static files from the host document root',\n files.length\n ? `Would pack ${files.length} file(s) from ${config.kind === 'static' && config.outDir ? config.outDir : '.'}`\n : `Would pack the build output (${config.outDir ?? 'dist'}) after building`,\n ].join('\\n');\n return text(plan, { dryRun: true, config });\n }\n\n const logLines: string[] = [];\n const outcome = await deployProject({\n cwd: args.dir,\n roxyon: session.roxyon,\n preferredSubscription: session.preferredSubscription,\n build: args.build,\n follow: args.follow ?? true,\n timeoutMs: 5 * 60 * 1000,\n reporter: {\n step: (m) => logLines.push(`» ${m}`),\n log: (l) => logLines.push(` ${l}`),\n },\n });\n\n const tail = logLines.slice(-60).join('\\n');\n if (outcome.kind === 'static' && outcome.ok) {\n return text(`${tail}\\n\\n✓ Live: ${outcome.url} (${outcome.files} files)`, {\n ok: true,\n kind: 'static',\n url: outcome.url,\n });\n }\n if (outcome.kind === 'app' && outcome.ok) {\n return text(\n `${tail}\\n\\n✓ ${outcome.status === 'running' ? `Live: ${outcome.url ?? outcome.application}` : `Build queued (revision ${outcome.revision})`}`,\n {\n ok: true,\n kind: 'app',\n application: outcome.application,\n status: outcome.status,\n url: outcome.url,\n },\n );\n }\n return errorResult(\n `${tail}\\n\\n✗ Deploy failed: ${'error' in outcome ? outcome.error : 'unknown'}`,\n { ok: false, application: 'application' in outcome ? outcome.application : undefined },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_app_status',\n {\n title: 'Roxyon: application status',\n description:\n 'Current status, revisions and last error for an application (by id or project dir).',\n inputSchema: {\n application: z.string().optional(),\n dir: z\n .string()\n .optional()\n .describe('A project directory whose roxyon.json links an application.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const app = await session.roxyon.account.getApp(applicationId);\n if (!app) return errorResult(`Application ${applicationId} not found.`);\n const settled = app.configRevision <= app.appliedRevision;\n const body = [\n `${app.name} [${app.id}]`,\n `Status: ${app.status || '?'}${settled ? '' : ' (applying)'}`,\n `Revision: ${app.appliedRevision} / ${app.configRevision}`,\n `Runtime: ${app.runtime}`.trim(),\n app.lastError ? `\\nLast error:\\n${app.lastError}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, {\n id: app.id,\n status: app.status,\n settled,\n configRevision: app.configRevision,\n appliedRevision: app.appliedRevision,\n lastError: app.lastError || undefined,\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_logs',\n {\n title: 'Roxyon: application logs',\n description: 'Recent journal lines for an application (by id or project dir).',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n lines: z\n .number()\n .int()\n .min(1)\n .max(1000)\n .optional()\n .describe('How many lines (default 100).'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const lines = await session.roxyon.applications.logs(applicationId, args.lines ?? 100);\n return text(lines.join('\\n') || '(no log lines)', { lines });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_restart',\n {\n title: 'Roxyon: restart an application',\n description: 'Bounce the application process (no rebuild). Needs confirm:true.',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n if (!args.confirm)\n return text(`Would restart ${applicationId}. Pass confirm:true.`, { dryRun: true });\n await session.roxyon.applications.restart(applicationId);\n return text(`Restart queued for ${applicationId}.`, { ok: true });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_env_get',\n {\n title: 'Roxyon: read environment variables',\n description: \"An application's environment variables as KEY=value lines.\",\n inputSchema: { application: z.string().optional(), dir: z.string().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const env = await session.roxyon.applications.getEnv(applicationId);\n return text(formatEnv(env) || '(none set)', { env });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_env_set',\n {\n title: 'Roxyon: set environment variables',\n description:\n \"Merge variables into an application's environment and bump its revision. Run roxyon_deploy \" +\n 'afterwards to apply. Needs confirm:true. PORT and HOST are platform-managed and ignored.',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n vars: z.record(z.string()).describe('{ KEY: \"value\", ... } to set.'),\n remove: z.array(z.string()).optional().describe('Keys to delete.'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n const set: Record<string, string> = {};\n for (const [k, v] of Object.entries(args.vars)) {\n if (k === 'PORT' || k === 'HOST') continue;\n if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(k)) return errorResult(`Invalid env key \"${k}\".`);\n set[k] = v;\n }\n const planned = [...Object.keys(set), ...(args.remove ?? []).map((k) => `-${k}`)];\n if (!args.confirm) {\n return text(`Would update: ${planned.join(', ') || '(nothing)'}. Pass confirm:true.`, {\n dryRun: true,\n changed: planned,\n });\n }\n const r = await session.roxyon.applications.setEnv(applicationId, {\n set,\n remove: args.remove ?? [],\n });\n return text(`Updated ${r.changed.join(', ') || '(nothing)'}. Run roxyon_deploy to apply.`, {\n ok: true,\n changed: r.changed,\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_link_github',\n {\n title: 'Roxyon: connect a git remote',\n description:\n 'Connect a git repository to an application for push-to-deploy. Returns the deploy key and ' +\n 'webhook URL to add to the repo. Needs confirm:true.',\n inputSchema: {\n application: z.string().optional(),\n dir: z.string().optional(),\n repoUrl: z.string().describe('SSH git URL, e.g. git@github.com:you/app.git'),\n branch: z.string().optional().describe('Branch to deploy (default main).'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const { applicationId } = await resolveApp(args);\n if (!args.confirm) {\n return text(\n `Would connect ${args.repoUrl} (${args.branch ?? 'main'}) to ${applicationId}. Pass confirm:true.`,\n { dryRun: true },\n );\n }\n const res = await session.roxyon.applications.repoConnect(\n applicationId,\n args.repoUrl,\n args.branch ?? 'main',\n );\n const body = [\n `Connected ${args.repoUrl} (${args.branch ?? 'main'}).`,\n res.deployKey ? `\\nDeploy key (add to the repo, read-only):\\n${res.deployKey}` : '',\n res.webhookUrl ? `\\nWebhook URL: ${res.webhookUrl}` : '',\n res.secret ? `Webhook secret: ${res.secret}` : '',\n res.hint ? `\\n${res.hint}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, {\n ok: true,\n deployKey: res.deployKey,\n webhookUrl: res.webhookUrl,\n secret: res.secret,\n });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_add_domain',\n {\n title: 'Roxyon: add a subdomain / host',\n description:\n 'Provision a host — DNS + web server + automatic HTTPS. The host must be a subdomain ' +\n 'of a domain the account already hosts (or a *.roxyon.com subdomain). Returns while it ' +\n 'is still coming up; TLS follows a minute or two later. Needs confirm:true.',\n inputSchema: {\n host: z.string().describe('The full hostname, e.g. promo.mycompany.com'),\n subscription: z\n .string()\n .optional()\n .describe('Which subscription to attach it to (omit if the account has one).'),\n spa: z.boolean().optional().describe('Single-page app: unmatched paths serve /index.html.'),\n phpVersion: z\n .string()\n .optional()\n .describe(\n 'PHP version for the vhost, e.g. \"8.3\" (needed to run PHP apps like WordPress).',\n ),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(\n `Would provision ${args.host}${args.spa ? ' (SPA routing)' : ''}. Pass confirm:true.`,\n { dryRun: true },\n );\n }\n const res = await session.roxyon.domains.create({\n host: args.host,\n subscription: args.subscription ?? session.preferredSubscription,\n siteType: args.spa ? 'spa' : undefined,\n phpVersion: args.phpVersion,\n });\n const live = res.status === 'active';\n return text(\n [\n `${res.host} — ${res.type}, ${res.status}.`,\n live\n ? 'The host is up. HTTPS may take another minute to issue.'\n : 'DNS + web server are being set up (~1–2 min), then HTTPS. ' +\n 'Check roxyon_list_domains, or just deploy now — files are kept and served once it is live.',\n ].join('\\n'),\n { ok: true, host: res.host, type: res.type, status: res.status },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_deploy_content',\n {\n title: 'Roxyon: deploy generated files',\n description: [\n 'Publish a set of files you generated (HTML/CSS/JS/assets) to a host on the account.',\n 'The host must already exist (roxyon_add_domain, or an existing site). Overlay by',\n 'default — pass clean:true to replace the whole document root. Needs confirm:true.',\n `Limits: ${MAX_FILES} files, ${(MAX_FILE_BYTES / 1024) | 0} KB per file,`,\n `${(MAX_TOTAL_BYTES / 1024 / 1024).toFixed(1)} MB total (base64-encode binaries).`,\n ].join(' '),\n inputSchema: {\n host: z.string().describe('Target host, e.g. promo.mycompany.com'),\n folder: z.string().optional().describe('Sub-path under the host; \"\" = site root.'),\n files: z\n .array(\n z.object({\n path: z.string().describe('Relative path, e.g. index.html, about/index.html'),\n content: z.string(),\n encoding: z.enum(['utf8', 'base64']).optional(),\n }),\n )\n .min(1),\n clean: z.boolean().optional().describe('Replace the whole docroot (keeps .well-known).'),\n spa: z.boolean().optional().describe('Also flip the host to SPA routing.'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (args.files.length > MAX_FILES) {\n return errorResult(`Too many files (${args.files.length}); the limit is ${MAX_FILES}.`);\n }\n let total = 0;\n for (const f of args.files) {\n const n = Buffer.byteLength(f.content, f.encoding === 'base64' ? 'base64' : 'utf8');\n if (n > MAX_FILE_BYTES) {\n return errorResult(\n `\"${f.path}\" is ${(n / 1024) | 0} KB; the per-file limit is ${(MAX_FILE_BYTES / 1024) | 0} KB.`,\n );\n }\n total += n;\n }\n if (total > MAX_TOTAL_BYTES) {\n return errorResult(\n `Total content is ${(total / 1024 / 1024).toFixed(1)} MB; the limit is ` +\n `${(MAX_TOTAL_BYTES / 1024 / 1024).toFixed(1)} MB. Deploy in parts or use the CLI.`,\n );\n }\n\n const folder = args.folder ?? '';\n if (!args.confirm) {\n return text(\n [\n 'DRY RUN — pass confirm:true to deploy.',\n '',\n `Host: ${args.host}${folder ? `/${folder}` : ''}`,\n `Files: ${args.files.length} (${(total / 1024) | 0} KB)`,\n `Mode: ${args.clean ? 'clean (replaces the document root)' : 'overlay'}${args.spa ? ' + SPA routing' : ''}`,\n ...args.files.slice(0, 20).map((f) => ` ${f.path}`),\n args.files.length > 20 ? ` … ${args.files.length - 20} more` : '',\n ]\n .filter(Boolean)\n .join('\\n'),\n { dryRun: true },\n );\n }\n\n const { buffer, files } = await packFiles(args.files, { maxBytes: MAX_TOTAL_BYTES });\n const r = await session.roxyon.sites.deploy(args.host, folder, buffer, {\n clean: args.clean,\n spa: args.spa,\n });\n const size = r.bytes ? ` (${(r.bytes / 1024) | 0} KB)` : '';\n const spaNote = args.spa ? '\\nSPA routing enabled — deep links resolve to index.html.' : '';\n return text(\n `✓ Deployed ${files.length} file(s) to https://${args.host}${folder ? `/${folder}` : ''}${size}.${spaNote}`,\n { ok: true, host: args.host, files: files.length },\n );\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_list_files',\n {\n title: 'Roxyon: list a site’s files',\n description: \"The files currently deployed to a host's document root.\",\n inputSchema: {\n host: z.string(),\n folder: z.string().optional(),\n path: z.string().optional().describe('List under this sub-path only.'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const files = await session.roxyon.sites.listFiles(\n args.host,\n args.folder ?? '',\n args.path ?? '',\n );\n const body = files.length\n ? files\n .map(\n (f) => `${f.type === 'dir' ? 'd' : '-'} ${String(f.size).padStart(8)} ${f.path}`,\n )\n .join('\\n')\n : '(empty)';\n return text(body, { files });\n }),\n );\n\n // -----------------------------------------------------------------------\n server.registerTool(\n 'roxyon_read_file',\n {\n title: 'Roxyon: read a site file',\n description: \"Read one file from a host's document root (to review or edit it).\",\n inputSchema: {\n host: z.string(),\n folder: z.string().optional(),\n path: z.string().describe('Relative path, e.g. index.html'),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const f = await session.roxyon.sites.readFile(args.host, args.folder ?? '', args.path);\n if (f.encoding === 'base64') {\n return text(\n `${f.path} — ${f.size} bytes, binary (base64):\\n\\n${f.content.slice(0, 4096)}`,\n { path: f.path, size: f.size, encoding: 'base64' },\n );\n }\n return text(f.content, { path: f.path, size: f.size, encoding: 'utf8' });\n }),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_database_create',\n {\n title: 'Roxyon: create a database',\n description:\n \"Provision a MySQL/MariaDB database + user. The name is prefixed with the account's own \" +\n 'username (globally unique across the shared cluster) — pass just the suffix, e.g. \"wordpress\". ' +\n 'The password is shown once in the result; there is no way to retrieve it later. Needs confirm:true.',\n inputSchema: {\n name: z.string().describe('DB name suffix: lowercase letters, digits, underscore.'),\n subscription: z.string().optional(),\n password: z.string().optional().describe('Omit to have Roxyon generate one.'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(`Would create database \"${args.name}\". Pass confirm:true.`, {\n dryRun: true,\n });\n }\n const r = await session.roxyon.databases.create({\n name: args.name,\n subscription: args.subscription ?? session.preferredSubscription,\n password: args.password,\n });\n const body = [\n `${r.status === 'active' ? '✓' : '»'} Database ${r.name} (user ${r.username}) — ${r.status}.`,\n r.password ? `\\nPassword (save this now — shown once):\\n${r.password}` : '',\n r.host ? `Host: ${r.host}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, {\n ok: true,\n objectId: r.objectId,\n name: r.name,\n username: r.username,\n host: r.host,\n status: r.status,\n });\n }),\n ),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_list_databases',\n {\n title: 'Roxyon: list databases',\n description: 'Databases on the active subscription.',\n inputSchema: { subscription: z.string().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const subscription = args.subscription ?? session.preferredSubscription;\n if (!subscription) return errorResult('No subscription — pass \"subscription\".');\n const rows = await session.roxyon.databases.list(subscription);\n const body = rows.length\n ? rows\n .map((d) => `- ${d.Name} [${d.objectId}] — ${d.Status} (user ${d.Username})`)\n .join('\\n')\n : '(no databases)';\n return text(body, { databases: rows });\n }),\n ),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_database_delete',\n {\n title: 'Roxyon: delete a database',\n description:\n 'Delete a database by its objectId (from roxyon_database_create/roxyon_list_databases). Needs confirm:true.',\n inputSchema: { database: z.string(), confirm: z.boolean().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(`Would delete database ${args.database}. Pass confirm:true.`, {\n dryRun: true,\n });\n }\n const r = await session.roxyon.databases.delete(args.database);\n return text(`Database ${args.database} — ${r.status}.`, { ok: true, status: r.status });\n }),\n ),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_email_create',\n {\n title: 'Roxyon: create a mailbox',\n description:\n 'Provision a mailbox on a host already on the account. The password is shown once in the ' +\n 'result; there is no way to retrieve it later. Needs confirm:true.',\n inputSchema: {\n localPart: z.string().describe('The part before @, e.g. \"info\".'),\n domain: z.string().describe('A hostname already on the account.'),\n password: z.string().optional().describe('Omit to have Roxyon generate one.'),\n quota: z.number().int().positive().optional().describe('Quota in MB (default 1024).'),\n forwardTo: z.string().optional(),\n saveCopy: z.boolean().optional(),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const email = `${args.localPart}@${args.domain}`;\n if (!args.confirm) {\n return text(`Would create mailbox ${email}. Pass confirm:true.`, { dryRun: true });\n }\n const r = await session.roxyon.email.create({\n localPart: args.localPart,\n domain: args.domain,\n password: args.password,\n quota: args.quota,\n forwardTo: args.forwardTo,\n saveCopy: args.saveCopy,\n });\n const body = [\n `${r.status === 'active' ? '✓' : '»'} Mailbox ${r.email} — ${r.status}.`,\n r.password ? `\\nPassword (save this now — shown once):\\n${r.password}` : '',\n ]\n .filter(Boolean)\n .join('\\n');\n return text(body, { ok: true, objectId: r.objectId, email: r.email, status: r.status });\n }),\n ),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_list_emails',\n {\n title: 'Roxyon: list mailboxes',\n description: 'Mailboxes on the active subscription.',\n inputSchema: { subscription: z.string().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n const subscription = args.subscription ?? session.preferredSubscription;\n if (!subscription) return errorResult('No subscription — pass \"subscription\".');\n const rows = await session.roxyon.email.list(subscription);\n const body = rows.length\n ? rows.map((e) => `- ${e.Email} [${e.objectId}] — ${e.Status}`).join('\\n')\n : '(no mailboxes)';\n return text(body, { emails: rows });\n }),\n ),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_email_delete',\n {\n title: 'Roxyon: delete a mailbox',\n description:\n 'Delete a mailbox by its objectId (from roxyon_email_create/roxyon_list_emails). Needs confirm:true.',\n inputSchema: { email: z.string(), confirm: z.boolean().optional() },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text(`Would delete mailbox ${args.email}. Pass confirm:true.`, { dryRun: true });\n }\n const r = await session.roxyon.email.delete(args.email);\n return text(`Mailbox ${args.email} — ${r.status}.`, { ok: true, status: r.status });\n }),\n ),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_ssh_reset_password',\n {\n title: 'Roxyon: reset the SSH/SFTP password',\n description:\n \"Reset a subscription's shell password — used for SSH, SFTP, and the file manager. Changing \" +\n 'it signs out anything using the old one. The password is shown once in the result; the ' +\n 'platform never stores or re-shows it. Needs confirm:true.',\n inputSchema: {\n subscription: z.string().optional(),\n password: z\n .string()\n .optional()\n .describe('Omit to have Roxyon generate one (12+ chars, mixed case, number, symbol).'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const session = await getSession();\n if (!args.confirm) {\n return text('Would reset the SSH/SFTP password. Pass confirm:true.', { dryRun: true });\n }\n const r = await session.roxyon.ssh.resetPassword({\n subscription: args.subscription ?? session.preferredSubscription,\n password: args.password,\n });\n return text(\n `${r.status === 'active' ? '✓' : '»'} SSH/SFTP password ${r.status === 'active' ? 'changed' : 'change queued'}.\\n\\n` +\n `Password (save this now — shown once):\\n${r.password}`,\n { ok: true, subscription: r.subscription, status: r.status },\n );\n }),\n ),\n );\n\n // -----------------------------------------------------------------------\n hideUntilLive(\n server.registerTool(\n 'roxyon_install_wordpress',\n {\n title: 'Roxyon: install WordPress',\n description: [\n 'One-shot recipe: create a subdomain (if it does not already exist), provision a database',\n 'for it, download WordPress core, and deploy it. v1 scope — core only, no plugin/theme',\n 'selection, single site. Local-only (needs your filesystem to unpack WordPress into) — run',\n 'this from the CLI-backed MCP, not the hosted mcp.roxyon.com connector. Needs confirm:true.',\n ].join(' '),\n inputSchema: {\n host: z\n .string()\n .describe('The site host, e.g. blog.mycompany.com — created if it does not exist.'),\n folder: z\n .string()\n .optional()\n .describe('Sub-path under the host; \"\" = site root (recommended).'),\n subscription: z.string().optional(),\n dbName: z\n .string()\n .optional()\n .describe(\n 'Database name suffix (default derived from the host). See roxyon_database_create.',\n ),\n phpVersion: z.string().optional().describe('Default \"8.3\".'),\n confirm: z.boolean().optional(),\n },\n },\n (args) =>\n guard(async () => {\n const blocked = remoteFilesystemBlock('roxyon_install_wordpress');\n if (blocked) return blocked;\n const session = await getSession();\n const folder = args.folder ?? '';\n const dbSuffix =\n (args.dbName ?? args.host.split('.')[0] ?? 'wordpress')\n .toLowerCase()\n .replace(/[^a-z0-9_]/g, '_')\n .replace(/^[^a-z]+/, '')\n .slice(0, 20) || 'wordpress';\n\n if (!args.confirm) {\n return text(\n [\n 'DRY RUN — pass confirm:true to install.',\n '',\n `Host: ${args.host}${folder ? `/${folder}` : ''} (created if missing)`,\n `Database: ${dbSuffix} (prefixed with your account username)`,\n 'Steps: add domain -> create database -> download WordPress core -> upload',\n ].join('\\n'),\n { dryRun: true },\n );\n }\n\n const subscription = args.subscription ?? session.preferredSubscription;\n\n const domain = await session.roxyon.domains.create({\n host: args.host,\n subscription,\n phpVersion: args.phpVersion ?? '8.3',\n });\n if (domain.status === 'failed') {\n return errorResult(\n `Could not provision ${args.host}: ${domain.error ?? 'unknown error'}`,\n );\n }\n\n const db = await session.roxyon.databases.create({ name: dbSuffix, subscription });\n if (db.status === 'failed' || !db.password || !db.host) {\n return errorResult(`Could not provision the database: ${db.error ?? 'unknown error'}`);\n }\n\n const scratchDir = await mkdtemp(join(tmpdir(), 'roxyon-wp-'));\n await installWordPress({\n dir: scratchDir,\n db: { name: db.name, username: db.username, password: db.password, host: db.host },\n });\n\n const pack = await packDirectory(scratchDir);\n const deployRes = await session.roxyon.sites.deploy(args.host, folder, pack.buffer);\n\n const url = `https://${deployRes.host}${deployRes.path && deployRes.path !== '/' ? deployRes.path : ''}`;\n return text(\n [\n `✓ WordPress installed at ${url} (${pack.files.length} files).`,\n 'Visit the site to finish setup (site title, admin account) — WordPress asks for these',\n 'on first load.',\n '',\n `Database: ${db.name} / ${db.username} — password shown once, save it now:`,\n db.password,\n ].join('\\n'),\n { ok: true, url, database: { name: db.name, username: db.username } },\n );\n }),\n ),\n );\n}\n\n// Re-exported for tests.\nexport { resolveApp };\nexport type { Roxyon, ToolResult };\n"],"mappings":"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","names":["Roxyon","endpointsFromEnv","z","endpointsFromEnv","Roxyon","z","z","readFile","join","join","z","z","join"]}