@studiometa/forge-mcp 0.4.3 → 0.4.5

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","names":[],"sources":["../src/server.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Forge MCP Server - HTTP Transport (Streamable HTTP)\n *\n * Implements the official MCP Streamable HTTP transport specification.\n * Supports both raw Bearer tokens and OAuth 2.1 with PKCE for\n * Claude Desktop compatibility.\n *\n * Token formats:\n * - Raw Forge API token (Bearer <token>)\n * - Base64-encoded token from OAuth flow (Bearer base64(<token>))\n *\n * Environment variables:\n * PORT - HTTP port (default: 3000)\n * HOST - Bind address (default: 0.0.0.0)\n * FORGE_READ_ONLY - Disable write operations (default: false)\n * OAUTH_SECRET - AES-256-GCM encryption key for OAuth tokens.\n * Required in production. A default is used if unset.\n *\n * Usage:\n * forge-mcp-server\n * forge-mcp-server --read-only\n * OAUTH_SECRET=my-secret forge-mcp-server\n * PORT=3000 forge-mcp-server\n *\n * Endpoints:\n * POST /mcp - MCP Streamable HTTP (JSON-RPC messages)\n * GET /mcp - MCP Streamable HTTP (SSE stream for server notifications)\n * DELETE /mcp - MCP Streamable HTTP (session termination)\n * GET / - Service info\n * GET /health - Health check\n *\n * OAuth 2.1 endpoints (for Claude Desktop):\n * GET /.well-known/oauth-authorization-server - OAuth metadata (RFC 8414)\n * GET /.well-known/oauth-protected-resource - Protected resource (RFC 9728)\n * POST /register - Dynamic client registration (RFC 7591)\n * GET /authorize - Login form\n * POST /authorize - Process login\n * POST /token - Token exchange (PKCE)\n */\n\nimport { toNodeHandler } from \"h3/node\";\nimport { createServer, type Server } from \"node:http\";\n\nimport { createHealthApp, createMcpRequestHandler } from \"./http.ts\";\nimport { parseReadOnlyFlag } from \"./flags.ts\";\nimport { SessionManager } from \"./sessions.ts\";\nimport { VERSION } from \"./version.ts\";\n\nconst DEFAULT_PORT = 3000;\nconst DEFAULT_HOST = \"0.0.0.0\";\n\n/**\n * Options for the HTTP server.\n */\nexport interface HttpStartOptions {\n /** When true, forge_write tool is not registered. */\n readOnly?: boolean;\n}\n\n/**\n * Start the HTTP server with Streamable HTTP transport.\n */\nexport function startHttpServer(\n port: number = DEFAULT_PORT,\n host: string = DEFAULT_HOST,\n options?: HttpStartOptions,\n): Promise<Server> {\n return new Promise((resolve) => {\n const readOnly = options?.readOnly ?? false;\n const sessions = new SessionManager();\n const handleMcp = createMcpRequestHandler(sessions, { readOnly });\n const healthApp = createHealthApp();\n const healthHandler = toNodeHandler(healthApp);\n\n const server = createServer(async (req, res) => {\n const url = req.url ?? \"/\";\n\n // Route /mcp to MCP Streamable HTTP transport\n if (url === \"/mcp\" || url.startsWith(\"/mcp?\")) {\n await handleMcp(req, res);\n return;\n }\n\n // Everything else goes to h3 (health checks, service info)\n healthHandler(req, res);\n });\n\n server.listen(port, host, () => {\n const displayHost = host === \"0.0.0.0\" ? \"localhost\" : host;\n const mode = readOnly ? \" (read-only)\" : \"\";\n console.log(`Forge MCP server v${VERSION}${mode}`);\n console.log(`Node.js ${process.version}`);\n console.log(\"\");\n console.log(`Running at http://${displayHost}:${port}`);\n console.log(\"\");\n console.log(\"Endpoints:\");\n console.log(\n ` POST/GET/DELETE http://${displayHost}:${port}/mcp - MCP Streamable HTTP endpoint`,\n );\n console.log(` GET http://${displayHost}:${port}/health - Health check`);\n console.log(\"\");\n console.log(\"Authentication:\");\n console.log(\" Bearer token in Authorization header\");\n console.log(\" Token format: raw Forge API token or OAuth 2.1 access token\");\n console.log(\"\");\n console.log(\"OAuth 2.1 (Claude Desktop):\");\n console.log(` GET http://${displayHost}:${port}/.well-known/oauth-authorization-server`);\n console.log(` POST http://${displayHost}:${port}/register`);\n console.log(` GET http://${displayHost}:${port}/authorize`);\n console.log(` POST http://${displayHost}:${port}/token`);\n if (readOnly) {\n console.log(\"\");\n console.log(\"Mode: READ-ONLY (write operations disabled)\");\n }\n console.log(\"\");\n resolve(server);\n });\n });\n}\n\n// Start server when run directly\nconst isMainModule =\n import.meta.url === `file://${process.argv[1]}` ||\n process.argv[1]?.endsWith(\"/forge-mcp-server\") ||\n process.argv[1]?.endsWith(\"\\\\forge-mcp-server\");\n\nif (isMainModule) {\n const port = Number.parseInt(process.env.PORT || String(DEFAULT_PORT), 10);\n const host = process.env.HOST || DEFAULT_HOST;\n const readOnly = parseReadOnlyFlag();\n\n startHttpServer(port, host, { readOnly }).catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,IAAM,eAAe;AACrB,IAAM,eAAe;;;;AAarB,SAAgB,gBACd,OAAe,cACf,OAAe,cACf,SACiB;AACjB,QAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,WAAW,SAAS,YAAY;EAEtC,MAAM,YAAY,wBADD,IAAI,gBAAgB,EACe,EAAE,UAAU,CAAC;EAEjE,MAAM,gBAAgB,cADJ,iBAAiB,CACW;EAE9C,MAAM,SAAS,aAAa,OAAO,KAAK,QAAQ;GAC9C,MAAM,MAAM,IAAI,OAAO;AAGvB,OAAI,QAAQ,UAAU,IAAI,WAAW,QAAQ,EAAE;AAC7C,UAAM,UAAU,KAAK,IAAI;AACzB;;AAIF,iBAAc,KAAK,IAAI;IACvB;AAEF,SAAO,OAAO,MAAM,YAAY;GAC9B,MAAM,cAAc,SAAS,YAAY,cAAc;GACvD,MAAM,OAAO,WAAW,iBAAiB;AACzC,WAAQ,IAAI,qBAAqB,UAAU,OAAO;AAClD,WAAQ,IAAI,WAAW,QAAQ,UAAU;AACzC,WAAQ,IAAI,GAAG;AACf,WAAQ,IAAI,qBAAqB,YAAY,GAAG,OAAO;AACvD,WAAQ,IAAI,GAAG;AACf,WAAQ,IAAI,aAAa;AACzB,WAAQ,IACN,4BAA4B,YAAY,GAAG,KAAK,qCACjD;AACD,WAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,wBAAwB;AACzE,WAAQ,IAAI,GAAG;AACf,WAAQ,IAAI,kBAAkB;AAC9B,WAAQ,IAAI,yCAAyC;AACrD,WAAQ,IAAI,gEAAgE;AAC5E,WAAQ,IAAI,GAAG;AACf,WAAQ,IAAI,8BAA8B;AAC1C,WAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,yCAAyC;AAC1F,WAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,WAAW;AAC5D,WAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,YAAY;AAC7D,WAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,QAAQ;AACzD,OAAI,UAAU;AACZ,YAAQ,IAAI,GAAG;AACf,YAAQ,IAAI,8CAA8C;;AAE5D,WAAQ,IAAI,GAAG;AACf,WAAQ,OAAO;IACf;GACF;;AASJ,IAJE,OAAO,KAAK,QAAQ,UAAU,QAAQ,KAAK,QAC3C,QAAQ,KAAK,IAAI,SAAS,oBAAoB,IAC9C,QAAQ,KAAK,IAAI,SAAS,qBAAqB,CAO/C,iBAJa,OAAO,SAAS,QAAQ,IAAI,QAAQ,OAAO,aAAa,EAAE,GAAG,EAC7D,QAAQ,IAAI,QAAQ,cAGL,EAAE,UAFb,mBAAmB,EAEI,CAAC,CAAC,OAAO,UAAU;AACzD,SAAQ,MAAM,gBAAgB,MAAM;AACpC,SAAQ,KAAK,EAAE;EACf"}
1
+ {"version":3,"file":"server.js","names":[],"sources":["../src/server.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * Forge MCP Server - HTTP Transport (Streamable HTTP)\n *\n * Implements the official MCP Streamable HTTP transport specification.\n * Supports both raw Bearer tokens and OAuth 2.1 with PKCE for\n * Claude Desktop compatibility.\n *\n * Token formats:\n * - Raw Forge API token (Bearer <token>)\n * - Base64-encoded token from OAuth flow (Bearer base64(<token>))\n *\n * Environment variables:\n * PORT - HTTP port (default: 3000)\n * HOST - Bind address (default: 0.0.0.0)\n * FORGE_READ_ONLY - Disable write operations (default: false)\n * OAUTH_SECRET - AES-256-GCM encryption key for OAuth tokens.\n * Required in production. A default is used if unset.\n *\n * Usage:\n * forge-mcp-server\n * forge-mcp-server --read-only\n * OAUTH_SECRET=my-secret forge-mcp-server\n * PORT=3000 forge-mcp-server\n *\n * Endpoints:\n * POST /mcp - MCP Streamable HTTP (JSON-RPC messages)\n * GET /mcp - MCP Streamable HTTP (SSE stream for server notifications)\n * DELETE /mcp - MCP Streamable HTTP (session termination)\n * GET / - Service info\n * GET /health - Health check\n *\n * OAuth 2.1 endpoints (for Claude Desktop):\n * GET /.well-known/oauth-authorization-server - OAuth metadata (RFC 8414)\n * GET /.well-known/oauth-protected-resource - Protected resource (RFC 9728)\n * POST /register - Dynamic client registration (RFC 7591)\n * GET /authorize - Login form\n * POST /authorize - Process login\n * POST /token - Token exchange (PKCE)\n */\n\nimport { toNodeHandler } from \"h3/node\";\nimport { createServer, type Server } from \"node:http\";\n\nimport { createHealthApp, createMcpRequestHandler } from \"./http.ts\";\nimport { parseReadOnlyFlag } from \"./flags.ts\";\nimport { SessionManager } from \"./sessions.ts\";\nimport { VERSION } from \"./version.ts\";\n\nconst DEFAULT_PORT = 3000;\nconst DEFAULT_HOST = \"0.0.0.0\";\n\n/**\n * Options for the HTTP server.\n */\nexport interface HttpStartOptions {\n /** When true, forge_write tool is not registered. */\n readOnly?: boolean;\n}\n\n/**\n * Start the HTTP server with Streamable HTTP transport.\n */\nexport function startHttpServer(\n port: number = DEFAULT_PORT,\n host: string = DEFAULT_HOST,\n options?: HttpStartOptions,\n): Promise<Server> {\n return new Promise((resolve) => {\n const readOnly = options?.readOnly ?? false;\n const sessions = new SessionManager();\n const handleMcp = createMcpRequestHandler(sessions, { readOnly });\n const healthApp = createHealthApp();\n const healthHandler = toNodeHandler(healthApp);\n\n const server = createServer(async (req, res) => {\n const url = req.url ?? \"/\";\n\n // Route /mcp to MCP Streamable HTTP transport\n if (url === \"/mcp\" || url.startsWith(\"/mcp?\")) {\n await handleMcp(req, res);\n return;\n }\n\n // Everything else goes to h3 (health checks, service info)\n healthHandler(req, res);\n });\n\n server.listen(port, host, () => {\n const displayHost = host === \"0.0.0.0\" ? \"localhost\" : host;\n const mode = readOnly ? \" (read-only)\" : \"\";\n console.log(`Forge MCP server v${VERSION}${mode}`);\n console.log(`Node.js ${process.version}`);\n console.log(\"\");\n console.log(`Running at http://${displayHost}:${port}`);\n console.log(\"\");\n console.log(\"Endpoints:\");\n console.log(\n ` POST/GET/DELETE http://${displayHost}:${port}/mcp - MCP Streamable HTTP endpoint`,\n );\n console.log(` GET http://${displayHost}:${port}/health - Health check`);\n console.log(\"\");\n console.log(\"Authentication:\");\n console.log(\" Bearer token in Authorization header\");\n console.log(\" Token format: raw Forge API token or OAuth 2.1 access token\");\n console.log(\"\");\n console.log(\"OAuth 2.1 (Claude Desktop):\");\n console.log(` GET http://${displayHost}:${port}/.well-known/oauth-authorization-server`);\n console.log(` POST http://${displayHost}:${port}/register`);\n console.log(` GET http://${displayHost}:${port}/authorize`);\n console.log(` POST http://${displayHost}:${port}/token`);\n if (readOnly) {\n console.log(\"\");\n console.log(\"Mode: READ-ONLY (write operations disabled)\");\n }\n console.log(\"\");\n resolve(server);\n });\n });\n}\n\n// Start server when run directly\nconst isMainModule =\n import.meta.url === `file://${process.argv[1]}` ||\n process.argv[1]?.endsWith(\"/forge-mcp-server\") ||\n process.argv[1]?.endsWith(\"\\\\forge-mcp-server\");\n\nif (isMainModule) {\n const port = Number.parseInt(process.env.PORT || String(DEFAULT_PORT), 10);\n const host = process.env.HOST || DEFAULT_HOST;\n const readOnly = parseReadOnlyFlag();\n\n startHttpServer(port, host, { readOnly }).catch((error) => {\n console.error(\"Fatal error:\", error);\n process.exit(1);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkDA,IAAM,eAAe;AACrB,IAAM,eAAe;;;;AAarB,SAAgB,gBACd,OAAe,cACf,OAAe,cACf,SACiB;CACjB,OAAO,IAAI,SAAS,YAAY;EAC9B,MAAM,WAAW,SAAS,YAAY;EAEtC,MAAM,YAAY,wBAAwB,IADrB,eACqB,GAAU,EAAE,SAAS,CAAC;EAEhE,MAAM,gBAAgB,cADJ,gBACkB,CAAS;EAE7C,MAAM,SAAS,aAAa,OAAO,KAAK,QAAQ;GAC9C,MAAM,MAAM,IAAI,OAAO;GAGvB,IAAI,QAAQ,UAAU,IAAI,WAAW,OAAO,GAAG;IAC7C,MAAM,UAAU,KAAK,GAAG;IACxB;GACF;GAGA,cAAc,KAAK,GAAG;EACxB,CAAC;EAED,OAAO,OAAO,MAAM,YAAY;GAC9B,MAAM,cAAc,SAAS,YAAY,cAAc;GAEvD,QAAQ,IAAI,qBAAqB,UADpB,WAAW,iBAAiB,IACQ;GACjD,QAAQ,IAAI,WAAW,QAAQ,SAAS;GACxC,QAAQ,IAAI,EAAE;GACd,QAAQ,IAAI,qBAAqB,YAAY,GAAG,MAAM;GACtD,QAAQ,IAAI,EAAE;GACd,QAAQ,IAAI,YAAY;GACxB,QAAQ,IACN,4BAA4B,YAAY,GAAG,KAAK,oCAClD;GACA,QAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,uBAAuB;GACxE,QAAQ,IAAI,EAAE;GACd,QAAQ,IAAI,iBAAiB;GAC7B,QAAQ,IAAI,wCAAwC;GACpD,QAAQ,IAAI,+DAA+D;GAC3E,QAAQ,IAAI,EAAE;GACd,QAAQ,IAAI,6BAA6B;GACzC,QAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,wCAAwC;GACzF,QAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,UAAU;GAC3D,QAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,WAAW;GAC5D,QAAQ,IAAI,iBAAiB,YAAY,GAAG,KAAK,OAAO;GACxD,IAAI,UAAU;IACZ,QAAQ,IAAI,EAAE;IACd,QAAQ,IAAI,6CAA6C;GAC3D;GACA,QAAQ,IAAI,EAAE;GACd,QAAQ,MAAM;EAChB,CAAC;CACH,CAAC;AACH;AAQA,IAJE,OAAO,KAAK,QAAQ,UAAU,QAAQ,KAAK,QAC3C,QAAQ,KAAK,EAAE,EAAE,SAAS,mBAAmB,KAC7C,QAAQ,KAAK,EAAE,EAAE,SAAS,oBAAoB,GAO9C,gBAJa,OAAO,SAAS,QAAQ,IAAI,QAAQ,OAAO,YAAY,GAAG,EAIvD,GAHH,QAAQ,IAAI,QAAQ,cAGL,EAAE,UAFb,kBAEa,EAAS,CAAC,CAAC,CAAC,OAAO,UAAU;CACzD,QAAQ,MAAM,gBAAgB,KAAK;CACnC,QAAQ,KAAK,CAAC;AAChB,CAAC"}
@@ -3,6 +3,7 @@ import { dirname, join } from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { HttpClient, isForgeApiError } from "@studiometa/forge-api";
5
5
  import { RESOURCES, activateCertificate, createAuditLogger, createBackupConfig, createCertificate, createCommand, createDaemon, createDatabase, createDatabaseUser, createFirewallRule, createMonitor, createNginxTemplate, createRecipe, createRedirectRule, createScheduledJob, createSecurityRule, createServer, createSite, createSshKey, deleteBackupConfig, deleteCertificate, deleteDaemon, deleteDatabase, deleteDatabaseUser, deleteFirewallRule, deleteMonitor, deleteNginxTemplate, deleteRecipe, deleteRedirectRule, deleteScheduledJob, deleteSecurityRule, deleteServer, deleteSite, deleteSshKey, deploySiteAndWait, getBackupConfig, getCertificate, getCommand, getDaemon, getDatabase, getDatabaseUser, getDeploymentLog, getDeploymentScript, getEnv, getFirewallRule, getMonitor, getNginxConfig, getNginxTemplate, getRecipe, getRedirectRule, getScheduledJob, getSecurityRule, getServer, getSite, getSshKey, getUser, listBackupConfigs, listCommands, listDaemons, listDatabaseUsers, listDatabases, listDeployments, listFirewallRules, listMonitors, listNginxTemplates, listRecipes, listRedirectRules, listScheduledJobs, listSecurityRules, listServers, listSites, listSshKeys, rebootServer, resolveServers, resolveSites, restartDaemon, runRecipe, updateBackupConfig, updateDaemon, updateDatabaseUser, updateDeploymentScript, updateEnv, updateNginxConfig, updateNginxTemplate, updateRecipe, updateSecurityRule, updateSite } from "@studiometa/forge-core";
6
+ //#region src/instructions.ts
6
7
  /**
7
8
  * MCP Server Instructions
8
9
  *
@@ -24,7 +25,9 @@ function loadInstructions() {
24
25
  return "Laravel Forge MCP Server - Use the forge tool with resource and action parameters. Call action=\"help\" for documentation.";
25
26
  }
26
27
  }
27
- const INSTRUCTIONS = loadInstructions();
28
+ var INSTRUCTIONS = loadInstructions();
29
+ //#endregion
30
+ //#region ../../node_modules/valibot/dist/index.mjs
28
31
  var store$4;
29
32
  /**
30
33
  * Returns the global configuration.
@@ -417,6 +420,8 @@ function safeParse(schema, input, config$1) {
417
420
  issues: dataset.issues
418
421
  };
419
422
  }
423
+ //#endregion
424
+ //#region src/formatters.ts
420
425
  /**
421
426
  * Format a list of servers.
422
427
  */
@@ -740,6 +745,8 @@ function formatUser(user) {
740
745
  `Created: ${user.created_at}`
741
746
  ].join("\n");
742
747
  }
