@masonator/coolify-mcp 2.6.2 → 2.6.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -802,6 +802,86 @@ describe('CoolifyClient', () => {
802
802
  expect(result).toEqual({ uuid: 'new-app-uuid' });
803
803
  expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/applications/private-deploy-key', expect.objectContaining({ method: 'POST' }));
804
804
  });
805
+ it('should map fqdn to domains in createApplicationPublic', async () => {
806
+ mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'new-app-uuid' }));
807
+ await client.createApplicationPublic({
808
+ project_uuid: 'proj-uuid',
809
+ server_uuid: 'server-uuid',
810
+ git_repository: 'https://github.com/user/repo',
811
+ git_branch: 'main',
812
+ build_pack: 'nixpacks',
813
+ ports_exposes: '3000',
814
+ fqdn: 'https://app.example.com',
815
+ });
816
+ const callBody = JSON.parse(mockFetch.mock.calls[0][1]?.body);
817
+ expect(callBody.domains).toBe('https://app.example.com');
818
+ expect(callBody.fqdn).toBeUndefined();
819
+ });
820
+ it('should map fqdn to domains in createApplicationPrivateGH', async () => {
821
+ mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'new-app-uuid' }));
822
+ await client.createApplicationPrivateGH({
823
+ project_uuid: 'proj-uuid',
824
+ server_uuid: 'server-uuid',
825
+ github_app_uuid: 'gh-app-uuid',
826
+ git_repository: 'user/repo',
827
+ git_branch: 'main',
828
+ build_pack: 'nixpacks',
829
+ ports_exposes: '3000',
830
+ fqdn: 'https://app.example.com',
831
+ });
832
+ const callBody = JSON.parse(mockFetch.mock.calls[0][1]?.body);
833
+ expect(callBody.domains).toBe('https://app.example.com');
834
+ expect(callBody.fqdn).toBeUndefined();
835
+ });
836
+ it('should map fqdn to domains in createApplicationPrivateKey', async () => {
837
+ mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'new-app-uuid' }));
838
+ await client.createApplicationPrivateKey({
839
+ project_uuid: 'proj-uuid',
840
+ server_uuid: 'server-uuid',
841
+ private_key_uuid: 'key-uuid',
842
+ git_repository: 'git@github.com:user/repo.git',
843
+ git_branch: 'main',
844
+ build_pack: 'nixpacks',
845
+ ports_exposes: '22',
846
+ fqdn: 'https://app.example.com',
847
+ });
848
+ const callBody = JSON.parse(mockFetch.mock.calls[0][1]?.body);
849
+ expect(callBody.domains).toBe('https://app.example.com');
850
+ expect(callBody.fqdn).toBeUndefined();
851
+ });
852
+ it('should map fqdn to domains in updateApplication', async () => {
853
+ mockFetch.mockResolvedValueOnce(mockResponse(mockApplication));
854
+ await client.updateApplication('app-uuid', { fqdn: 'https://new.example.com' });
855
+ const callBody = JSON.parse(mockFetch.mock.calls[0][1]?.body);
856
+ expect(callBody.domains).toBe('https://new.example.com');
857
+ expect(callBody.fqdn).toBeUndefined();
858
+ });
859
+ it('should handle fqdn and docker_compose_raw together in updateApplication', async () => {
860
+ mockFetch.mockResolvedValueOnce(mockResponse(mockApplication));
861
+ const compose = 'version: "3"\nservices:\n app:\n image: nginx';
862
+ await client.updateApplication('app-uuid', {
863
+ fqdn: 'https://combo.example.com',
864
+ docker_compose_raw: compose,
865
+ });
866
+ const callBody = JSON.parse(mockFetch.mock.calls[0][1]?.body);
867
+ expect(callBody.domains).toBe('https://combo.example.com');
868
+ expect(callBody.fqdn).toBeUndefined();
869
+ expect(callBody.docker_compose_raw).toBe(Buffer.from(compose).toString('base64'));
870
+ });
871
+ it('should not modify request body when fqdn is not provided', async () => {
872
+ mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'new-app-uuid' }));
873
+ await client.createApplicationPublic({
874
+ project_uuid: 'proj-uuid',
875
+ server_uuid: 'server-uuid',
876
+ git_repository: 'https://github.com/user/repo',
877
+ git_branch: 'main',
878
+ build_pack: 'nixpacks',
879
+ ports_exposes: '3000',
880
+ });
881
+ const callBody = JSON.parse(mockFetch.mock.calls[0][1]?.body);
882
+ expect(callBody.fqdn).toBeUndefined();
883
+ expect(callBody.domains).toBeUndefined();
884
+ });
805
885
  it('should create application from dockerfile', async () => {
806
886
  mockFetch.mockResolvedValueOnce(mockResponse({ uuid: 'new-app-uuid' }));
807
887
  const result = await client.createApplicationDockerfile({
@@ -1381,7 +1461,7 @@ describe('CoolifyClient', () => {
1381
1461
  mockFetch.mockResolvedValueOnce(mockResponse([mockDeployment]));
1382
1462
  const result = await client.listApplicationDeployments('app-uuid');
1383
1463
  expect(result).toEqual([mockDeployment]);
1384
- expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/applications/app-uuid/deployments', expect.any(Object));
1464
+ expect(mockFetch).toHaveBeenCalledWith('http://localhost:3000/api/v1/deployments/applications/app-uuid', expect.any(Object));
1385
1465
  });
1386
1466
  });
1387
1467
  // =========================================================================
@@ -28,6 +28,18 @@ function toBase64(value) {
28
28
  }
29
29
  return Buffer.from(value, 'utf-8').toString('base64');
30
30
  }
31
+ /**
32
+ * Map 'fqdn' to 'domains' for Coolify API compatibility.
33
+ * Coolify API uses 'domains' field for setting application domain, not 'fqdn'.
34
+ * This provides backward compatibility for callers using 'fqdn'.
35
+ */
36
+ function mapFqdnToDomains(data) {
37
+ const { fqdn, ...rest } = data;
38
+ if (fqdn === undefined) {
39
+ return rest;
40
+ }
41
+ return { ...rest, domains: fqdn };
42
+ }
31
43
  // =============================================================================
32
44
  // Summary Transformers - reduce full objects to essential fields
33
45
  // =============================================================================
@@ -348,19 +360,19 @@ export class CoolifyClient {
348
360
  async createApplicationPublic(data) {
349
361
  return this.request('/applications/public', {
350
362
  method: 'POST',
351
- body: JSON.stringify(data),
363
+ body: JSON.stringify(mapFqdnToDomains(data)),
352
364
  });
353
365
  }
354
366
  async createApplicationPrivateGH(data) {
355
367
  return this.request('/applications/private-github-app', {
356
368
  method: 'POST',
357
- body: JSON.stringify(data),
369
+ body: JSON.stringify(mapFqdnToDomains(data)),
358
370
  });
359
371
  }
360
372
  async createApplicationPrivateKey(data) {
361
373
  return this.request('/applications/private-deploy-key', {
362
374
  method: 'POST',
363
- body: JSON.stringify(data),
375
+ body: JSON.stringify(mapFqdnToDomains(data)),
364
376
  });
365
377
  }
366
378
  async createApplicationDockerfile(data) {
@@ -386,9 +398,10 @@ export class CoolifyClient {
386
398
  });
387
399
  }
388
400
  async updateApplication(uuid, data) {
389
- const payload = { ...data };
390
- if (payload.docker_compose_raw) {
391
- payload.docker_compose_raw = toBase64(payload.docker_compose_raw);
401
+ const mapped = mapFqdnToDomains(data);
402
+ const payload = { ...mapped };
403
+ if (mapped.docker_compose_raw) {
404
+ payload.docker_compose_raw = toBase64(mapped.docker_compose_raw);
392
405
  }
393
406
  return this.request(`/applications/${uuid}`, {
394
407
  method: 'PATCH',
@@ -659,7 +672,7 @@ export class CoolifyClient {
659
672
  return this.request(`/deploy?${param}=${encodeURIComponent(tagOrUuid)}&force=${force}`, { method: 'GET' });
660
673
  }
661
674
  async listApplicationDeployments(appUuid) {
662
- return this.request(`/applications/${appUuid}/deployments`);
675
+ return this.request(`/deployments/applications/${appUuid}`);
663
676
  }
664
677
  // ===========================================================================
665
678
  // Team endpoints
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@masonator/coolify-mcp",
3
3
  "scope": "@masonator",
4
- "version": "2.6.2",
4
+ "version": "2.6.5",
5
5
  "description": "MCP server implementation for Coolify",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -49,19 +49,20 @@
49
49
  "zod": "^4.3.5"
50
50
  },
51
51
  "devDependencies": {
52
+ "@eslint/js": "^9.39.3",
52
53
  "@types/jest": "^29.5.14",
53
54
  "@types/node": "^25.0.3",
54
55
  "@typescript-eslint/eslint-plugin": "^8.51.0",
55
56
  "@typescript-eslint/parser": "^8.51.0",
56
57
  "dotenv": "^17.2.3",
57
- "eslint": "^9.39.2",
58
+ "eslint": "^10.0.0",
58
59
  "eslint-config-prettier": "^10.1.8",
59
60
  "globals": "^17.0.0",
60
61
  "husky": "^9.0.11",
61
62
  "jest": "^29.7.0",
62
63
  "jest-junit": "^16.0.0",
63
64
  "lint-staged": "^16.2.7",
64
- "markdownlint-cli2": "^0.20.0",
65
+ "markdownlint-cli2": "^0.21.0",
65
66
  "prettier": "^3.5.3",
66
67
  "shx": "^0.4.0",
67
68
  "ts-jest": "^29.2.6",