@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.
- package/dist/auth.js +2 -0
- package/dist/auth.js.map +1 -1
- package/dist/crypto.js +5 -3
- package/dist/crypto.js.map +1 -1
- package/dist/{flags-LFbdErsZ.js → flags-CIh56cQ7.js} +3 -1
- package/dist/{flags-LFbdErsZ.js.map → flags-CIh56cQ7.js.map} +1 -1
- package/dist/{http-DyGKZqn4.js → http-DVoeL5Wa.js} +6 -2
- package/dist/{http-DyGKZqn4.js.map → http-DVoeL5Wa.js.map} +1 -1
- package/dist/http.js +1 -2
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/oauth.js +8 -6
- package/dist/oauth.js.map +1 -1
- package/dist/server.js +6 -5
- package/dist/server.js.map +1 -1
- package/dist/{version-brWM16Jb.js → version-BdjPN_IX.js} +117 -24
- package/dist/{version-brWM16Jb.js.map → version-BdjPN_IX.js.map} +1 -1
- package/package.json +3 -3
package/dist/server.js.map
CHANGED
|
@@ -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":"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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-
|
|
4474
|
+
//# sourceMappingURL=version-BdjPN_IX.js.map
|