748
+ //#endregion
749
+ //#region src/errors.ts
743
750
  /**
744
751
  * Custom error classes for MCP server
745
752
  *
@@ -774,6 +781,8 @@ var UserInputError = class extends Error {
774
781
  function isUserInputError(error) {
775
782
  return error instanceof UserInputError;
776
783
  }
784
+ //#endregion
785
+ //#region src/handlers/utils.ts
777
786
  /**
778
787
  * Create a successful result with both human-readable text and structured content.
779
788
  *
@@ -818,6 +827,8 @@ function errorResult(message) {
818
827
  isError: true
819
828
  };
820
829
  }
830
+ //#endregion
831
+ //#region src/handlers/factory.ts
821
832
  /**
822
833
  * Factory for creating Forge resource handlers.
823
834
  *
@@ -875,7 +886,9 @@ function createResourceHandler(config) {
875
886
  return jsonResult(result.data);
876
887
  };
877
888
  }
878
- const handleBackups = createResourceHandler({
889
+ //#endregion
890
+ //#region src/handlers/backups.ts
891
+ var handleBackups = createResourceHandler({
879
892
  resource: "backups",
880
893
  actions: [
881
894
  "list",
@@ -931,14 +944,17 @@ const handleBackups = createResourceHandler({
931
944
  case "create": return "Done.";
932
945
  case "update": return "Done.";
933
946
  case "delete": return `Backup config ${args.id} deleted.`;
947
+ /* v8 ignore next */
934
948
  default: return "Done.";
