@hanzo/platform-mcp 1.4.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.
- package/LICENSE +13 -0
- package/README.md +534 -0
- package/build/http-server.js +286 -0
- package/build/index.js +35 -0
- package/build/mcp/tools/application/applicationCleanQueues.js +23 -0
- package/build/mcp/tools/application/applicationCreate.js +39 -0
- package/build/mcp/tools/application/applicationDelete.js +21 -0
- package/build/mcp/tools/application/applicationDeploy.js +21 -0
- package/build/mcp/tools/application/applicationMarkRunning.js +23 -0
- package/build/mcp/tools/application/applicationMove.js +22 -0
- package/build/mcp/tools/application/applicationOne.js +26 -0
- package/build/mcp/tools/application/applicationReadAppMonitoring.js +26 -0
- package/build/mcp/tools/application/applicationReadTraefikConfig.js +26 -0
- package/build/mcp/tools/application/applicationRedeploy.js +23 -0
- package/build/mcp/tools/application/applicationRefreshToken.js +23 -0
- package/build/mcp/tools/application/applicationReload.js +22 -0
- package/build/mcp/tools/application/applicationSaveBitbucketProvider.js +49 -0
- package/build/mcp/tools/application/applicationSaveBuildType.js +56 -0
- package/build/mcp/tools/application/applicationSaveDockerProvider.js +43 -0
- package/build/mcp/tools/application/applicationSaveEnvironment.js +33 -0
- package/build/mcp/tools/application/applicationSaveGitProvider.js +49 -0
- package/build/mcp/tools/application/applicationSaveGiteaProvider.js +43 -0
- package/build/mcp/tools/application/applicationSaveGithubProvider.js +51 -0
- package/build/mcp/tools/application/applicationSaveGitlabProvider.js +48 -0
- package/build/mcp/tools/application/applicationStart.js +21 -0
- package/build/mcp/tools/application/applicationStop.js +21 -0
- package/build/mcp/tools/application/applicationUpdate.js +319 -0
- package/build/mcp/tools/application/applicationUpdateTraefikConfig.js +26 -0
- package/build/mcp/tools/application/index.js +24 -0
- package/build/mcp/tools/compose/composeCreate.js +31 -0
- package/build/mcp/tools/compose/composeDeploy.js +26 -0
- package/build/mcp/tools/compose/composeOne.js +24 -0
- package/build/mcp/tools/compose/composeReload.js +28 -0
- package/build/mcp/tools/compose/composeRemove.js +26 -0
- package/build/mcp/tools/compose/composeSaveEnvironment.js +28 -0
- package/build/mcp/tools/compose/composeStart.js +26 -0
- package/build/mcp/tools/compose/composeStop.js +26 -0
- package/build/mcp/tools/compose/composeUpdate.js +34 -0
- package/build/mcp/tools/compose/index.js +9 -0
- package/build/mcp/tools/index.js +12 -0
- package/build/mcp/tools/mysql/index.js +13 -0
- package/build/mcp/tools/mysql/mysqlChangeStatus.js +24 -0
- package/build/mcp/tools/mysql/mysqlCreate.js +50 -0
- package/build/mcp/tools/mysql/mysqlDeploy.js +21 -0
- package/build/mcp/tools/mysql/mysqlMove.js +24 -0
- package/build/mcp/tools/mysql/mysqlOne.js +23 -0
- package/build/mcp/tools/mysql/mysqlRebuild.js +21 -0
- package/build/mcp/tools/mysql/mysqlReload.js +22 -0
- package/build/mcp/tools/mysql/mysqlRemove.js +21 -0
- package/build/mcp/tools/mysql/mysqlSaveEnvironment.js +26 -0
- package/build/mcp/tools/mysql/mysqlSaveExternalPort.js +25 -0
- package/build/mcp/tools/mysql/mysqlStart.js +21 -0
- package/build/mcp/tools/mysql/mysqlStop.js +21 -0
- package/build/mcp/tools/mysql/mysqlUpdate.js +103 -0
- package/build/mcp/tools/postgres/index.js +13 -0
- package/build/mcp/tools/postgres/postgresChangeStatus.js +26 -0
- package/build/mcp/tools/postgres/postgresCreate.js +48 -0
- package/build/mcp/tools/postgres/postgresDeploy.js +23 -0
- package/build/mcp/tools/postgres/postgresMove.js +26 -0
- package/build/mcp/tools/postgres/postgresOne.js +26 -0
- package/build/mcp/tools/postgres/postgresRebuild.js +23 -0
- package/build/mcp/tools/postgres/postgresReload.js +26 -0
- package/build/mcp/tools/postgres/postgresRemove.js +23 -0
- package/build/mcp/tools/postgres/postgresSaveEnvironment.js +28 -0
- package/build/mcp/tools/postgres/postgresSaveExternalPort.js +27 -0
- package/build/mcp/tools/postgres/postgresStart.js +23 -0
- package/build/mcp/tools/postgres/postgresStop.js +23 -0
- package/build/mcp/tools/postgres/postgresUpdate.js +97 -0
- package/build/mcp/tools/project/index.js +6 -0
- package/build/mcp/tools/project/projectAll.js +68 -0
- package/build/mcp/tools/project/projectCreate.js +30 -0
- package/build/mcp/tools/project/projectDuplicate.js +54 -0
- package/build/mcp/tools/project/projectOne.js +24 -0
- package/build/mcp/tools/project/projectRemove.js +21 -0
- package/build/mcp/tools/project/projectUpdate.js +39 -0
- package/build/mcp/tools/toolFactory.js +60 -0
- package/build/server.js +12 -0
- package/build/types/platform.js +3 -0
- package/build/utils/apiClient.js +126 -0
- package/build/utils/clientConfig.js +37 -0
- package/build/utils/logger.js +38 -0
- package/build/utils/responseFormatter.js +33 -0
- package/package.json +63 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
3
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
4
|
+
import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
+
import express from "express";
|
|
6
|
+
import { randomUUID } from "node:crypto";
|
|
7
|
+
import { createServer } from "./server.js";
|
|
8
|
+
import { createLogger } from "./utils/logger.js";
|
|
9
|
+
// Container always uses port 3000 internally
|
|
10
|
+
const PORT = 3000;
|
|
11
|
+
const logger = createLogger("MCP-HTTP-Server");
|
|
12
|
+
export async function main() {
|
|
13
|
+
const app = express();
|
|
14
|
+
app.use(express.json());
|
|
15
|
+
// Store active transports by session ID for different transport types
|
|
16
|
+
const transports = {
|
|
17
|
+
streamable: {},
|
|
18
|
+
sse: {},
|
|
19
|
+
};
|
|
20
|
+
// Health check endpoint
|
|
21
|
+
app.get("/health", (_req, res) => {
|
|
22
|
+
res.json({ status: "ok", timestamp: new Date().toISOString() });
|
|
23
|
+
});
|
|
24
|
+
// Modern Streamable HTTP endpoint for POST requests (client-to-server)
|
|
25
|
+
app.post("/mcp", async (req, res) => {
|
|
26
|
+
try {
|
|
27
|
+
// Check for existing session ID
|
|
28
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
29
|
+
let transport;
|
|
30
|
+
if (sessionId && transports.streamable[sessionId]) {
|
|
31
|
+
// Reuse existing transport
|
|
32
|
+
transport = transports.streamable[sessionId];
|
|
33
|
+
}
|
|
34
|
+
else if (!sessionId && isInitializeRequest(req.body)) {
|
|
35
|
+
// New initialization request
|
|
36
|
+
transport = new StreamableHTTPServerTransport({
|
|
37
|
+
sessionIdGenerator: () => randomUUID(),
|
|
38
|
+
onsessioninitialized: (sessionId) => {
|
|
39
|
+
// Store the transport by session ID
|
|
40
|
+
transports.streamable[sessionId] = transport;
|
|
41
|
+
logger.info("New MCP session initialized", { sessionId });
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
// Clean up transport when closed
|
|
45
|
+
transport.onclose = () => {
|
|
46
|
+
if (transport.sessionId) {
|
|
47
|
+
logger.info("MCP session closed", {
|
|
48
|
+
sessionId: transport.sessionId,
|
|
49
|
+
});
|
|
50
|
+
delete transports.streamable[transport.sessionId];
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
// Create and connect server first
|
|
54
|
+
const server = createServer();
|
|
55
|
+
// The transport will have sessionId after initialization
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
57
|
+
await server.connect(transport);
|
|
58
|
+
// Log after successful connection
|
|
59
|
+
logger.info("New MCP session server connected", {
|
|
60
|
+
sessionId: transport.sessionId,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
// Invalid request
|
|
65
|
+
res.status(400).json({
|
|
66
|
+
jsonrpc: "2.0",
|
|
67
|
+
error: {
|
|
68
|
+
code: -32000,
|
|
69
|
+
message: "Bad Request: No valid session ID provided for existing session or invalid initialization request",
|
|
70
|
+
},
|
|
71
|
+
id: null,
|
|
72
|
+
});
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// Handle the request
|
|
76
|
+
await transport.handleRequest(req, res, req.body);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
logger.error("Error handling HTTP request", {
|
|
80
|
+
error: error instanceof Error ? error.message : String(error),
|
|
81
|
+
sessionId: req.headers["mcp-session-id"],
|
|
82
|
+
});
|
|
83
|
+
if (!res.headersSent) {
|
|
84
|
+
res.status(500).json({
|
|
85
|
+
jsonrpc: "2.0",
|
|
86
|
+
error: {
|
|
87
|
+
code: -32603,
|
|
88
|
+
message: "Internal server error",
|
|
89
|
+
},
|
|
90
|
+
id: null,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
// Reusable handler for GET and DELETE requests (Streamable HTTP)
|
|
96
|
+
const handleSessionRequest = async (req, res) => {
|
|
97
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
98
|
+
if (!sessionId || !transports.streamable[sessionId]) {
|
|
99
|
+
res.status(400).json({
|
|
100
|
+
jsonrpc: "2.0",
|
|
101
|
+
error: {
|
|
102
|
+
code: -32000,
|
|
103
|
+
message: "Invalid or missing session ID",
|
|
104
|
+
},
|
|
105
|
+
id: null,
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const transport = transports.streamable[sessionId];
|
|
111
|
+
await transport.handleRequest(req, res);
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
logger.error("Error handling session request", {
|
|
115
|
+
error: error instanceof Error ? error.message : String(error),
|
|
116
|
+
sessionId,
|
|
117
|
+
method: req.method,
|
|
118
|
+
});
|
|
119
|
+
if (!res.headersSent) {
|
|
120
|
+
res.status(500).json({
|
|
121
|
+
jsonrpc: "2.0",
|
|
122
|
+
error: {
|
|
123
|
+
code: -32603,
|
|
124
|
+
message: "Internal server error",
|
|
125
|
+
},
|
|
126
|
+
id: null,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
// Handle GET requests for server-to-client notifications via SSE
|
|
132
|
+
app.get("/mcp", handleSessionRequest);
|
|
133
|
+
// Handle DELETE requests for session termination
|
|
134
|
+
app.delete("/mcp", async (req, res) => {
|
|
135
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
136
|
+
if (!sessionId || !transports.streamable[sessionId]) {
|
|
137
|
+
res.status(400).json({
|
|
138
|
+
jsonrpc: "2.0",
|
|
139
|
+
error: {
|
|
140
|
+
code: -32000,
|
|
141
|
+
message: "Invalid or missing session ID",
|
|
142
|
+
},
|
|
143
|
+
id: null,
|
|
144
|
+
});
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
try {
|
|
148
|
+
const transport = transports.streamable[sessionId];
|
|
149
|
+
await transport.handleRequest(req, res);
|
|
150
|
+
// Clean up after session termination
|
|
151
|
+
if (transports.streamable[sessionId]) {
|
|
152
|
+
logger.info("MCP session terminated", { sessionId });
|
|
153
|
+
delete transports.streamable[sessionId];
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
logger.error("Error handling DELETE request", {
|
|
158
|
+
error: error instanceof Error ? error.message : String(error),
|
|
159
|
+
sessionId,
|
|
160
|
+
});
|
|
161
|
+
if (!res.headersSent) {
|
|
162
|
+
res.status(500).json({
|
|
163
|
+
jsonrpc: "2.0",
|
|
164
|
+
error: {
|
|
165
|
+
code: -32603,
|
|
166
|
+
message: "Internal server error",
|
|
167
|
+
},
|
|
168
|
+
id: null,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
// Legacy SSE endpoint for older clients (protocol version 2024-11-05)
|
|
174
|
+
app.get("/sse", async (_req, res) => {
|
|
175
|
+
try {
|
|
176
|
+
// Create SSE transport for legacy clients
|
|
177
|
+
const transport = new SSEServerTransport("/messages", res);
|
|
178
|
+
transports.sse[transport.sessionId] = transport;
|
|
179
|
+
res.on("close", () => {
|
|
180
|
+
logger.info("Legacy SSE session closed", {
|
|
181
|
+
sessionId: transport.sessionId,
|
|
182
|
+
});
|
|
183
|
+
delete transports.sse[transport.sessionId];
|
|
184
|
+
});
|
|
185
|
+
// Create and connect server for this transport
|
|
186
|
+
const server = createServer();
|
|
187
|
+
await server.connect(transport);
|
|
188
|
+
logger.info("New legacy SSE session initialized", {
|
|
189
|
+
sessionId: transport.sessionId,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
catch (error) {
|
|
193
|
+
logger.error("Error handling SSE request", {
|
|
194
|
+
error: error instanceof Error ? error.message : String(error),
|
|
195
|
+
});
|
|
196
|
+
if (!res.headersSent) {
|
|
197
|
+
res.status(500).json({
|
|
198
|
+
jsonrpc: "2.0",
|
|
199
|
+
error: {
|
|
200
|
+
code: -32603,
|
|
201
|
+
message: "Internal server error",
|
|
202
|
+
},
|
|
203
|
+
id: null,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
// Legacy message endpoint for older clients
|
|
209
|
+
app.post("/messages", async (req, res) => {
|
|
210
|
+
try {
|
|
211
|
+
const sessionId = req.query.sessionId;
|
|
212
|
+
if (!sessionId) {
|
|
213
|
+
logger.warn("No sessionId provided in message request");
|
|
214
|
+
res.status(400).json({
|
|
215
|
+
jsonrpc: "2.0",
|
|
216
|
+
error: {
|
|
217
|
+
code: -32000,
|
|
218
|
+
message: "sessionId query parameter is required",
|
|
219
|
+
},
|
|
220
|
+
id: null,
|
|
221
|
+
});
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
const transport = transports.sse[sessionId];
|
|
225
|
+
if (!transport) {
|
|
226
|
+
logger.warn("No SSE transport found for sessionId", { sessionId });
|
|
227
|
+
res.status(400).json({
|
|
228
|
+
jsonrpc: "2.0",
|
|
229
|
+
error: {
|
|
230
|
+
code: -32000,
|
|
231
|
+
message: "No transport found for sessionId",
|
|
232
|
+
},
|
|
233
|
+
id: null,
|
|
234
|
+
});
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
await transport.handlePostMessage(req, res, req.body);
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
logger.error("Error handling legacy message request", {
|
|
241
|
+
error: error instanceof Error ? error.message : String(error),
|
|
242
|
+
sessionId: req.query.sessionId,
|
|
243
|
+
});
|
|
244
|
+
if (!res.headersSent) {
|
|
245
|
+
res.status(500).json({
|
|
246
|
+
jsonrpc: "2.0",
|
|
247
|
+
error: {
|
|
248
|
+
code: -32603,
|
|
249
|
+
message: "Internal server error",
|
|
250
|
+
},
|
|
251
|
+
id: null,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
// Start the server
|
|
257
|
+
app.listen(PORT, () => {
|
|
258
|
+
logger.info("MCP Platform server started", {
|
|
259
|
+
port: PORT,
|
|
260
|
+
protocols: [
|
|
261
|
+
"Streamable HTTP (MCP 2025-03-26)",
|
|
262
|
+
"Legacy SSE (MCP 2024-11-05)",
|
|
263
|
+
],
|
|
264
|
+
endpoints: {
|
|
265
|
+
modern: {
|
|
266
|
+
mcp: `http://localhost:${PORT}/mcp`,
|
|
267
|
+
health: `http://localhost:${PORT}/health`,
|
|
268
|
+
},
|
|
269
|
+
legacy: {
|
|
270
|
+
sse: `http://localhost:${PORT}/sse`,
|
|
271
|
+
messages: `http://localhost:${PORT}/messages`,
|
|
272
|
+
},
|
|
273
|
+
},
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
// Only run if this file is executed directly
|
|
278
|
+
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
279
|
+
main().catch((error) => {
|
|
280
|
+
logger.error("Fatal error occurred", {
|
|
281
|
+
error: error instanceof Error ? error.message : String(error),
|
|
282
|
+
stack: error instanceof Error ? error.stack : undefined,
|
|
283
|
+
});
|
|
284
|
+
process.exit(1);
|
|
285
|
+
});
|
|
286
|
+
}
|
package/build/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { createServer } from "./server.js";
|
|
4
|
+
import { createLogger } from "./utils/logger.js";
|
|
5
|
+
const logger = createLogger("MCP-Entry");
|
|
6
|
+
async function main() {
|
|
7
|
+
// Check if running in HTTP mode
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
const httpMode = args.includes("--http") ||
|
|
10
|
+
args.includes("--sse") ||
|
|
11
|
+
process.env.MCP_TRANSPORT === "http" ||
|
|
12
|
+
process.env.MCP_TRANSPORT === "sse";
|
|
13
|
+
if (httpMode) {
|
|
14
|
+
// Dynamic import to avoid loading Express dependencies when not needed
|
|
15
|
+
const httpModule = await import("./http-server.js");
|
|
16
|
+
if (typeof httpModule.main === "function") {
|
|
17
|
+
return httpModule.main();
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
throw new Error("HTTP server module does not export main function");
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
// Default: stdio mode
|
|
24
|
+
const server = createServer();
|
|
25
|
+
const transport = new StdioServerTransport();
|
|
26
|
+
await server.connect(transport);
|
|
27
|
+
logger.info("MCP Platform CLI server running via stdio");
|
|
28
|
+
}
|
|
29
|
+
main().catch((error) => {
|
|
30
|
+
logger.error("Fatal error occurred", {
|
|
31
|
+
error: error.message,
|
|
32
|
+
stack: error.stack,
|
|
33
|
+
});
|
|
34
|
+
process.exit(1);
|
|
35
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationCleanQueues = createTool({
|
|
6
|
+
name: "application-cleanQueues",
|
|
7
|
+
description: "Cleans the queues for an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The ID of the application to clean queues for."),
|
|
12
|
+
}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: "Clean Application Queues",
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
idempotentHint: true,
|
|
17
|
+
openWorldHint: true,
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const response = await apiClient.post("/application.cleanQueues", input);
|
|
21
|
+
return ResponseFormatter.success(`Queues for application "${input.applicationId}" cleaned successfully`, response.data);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { createTool } from "../toolFactory.js";
|
|
4
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
5
|
+
export const applicationCreate = createTool({
|
|
6
|
+
name: "application-create",
|
|
7
|
+
description: "Creates a new application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
name: z.string().min(1).describe("The name of the application."),
|
|
10
|
+
appName: z
|
|
11
|
+
.string()
|
|
12
|
+
.optional()
|
|
13
|
+
.describe("The app name for the application."),
|
|
14
|
+
description: z
|
|
15
|
+
.string()
|
|
16
|
+
.nullable()
|
|
17
|
+
.optional()
|
|
18
|
+
.describe("An optional description for the application."),
|
|
19
|
+
projectId: z
|
|
20
|
+
.string()
|
|
21
|
+
.min(1)
|
|
22
|
+
.describe("The ID of the project where the application will be created."),
|
|
23
|
+
serverId: z
|
|
24
|
+
.string()
|
|
25
|
+
.nullable()
|
|
26
|
+
.optional()
|
|
27
|
+
.describe("The ID of the server where the application will be deployed."),
|
|
28
|
+
}),
|
|
29
|
+
annotations: {
|
|
30
|
+
title: "Create Application",
|
|
31
|
+
destructiveHint: false,
|
|
32
|
+
idempotentHint: false,
|
|
33
|
+
openWorldHint: true,
|
|
34
|
+
},
|
|
35
|
+
handler: async (input) => {
|
|
36
|
+
const response = await apiClient.post("/application.create", input);
|
|
37
|
+
return ResponseFormatter.success(`Application "${input.name}" created successfully in project "${input.projectId}"`, response.data);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationDelete = createTool({
|
|
6
|
+
name: "application-delete",
|
|
7
|
+
description: "Deletes an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z.string().describe("The ID of the application to delete."),
|
|
10
|
+
}),
|
|
11
|
+
annotations: {
|
|
12
|
+
title: "Delete Application",
|
|
13
|
+
destructiveHint: true,
|
|
14
|
+
idempotentHint: false,
|
|
15
|
+
openWorldHint: true,
|
|
16
|
+
},
|
|
17
|
+
handler: async (input) => {
|
|
18
|
+
const response = await apiClient.post("/application.delete", input);
|
|
19
|
+
return ResponseFormatter.success(`Application "${input.applicationId}" deleted successfully`, response.data);
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationDeploy = createTool({
|
|
6
|
+
name: "application-deploy",
|
|
7
|
+
description: "Deploys an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z.string().describe("The ID of the application to deploy."),
|
|
10
|
+
}),
|
|
11
|
+
annotations: {
|
|
12
|
+
title: "Deploy Application",
|
|
13
|
+
destructiveHint: false,
|
|
14
|
+
idempotentHint: false,
|
|
15
|
+
openWorldHint: true,
|
|
16
|
+
},
|
|
17
|
+
handler: async (input) => {
|
|
18
|
+
const response = await apiClient.post("/application.deploy", input);
|
|
19
|
+
return ResponseFormatter.success(`Application "${input.applicationId}" deployment started successfully`, response.data);
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationMarkRunning = createTool({
|
|
6
|
+
name: "application-markRunning",
|
|
7
|
+
description: "Marks an application as running in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The ID of the application to mark as running."),
|
|
12
|
+
}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: "Mark Application as Running",
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
idempotentHint: true,
|
|
17
|
+
openWorldHint: true,
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const response = await apiClient.post("/application.markRunning", input);
|
|
21
|
+
return ResponseFormatter.success(`Application "${input.applicationId}" marked as running successfully`, response.data);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationMove = createTool({
|
|
6
|
+
name: "application-move",
|
|
7
|
+
description: "Moves an application to a different project in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z.string().describe("The ID of the application to move."),
|
|
10
|
+
targetProjectId: z.string().describe("The ID of the destination project."),
|
|
11
|
+
}),
|
|
12
|
+
annotations: {
|
|
13
|
+
title: "Move Application",
|
|
14
|
+
destructiveHint: true,
|
|
15
|
+
idempotentHint: false,
|
|
16
|
+
openWorldHint: true,
|
|
17
|
+
},
|
|
18
|
+
handler: async (input) => {
|
|
19
|
+
const response = await apiClient.post("/application.move", input);
|
|
20
|
+
return ResponseFormatter.success(`Application "${input.applicationId}" moved to project "${input.targetProjectId}" successfully`, response.data);
|
|
21
|
+
},
|
|
22
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { createTool } from "../toolFactory.js";
|
|
4
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
5
|
+
export const applicationOne = createTool({
|
|
6
|
+
name: "application-one",
|
|
7
|
+
description: "Gets a specific application by its ID in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The ID of the application to retrieve."),
|
|
12
|
+
}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: "Get Application Details",
|
|
15
|
+
readOnlyHint: true,
|
|
16
|
+
idempotentHint: true,
|
|
17
|
+
openWorldHint: true,
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const application = await apiClient.get(`/application.one?applicationId=${input.applicationId}`);
|
|
21
|
+
if (!application?.data) {
|
|
22
|
+
return ResponseFormatter.error("Failed to fetch application", `Application with ID "${input.applicationId}" not found`);
|
|
23
|
+
}
|
|
24
|
+
return ResponseFormatter.success(`Successfully fetched application "${input.applicationId}"`, application.data);
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationReadAppMonitoring = createTool({
|
|
6
|
+
name: "application-readAppMonitoring",
|
|
7
|
+
description: "Reads monitoring data for an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
appName: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The app name of the application to get monitoring data for."),
|
|
12
|
+
}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: "Read Application Monitoring",
|
|
15
|
+
readOnlyHint: true,
|
|
16
|
+
idempotentHint: true,
|
|
17
|
+
openWorldHint: true,
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const response = await apiClient.get(`/application.readAppMonitoring?appName=${input.appName}`);
|
|
21
|
+
if (!response?.data) {
|
|
22
|
+
return ResponseFormatter.error("Failed to fetch application monitoring data", `No monitoring data found for application "${input.appName}"`);
|
|
23
|
+
}
|
|
24
|
+
return ResponseFormatter.success(`Successfully fetched monitoring data for application "${input.appName}"`, response.data);
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationReadTraefikConfig = createTool({
|
|
6
|
+
name: "application-readTraefikConfig",
|
|
7
|
+
description: "Reads Traefik configuration for an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The ID of the application to get Traefik config for."),
|
|
12
|
+
}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: "Read Application Traefik Config",
|
|
15
|
+
readOnlyHint: true,
|
|
16
|
+
idempotentHint: true,
|
|
17
|
+
openWorldHint: true,
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const response = await apiClient.get(`/application.readTraefikConfig?applicationId=${input.applicationId}`);
|
|
21
|
+
if (!response?.data) {
|
|
22
|
+
return ResponseFormatter.error("Failed to fetch application Traefik configuration", `No Traefik configuration found for application "${input.applicationId}"`);
|
|
23
|
+
}
|
|
24
|
+
return ResponseFormatter.success(`Successfully fetched Traefik configuration for application "${input.applicationId}"`, response.data);
|
|
25
|
+
},
|
|
26
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationRedeploy = createTool({
|
|
6
|
+
name: "application-redeploy",
|
|
7
|
+
description: "Redeploys an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The ID of the application to redeploy."),
|
|
12
|
+
}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: "Redeploy Application",
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
idempotentHint: false,
|
|
17
|
+
openWorldHint: true,
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const response = await apiClient.post("/application.redeploy", input);
|
|
21
|
+
return ResponseFormatter.success(`Application "${input.applicationId}" redeployment started successfully`, response.data);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationRefreshToken = createTool({
|
|
6
|
+
name: "application-refreshToken",
|
|
7
|
+
description: "Refreshes the token for an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z
|
|
10
|
+
.string()
|
|
11
|
+
.describe("The ID of the application to refresh token for."),
|
|
12
|
+
}),
|
|
13
|
+
annotations: {
|
|
14
|
+
title: "Refresh Application Token",
|
|
15
|
+
destructiveHint: false,
|
|
16
|
+
idempotentHint: false,
|
|
17
|
+
openWorldHint: true,
|
|
18
|
+
},
|
|
19
|
+
handler: async (input) => {
|
|
20
|
+
const response = await apiClient.post("/application.refreshToken", input);
|
|
21
|
+
return ResponseFormatter.success(`Token for application "${input.applicationId}" refreshed successfully`, response.data);
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import apiClient from "../../../utils/apiClient.js";
|
|
3
|
+
import { ResponseFormatter } from "../../../utils/responseFormatter.js";
|
|
4
|
+
import { createTool } from "../toolFactory.js";
|
|
5
|
+
export const applicationReload = createTool({
|
|
6
|
+
name: "application-reload",
|
|
7
|
+
description: "Reloads an application in Platform.",
|
|
8
|
+
schema: z.object({
|
|
9
|
+
applicationId: z.string().describe("The ID of the application to reload."),
|
|
10
|
+
appName: z.string().describe("The app name of the application to reload."),
|
|
11
|
+
}),
|
|
12
|
+
annotations: {
|
|
13
|
+
title: "Reload Application",
|
|
14
|
+
destructiveHint: false,
|
|
15
|
+
idempotentHint: false,
|
|
16
|
+
openWorldHint: true,
|
|
17
|
+
},
|
|
18
|
+
handler: async (input) => {
|
|
19
|
+
const response = await apiClient.post("/application.reload", input);
|
|
20
|
+
return ResponseFormatter.success(`Application "${input.applicationId}" reloaded successfully`, response.data);
|
|
21
|
+
},
|
|
22
|
+
});
|