@masonator/coolify-mcp 0.1.2 → 0.1.4
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/__tests__/coolify-client.test.js +137 -398
- package/dist/__tests__/mcp-server.test.js +24 -26
- package/dist/__tests__/resources/application-resources.test.js +6 -9
- package/dist/__tests__/resources/database-resources.test.js +30 -34
- package/dist/__tests__/resources/deployment-resources.test.js +19 -20
- package/dist/__tests__/resources/service-resources.test.js +36 -41
- package/dist/index.js +4 -6
- package/dist/lib/coolify-client.js +1 -5
- package/dist/lib/mcp-server.d.ts +2 -2
- package/dist/lib/mcp-server.js +542 -509
- package/dist/lib/resource.js +3 -7
- package/dist/resources/application-resources.js +6 -10
- package/dist/resources/database-resources.js +6 -10
- package/dist/resources/deployment-resources.js +5 -9
- package/dist/resources/index.js +4 -20
- package/dist/resources/service-resources.js +6 -10
- package/dist/types/coolify.js +1 -2
- package/package.json +17 -11
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const mcp_server_js_1 = require("../lib/mcp-server.js");
|
|
4
|
-
const globals_1 = require("@jest/globals");
|
|
1
|
+
import { CoolifyMcpServer } from '../lib/mcp-server.js';
|
|
2
|
+
import { jest } from '@jest/globals';
|
|
5
3
|
describe('CoolifyMcpServer', () => {
|
|
6
4
|
const mockConfig = {
|
|
7
5
|
baseUrl: 'https://coolify.test',
|
|
@@ -9,9 +7,9 @@ describe('CoolifyMcpServer', () => {
|
|
|
9
7
|
};
|
|
10
8
|
let server;
|
|
11
9
|
beforeEach(() => {
|
|
12
|
-
server = new
|
|
10
|
+
server = new CoolifyMcpServer(mockConfig);
|
|
13
11
|
// Mock validateConnection to prevent actual HTTP calls
|
|
14
|
-
|
|
12
|
+
jest.spyOn(server['client'], 'validateConnection').mockResolvedValue();
|
|
15
13
|
});
|
|
16
14
|
describe('get_server_resources', () => {
|
|
17
15
|
it('should call client getServerResources', async () => {
|
|
@@ -27,7 +25,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
27
25
|
status: 'running',
|
|
28
26
|
},
|
|
29
27
|
];
|
|
30
|
-
const spy =
|
|
28
|
+
const spy = jest
|
|
31
29
|
.spyOn(server['client'], 'getServerResources')
|
|
32
30
|
.mockResolvedValue(mockResources);
|
|
33
31
|
await server.get_server_resources('test-uuid');
|
|
@@ -40,7 +38,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
40
38
|
const mockValidation = {
|
|
41
39
|
message: 'Server is valid',
|
|
42
40
|
};
|
|
43
|
-
const spy =
|
|
41
|
+
const spy = jest.spyOn(server['client'], 'validateServer').mockResolvedValue(mockValidation);
|
|
44
42
|
await server.validate_server('test-uuid');
|
|
45
43
|
expect(spy).toHaveBeenCalledWith('test-uuid');
|
|
46
44
|
});
|
|
@@ -56,7 +54,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
56
54
|
environments: [],
|
|
57
55
|
},
|
|
58
56
|
];
|
|
59
|
-
const spy =
|
|
57
|
+
const spy = jest.spyOn(server['client'], 'listProjects').mockResolvedValue(mockProjects);
|
|
60
58
|
await server.list_projects();
|
|
61
59
|
expect(spy).toHaveBeenCalled();
|
|
62
60
|
});
|
|
@@ -70,7 +68,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
70
68
|
description: 'Test project description',
|
|
71
69
|
environments: [],
|
|
72
70
|
};
|
|
73
|
-
const spy =
|
|
71
|
+
const spy = jest.spyOn(server['client'], 'getProject').mockResolvedValue(mockProject);
|
|
74
72
|
await server.get_project('test-project-uuid');
|
|
75
73
|
expect(spy).toHaveBeenCalledWith('test-project-uuid');
|
|
76
74
|
});
|
|
@@ -82,7 +80,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
82
80
|
name: 'New Project',
|
|
83
81
|
description: 'New project description',
|
|
84
82
|
};
|
|
85
|
-
const spy =
|
|
83
|
+
const spy = jest.spyOn(server['client'], 'createProject').mockResolvedValue(mockResponse);
|
|
86
84
|
await server.create_project(createRequest);
|
|
87
85
|
expect(spy).toHaveBeenCalledWith(createRequest);
|
|
88
86
|
});
|
|
@@ -100,7 +98,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
100
98
|
name: 'Updated Project',
|
|
101
99
|
description: 'Updated description',
|
|
102
100
|
};
|
|
103
|
-
const spy =
|
|
101
|
+
const spy = jest.spyOn(server['client'], 'updateProject').mockResolvedValue(mockProject);
|
|
104
102
|
await server.update_project('test-project-uuid', updateRequest);
|
|
105
103
|
expect(spy).toHaveBeenCalledWith('test-project-uuid', updateRequest);
|
|
106
104
|
});
|
|
@@ -108,7 +106,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
108
106
|
describe('delete_project', () => {
|
|
109
107
|
it('should call client deleteProject', async () => {
|
|
110
108
|
const mockResponse = { message: 'Project deleted successfully' };
|
|
111
|
-
const spy =
|
|
109
|
+
const spy = jest.spyOn(server['client'], 'deleteProject').mockResolvedValue(mockResponse);
|
|
112
110
|
await server.delete_project('test-project-uuid');
|
|
113
111
|
expect(spy).toHaveBeenCalledWith('test-project-uuid');
|
|
114
112
|
});
|
|
@@ -124,7 +122,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
124
122
|
created_at: '2024-03-06T12:00:00Z',
|
|
125
123
|
updated_at: '2024-03-06T12:00:00Z',
|
|
126
124
|
};
|
|
127
|
-
const spy =
|
|
125
|
+
const spy = jest
|
|
128
126
|
.spyOn(server['client'], 'getProjectEnvironment')
|
|
129
127
|
.mockResolvedValue(mockEnvironment);
|
|
130
128
|
await server.get_project_environment('test-project-uuid', 'test-env-uuid');
|
|
@@ -141,14 +139,14 @@ describe('CoolifyMcpServer', () => {
|
|
|
141
139
|
created_at: '2024-03-20T12:00:00Z',
|
|
142
140
|
updated_at: '2024-03-20T12:00:00Z',
|
|
143
141
|
};
|
|
144
|
-
|
|
142
|
+
jest.spyOn(server['client'], 'deployApplication').mockResolvedValue(mockDeployment);
|
|
145
143
|
const result = await server.deploy_application({ uuid: 'test-app-uuid' });
|
|
146
144
|
expect(result).toEqual(mockDeployment);
|
|
147
145
|
expect(server['client'].deployApplication).toHaveBeenCalledWith('test-app-uuid');
|
|
148
146
|
});
|
|
149
147
|
it('should handle errors when deploying an application', async () => {
|
|
150
148
|
const error = new Error('Failed to deploy application');
|
|
151
|
-
|
|
149
|
+
jest.spyOn(server['client'], 'deployApplication').mockRejectedValue(error);
|
|
152
150
|
await expect(server.deploy_application({ uuid: 'test-app-uuid' })).rejects.toThrow('Failed to deploy application');
|
|
153
151
|
});
|
|
154
152
|
});
|
|
@@ -169,13 +167,13 @@ describe('CoolifyMcpServer', () => {
|
|
|
169
167
|
postgres_db: 'testdb',
|
|
170
168
|
};
|
|
171
169
|
it('should list databases', async () => {
|
|
172
|
-
const spy =
|
|
170
|
+
const spy = jest.spyOn(server['client'], 'listDatabases').mockResolvedValue([mockDatabase]);
|
|
173
171
|
const result = await server.list_databases();
|
|
174
172
|
expect(result).toEqual([mockDatabase]);
|
|
175
173
|
expect(spy).toHaveBeenCalled();
|
|
176
174
|
});
|
|
177
175
|
it('should get database details', async () => {
|
|
178
|
-
const spy =
|
|
176
|
+
const spy = jest.spyOn(server['client'], 'getDatabase').mockResolvedValue(mockDatabase);
|
|
179
177
|
const result = await server.get_database('test-db-uuid');
|
|
180
178
|
expect(result).toEqual(mockDatabase);
|
|
181
179
|
expect(spy).toHaveBeenCalledWith('test-db-uuid');
|
|
@@ -185,7 +183,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
185
183
|
name: 'updated-db',
|
|
186
184
|
description: 'Updated description',
|
|
187
185
|
};
|
|
188
|
-
const spy =
|
|
186
|
+
const spy = jest
|
|
189
187
|
.spyOn(server['client'], 'updateDatabase')
|
|
190
188
|
.mockResolvedValue({ ...mockDatabase, ...updateData, type: 'postgresql' });
|
|
191
189
|
const result = await server.update_database('test-db-uuid', updateData);
|
|
@@ -198,7 +196,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
198
196
|
});
|
|
199
197
|
it('should delete database', async () => {
|
|
200
198
|
const mockResponse = { message: 'Database deleted' };
|
|
201
|
-
const spy =
|
|
199
|
+
const spy = jest.spyOn(server['client'], 'deleteDatabase').mockResolvedValue(mockResponse);
|
|
202
200
|
const result = await server.delete_database('test-db-uuid', {
|
|
203
201
|
deleteConfigurations: true,
|
|
204
202
|
deleteVolumes: true,
|
|
@@ -211,7 +209,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
211
209
|
});
|
|
212
210
|
it('should handle database errors', async () => {
|
|
213
211
|
const errorMessage = 'Database not found';
|
|
214
|
-
|
|
212
|
+
jest.spyOn(server['client'], 'getDatabase').mockRejectedValue(new Error(errorMessage));
|
|
215
213
|
await expect(server.get_database('invalid-uuid')).rejects.toThrow(errorMessage);
|
|
216
214
|
});
|
|
217
215
|
});
|
|
@@ -232,13 +230,13 @@ describe('CoolifyMcpServer', () => {
|
|
|
232
230
|
domains: ['test-service.example.com'],
|
|
233
231
|
};
|
|
234
232
|
it('should list services', async () => {
|
|
235
|
-
const spy =
|
|
233
|
+
const spy = jest.spyOn(server['client'], 'listServices').mockResolvedValue([mockService]);
|
|
236
234
|
const result = await server.list_services();
|
|
237
235
|
expect(result).toEqual([mockService]);
|
|
238
236
|
expect(spy).toHaveBeenCalled();
|
|
239
237
|
});
|
|
240
238
|
it('should get service details', async () => {
|
|
241
|
-
const spy =
|
|
239
|
+
const spy = jest.spyOn(server['client'], 'getService').mockResolvedValue(mockService);
|
|
242
240
|
const result = await server.get_service('test-service-uuid');
|
|
243
241
|
expect(result).toEqual(mockService);
|
|
244
242
|
expect(spy).toHaveBeenCalledWith('test-service-uuid');
|
|
@@ -257,14 +255,14 @@ describe('CoolifyMcpServer', () => {
|
|
|
257
255
|
uuid: 'test-service-uuid',
|
|
258
256
|
domains: ['test-service.example.com'],
|
|
259
257
|
};
|
|
260
|
-
const spy =
|
|
258
|
+
const spy = jest.spyOn(server['client'], 'createService').mockResolvedValue(mockResponse);
|
|
261
259
|
const result = await server.create_service(createData);
|
|
262
260
|
expect(result).toEqual(mockResponse);
|
|
263
261
|
expect(spy).toHaveBeenCalledWith(createData);
|
|
264
262
|
});
|
|
265
263
|
it('should delete service', async () => {
|
|
266
264
|
const mockResponse = { message: 'Service deleted' };
|
|
267
|
-
const spy =
|
|
265
|
+
const spy = jest.spyOn(server['client'], 'deleteService').mockResolvedValue(mockResponse);
|
|
268
266
|
const result = await server.delete_service('test-service-uuid', {
|
|
269
267
|
deleteConfigurations: true,
|
|
270
268
|
deleteVolumes: true,
|
|
@@ -277,7 +275,7 @@ describe('CoolifyMcpServer', () => {
|
|
|
277
275
|
});
|
|
278
276
|
it('should handle service errors', async () => {
|
|
279
277
|
const errorMessage = 'Service not found';
|
|
280
|
-
|
|
278
|
+
jest.spyOn(server['client'], 'getService').mockRejectedValue(new Error(errorMessage));
|
|
281
279
|
await expect(server.get_service('invalid-uuid')).rejects.toThrow(errorMessage);
|
|
282
280
|
});
|
|
283
281
|
});
|
|
@@ -1,17 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const application_resources_js_1 = require("../../resources/application-resources.js");
|
|
4
|
-
const coolify_client_js_1 = require("../../lib/coolify-client.js");
|
|
1
|
+
import { ApplicationResources } from '../../resources/application-resources.js';
|
|
2
|
+
import { jest } from '@jest/globals';
|
|
5
3
|
jest.mock('../../lib/coolify-client.js');
|
|
6
4
|
describe('ApplicationResources', () => {
|
|
7
5
|
let resources;
|
|
8
6
|
let mockClient;
|
|
9
7
|
beforeEach(() => {
|
|
10
|
-
mockClient =
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
resources = new application_resources_js_1.ApplicationResources(mockClient);
|
|
8
|
+
mockClient = {
|
|
9
|
+
deployApplication: jest.fn(),
|
|
10
|
+
};
|
|
11
|
+
resources = new ApplicationResources(mockClient);
|
|
15
12
|
});
|
|
16
13
|
describe('listApplications', () => {
|
|
17
14
|
it('should throw not implemented error', async () => {
|
|
@@ -1,72 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const database_resources_js_1 = require("../../resources/database-resources.js");
|
|
4
|
-
const coolify_client_js_1 = require("../../lib/coolify-client.js");
|
|
1
|
+
import { DatabaseResources } from '../../resources/database-resources.js';
|
|
2
|
+
import { jest } from '@jest/globals';
|
|
5
3
|
jest.mock('../../lib/coolify-client.js');
|
|
6
4
|
describe('DatabaseResources', () => {
|
|
7
|
-
let resources;
|
|
8
5
|
let mockClient;
|
|
6
|
+
let resources;
|
|
9
7
|
const mockDatabase = {
|
|
10
8
|
id: 1,
|
|
11
|
-
uuid: 'test-
|
|
9
|
+
uuid: 'test-uuid',
|
|
12
10
|
name: 'test-db',
|
|
13
|
-
description: '
|
|
11
|
+
description: 'test description',
|
|
14
12
|
type: 'postgresql',
|
|
15
13
|
status: 'running',
|
|
16
|
-
created_at: '2024-
|
|
17
|
-
updated_at: '2024-
|
|
14
|
+
created_at: '2024-01-01',
|
|
15
|
+
updated_at: '2024-01-01',
|
|
18
16
|
is_public: false,
|
|
19
17
|
image: 'postgres:latest',
|
|
20
|
-
postgres_user: '
|
|
21
|
-
postgres_password: '
|
|
22
|
-
postgres_db: '
|
|
18
|
+
postgres_user: 'test',
|
|
19
|
+
postgres_password: 'test',
|
|
20
|
+
postgres_db: 'test',
|
|
23
21
|
};
|
|
24
22
|
beforeEach(() => {
|
|
25
|
-
mockClient =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
mockClient = {
|
|
24
|
+
listDatabases: jest.fn(),
|
|
25
|
+
getDatabase: jest.fn(),
|
|
26
|
+
updateDatabase: jest.fn(),
|
|
27
|
+
deleteDatabase: jest.fn(),
|
|
28
|
+
};
|
|
29
|
+
resources = new DatabaseResources(mockClient);
|
|
30
30
|
});
|
|
31
31
|
describe('listDatabases', () => {
|
|
32
32
|
it('should return a list of databases', async () => {
|
|
33
|
-
mockClient.listDatabases
|
|
33
|
+
mockClient.listDatabases.mockResolvedValue([mockDatabase]);
|
|
34
34
|
const result = await resources.listDatabases();
|
|
35
35
|
expect(result).toEqual([mockDatabase]);
|
|
36
36
|
expect(mockClient.listDatabases).toHaveBeenCalled();
|
|
37
37
|
});
|
|
38
38
|
});
|
|
39
39
|
describe('getDatabase', () => {
|
|
40
|
-
it('should return a
|
|
41
|
-
mockClient.getDatabase
|
|
42
|
-
const result = await resources.getDatabase('test-
|
|
40
|
+
it('should return a database by uuid', async () => {
|
|
41
|
+
mockClient.getDatabase.mockResolvedValue(mockDatabase);
|
|
42
|
+
const result = await resources.getDatabase('test-uuid');
|
|
43
43
|
expect(result).toEqual(mockDatabase);
|
|
44
|
-
expect(mockClient.getDatabase).toHaveBeenCalledWith('test-
|
|
44
|
+
expect(mockClient.getDatabase).toHaveBeenCalledWith('test-uuid');
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
describe('updateDatabase', () => {
|
|
48
48
|
it('should update a database', async () => {
|
|
49
49
|
const updateData = {
|
|
50
50
|
name: 'updated-db',
|
|
51
|
-
description: '
|
|
51
|
+
description: 'updated description',
|
|
52
52
|
};
|
|
53
|
-
mockClient.updateDatabase
|
|
54
|
-
const result = await resources.updateDatabase('test-
|
|
53
|
+
mockClient.updateDatabase.mockResolvedValue({ ...mockDatabase, ...updateData });
|
|
54
|
+
const result = await resources.updateDatabase('test-uuid', updateData);
|
|
55
55
|
expect(result).toEqual({ ...mockDatabase, ...updateData });
|
|
56
|
-
expect(mockClient.updateDatabase).toHaveBeenCalledWith('test-
|
|
56
|
+
expect(mockClient.updateDatabase).toHaveBeenCalledWith('test-uuid', updateData);
|
|
57
57
|
});
|
|
58
58
|
});
|
|
59
59
|
describe('deleteDatabase', () => {
|
|
60
60
|
it('should delete a database', async () => {
|
|
61
|
-
const mockResponse = { message: 'Database deleted' };
|
|
62
|
-
mockClient.deleteDatabase
|
|
63
|
-
const
|
|
64
|
-
deleteConfigurations: true,
|
|
65
|
-
deleteVolumes: true,
|
|
66
|
-
};
|
|
67
|
-
const result = await resources.deleteDatabase('test-db-uuid', options);
|
|
61
|
+
const mockResponse = { message: 'Database deleted successfully' };
|
|
62
|
+
mockClient.deleteDatabase.mockResolvedValue(mockResponse);
|
|
63
|
+
const result = await resources.deleteDatabase('test-uuid', {});
|
|
68
64
|
expect(result).toEqual(mockResponse);
|
|
69
|
-
expect(mockClient.deleteDatabase).toHaveBeenCalledWith('test-
|
|
65
|
+
expect(mockClient.deleteDatabase).toHaveBeenCalledWith('test-uuid', {});
|
|
70
66
|
});
|
|
71
67
|
});
|
|
72
68
|
});
|
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const deployment_resources_js_1 = require("../../resources/deployment-resources.js");
|
|
4
|
-
const coolify_client_js_1 = require("../../lib/coolify-client.js");
|
|
1
|
+
import { DeploymentResources } from '../../resources/deployment-resources.js';
|
|
2
|
+
import { jest } from '@jest/globals';
|
|
5
3
|
jest.mock('../../lib/coolify-client.js');
|
|
6
4
|
describe('DeploymentResources', () => {
|
|
7
|
-
let resources;
|
|
8
5
|
let mockClient;
|
|
6
|
+
let resources;
|
|
9
7
|
const mockDeployment = {
|
|
10
8
|
id: 1,
|
|
11
|
-
uuid: 'test-
|
|
12
|
-
application_uuid: 'test-app-uuid',
|
|
9
|
+
uuid: 'test-uuid',
|
|
13
10
|
status: 'running',
|
|
14
|
-
created_at: '2024-
|
|
15
|
-
updated_at: '2024-
|
|
11
|
+
created_at: '2024-01-01',
|
|
12
|
+
updated_at: '2024-01-01',
|
|
13
|
+
application_uuid: 'app-uuid',
|
|
14
|
+
environment_uuid: 'env-uuid',
|
|
16
15
|
};
|
|
17
16
|
beforeEach(() => {
|
|
18
|
-
mockClient =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
resources = new deployment_resources_js_1.DeploymentResources(mockClient);
|
|
17
|
+
mockClient = {
|
|
18
|
+
deployApplication: jest.fn(),
|
|
19
|
+
};
|
|
20
|
+
resources = new DeploymentResources(mockClient);
|
|
23
21
|
});
|
|
24
22
|
describe('listDeployments', () => {
|
|
25
23
|
it('should throw not implemented error', async () => {
|
|
@@ -33,15 +31,16 @@ describe('DeploymentResources', () => {
|
|
|
33
31
|
});
|
|
34
32
|
describe('deploy', () => {
|
|
35
33
|
it('should deploy an application', async () => {
|
|
36
|
-
mockClient.deployApplication
|
|
37
|
-
const result = await resources.deploy({ uuid: 'test-
|
|
34
|
+
mockClient.deployApplication.mockResolvedValue(mockDeployment);
|
|
35
|
+
const result = await resources.deploy({ uuid: 'test-uuid' });
|
|
38
36
|
expect(result).toEqual(mockDeployment);
|
|
39
|
-
expect(mockClient.deployApplication).toHaveBeenCalledWith('test-
|
|
37
|
+
expect(mockClient.deployApplication).toHaveBeenCalledWith('test-uuid');
|
|
40
38
|
});
|
|
41
39
|
it('should handle deployment errors', async () => {
|
|
42
|
-
const error = new Error('
|
|
43
|
-
mockClient.deployApplication
|
|
44
|
-
await expect(resources.deploy({ uuid: 'test-
|
|
40
|
+
const error = new Error('Deployment failed');
|
|
41
|
+
mockClient.deployApplication.mockRejectedValue(error);
|
|
42
|
+
await expect(resources.deploy({ uuid: 'test-uuid' })).rejects.toThrow('Deployment failed');
|
|
43
|
+
expect(mockClient.deployApplication).toHaveBeenCalledWith('test-uuid');
|
|
45
44
|
});
|
|
46
45
|
});
|
|
47
46
|
});
|
|
@@ -1,65 +1,64 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const service_resources_js_1 = require("../../resources/service-resources.js");
|
|
4
|
-
const coolify_client_js_1 = require("../../lib/coolify-client.js");
|
|
1
|
+
import { ServiceResources } from '../../resources/service-resources.js';
|
|
2
|
+
import { jest } from '@jest/globals';
|
|
5
3
|
jest.mock('../../lib/coolify-client.js');
|
|
6
4
|
describe('ServiceResources', () => {
|
|
7
|
-
let resources;
|
|
8
5
|
let mockClient;
|
|
6
|
+
let resources;
|
|
9
7
|
const mockService = {
|
|
10
8
|
id: 1,
|
|
11
|
-
uuid: 'test-
|
|
9
|
+
uuid: 'test-uuid',
|
|
12
10
|
name: 'test-service',
|
|
13
|
-
description: '
|
|
11
|
+
description: 'test description',
|
|
14
12
|
type: 'code-server',
|
|
15
13
|
status: 'running',
|
|
16
|
-
created_at: '2024-
|
|
17
|
-
updated_at: '2024-
|
|
18
|
-
project_uuid: '
|
|
19
|
-
environment_name: '
|
|
20
|
-
environment_uuid: '
|
|
21
|
-
server_uuid: '
|
|
22
|
-
domains: ['test
|
|
14
|
+
created_at: '2024-01-01',
|
|
15
|
+
updated_at: '2024-01-01',
|
|
16
|
+
project_uuid: 'project-uuid',
|
|
17
|
+
environment_name: 'test-env',
|
|
18
|
+
environment_uuid: 'env-uuid',
|
|
19
|
+
server_uuid: 'server-uuid',
|
|
20
|
+
domains: ['test.com'],
|
|
23
21
|
};
|
|
24
22
|
beforeEach(() => {
|
|
25
|
-
mockClient =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
mockClient = {
|
|
24
|
+
listServices: jest.fn(),
|
|
25
|
+
getService: jest.fn(),
|
|
26
|
+
createService: jest.fn(),
|
|
27
|
+
deleteService: jest.fn(),
|
|
28
|
+
};
|
|
29
|
+
resources = new ServiceResources(mockClient);
|
|
30
30
|
});
|
|
31
31
|
describe('listServices', () => {
|
|
32
32
|
it('should return a list of services', async () => {
|
|
33
|
-
mockClient.listServices
|
|
33
|
+
mockClient.listServices.mockResolvedValue([mockService]);
|
|
34
34
|
const result = await resources.listServices();
|
|
35
35
|
expect(result).toEqual([mockService]);
|
|
36
36
|
expect(mockClient.listServices).toHaveBeenCalled();
|
|
37
37
|
});
|
|
38
38
|
});
|
|
39
39
|
describe('getService', () => {
|
|
40
|
-
it('should return a
|
|
41
|
-
mockClient.getService
|
|
42
|
-
const result = await resources.getService('test-
|
|
40
|
+
it('should return a service by uuid', async () => {
|
|
41
|
+
mockClient.getService.mockResolvedValue(mockService);
|
|
42
|
+
const result = await resources.getService('test-uuid');
|
|
43
43
|
expect(result).toEqual(mockService);
|
|
44
|
-
expect(mockClient.getService).toHaveBeenCalledWith('test-
|
|
44
|
+
expect(mockClient.getService).toHaveBeenCalledWith('test-uuid');
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
describe('createService', () => {
|
|
48
|
-
it('should create a service', async () => {
|
|
48
|
+
it('should create a new service', async () => {
|
|
49
49
|
const createData = {
|
|
50
|
+
name: 'new-service',
|
|
50
51
|
type: 'code-server',
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
server_uuid: 'test-server-uuid',
|
|
56
|
-
instant_deploy: true,
|
|
52
|
+
project_uuid: 'project-uuid',
|
|
53
|
+
environment_name: 'test-env',
|
|
54
|
+
environment_uuid: 'env-uuid',
|
|
55
|
+
server_uuid: 'server-uuid',
|
|
57
56
|
};
|
|
58
57
|
const mockResponse = {
|
|
59
|
-
uuid: '
|
|
60
|
-
domains: ['
|
|
58
|
+
uuid: 'new-uuid',
|
|
59
|
+
domains: ['new-service.test.com'],
|
|
61
60
|
};
|
|
62
|
-
mockClient.createService
|
|
61
|
+
mockClient.createService.mockResolvedValue(mockResponse);
|
|
63
62
|
const result = await resources.createService(createData);
|
|
64
63
|
expect(result).toEqual(mockResponse);
|
|
65
64
|
expect(mockClient.createService).toHaveBeenCalledWith(createData);
|
|
@@ -68,14 +67,10 @@ describe('ServiceResources', () => {
|
|
|
68
67
|
describe('deleteService', () => {
|
|
69
68
|
it('should delete a service', async () => {
|
|
70
69
|
const mockResponse = { message: 'Service deleted' };
|
|
71
|
-
mockClient.deleteService
|
|
72
|
-
const
|
|
73
|
-
deleteConfigurations: true,
|
|
74
|
-
deleteVolumes: true,
|
|
75
|
-
};
|
|
76
|
-
const result = await resources.deleteService('test-service-uuid', options);
|
|
70
|
+
mockClient.deleteService.mockResolvedValue(mockResponse);
|
|
71
|
+
const result = await resources.deleteService('test-uuid');
|
|
77
72
|
expect(result).toEqual(mockResponse);
|
|
78
|
-
expect(mockClient.deleteService).toHaveBeenCalledWith('test-
|
|
73
|
+
expect(mockClient.deleteService).toHaveBeenCalledWith('test-uuid', undefined);
|
|
79
74
|
});
|
|
80
75
|
});
|
|
81
76
|
});
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
5
|
-
const mcp_server_js_1 = require("./lib/mcp-server.js");
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { CoolifyMcpServer } from './lib/mcp-server.js';
|
|
6
4
|
async function main() {
|
|
7
5
|
const config = {
|
|
8
6
|
baseUrl: process.env.COOLIFY_BASE_URL || 'http://localhost:3000',
|
|
@@ -11,8 +9,8 @@ async function main() {
|
|
|
11
9
|
if (!config.accessToken) {
|
|
12
10
|
throw new Error('COOLIFY_ACCESS_TOKEN environment variable is required');
|
|
13
11
|
}
|
|
14
|
-
const server = new
|
|
15
|
-
const transport = new
|
|
12
|
+
const server = new CoolifyMcpServer(config);
|
|
13
|
+
const transport = new StdioServerTransport();
|
|
16
14
|
await server.start(transport);
|
|
17
15
|
}
|
|
18
16
|
main().catch((error) => {
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CoolifyClient = void 0;
|
|
4
|
-
class CoolifyClient {
|
|
1
|
+
export class CoolifyClient {
|
|
5
2
|
constructor(config) {
|
|
6
3
|
if (!config.baseUrl) {
|
|
7
4
|
throw new Error('Coolify base URL is required');
|
|
@@ -160,4 +157,3 @@ class CoolifyClient {
|
|
|
160
157
|
});
|
|
161
158
|
}
|
|
162
159
|
}
|
|
163
|
-
exports.CoolifyClient = CoolifyClient;
|
package/dist/lib/mcp-server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Transport } from '@modelcontextprotocol/sdk/shared/transport';
|
|
1
|
+
import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
2
2
|
import { CoolifyConfig, ServerInfo, ServerResources, ServerDomain, ValidationResponse, Project, CreateProjectRequest, UpdateProjectRequest, Environment, Deployment, Database, DatabaseUpdateRequest, Service, CreateServiceRequest, DeleteServiceOptions } from '../types/coolify.js';
|
|
3
3
|
export declare class CoolifyMcpServer {
|
|
4
4
|
private server;
|
|
@@ -8,7 +8,7 @@ export declare class CoolifyMcpServer {
|
|
|
8
8
|
private applicationResources;
|
|
9
9
|
private serviceResources;
|
|
10
10
|
constructor(config: CoolifyConfig);
|
|
11
|
-
private
|
|
11
|
+
private setupHandlers;
|
|
12
12
|
start(transport: Transport): Promise<void>;
|
|
13
13
|
list_servers(): Promise<ServerInfo[]>;
|
|
14
14
|
get_server(uuid: string): Promise<ServerInfo>;
|