935
949
  }
936
950
  }
937
951
  });
952
+ //#endregion
953
+ //#region src/tools.ts
938
954
  /**
939
955
  * Read-only actions — safe operations that don't modify server state.
940
956
  */
941
- const READ_ACTIONS = [
957
+ var READ_ACTIONS = [
942
958
  "list",
943
959
  "get",
944
960
  "resolve",
@@ -950,7 +966,7 @@ const READ_ACTIONS = [
950
966
  * Write actions — operations that modify server state.
951
967
  * These are separated into the `forge_write` tool for safety.
952
968
  */
953
- const WRITE_ACTIONS = [
969
+ var WRITE_ACTIONS = [
954
970
  "create",
955
971
  "update",
956
972
  "delete",
@@ -1042,7 +1058,7 @@ var SHARED_INPUT_PROPERTIES = {
1042
1058
  * - `forge` — read-only operations (auto-approvable by MCP clients)
1043
1059
  * - `forge_write` — write operations (always requires confirmation)
1044
1060
  */
1045
- const TOOLS = [{
1061
+ var TOOLS = [{
1046
1062
  name: "forge",
1047
1063
  title: "Laravel Forge",
1048
1064
  description: [
@@ -1227,7 +1243,7 @@ function getTools(options) {
1227
1243
  /**
1228
1244
  * Additional tools only available in stdio mode.
1229
1245
  */
1230
- const STDIO_ONLY_TOOLS = [{
1246
+ var STDIO_ONLY_TOOLS = [{
1231
1247
  name: "forge_configure",
1232
1248
  title: "Configure Forge",
1233
1249
  description: "Configure Laravel Forge API credentials. The token is stored locally in the XDG config directory.",
@@ -1300,6 +1316,8 @@ const STDIO_ONLY_TOOLS = [{
1300
1316
  required: ["configured"]
1301
1317
  }
1302
1318
  }];
1319
+ //#endregion
1320
+ //#region src/handlers/batch.ts
1303
1321
  var MAX_OPERATIONS = 10;
1304
1322
  /**
1305
1323
  * Validate and narrow an array element to a BatchOperation.
@@ -1392,6 +1410,8 @@ async function handleBatch(action, args, ctx, routeToHandler) {
1392
1410
  results
1393
1411
  });
1394
1412
  }
1413
+ //#endregion
1414
+ //#region src/hints.ts
1395
1415
  /**
1396
1416
  * Hints after getting a server.
1397
1417
  */
@@ -1755,7 +1775,9 @@ function getNginxTemplateHints(serverId, templateId) {
1755
1775
  }]
1756
1776
  };
1757
1777
  }
1758
- const handleCertificates = createResourceHandler({
1778
+ //#endregion
1779
+ //#region src/handlers/certificates.ts
1780
+ var handleCertificates = createResourceHandler({
1759
1781
  resource: "certificates",
1760
1782
  actions: [
1761
1783
  "get",
@@ -1799,11 +1821,14 @@ const handleCertificates = createResourceHandler({
1799
1821
  case "create": return formatCertificate(data);
1800
1822
  case "delete": return `Certificate for domain ${String(args.domain_id)} deleted.`;
1801
1823
  case "activate": return `Certificate for domain ${String(args.domain_id)} activated.`;
1824
+ /* v8 ignore next */
1802
1825
  default: return "Done.";
1803
1826
  }
1804
1827
  }
1805
1828
  });
1806
- const handleCommands = createResourceHandler({
1829
+ //#endregion
1830
+ //#region src/handlers/commands.ts
1831
+ var handleCommands = createResourceHandler({
1807
1832
  resource: "commands",
1808
1833
  actions: [
1809
1834
  "list",
@@ -1836,11 +1861,14 @@ const handleCommands = createResourceHandler({
1836
1861
  case "list": return formatCommandList(data);
1837
1862
  case "get": return formatCommand(data);
1838
1863
  case "create": return "Done.";
1864
+ /* v8 ignore next */
1839
1865
  default: return "Done.";
1840
1866
  }
1841
1867
  }
1842
1868
  });
1843
- const handleDaemons = createResourceHandler({
1869
+ //#endregion
1870
+ //#region src/handlers/daemons.ts
1871
+ var handleDaemons = createResourceHandler({
1844
1872
  resource: "daemons",
1845
1873
  actions: [
1846
1874
  "list",
@@ -1892,11 +1920,14 @@ const handleDaemons = createResourceHandler({
1892
1920
  case "update": return formatDaemon(data);
1893
1921
  case "delete": return `Daemon ${args.id} deleted.`;
1894
1922
  case "restart": return `Daemon ${args.id} restarted.`;
1923
+ /* v8 ignore next */
1895
1924
  default: return "Done.";
1896
1925
  }
1897
1926
  }
1898
1927
  });
1899
- const handleDatabases = createResourceHandler({
1928
+ //#endregion
1929
+ //#region src/handlers/databases.ts
1930
+ var handleDatabases = createResourceHandler({
1900
1931
  resource: "databases",
1901
1932
  actions: [
1902
1933
  "list",
@@ -1932,11 +1963,14 @@ const handleDatabases = createResourceHandler({
1932
1963
  case "get": return formatDatabase(data);
1933
1964
  case "create": return formatDatabase(data);
1934
1965
  case "delete": return `Database ${args.id} deleted.`;
1966
+ /* v8 ignore next */
1935
1967
  default: return "Done.";
1936
1968
  }
1937
1969
  }
1938
1970
  });
1939
- const handleDatabaseUsers = createResourceHandler({
1971
+ //#endregion
1972
+ //#region src/handlers/database-users.ts
1973
+ var handleDatabaseUsers = createResourceHandler({
1940
1974
  resource: "database-users",
1941
1975
  actions: [
1942
1976
  "list",
@@ -1982,10 +2016,13 @@ const handleDatabaseUsers = createResourceHandler({
1982
2016
  case "create": return formatDatabaseUser(data);
1983
2017
  case "update": return formatDatabaseUser(data);
1984
2018
  case "delete": return `Database user ${args.id} deleted.`;
2019
+ /* v8 ignore next */
1985
2020
  default: return "Done.";
1986
2021
  }
1987
2022
  }
1988
2023
  });
2024
+ //#endregion
2025
+ //#region src/handlers/deployments.ts
1989
2026
  /**
1990
2027
  * Handle deployment resource actions.
1991
2028
  *
@@ -2031,7 +2068,9 @@ async function handleDeployments(action, args, ctx) {
2031
2068
  default: return errorResult(`Unknown action "${action}" for deployments. Valid actions: list, deploy, get, update.`);
2032
2069
  }
2033
2070
  }
2034
- const handleEnv = createResourceHandler({
2071
+ //#endregion
2072
+ //#region src/handlers/env.ts
2073
+ var handleEnv = createResourceHandler({
2035
2074
  resource: "env",
2036
2075
  actions: ["get", "update"],
2037
2076
  inputSchemas: {
@@ -2058,11 +2097,14 @@ const handleEnv = createResourceHandler({
2058
2097
  switch (action) {
2059
2098
  case "get": return formatEnv(data);
2060
2099
  case "update": return "Environment variables updated.";
2100
+ /* v8 ignore next */
2061
2101
  default: return "Done.";
2062
2102
  }
2063
2103
  }
2064
2104
  });
2065
- const handleFirewallRules = createResourceHandler({
2105
+ //#endregion
2106
+ //#region src/handlers/firewall-rules.ts
2107
+ var handleFirewallRules = createResourceHandler({
2066
2108
  resource: "firewall-rules",
2067
2109
  actions: [
2068
2110
  "list",
@@ -2099,10 +2141,13 @@ const handleFirewallRules = createResourceHandler({
2099
2141
  case "get": return formatFirewallRule(data);
2100
2142
  case "create": return "Done.";
2101
2143
  case "delete": return `Firewall rule ${args.id} deleted.`;
2144
+ /* v8 ignore next */
2102
2145
  default: return "Done.";
2103
2146
  }
2104
2147
  }
2105
2148
  });
2149
+ //#endregion
2150
+ //#region src/handlers/help.ts
2106
2151
  var RESOURCE_HELP = {
2107
2152
  servers: {
2108
2153
  description: "Manage Laravel Forge servers — provisioned cloud instances (DigitalOcean, AWS, Hetzner, etc.)",
@@ -2893,7 +2938,9 @@ function handleHelpOverview() {
2893
2938
  _tip: "Always call { action: 'help', resource: '<name>' } before your first interaction with any resource to learn required fields and examples."
2894
2939
  });
2895
2940
  }
2896
- const handleMonitors = createResourceHandler({
2941
+ //#endregion
2942
+ //#region src/handlers/monitors.ts
2943
+ var handleMonitors = createResourceHandler({
2897
2944
  resource: "monitors",
2898
2945
  actions: [
2899
2946
  "list",
@@ -2931,11 +2978,14 @@ const handleMonitors = createResourceHandler({
2931
2978
  case "get": return formatMonitor(data);
2932
2979
  case "create": return formatMonitor(data);
2933
2980
  case "delete": return `Monitor ${args.id} deleted.`;
2981
+ /* v8 ignore next */
2934
2982
  default: return "Done.";
2935
2983
  }
2936
2984
  }
2937
2985
  });
2938
- const handleNginxConfig = createResourceHandler({
2986
+ //#endregion
2987
+ //#region src/handlers/nginx-config.ts
2988
+ var handleNginxConfig = createResourceHandler({
2939
2989
  resource: "nginx",
2940
2990
  actions: ["get", "update"],
2941
2991
  inputSchemas: {
@@ -2962,11 +3012,14 @@ const handleNginxConfig = createResourceHandler({
2962
3012
  switch (action) {
2963
3013
  case "get": return formatNginxConfig(data);
2964
3014
  case "update": return "Nginx configuration updated.";
3015
+ /* v8 ignore next */
2965
3016
  default: return "Done.";
2966
3017
  }
2967
3018
  }
2968
3019
  });
2969
- const handleNginxTemplates = createResourceHandler({
3020
+ //#endregion
3021
+ //#region src/handlers/nginx-templates.ts
3022
+ var handleNginxTemplates = createResourceHandler({
2970
3023
  resource: "nginx-templates",
2971
3024
  actions: [
2972
3025
  "list",
@@ -3010,11 +3063,14 @@ const handleNginxTemplates = createResourceHandler({
3010
3063
  case "create": return formatNginxTemplate(data);
3011
3064
  case "update": return formatNginxTemplate(data);
3012
3065
  case "delete": return `Nginx template ${args.id} deleted.`;
3066
+ /* v8 ignore next */
3013
3067
  default: return "Done.";
3014
3068
  }
3015
3069
  }
3016
3070
  });
3017
- const handleRecipes = createResourceHandler({
3071
+ //#endregion
3072
+ //#region src/handlers/recipes.ts
3073
+ var handleRecipes = createResourceHandler({
3018
3074
  resource: "recipes",
3019
3075
  actions: [
3020
3076
  "list",
@@ -3063,11 +3119,14 @@ const handleRecipes = createResourceHandler({
3063
3119
  const count = Array.isArray(servers) ? servers.length : 1;
3064
3120
  return `Recipe ${args.id} run on ${count} server(s).`;
3065
3121
  }
3122
+ /* v8 ignore next */
3066
3123
  default: return "Done.";
3067
3124
  }
3068
3125
  }
3069
3126
  });
3070
- const handleRedirectRules = createResourceHandler({
3127
+ //#endregion
3128
+ //#region src/handlers/redirect-rules.ts
3129
+ var handleRedirectRules = createResourceHandler({
3071
3130
  resource: "redirect-rules",
3072
3131
  actions: [
3073
3132
  "list",
@@ -3109,11 +3168,14 @@ const handleRedirectRules = createResourceHandler({
3109
3168
  case "get": return formatRedirectRule(data);
3110
3169
  case "create": return "Done.";
3111
3170
  case "delete": return `Redirect rule ${args.id} deleted.`;
3171
+ /* v8 ignore next */
3112
3172
  default: return "Done.";
3113
3173
  }
3114
3174
  }
3115
3175
  });
3116
- const handleScheduledJobs = createResourceHandler({
3176
+ //#endregion
3177
+ //#region src/handlers/scheduled-jobs.ts
3178
+ var handleScheduledJobs = createResourceHandler({
3117
3179
  resource: "scheduled-jobs",
3118
3180
  actions: [
3119
3181
  "list",
@@ -3154,10 +3216,13 @@ const handleScheduledJobs = createResourceHandler({
3154
3216
  case "get": return formatScheduledJob(data);
3155
3217
  case "create": return formatScheduledJob(data);
3156
3218
  case "delete": return `Scheduled job ${args.id} deleted.`;
3219
+ /* v8 ignore next */
3157
3220
  default: return "Done.";
3158
3221
  }
3159
3222
  }
3160
3223
  });
3224
+ //#endregion
3225
+ //#region src/handlers/schema.ts
3161
3226
  var RESOURCE_SCHEMAS = {
3162
3227
  servers: {
3163
3228
  actions: [
@@ -3851,7 +3916,9 @@ function handleSchemaOverview() {
3851
3916
  }))
3852
3917
  });
3853
3918
  }
3854
- const handleSecurityRules = createResourceHandler({
3919
+ //#endregion
3920
+ //#region src/handlers/security-rules.ts
3921
+ var handleSecurityRules = createResourceHandler({
3855
3922
  resource: "security-rules",
3856
3923
  actions: [
3857
3924
  "list",
@@ -3904,10 +3971,13 @@ const handleSecurityRules = createResourceHandler({
3904
3971
  case "create": return formatSecurityRule(data);
3905
3972
  case "update": return formatSecurityRule(data);
3906
3973
  case "delete": return `Security rule ${args.id} deleted.`;
3974
+ /* v8 ignore next */
3907
3975
  default: return "Done.";
3908
3976
  }
3909
3977
  }
3910
3978
  });
3979
+ //#endregion
3980
+ //#region src/handlers/context.ts
3911
3981
  /**
3912
3982
  * Handle server context action — fetches server details plus all sub-resources
3913
3983
  * (sites, databases, database users, daemons, firewall rules, scheduled jobs)
@@ -3973,6 +4043,8 @@ async function handleSiteContext(args, ctx) {
3973
4043
  security_rules: securityRules.data
3974
4044
  });
3975
4045
  }
4046
+ //#endregion
4047
+ //#region src/handlers/servers.ts
3976
4048
  var _handleServers = createResourceHandler({
3977
4049
  resource: "servers",
3978
4050
  actions: [
@@ -4011,9 +4083,12 @@ var _handleServers = createResourceHandler({
4011
4083
  case "reboot": return { server_id: args.id };
4012
4084
  case "create": return {
4013
4085
  provider: args.provider,
4086
+ /* v8 ignore next */
4014
4087
  credential_id: Number(args.credential_id) || 0,
4015
4088
  name: args.name,
4089
+ /* v8 ignore next */
4016
4090
  type: args.type ?? "app",
4091
+ /* v8 ignore next */
4017
4092
  size: args.size ?? "",
4018
4093
  region: args.region
4019
4094
  };
@@ -4034,6 +4109,7 @@ var _handleServers = createResourceHandler({
4034
4109
  const lines = result.matches.map((m) => `• ${m.name} (ID: ${m.id})`);
4035
4110
  return `${result.total} server(s) matching "${result.query}":\n${lines.join("\n")}`;
4036
4111
  }
4112
+ /* v8 ignore next */
4037
4113
  default: return "Done.";
4038
4114
  }
4039
4115
  }
@@ -4046,6 +4122,8 @@ async function handleServers(action, args, ctx) {
4046
4122
  if (action === "context") return handleServerContext(args, ctx);
4047
4123
  return _handleServers(action, args, ctx);
4048
4124
  }
4125
+ //#endregion
4126
+ //#region src/handlers/sites.ts
4049
4127
  var _handleSites = createResourceHandler({
4050
4128
  resource: "sites",
4051
4129
  actions: [
@@ -4119,6 +4197,7 @@ var _handleSites = createResourceHandler({
4119
4197
  server_id: args.server_id,
4120
4198
  query: args.query
4121
4199
  };
4200
+ /* v8 ignore next */
4122
4201
  default: return {};
4123
4202
  }
4124
4203
  },
@@ -4135,6 +4214,7 @@ var _handleSites = createResourceHandler({
4135
4214
  const lines = result.matches.map((m) => `• ${m.name} (ID: ${m.id})`);
4136
4215
  return `${result.total} site(s) matching "${result.query}" on server ${args.server_id}:\n${lines.join("\n")}`;
4137
4216
  }
4217
+ /* v8 ignore next */
4138
4218
  default: return "Done.";
4139
4219
  }
4140
4220
  }
@@ -4147,7 +4227,9 @@ async function handleSites(action, args, ctx) {
4147
4227
  if (action === "context") return handleSiteContext(args, ctx);
4148
4228
  return _handleSites(action, args, ctx);
4149
4229
  }
4150
- const handleSshKeys = createResourceHandler({
4230
+ //#endregion
4231
+ //#region src/handlers/ssh-keys.ts
4232
+ var handleSshKeys = createResourceHandler({
4151
4233
  resource: "ssh-keys",
4152
4234
  actions: [
4153
4235
  "list",
@@ -4184,11 +4266,14 @@ const handleSshKeys = createResourceHandler({
4184
4266
  case "get": return formatSshKey(data);
4185
4267
  case "create": return "Done.";
4186
4268
  case "delete": return `SSH key ${args.id} deleted.`;
4269
+ /* v8 ignore next */
4187
4270
  default: return "Done.";
4188
4271
  }
4189
4272
  }
4190
4273
  });
4191
- const handleUser = createResourceHandler({
4274
+ //#endregion
4275
+ //#region src/handlers/user.ts
4276
+ var handleUser = createResourceHandler({
4192
4277
  resource: "user",
4193
4278
  actions: ["get"],
4194
4279
  executors: { get: getUser },
@@ -4196,6 +4281,8 @@ const handleUser = createResourceHandler({
4196
4281
  return formatUser(data);
4197
4282
  }
4198
4283
  });
4284
+ //#endregion
4285
+ //#region src/handlers/auto-resolve.ts
4199
4286
  /**
4200
4287
  * Check if a value is a numeric ID.
4201
4288
  */
@@ -4258,6 +4345,8 @@ async function autoResolveIds(args, executorContext) {
4258
4345
  args: resolved
4259
4346
  };
4260
4347
  }
4348
+ //#endregion
4349
+ //#region src/handlers/index.ts
4261
4350
  /** Valid resources derived from core constants */
4262
4351
  var VALID_RESOURCES = [...RESOURCES];
4263
4352
  var _auditLogger = null;
@@ -4291,6 +4380,7 @@ function routeToHandler(resource, action, args, ctx) {
4291
4380
  case "scheduled-jobs": return handleScheduledJobs(action, args, ctx);
4292
4381
  case "user": return handleUser(action, args, ctx);
4293
4382
  case "batch": return handleBatch(action, args, ctx, routeToHandler);
4383
+ /* v8 ignore next 6 -- all valid resources are handled above; unreachable in practice */
4294
4384
  default: return Promise.resolve(errorResult(`Unknown resource "${resource}". Valid resources: ${VALID_RESOURCES.join(", ")}. Use action="help" for documentation.`));
4295
4385
  }
4296
4386
  }
@@ -4375,7 +4465,10 @@ async function executeToolWithCredentials(name, args, credentials) {
4375
4465
  return errorResult(errorMessage);
4376
4466
  }
4377
4467
  }
4378
- const VERSION = "0.4.3";
4468
+ //#endregion
4469
+ //#region src/version.ts
4470
+ var VERSION = "0.4.5";
4471
+ //#endregion
4379
4472
  export { INSTRUCTIONS as a, getTools as i, executeToolWithCredentials as n, STDIO_ONLY_TOOLS as r, VERSION as t };
4380
4473
 
4381
- //# sourceMappingURL=version-brWM16Jb.js.map
4474
+ //# sourceMappingURL=version-BdjPN_IX.js.map