@masonator/coolify-mcp 1.1.1 → 1.6.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/README.md +48 -18
- package/dist/__tests__/coolify-client.test.js +83 -2
- package/dist/__tests__/mcp-server.test.js +81 -0
- package/dist/lib/coolify-client.d.ts +10 -2
- package/dist/lib/coolify-client.js +51 -2
- package/dist/lib/mcp-server.js +78 -3
- package/dist/types/coolify.d.ts +66 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,26 +1,35 @@
|
|
|
1
1
|
# Coolify MCP Server
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@masonator/coolify-mcp)
|
|
4
|
+
[](https://www.npmjs.com/package/@masonator/coolify-mcp)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
[](https://github.com/StuMason/coolify-mcp/actions/workflows/ci.yml)
|
|
9
|
+
[](https://codecov.io/gh/StuMason/coolify-mcp)
|
|
3
10
|
[](https://mseep.ai/app/stumason-coolify-mcp)
|
|
4
11
|
|
|
12
|
+
> **The most comprehensive MCP server for Coolify** - 75 tools, 7 workflow prompts, smart diagnostics, and batch operations for managing your self-hosted PaaS through AI assistants.
|
|
13
|
+
|
|
5
14
|
A Model Context Protocol (MCP) server for [Coolify](https://coolify.io/), enabling AI assistants to manage and debug your Coolify instances through natural language.
|
|
6
15
|
|
|
7
16
|
## Features
|
|
8
17
|
|
|
9
|
-
This MCP server provides **
|
|
10
|
-
|
|
11
|
-
| Category | Tools
|
|
12
|
-
| -------------------- |
|
|
13
|
-
| **Infrastructure** | overview, mcp_version (all resources at once)
|
|
14
|
-
| **Diagnostics** | diagnose_app, diagnose_server, find_issues (smart lookup by name/domain/IP)
|
|
15
|
-
| **Batch Operations** | restart_project_apps, bulk_env_update, stop_all_apps, redeploy_project
|
|
16
|
-
| **Servers** | list, get, validate, resources, domains
|
|
17
|
-
| **Projects** | list, get, create, update, delete
|
|
18
|
-
| **Environments** | list, get, create, delete
|
|
19
|
-
| **Applications** | list, get, update, delete, start, stop, restart, logs, env vars (CRUD), create (private-gh, private-key)
|
|
20
|
-
| **Databases** | list, get, delete, start, stop, restart, backups (list, get), backup executions (list, get)
|
|
21
|
-
| **Services** | list, get, create, update, delete, start, stop, restart, env vars (list, create, delete)
|
|
22
|
-
| **Deployments** | list, get, deploy, cancel, list by application
|
|
23
|
-
| **Private Keys** | list, get, create, update, delete
|
|
18
|
+
This MCP server provides **75 tools** and **7 workflow prompts** for **debugging, management, and deployment**:
|
|
19
|
+
|
|
20
|
+
| Category | Tools |
|
|
21
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
22
|
+
| **Infrastructure** | overview, mcp_version (all resources at once) |
|
|
23
|
+
| **Diagnostics** | diagnose_app, diagnose_server, find_issues (smart lookup by name/domain/IP) |
|
|
24
|
+
| **Batch Operations** | restart_project_apps, bulk_env_update, stop_all_apps, redeploy_project |
|
|
25
|
+
| **Servers** | list, get, validate, resources, domains |
|
|
26
|
+
| **Projects** | list, get, create, update, delete |
|
|
27
|
+
| **Environments** | list, get, create, delete |
|
|
28
|
+
| **Applications** | list, get, update, delete, start, stop, restart, logs, env vars (CRUD), create (private-gh, private-key) |
|
|
29
|
+
| **Databases** | list, get, create (8 types), delete, start, stop, restart, backups (list, get), backup executions (list, get) |
|
|
30
|
+
| **Services** | list, get, create, update, delete, start, stop, restart, env vars (list, create, delete) |
|
|
31
|
+
| **Deployments** | list, get, deploy, cancel, list by application |
|
|
32
|
+
| **Private Keys** | list, get, create, update, delete |
|
|
24
33
|
|
|
25
34
|
### Workflow Prompts
|
|
26
35
|
|
|
@@ -297,15 +306,36 @@ Power user tools for operating on multiple resources at once:
|
|
|
297
306
|
- `stop_all_apps` - Emergency stop all running applications (requires confirmation)
|
|
298
307
|
- `redeploy_project` - Redeploy all applications in a project with force rebuild
|
|
299
308
|
|
|
309
|
+
## Why Coolify MCP?
|
|
310
|
+
|
|
311
|
+
- **Context-Optimized**: Responses are 90-99% smaller than raw API, preventing context window exhaustion
|
|
312
|
+
- **Smart Lookup**: Find apps by domain (`stuartmason.co.uk`), servers by IP, not just UUIDs
|
|
313
|
+
- **Batch Operations**: Restart entire projects, bulk update env vars, emergency stop all apps
|
|
314
|
+
- **Workflow Prompts**: Pre-built guided workflows for common tasks
|
|
315
|
+
- **Production Ready**: 98%+ test coverage, TypeScript strict mode, comprehensive error handling
|
|
316
|
+
- **Always Current**: Weekly OpenAPI drift detection ensures we stay in sync with Coolify
|
|
317
|
+
|
|
318
|
+
## Related Links
|
|
319
|
+
|
|
320
|
+
- [Coolify](https://coolify.io/) - The open-source & self-hostable Heroku/Netlify/Vercel alternative
|
|
321
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/) - The protocol powering AI tool integrations
|
|
322
|
+
- [MCP Server Registry](https://github.com/modelcontextprotocol/servers) - Official MCP server directory
|
|
323
|
+
|
|
300
324
|
## Contributing
|
|
301
325
|
|
|
302
|
-
Contributions welcome! Please
|
|
326
|
+
Contributions welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
303
327
|
|
|
304
328
|
## License
|
|
305
329
|
|
|
306
|
-
MIT
|
|
330
|
+
MIT - see [LICENSE](LICENSE) for details.
|
|
307
331
|
|
|
308
332
|
## Support
|
|
309
333
|
|
|
310
|
-
- [GitHub Issues](https://github.com/
|
|
334
|
+
- [GitHub Issues](https://github.com/StuMason/coolify-mcp/issues)
|
|
311
335
|
- [Coolify Community](https://coolify.io/docs/contact)
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
<p align="center">
|
|
340
|
+
<strong>If you find this useful, please ⭐ star the repo!</strong>
|
|
341
|
+
</p>
|
|
@@ -495,9 +495,9 @@ describe('CoolifyClient', () => {
|
|
|
495
495
|
});
|
|
496
496
|
it('should delete a project environment', async () => {
|
|
497
497
|
mockFetch.mockResolvedValueOnce(mockResponse({ message: 'Deleted' }));
|
|
498
|
-
const result = await client.deleteProjectEnvironment('env-uuid');
|
|
498
|
+
const result = await client.deleteProjectEnvironment('project-uuid', 'env-uuid');
|
|
499
499
|
expect(result).toEqual({ message: 'Deleted' });
|
|
500
|
-
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/projects/environments/env-uuid', expect.objectContaining({ method: 'DELETE' }));
|
|
500
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/projects/project-uuid/environments/env-uuid', expect.objectContaining({ method: 'DELETE' }));
|
|
501
501
|
});
|
|
502
502
|
});
|
|
503
503
|
// =========================================================================
|
|
@@ -794,6 +794,87 @@ describe('CoolifyClient', () => {
|
|
|
794
794
|
expect(result).toEqual(mockExecution);
|
|
795
795
|
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/db-uuid/backups/backup-uuid/executions/exec-uuid', expect.any(Object));
|
|
796
796
|
});
|
|
797
|
+
it('should create a PostgreSQL database', async () => {
|
|
798
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'pg-uuid' }));
|
|
799
|
+
const result = await client.createPostgresql({
|
|
800
|
+
server_uuid: 'server-uuid',
|
|
801
|
+
project_uuid: 'project-uuid',
|
|
802
|
+
environment_name: 'production',
|
|
803
|
+
postgres_user: 'myuser',
|
|
804
|
+
postgres_db: 'mydb',
|
|
805
|
+
});
|
|
806
|
+
expect(result).toEqual({ uuid: 'pg-uuid' });
|
|
807
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/postgresql', expect.objectContaining({ method: 'POST' }));
|
|
808
|
+
});
|
|
809
|
+
it('should create a MySQL database', async () => {
|
|
810
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'mysql-uuid' }));
|
|
811
|
+
const result = await client.createMysql({
|
|
812
|
+
server_uuid: 'server-uuid',
|
|
813
|
+
project_uuid: 'project-uuid',
|
|
814
|
+
mysql_user: 'myuser',
|
|
815
|
+
mysql_database: 'mydb',
|
|
816
|
+
});
|
|
817
|
+
expect(result).toEqual({ uuid: 'mysql-uuid' });
|
|
818
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/mysql', expect.objectContaining({ method: 'POST' }));
|
|
819
|
+
});
|
|
820
|
+
it('should create a MariaDB database', async () => {
|
|
821
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'mariadb-uuid' }));
|
|
822
|
+
const result = await client.createMariadb({
|
|
823
|
+
server_uuid: 'server-uuid',
|
|
824
|
+
project_uuid: 'project-uuid',
|
|
825
|
+
});
|
|
826
|
+
expect(result).toEqual({ uuid: 'mariadb-uuid' });
|
|
827
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/mariadb', expect.objectContaining({ method: 'POST' }));
|
|
828
|
+
});
|
|
829
|
+
it('should create a MongoDB database', async () => {
|
|
830
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'mongo-uuid' }));
|
|
831
|
+
const result = await client.createMongodb({
|
|
832
|
+
server_uuid: 'server-uuid',
|
|
833
|
+
project_uuid: 'project-uuid',
|
|
834
|
+
mongo_initdb_root_username: 'admin',
|
|
835
|
+
});
|
|
836
|
+
expect(result).toEqual({ uuid: 'mongo-uuid' });
|
|
837
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/mongodb', expect.objectContaining({ method: 'POST' }));
|
|
838
|
+
});
|
|
839
|
+
it('should create a Redis database', async () => {
|
|
840
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'redis-uuid' }));
|
|
841
|
+
const result = await client.createRedis({
|
|
842
|
+
server_uuid: 'server-uuid',
|
|
843
|
+
project_uuid: 'project-uuid',
|
|
844
|
+
redis_password: 'secret',
|
|
845
|
+
});
|
|
846
|
+
expect(result).toEqual({ uuid: 'redis-uuid' });
|
|
847
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/redis', expect.objectContaining({ method: 'POST' }));
|
|
848
|
+
});
|
|
849
|
+
it('should create a KeyDB database', async () => {
|
|
850
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'keydb-uuid' }));
|
|
851
|
+
const result = await client.createKeydb({
|
|
852
|
+
server_uuid: 'server-uuid',
|
|
853
|
+
project_uuid: 'project-uuid',
|
|
854
|
+
});
|
|
855
|
+
expect(result).toEqual({ uuid: 'keydb-uuid' });
|
|
856
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/keydb', expect.objectContaining({ method: 'POST' }));
|
|
857
|
+
});
|
|
858
|
+
it('should create a ClickHouse database', async () => {
|
|
859
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'clickhouse-uuid' }));
|
|
860
|
+
const result = await client.createClickhouse({
|
|
861
|
+
server_uuid: 'server-uuid',
|
|
862
|
+
project_uuid: 'project-uuid',
|
|
863
|
+
clickhouse_admin_user: 'admin',
|
|
864
|
+
});
|
|
865
|
+
expect(result).toEqual({ uuid: 'clickhouse-uuid' });
|
|
866
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/clickhouse', expect.objectContaining({ method: 'POST' }));
|
|
867
|
+
});
|
|
868
|
+
it('should create a Dragonfly database', async () => {
|
|
869
|
+
mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'dragonfly-uuid' }));
|
|
870
|
+
const result = await client.createDragonfly({
|
|
871
|
+
server_uuid: 'server-uuid',
|
|
872
|
+
project_uuid: 'project-uuid',
|
|
873
|
+
dragonfly_password: 'secret',
|
|
874
|
+
});
|
|
875
|
+
expect(result).toEqual({ uuid: 'dragonfly-uuid' });
|
|
876
|
+
expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/databases/dragonfly', expect.objectContaining({ method: 'POST' }));
|
|
877
|
+
});
|
|
797
878
|
});
|
|
798
879
|
// =========================================================================
|
|
799
880
|
// Service endpoints - extended coverage
|
|
@@ -16,6 +16,14 @@ const mockDiagnoseApplication = jest.fn();
|
|
|
16
16
|
const mockDiagnoseServer = jest.fn();
|
|
17
17
|
const mockFindInfrastructureIssues = jest.fn();
|
|
18
18
|
const mockDeleteDatabase = jest.fn();
|
|
19
|
+
const mockCreatePostgresql = jest.fn();
|
|
20
|
+
const mockCreateMysql = jest.fn();
|
|
21
|
+
const mockCreateMariadb = jest.fn();
|
|
22
|
+
const mockCreateMongodb = jest.fn();
|
|
23
|
+
const mockCreateRedis = jest.fn();
|
|
24
|
+
const mockCreateKeydb = jest.fn();
|
|
25
|
+
const mockCreateClickhouse = jest.fn();
|
|
26
|
+
const mockCreateDragonfly = jest.fn();
|
|
19
27
|
// Mock the CoolifyClient module
|
|
20
28
|
jest.mock('../lib/coolify-client.js', () => ({
|
|
21
29
|
CoolifyClient: jest.fn().mockImplementation(() => ({
|
|
@@ -28,6 +36,14 @@ jest.mock('../lib/coolify-client.js', () => ({
|
|
|
28
36
|
diagnoseServer: mockDiagnoseServer,
|
|
29
37
|
findInfrastructureIssues: mockFindInfrastructureIssues,
|
|
30
38
|
deleteDatabase: mockDeleteDatabase,
|
|
39
|
+
createPostgresql: mockCreatePostgresql,
|
|
40
|
+
createMysql: mockCreateMysql,
|
|
41
|
+
createMariadb: mockCreateMariadb,
|
|
42
|
+
createMongodb: mockCreateMongodb,
|
|
43
|
+
createRedis: mockCreateRedis,
|
|
44
|
+
createKeydb: mockCreateKeydb,
|
|
45
|
+
createClickhouse: mockCreateClickhouse,
|
|
46
|
+
createDragonfly: mockCreateDragonfly,
|
|
31
47
|
getVersion: jest.fn(),
|
|
32
48
|
})),
|
|
33
49
|
}));
|
|
@@ -317,6 +333,71 @@ describe('CoolifyMcpServer', () => {
|
|
|
317
333
|
expect(mockDeleteDatabase).toHaveBeenCalledWith('db-uuid-123', { deleteVolumes: true });
|
|
318
334
|
});
|
|
319
335
|
});
|
|
336
|
+
describe('database creation tools', () => {
|
|
337
|
+
const baseParams = {
|
|
338
|
+
server_uuid: 'server-uuid',
|
|
339
|
+
project_uuid: 'project-uuid',
|
|
340
|
+
environment_name: 'production',
|
|
341
|
+
};
|
|
342
|
+
it('should call createPostgresql with correct params', async () => {
|
|
343
|
+
mockCreatePostgresql.mockResolvedValue({ uuid: 'pg-uuid' });
|
|
344
|
+
await mockCreatePostgresql({ ...baseParams, postgres_user: 'myuser' });
|
|
345
|
+
expect(mockCreatePostgresql).toHaveBeenCalledWith({
|
|
346
|
+
...baseParams,
|
|
347
|
+
postgres_user: 'myuser',
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
it('should call createMysql with correct params', async () => {
|
|
351
|
+
mockCreateMysql.mockResolvedValue({ uuid: 'mysql-uuid' });
|
|
352
|
+
await mockCreateMysql({ ...baseParams, mysql_user: 'myuser' });
|
|
353
|
+
expect(mockCreateMysql).toHaveBeenCalledWith({
|
|
354
|
+
...baseParams,
|
|
355
|
+
mysql_user: 'myuser',
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
it('should call createMariadb with correct params', async () => {
|
|
359
|
+
mockCreateMariadb.mockResolvedValue({ uuid: 'mariadb-uuid' });
|
|
360
|
+
await mockCreateMariadb(baseParams);
|
|
361
|
+
expect(mockCreateMariadb).toHaveBeenCalledWith(baseParams);
|
|
362
|
+
});
|
|
363
|
+
it('should call createMongodb with correct params', async () => {
|
|
364
|
+
mockCreateMongodb.mockResolvedValue({ uuid: 'mongo-uuid' });
|
|
365
|
+
await mockCreateMongodb({ ...baseParams, mongo_initdb_root_username: 'admin' });
|
|
366
|
+
expect(mockCreateMongodb).toHaveBeenCalledWith({
|
|
367
|
+
...baseParams,
|
|
368
|
+
mongo_initdb_root_username: 'admin',
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
it('should call createRedis with correct params', async () => {
|
|
372
|
+
mockCreateRedis.mockResolvedValue({ uuid: 'redis-uuid' });
|
|
373
|
+
await mockCreateRedis({ ...baseParams, redis_password: 'secret' });
|
|
374
|
+
expect(mockCreateRedis).toHaveBeenCalledWith({
|
|
375
|
+
...baseParams,
|
|
376
|
+
redis_password: 'secret',
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
it('should call createKeydb with correct params', async () => {
|
|
380
|
+
mockCreateKeydb.mockResolvedValue({ uuid: 'keydb-uuid' });
|
|
381
|
+
await mockCreateKeydb(baseParams);
|
|
382
|
+
expect(mockCreateKeydb).toHaveBeenCalledWith(baseParams);
|
|
383
|
+
});
|
|
384
|
+
it('should call createClickhouse with correct params', async () => {
|
|
385
|
+
mockCreateClickhouse.mockResolvedValue({ uuid: 'clickhouse-uuid' });
|
|
386
|
+
await mockCreateClickhouse({ ...baseParams, clickhouse_admin_user: 'admin' });
|
|
387
|
+
expect(mockCreateClickhouse).toHaveBeenCalledWith({
|
|
388
|
+
...baseParams,
|
|
389
|
+
clickhouse_admin_user: 'admin',
|
|
390
|
+
});
|
|
391
|
+
});
|
|
392
|
+
it('should call createDragonfly with correct params', async () => {
|
|
393
|
+
mockCreateDragonfly.mockResolvedValue({ uuid: 'dragonfly-uuid' });
|
|
394
|
+
await mockCreateDragonfly({ ...baseParams, dragonfly_password: 'secret' });
|
|
395
|
+
expect(mockCreateDragonfly).toHaveBeenCalledWith({
|
|
396
|
+
...baseParams,
|
|
397
|
+
dragonfly_password: 'secret',
|
|
398
|
+
});
|
|
399
|
+
});
|
|
400
|
+
});
|
|
320
401
|
});
|
|
321
402
|
describe('version tools', () => {
|
|
322
403
|
it('get_mcp_version should return correct version format', () => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Coolify API Client
|
|
3
3
|
* Complete HTTP client for the Coolify API v1
|
|
4
4
|
*/
|
|
5
|
-
import type { CoolifyConfig, DeleteOptions, MessageResponse, UuidResponse, Server, ServerResource, ServerDomain, ServerValidation, CreateServerRequest, UpdateServerRequest, Project, CreateProjectRequest, UpdateProjectRequest, Environment, CreateEnvironmentRequest, Application, CreateApplicationPublicRequest, CreateApplicationPrivateGHRequest, CreateApplicationPrivateKeyRequest, CreateApplicationDockerfileRequest, CreateApplicationDockerImageRequest, CreateApplicationDockerComposeRequest, UpdateApplicationRequest, ApplicationActionResponse, EnvironmentVariable, EnvVarSummary, CreateEnvVarRequest, UpdateEnvVarRequest, BulkUpdateEnvVarsRequest, Database, UpdateDatabaseRequest, DatabaseBackup, BackupExecution, Service, CreateServiceRequest, UpdateServiceRequest, ServiceCreateResponse, Deployment, Team, TeamMember, PrivateKey, CreatePrivateKeyRequest, UpdatePrivateKeyRequest, CloudToken, CreateCloudTokenRequest, UpdateCloudTokenRequest, CloudTokenValidation, Version, ApplicationDiagnostic, ServerDiagnostic, InfrastructureIssuesReport, BatchOperationResult } from '../types/coolify.js';
|
|
5
|
+
import type { CoolifyConfig, DeleteOptions, MessageResponse, UuidResponse, Server, ServerResource, ServerDomain, ServerValidation, CreateServerRequest, UpdateServerRequest, Project, CreateProjectRequest, UpdateProjectRequest, Environment, CreateEnvironmentRequest, Application, CreateApplicationPublicRequest, CreateApplicationPrivateGHRequest, CreateApplicationPrivateKeyRequest, CreateApplicationDockerfileRequest, CreateApplicationDockerImageRequest, CreateApplicationDockerComposeRequest, UpdateApplicationRequest, ApplicationActionResponse, EnvironmentVariable, EnvVarSummary, CreateEnvVarRequest, UpdateEnvVarRequest, BulkUpdateEnvVarsRequest, Database, UpdateDatabaseRequest, CreatePostgresqlRequest, CreateMysqlRequest, CreateMariadbRequest, CreateMongodbRequest, CreateRedisRequest, CreateKeydbRequest, CreateClickhouseRequest, CreateDragonflyRequest, CreateDatabaseResponse, DatabaseBackup, BackupExecution, Service, CreateServiceRequest, UpdateServiceRequest, ServiceCreateResponse, Deployment, Team, TeamMember, PrivateKey, CreatePrivateKeyRequest, UpdatePrivateKeyRequest, CloudToken, CreateCloudTokenRequest, UpdateCloudTokenRequest, CloudTokenValidation, Version, ApplicationDiagnostic, ServerDiagnostic, InfrastructureIssuesReport, BatchOperationResult } from '../types/coolify.js';
|
|
6
6
|
export interface ListOptions {
|
|
7
7
|
page?: number;
|
|
8
8
|
per_page?: number;
|
|
@@ -82,7 +82,7 @@ export declare class CoolifyClient {
|
|
|
82
82
|
listProjectEnvironments(projectUuid: string): Promise<Environment[]>;
|
|
83
83
|
getProjectEnvironment(projectUuid: string, environmentNameOrUuid: string): Promise<Environment>;
|
|
84
84
|
createProjectEnvironment(projectUuid: string, data: CreateEnvironmentRequest): Promise<UuidResponse>;
|
|
85
|
-
deleteProjectEnvironment(
|
|
85
|
+
deleteProjectEnvironment(projectUuid: string, environmentNameOrUuid: string): Promise<MessageResponse>;
|
|
86
86
|
listApplications(options?: ListOptions): Promise<Application[] | ApplicationSummary[]>;
|
|
87
87
|
getApplication(uuid: string): Promise<Application>;
|
|
88
88
|
createApplicationPublic(data: CreateApplicationPublicRequest): Promise<UuidResponse>;
|
|
@@ -114,6 +114,14 @@ export declare class CoolifyClient {
|
|
|
114
114
|
startDatabase(uuid: string): Promise<MessageResponse>;
|
|
115
115
|
stopDatabase(uuid: string): Promise<MessageResponse>;
|
|
116
116
|
restartDatabase(uuid: string): Promise<MessageResponse>;
|
|
117
|
+
createPostgresql(data: CreatePostgresqlRequest): Promise<CreateDatabaseResponse>;
|
|
118
|
+
createMysql(data: CreateMysqlRequest): Promise<CreateDatabaseResponse>;
|
|
119
|
+
createMariadb(data: CreateMariadbRequest): Promise<CreateDatabaseResponse>;
|
|
120
|
+
createMongodb(data: CreateMongodbRequest): Promise<CreateDatabaseResponse>;
|
|
121
|
+
createRedis(data: CreateRedisRequest): Promise<CreateDatabaseResponse>;
|
|
122
|
+
createKeydb(data: CreateKeydbRequest): Promise<CreateDatabaseResponse>;
|
|
123
|
+
createClickhouse(data: CreateClickhouseRequest): Promise<CreateDatabaseResponse>;
|
|
124
|
+
createDragonfly(data: CreateDragonflyRequest): Promise<CreateDatabaseResponse>;
|
|
117
125
|
listServices(options?: ListOptions): Promise<Service[] | ServiceSummary[]>;
|
|
118
126
|
getService(uuid: string): Promise<Service>;
|
|
119
127
|
createService(data: CreateServiceRequest): Promise<ServiceCreateResponse>;
|
|
@@ -244,8 +244,8 @@ export class CoolifyClient {
|
|
|
244
244
|
body: JSON.stringify(data),
|
|
245
245
|
});
|
|
246
246
|
}
|
|
247
|
-
async deleteProjectEnvironment(
|
|
248
|
-
return this.request(`/projects/environments/${
|
|
247
|
+
async deleteProjectEnvironment(projectUuid, environmentNameOrUuid) {
|
|
248
|
+
return this.request(`/projects/${projectUuid}/environments/${environmentNameOrUuid}`, {
|
|
249
249
|
method: 'DELETE',
|
|
250
250
|
});
|
|
251
251
|
}
|
|
@@ -414,6 +414,55 @@ export class CoolifyClient {
|
|
|
414
414
|
method: 'POST',
|
|
415
415
|
});
|
|
416
416
|
}
|
|
417
|
+
// Database creation methods
|
|
418
|
+
async createPostgresql(data) {
|
|
419
|
+
return this.request('/databases/postgresql', {
|
|
420
|
+
method: 'POST',
|
|
421
|
+
body: JSON.stringify(data),
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
async createMysql(data) {
|
|
425
|
+
return this.request('/databases/mysql', {
|
|
426
|
+
method: 'POST',
|
|
427
|
+
body: JSON.stringify(data),
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
async createMariadb(data) {
|
|
431
|
+
return this.request('/databases/mariadb', {
|
|
432
|
+
method: 'POST',
|
|
433
|
+
body: JSON.stringify(data),
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
async createMongodb(data) {
|
|
437
|
+
return this.request('/databases/mongodb', {
|
|
438
|
+
method: 'POST',
|
|
439
|
+
body: JSON.stringify(data),
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
async createRedis(data) {
|
|
443
|
+
return this.request('/databases/redis', {
|
|
444
|
+
method: 'POST',
|
|
445
|
+
body: JSON.stringify(data),
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
async createKeydb(data) {
|
|
449
|
+
return this.request('/databases/keydb', {
|
|
450
|
+
method: 'POST',
|
|
451
|
+
body: JSON.stringify(data),
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
async createClickhouse(data) {
|
|
455
|
+
return this.request('/databases/clickhouse', {
|
|
456
|
+
method: 'POST',
|
|
457
|
+
body: JSON.stringify(data),
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
async createDragonfly(data) {
|
|
461
|
+
return this.request('/databases/dragonfly', {
|
|
462
|
+
method: 'POST',
|
|
463
|
+
body: JSON.stringify(data),
|
|
464
|
+
});
|
|
465
|
+
}
|
|
417
466
|
// ===========================================================================
|
|
418
467
|
// Service endpoints
|
|
419
468
|
// ===========================================================================
|
package/dist/lib/mcp-server.js
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
21
21
|
import { z } from 'zod';
|
|
22
22
|
import { CoolifyClient, } from './coolify-client.js';
|
|
23
|
-
const VERSION = '1.
|
|
23
|
+
const VERSION = '1.6.0';
|
|
24
24
|
/** Wrap tool handler with consistent error handling */
|
|
25
25
|
function wrapHandler(fn) {
|
|
26
26
|
return fn()
|
|
@@ -146,7 +146,10 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
146
146
|
name: z.string().describe('Environment name'),
|
|
147
147
|
description: z.string().optional().describe('Description'),
|
|
148
148
|
}, async ({ project_uuid, ...data }) => wrapHandler(() => this.client.createProjectEnvironment(project_uuid, data)));
|
|
149
|
-
this.tool('delete_environment', 'Delete an environment
|
|
149
|
+
this.tool('delete_environment', 'Delete an environment. Environment must be empty (no resources).', {
|
|
150
|
+
project_uuid: z.string().describe('Project UUID'),
|
|
151
|
+
environment_name_or_uuid: z.string().describe('Environment name or UUID'),
|
|
152
|
+
}, async ({ project_uuid, environment_name_or_uuid }) => wrapHandler(() => this.client.deleteProjectEnvironment(project_uuid, environment_name_or_uuid)));
|
|
150
153
|
// =========================================================================
|
|
151
154
|
// Applications (15 tools)
|
|
152
155
|
// =========================================================================
|
|
@@ -219,7 +222,7 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
219
222
|
env_uuid: z.string().describe('Env variable UUID'),
|
|
220
223
|
}, async ({ uuid, env_uuid }) => wrapHandler(() => this.client.deleteApplicationEnvVar(uuid, env_uuid)));
|
|
221
224
|
// =========================================================================
|
|
222
|
-
// Databases (
|
|
225
|
+
// Databases (14 tools)
|
|
223
226
|
// =========================================================================
|
|
224
227
|
this.tool('list_databases', 'List all databases (returns summary: uuid, name, type, status). Use get_database for full details.', {
|
|
225
228
|
page: z.number().optional().describe('Page number for pagination'),
|
|
@@ -233,6 +236,78 @@ export class CoolifyMcpServer extends McpServer {
|
|
|
233
236
|
uuid: z.string().describe('Database UUID'),
|
|
234
237
|
delete_volumes: z.boolean().optional().describe('Delete volumes (default: false)'),
|
|
235
238
|
}, async ({ uuid, delete_volumes }) => wrapHandler(() => this.client.deleteDatabase(uuid, { deleteVolumes: delete_volumes })));
|
|
239
|
+
// Database creation tools - shared schema for base fields
|
|
240
|
+
const databaseBaseSchema = {
|
|
241
|
+
server_uuid: z.string().describe('Server UUID'),
|
|
242
|
+
project_uuid: z.string().describe('Project UUID'),
|
|
243
|
+
environment_name: z.string().optional().describe('Environment name'),
|
|
244
|
+
environment_uuid: z.string().optional().describe('Environment UUID'),
|
|
245
|
+
destination_uuid: z.string().optional().describe('Destination UUID'),
|
|
246
|
+
name: z.string().optional().describe('Database name'),
|
|
247
|
+
description: z.string().optional().describe('Database description'),
|
|
248
|
+
image: z.string().optional().describe('Docker image'),
|
|
249
|
+
is_public: z.boolean().optional().describe('Make database publicly accessible'),
|
|
250
|
+
public_port: z.number().optional().describe('Public port'),
|
|
251
|
+
limits_memory: z.string().optional().describe('Memory limit'),
|
|
252
|
+
limits_memory_swap: z.string().optional().describe('Memory swap limit'),
|
|
253
|
+
limits_memory_swappiness: z.number().optional().describe('Memory swappiness'),
|
|
254
|
+
limits_memory_reservation: z.string().optional().describe('Memory reservation'),
|
|
255
|
+
limits_cpus: z.string().optional().describe('CPU limit'),
|
|
256
|
+
limits_cpuset: z.string().optional().describe('CPU set'),
|
|
257
|
+
limits_cpu_shares: z.number().optional().describe('CPU shares'),
|
|
258
|
+
instant_deploy: z.boolean().optional().describe('Deploy immediately after creation'),
|
|
259
|
+
};
|
|
260
|
+
this.tool('create_postgresql', 'Create a new PostgreSQL database', {
|
|
261
|
+
...databaseBaseSchema,
|
|
262
|
+
postgres_user: z.string().optional().describe('PostgreSQL user'),
|
|
263
|
+
postgres_password: z.string().optional().describe('PostgreSQL password'),
|
|
264
|
+
postgres_db: z.string().optional().describe('PostgreSQL database name'),
|
|
265
|
+
postgres_initdb_args: z.string().optional().describe('PostgreSQL initdb args'),
|
|
266
|
+
postgres_host_auth_method: z.string().optional().describe('PostgreSQL host auth method'),
|
|
267
|
+
postgres_conf: z.string().optional().describe('PostgreSQL configuration'),
|
|
268
|
+
}, async (args) => wrapHandler(() => this.client.createPostgresql(args)));
|
|
269
|
+
this.tool('create_mysql', 'Create a new MySQL database', {
|
|
270
|
+
...databaseBaseSchema,
|
|
271
|
+
mysql_root_password: z.string().optional().describe('MySQL root password'),
|
|
272
|
+
mysql_user: z.string().optional().describe('MySQL user'),
|
|
273
|
+
mysql_password: z.string().optional().describe('MySQL password'),
|
|
274
|
+
mysql_database: z.string().optional().describe('MySQL database name'),
|
|
275
|
+
mysql_conf: z.string().optional().describe('MySQL configuration'),
|
|
276
|
+
}, async (args) => wrapHandler(() => this.client.createMysql(args)));
|
|
277
|
+
this.tool('create_mariadb', 'Create a new MariaDB database', {
|
|
278
|
+
...databaseBaseSchema,
|
|
279
|
+
mariadb_root_password: z.string().optional().describe('MariaDB root password'),
|
|
280
|
+
mariadb_user: z.string().optional().describe('MariaDB user'),
|
|
281
|
+
mariadb_password: z.string().optional().describe('MariaDB password'),
|
|
282
|
+
mariadb_database: z.string().optional().describe('MariaDB database name'),
|
|
283
|
+
mariadb_conf: z.string().optional().describe('MariaDB configuration'),
|
|
284
|
+
}, async (args) => wrapHandler(() => this.client.createMariadb(args)));
|
|
285
|
+
this.tool('create_mongodb', 'Create a new MongoDB database', {
|
|
286
|
+
...databaseBaseSchema,
|
|
287
|
+
mongo_initdb_root_username: z.string().optional().describe('MongoDB root username'),
|
|
288
|
+
mongo_initdb_root_password: z.string().optional().describe('MongoDB root password'),
|
|
289
|
+
mongo_initdb_database: z.string().optional().describe('MongoDB database name'),
|
|
290
|
+
mongo_conf: z.string().optional().describe('MongoDB configuration'),
|
|
291
|
+
}, async (args) => wrapHandler(() => this.client.createMongodb(args)));
|
|
292
|
+
this.tool('create_redis', 'Create a new Redis database', {
|
|
293
|
+
...databaseBaseSchema,
|
|
294
|
+
redis_password: z.string().optional().describe('Redis password'),
|
|
295
|
+
redis_conf: z.string().optional().describe('Redis configuration'),
|
|
296
|
+
}, async (args) => wrapHandler(() => this.client.createRedis(args)));
|
|
297
|
+
this.tool('create_keydb', 'Create a new KeyDB database', {
|
|
298
|
+
...databaseBaseSchema,
|
|
299
|
+
keydb_password: z.string().optional().describe('KeyDB password'),
|
|
300
|
+
keydb_conf: z.string().optional().describe('KeyDB configuration'),
|
|
301
|
+
}, async (args) => wrapHandler(() => this.client.createKeydb(args)));
|
|
302
|
+
this.tool('create_clickhouse', 'Create a new ClickHouse database', {
|
|
303
|
+
...databaseBaseSchema,
|
|
304
|
+
clickhouse_admin_user: z.string().optional().describe('ClickHouse admin user'),
|
|
305
|
+
clickhouse_admin_password: z.string().optional().describe('ClickHouse admin password'),
|
|
306
|
+
}, async (args) => wrapHandler(() => this.client.createClickhouse(args)));
|
|
307
|
+
this.tool('create_dragonfly', 'Create a new Dragonfly database (Redis-compatible)', {
|
|
308
|
+
...databaseBaseSchema,
|
|
309
|
+
dragonfly_password: z.string().optional().describe('Dragonfly password'),
|
|
310
|
+
}, async (args) => wrapHandler(() => this.client.createDragonfly(args)));
|
|
236
311
|
// =========================================================================
|
|
237
312
|
// Services (11 tools)
|
|
238
313
|
// =========================================================================
|
package/dist/types/coolify.d.ts
CHANGED
|
@@ -451,6 +451,72 @@ export interface UpdateDatabaseRequest {
|
|
|
451
451
|
clickhouse_admin_password?: string;
|
|
452
452
|
dragonfly_password?: string;
|
|
453
453
|
}
|
|
454
|
+
export interface CreateDatabaseBaseRequest {
|
|
455
|
+
server_uuid: string;
|
|
456
|
+
project_uuid: string;
|
|
457
|
+
environment_name?: string;
|
|
458
|
+
environment_uuid?: string;
|
|
459
|
+
destination_uuid?: string;
|
|
460
|
+
name?: string;
|
|
461
|
+
description?: string;
|
|
462
|
+
image?: string;
|
|
463
|
+
is_public?: boolean;
|
|
464
|
+
public_port?: number;
|
|
465
|
+
limits_memory?: string;
|
|
466
|
+
limits_memory_swap?: string;
|
|
467
|
+
limits_memory_swappiness?: number;
|
|
468
|
+
limits_memory_reservation?: string;
|
|
469
|
+
limits_cpus?: string;
|
|
470
|
+
limits_cpuset?: string;
|
|
471
|
+
limits_cpu_shares?: number;
|
|
472
|
+
instant_deploy?: boolean;
|
|
473
|
+
}
|
|
474
|
+
export interface CreatePostgresqlRequest extends CreateDatabaseBaseRequest {
|
|
475
|
+
postgres_user?: string;
|
|
476
|
+
postgres_password?: string;
|
|
477
|
+
postgres_db?: string;
|
|
478
|
+
postgres_initdb_args?: string;
|
|
479
|
+
postgres_host_auth_method?: string;
|
|
480
|
+
postgres_conf?: string;
|
|
481
|
+
}
|
|
482
|
+
export interface CreateMysqlRequest extends CreateDatabaseBaseRequest {
|
|
483
|
+
mysql_root_password?: string;
|
|
484
|
+
mysql_user?: string;
|
|
485
|
+
mysql_password?: string;
|
|
486
|
+
mysql_database?: string;
|
|
487
|
+
mysql_conf?: string;
|
|
488
|
+
}
|
|
489
|
+
export interface CreateMariadbRequest extends CreateDatabaseBaseRequest {
|
|
490
|
+
mariadb_root_password?: string;
|
|
491
|
+
mariadb_user?: string;
|
|
492
|
+
mariadb_password?: string;
|
|
493
|
+
mariadb_database?: string;
|
|
494
|
+
mariadb_conf?: string;
|
|
495
|
+
}
|
|
496
|
+
export interface CreateMongodbRequest extends CreateDatabaseBaseRequest {
|
|
497
|
+
mongo_initdb_root_username?: string;
|
|
498
|
+
mongo_initdb_root_password?: string;
|
|
499
|
+
mongo_initdb_database?: string;
|
|
500
|
+
mongo_conf?: string;
|
|
501
|
+
}
|
|
502
|
+
export interface CreateRedisRequest extends CreateDatabaseBaseRequest {
|
|
503
|
+
redis_password?: string;
|
|
504
|
+
redis_conf?: string;
|
|
505
|
+
}
|
|
506
|
+
export interface CreateKeydbRequest extends CreateDatabaseBaseRequest {
|
|
507
|
+
keydb_password?: string;
|
|
508
|
+
keydb_conf?: string;
|
|
509
|
+
}
|
|
510
|
+
export interface CreateClickhouseRequest extends CreateDatabaseBaseRequest {
|
|
511
|
+
clickhouse_admin_user?: string;
|
|
512
|
+
clickhouse_admin_password?: string;
|
|
513
|
+
}
|
|
514
|
+
export interface CreateDragonflyRequest extends CreateDatabaseBaseRequest {
|
|
515
|
+
dragonfly_password?: string;
|
|
516
|
+
}
|
|
517
|
+
export interface CreateDatabaseResponse {
|
|
518
|
+
uuid: string;
|
|
519
|
+
}
|
|
454
520
|
export interface DatabaseBackup {
|
|
455
521
|
id: number;
|
|
456
522
|
uuid: string;
|