@serenichron/mcp-cloudron 0.1.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 +21 -0
- package/README.md +189 -0
- package/dist/cloudron-client.d.ts +38 -0
- package/dist/cloudron-client.d.ts.map +1 -0
- package/dist/cloudron-client.js +109 -0
- package/dist/cloudron-client.js.map +1 -0
- package/dist/errors.d.ts +31 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +54 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +151 -0
- package/dist/server.js.map +1 -0
- package/dist/test.d.ts +6 -0
- package/dist/test.d.ts.map +1 -0
- package/dist/test.js +90 -0
- package/dist/test.js.map +1 -0
- package/dist/types.d.ts +67 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Serenichron
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# mcp-cloudron
|
|
2
|
+
|
|
3
|
+
MCP server for [Cloudron](https://cloudron.io) instance management. List apps, get status, and manage your self-hosted applications through the Model Context Protocol.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **List Applications**: Get all installed apps with status, health, and memory usage
|
|
8
|
+
- **Get App Details**: Retrieve detailed information about specific applications
|
|
9
|
+
- **Instance Status**: Check Cloudron version, provider, and configuration
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install @serenichron/mcp-cloudron
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or run directly with npx:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npx @serenichron/mcp-cloudron
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Configuration
|
|
24
|
+
|
|
25
|
+
### Environment Variables
|
|
26
|
+
|
|
27
|
+
| Variable | Required | Description |
|
|
28
|
+
|----------|----------|-------------|
|
|
29
|
+
| `CLOUDRON_BASE_URL` | Yes | Your Cloudron instance URL (e.g., `https://my.cloudron.io`) |
|
|
30
|
+
| `CLOUDRON_API_TOKEN` | Yes | API token from Cloudron Admin Panel |
|
|
31
|
+
|
|
32
|
+
### Getting an API Token
|
|
33
|
+
|
|
34
|
+
1. Log in to your Cloudron Admin Panel
|
|
35
|
+
2. Go to **Settings → API Tokens**
|
|
36
|
+
3. Click **Create API Token**
|
|
37
|
+
4. Give it a name (e.g., "MCP Server")
|
|
38
|
+
5. Copy the generated token
|
|
39
|
+
|
|
40
|
+
## Usage with Claude Desktop
|
|
41
|
+
|
|
42
|
+
Add to your Claude Desktop configuration (`claude_desktop_config.json`):
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"mcpServers": {
|
|
47
|
+
"cloudron": {
|
|
48
|
+
"command": "npx",
|
|
49
|
+
"args": ["@serenichron/mcp-cloudron"],
|
|
50
|
+
"env": {
|
|
51
|
+
"CLOUDRON_BASE_URL": "https://your-cloudron-instance.com",
|
|
52
|
+
"CLOUDRON_API_TOKEN": "your-api-token"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Usage with Docker MCP Gateway
|
|
60
|
+
|
|
61
|
+
Add to your Docker MCP config (`~/.docker/mcp/config.yaml`):
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
mcpServers:
|
|
65
|
+
cloudron:
|
|
66
|
+
command: npx
|
|
67
|
+
args: ["@serenichron/mcp-cloudron"]
|
|
68
|
+
env:
|
|
69
|
+
CLOUDRON_BASE_URL: "https://your-cloudron-instance.com"
|
|
70
|
+
CLOUDRON_API_TOKEN: "your-api-token"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Available Tools
|
|
74
|
+
|
|
75
|
+
### cloudron_list_apps
|
|
76
|
+
|
|
77
|
+
List all installed applications on the Cloudron instance.
|
|
78
|
+
|
|
79
|
+
**Parameters**: None
|
|
80
|
+
|
|
81
|
+
**Returns**: List of apps with name, domain, ID, state, health, and memory usage.
|
|
82
|
+
|
|
83
|
+
**Example output**:
|
|
84
|
+
```
|
|
85
|
+
Found 3 apps:
|
|
86
|
+
|
|
87
|
+
WordPress (blog.example.com)
|
|
88
|
+
ID: abc123-def456
|
|
89
|
+
State: installed
|
|
90
|
+
Health: healthy
|
|
91
|
+
Memory: 512 MB
|
|
92
|
+
|
|
93
|
+
GitLab (git.example.com)
|
|
94
|
+
ID: xyz789-uvw012
|
|
95
|
+
State: installed
|
|
96
|
+
Health: healthy
|
|
97
|
+
Memory: 4096 MB
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### cloudron_get_app
|
|
101
|
+
|
|
102
|
+
Get detailed information about a specific application.
|
|
103
|
+
|
|
104
|
+
**Parameters**:
|
|
105
|
+
| Name | Type | Required | Description |
|
|
106
|
+
|------|------|----------|-------------|
|
|
107
|
+
| `appId` | string | Yes | The unique identifier of the application |
|
|
108
|
+
|
|
109
|
+
**Returns**: App details including name, domain, state, health, and memory.
|
|
110
|
+
|
|
111
|
+
### cloudron_get_status
|
|
112
|
+
|
|
113
|
+
Get the current status and configuration of the Cloudron instance.
|
|
114
|
+
|
|
115
|
+
**Parameters**: None
|
|
116
|
+
|
|
117
|
+
**Returns**: Instance information including name, version, admin URL, provider, and demo mode status.
|
|
118
|
+
|
|
119
|
+
**Example output**:
|
|
120
|
+
```
|
|
121
|
+
Cloudron Status:
|
|
122
|
+
Name: My Cloudron
|
|
123
|
+
Version: 9.0.13
|
|
124
|
+
Admin URL: my.cloudron.io
|
|
125
|
+
Provider: digitalocean
|
|
126
|
+
Demo Mode: false
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Development
|
|
130
|
+
|
|
131
|
+
### Setup
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
git clone https://github.com/serenichron/mcp-cloudron.git
|
|
135
|
+
cd mcp-cloudron
|
|
136
|
+
npm install
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Build
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
npm run build
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Run locally
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
export CLOUDRON_BASE_URL="https://your-instance.com"
|
|
149
|
+
export CLOUDRON_API_TOKEN="your-token"
|
|
150
|
+
npm start
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Test
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
npm test
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## API Reference
|
|
160
|
+
|
|
161
|
+
The server uses the [Cloudron REST API](https://docs.cloudron.io/api/). Currently implemented endpoints:
|
|
162
|
+
|
|
163
|
+
- `GET /api/v1/apps` - List all applications
|
|
164
|
+
- `GET /api/v1/apps/:id` - Get application by ID
|
|
165
|
+
- `GET /api/v1/cloudron/status` - Get instance status
|
|
166
|
+
|
|
167
|
+
## Roadmap
|
|
168
|
+
|
|
169
|
+
Future versions may include:
|
|
170
|
+
|
|
171
|
+
- [ ] App lifecycle management (start, stop, restart)
|
|
172
|
+
- [ ] Backup operations
|
|
173
|
+
- [ ] User management
|
|
174
|
+
- [ ] Domain configuration
|
|
175
|
+
- [ ] App installation from App Store
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT - See [LICENSE](LICENSE) for details.
|
|
180
|
+
|
|
181
|
+
## Contributing
|
|
182
|
+
|
|
183
|
+
Contributions welcome! Please open an issue or submit a pull request.
|
|
184
|
+
|
|
185
|
+
## Related
|
|
186
|
+
|
|
187
|
+
- [Cloudron Documentation](https://docs.cloudron.io/)
|
|
188
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
|
189
|
+
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudron API Client
|
|
3
|
+
* MVP scope: listApps + getApp endpoints
|
|
4
|
+
* DI-enabled for testing
|
|
5
|
+
*/
|
|
6
|
+
import type { CloudronClientConfig, App, SystemStatus } from './types.js';
|
|
7
|
+
export declare class CloudronClient {
|
|
8
|
+
private readonly baseUrl;
|
|
9
|
+
private readonly token;
|
|
10
|
+
/**
|
|
11
|
+
* Create CloudronClient with DI support
|
|
12
|
+
* @param config - Optional config (defaults to env vars)
|
|
13
|
+
*/
|
|
14
|
+
constructor(config?: Partial<CloudronClientConfig>);
|
|
15
|
+
/**
|
|
16
|
+
* Make HTTP request to Cloudron API
|
|
17
|
+
* NO retry logic (deferred to Phase 3 with idempotency keys)
|
|
18
|
+
*/
|
|
19
|
+
private makeRequest;
|
|
20
|
+
/**
|
|
21
|
+
* List all installed apps
|
|
22
|
+
* GET /api/v1/apps
|
|
23
|
+
*/
|
|
24
|
+
listApps(): Promise<App[]>;
|
|
25
|
+
/**
|
|
26
|
+
* Get a specific app by ID
|
|
27
|
+
* GET /api/v1/apps/:appId
|
|
28
|
+
*
|
|
29
|
+
* Note: API returns app object directly, not wrapped in { app: {...} }
|
|
30
|
+
*/
|
|
31
|
+
getApp(appId: string): Promise<App>;
|
|
32
|
+
/**
|
|
33
|
+
* Get Cloudron system status
|
|
34
|
+
* GET /api/v1/cloudron/status
|
|
35
|
+
*/
|
|
36
|
+
getStatus(): Promise<SystemStatus>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=cloudron-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudron-client.d.ts","sourceRoot":"","sources":["../src/cloudron-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,oBAAoB,EAAE,GAAG,EAA6B,YAAY,EAAE,MAAM,YAAY,CAAC;AAKrG,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B;;;OAGG;gBACS,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC;IAelD;;;OAGG;YACW,WAAW;IAiEzB;;;OAGG;IACG,QAAQ,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAKhC;;;;;OAKG;IACG,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAOzC;;;OAGG;IACG,SAAS,IAAI,OAAO,CAAC,YAAY,CAAC;CAGzC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudron API Client
|
|
3
|
+
* MVP scope: listApps + getApp endpoints
|
|
4
|
+
* DI-enabled for testing
|
|
5
|
+
*/
|
|
6
|
+
import { CloudronError, CloudronAuthError, createErrorFromStatus } from './errors.js';
|
|
7
|
+
const DEFAULT_TIMEOUT = 30000;
|
|
8
|
+
export class CloudronClient {
|
|
9
|
+
baseUrl;
|
|
10
|
+
token;
|
|
11
|
+
/**
|
|
12
|
+
* Create CloudronClient with DI support
|
|
13
|
+
* @param config - Optional config (defaults to env vars)
|
|
14
|
+
*/
|
|
15
|
+
constructor(config) {
|
|
16
|
+
const baseUrl = config?.baseUrl ?? process.env.CLOUDRON_BASE_URL;
|
|
17
|
+
const token = config?.token ?? process.env.CLOUDRON_API_TOKEN;
|
|
18
|
+
if (!baseUrl) {
|
|
19
|
+
throw new CloudronError('CLOUDRON_BASE_URL not set. Provide via config or environment variable.');
|
|
20
|
+
}
|
|
21
|
+
if (!token) {
|
|
22
|
+
throw new CloudronError('CLOUDRON_API_TOKEN not set. Provide via config or environment variable.');
|
|
23
|
+
}
|
|
24
|
+
this.baseUrl = baseUrl.replace(/\/$/, ''); // Remove trailing slash
|
|
25
|
+
this.token = token;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Make HTTP request to Cloudron API
|
|
29
|
+
* NO retry logic (deferred to Phase 3 with idempotency keys)
|
|
30
|
+
*/
|
|
31
|
+
async makeRequest(method, endpoint, body, options) {
|
|
32
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
33
|
+
const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
|
|
34
|
+
const controller = new AbortController();
|
|
35
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
36
|
+
try {
|
|
37
|
+
const fetchOptions = {
|
|
38
|
+
method,
|
|
39
|
+
headers: {
|
|
40
|
+
'Authorization': `Bearer ${this.token}`,
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
'Accept': 'application/json',
|
|
43
|
+
},
|
|
44
|
+
signal: controller.signal,
|
|
45
|
+
};
|
|
46
|
+
if (body !== undefined) {
|
|
47
|
+
fetchOptions.body = JSON.stringify(body);
|
|
48
|
+
}
|
|
49
|
+
const response = await fetch(url, fetchOptions);
|
|
50
|
+
clearTimeout(timeoutId);
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
const errorBody = await response.text();
|
|
53
|
+
let message = `Cloudron API error: ${response.status} ${response.statusText}`;
|
|
54
|
+
try {
|
|
55
|
+
const parsed = JSON.parse(errorBody);
|
|
56
|
+
if (parsed.message)
|
|
57
|
+
message = parsed.message;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// Use default message if body isn't JSON
|
|
61
|
+
}
|
|
62
|
+
throw createErrorFromStatus(response.status, message);
|
|
63
|
+
}
|
|
64
|
+
return await response.json();
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
clearTimeout(timeoutId);
|
|
68
|
+
if (error instanceof CloudronError) {
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
if (error instanceof Error) {
|
|
72
|
+
if (error.name === 'AbortError') {
|
|
73
|
+
throw new CloudronError(`Request timeout after ${timeout}ms`, undefined, 'TIMEOUT');
|
|
74
|
+
}
|
|
75
|
+
throw new CloudronError(`Network error: ${error.message}`, undefined, 'NETWORK_ERROR');
|
|
76
|
+
}
|
|
77
|
+
throw new CloudronError('Unknown error occurred');
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// ==================== MVP Endpoints ====================
|
|
81
|
+
/**
|
|
82
|
+
* List all installed apps
|
|
83
|
+
* GET /api/v1/apps
|
|
84
|
+
*/
|
|
85
|
+
async listApps() {
|
|
86
|
+
const response = await this.makeRequest('GET', '/api/v1/apps');
|
|
87
|
+
return response.apps;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Get a specific app by ID
|
|
91
|
+
* GET /api/v1/apps/:appId
|
|
92
|
+
*
|
|
93
|
+
* Note: API returns app object directly, not wrapped in { app: {...} }
|
|
94
|
+
*/
|
|
95
|
+
async getApp(appId) {
|
|
96
|
+
if (!appId) {
|
|
97
|
+
throw new CloudronError('appId is required');
|
|
98
|
+
}
|
|
99
|
+
return await this.makeRequest('GET', `/api/v1/apps/${encodeURIComponent(appId)}`);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get Cloudron system status
|
|
103
|
+
* GET /api/v1/cloudron/status
|
|
104
|
+
*/
|
|
105
|
+
async getStatus() {
|
|
106
|
+
return await this.makeRequest('GET', '/api/v1/cloudron/status');
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=cloudron-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudron-client.js","sourceRoot":"","sources":["../src/cloudron-client.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEtF,MAAM,eAAe,GAAG,KAAK,CAAC;AAE9B,MAAM,OAAO,cAAc;IACR,OAAO,CAAS;IAChB,KAAK,CAAS;IAE/B;;;OAGG;IACH,YAAY,MAAsC;QAChD,MAAM,OAAO,GAAG,MAAM,EAAE,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;QACjE,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAE9D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,aAAa,CAAC,wEAAwE,CAAC,CAAC;QACpG,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,aAAa,CAAC,yEAAyE,CAAC,CAAC;QACrG,CAAC;QAED,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,wBAAwB;QACnE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,WAAW,CACvB,MAAyC,EACzC,QAAgB,EAChB,IAAc,EACd,OAA8B;QAE9B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,GAAG,QAAQ,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,eAAe,CAAC;QACpD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAEhE,IAAI,CAAC;YACH,MAAM,YAAY,GAAgB;gBAChC,MAAM;gBACN,OAAO,EAAE;oBACP,eAAe,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;oBACvC,cAAc,EAAE,kBAAkB;oBAClC,QAAQ,EAAE,kBAAkB;iBAC7B;gBACD,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC;YAEF,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,YAAY,CAAC,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC3C,CAAC;YAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;YAEhD,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,IAAI,OAAO,GAAG,uBAAuB,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAE9E,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;oBACrC,IAAI,MAAM,CAAC,OAAO;wBAAE,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;gBAC/C,CAAC;gBAAC,MAAM,CAAC;oBACP,yCAAyC;gBAC3C,CAAC;gBAED,MAAM,qBAAqB,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YACxD,CAAC;YAED,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAO,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,YAAY,CAAC,SAAS,CAAC,CAAC;YAExB,IAAI,KAAK,YAAY,aAAa,EAAE,CAAC;gBACnC,MAAM,KAAK,CAAC;YACd,CAAC;YAED,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;gBAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;oBAChC,MAAM,IAAI,aAAa,CAAC,yBAAyB,OAAO,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;gBACtF,CAAC;gBACD,MAAM,IAAI,aAAa,CAAC,kBAAkB,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,CAAC;YACzF,CAAC;YAED,MAAM,IAAI,aAAa,CAAC,wBAAwB,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,0DAA0D;IAE1D;;;OAGG;IACH,KAAK,CAAC,QAAQ;QACZ,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,WAAW,CAAe,KAAK,EAAE,cAAc,CAAC,CAAC;QAC7E,OAAO,QAAQ,CAAC,IAAI,CAAC;IACvB,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,MAAM,CAAC,KAAa;QACxB,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,aAAa,CAAC,mBAAmB,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO,MAAM,IAAI,CAAC,WAAW,CAAM,KAAK,EAAE,gBAAgB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACzF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,SAAS;QACb,OAAO,MAAM,IAAI,CAAC,WAAW,CAAe,KAAK,EAAE,yBAAyB,CAAC,CAAC;IAChF,CAAC;CACF"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudron Error Classes
|
|
3
|
+
* MVP scope: Base error + Auth error only
|
|
4
|
+
*/
|
|
5
|
+
/** Base error for all Cloudron API errors */
|
|
6
|
+
export declare class CloudronError extends Error {
|
|
7
|
+
readonly statusCode: number | undefined;
|
|
8
|
+
readonly code: string | undefined;
|
|
9
|
+
constructor(message: string, statusCode?: number, code?: string);
|
|
10
|
+
/**
|
|
11
|
+
* Check if error is retryable (for future Phase 3)
|
|
12
|
+
* 429 (rate limit) and 5xx errors are retryable
|
|
13
|
+
* 4xx errors (except 429) are NOT retryable
|
|
14
|
+
*/
|
|
15
|
+
isRetryable(): boolean;
|
|
16
|
+
}
|
|
17
|
+
/** Authentication/Authorization error (401/403) */
|
|
18
|
+
export declare class CloudronAuthError extends CloudronError {
|
|
19
|
+
constructor(message?: string, statusCode?: number);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Type guard for CloudronError
|
|
23
|
+
* Usage: if (isCloudronError(error)) { ... }
|
|
24
|
+
*/
|
|
25
|
+
export declare function isCloudronError(error: unknown): error is CloudronError;
|
|
26
|
+
/**
|
|
27
|
+
* Create appropriate error from HTTP status code
|
|
28
|
+
* Routes 401/403 to CloudronAuthError, others to CloudronError
|
|
29
|
+
*/
|
|
30
|
+
export declare function createErrorFromStatus(statusCode: number, message: string): CloudronError;
|
|
31
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6CAA6C;AAC7C,qBAAa,aAAc,SAAQ,KAAK;IACtC,SAAgB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,SAAgB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE7B,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;IAY/D;;;;OAIG;IACH,WAAW,IAAI,OAAO;CAIvB;AAED,mDAAmD;AACnD,qBAAa,iBAAkB,SAAQ,aAAa;gBAEhD,OAAO,SAAqD,EAC5D,UAAU,SAAM;CAKnB;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,aAAa,CAEtE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,aAAa,CAKf"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudron Error Classes
|
|
3
|
+
* MVP scope: Base error + Auth error only
|
|
4
|
+
*/
|
|
5
|
+
/** Base error for all Cloudron API errors */
|
|
6
|
+
export class CloudronError extends Error {
|
|
7
|
+
statusCode;
|
|
8
|
+
code;
|
|
9
|
+
constructor(message, statusCode, code) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = 'CloudronError';
|
|
12
|
+
this.statusCode = statusCode ?? undefined;
|
|
13
|
+
this.code = code ?? undefined;
|
|
14
|
+
// Maintains proper stack trace in V8 engines
|
|
15
|
+
if (Error.captureStackTrace) {
|
|
16
|
+
Error.captureStackTrace(this, CloudronError);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Check if error is retryable (for future Phase 3)
|
|
21
|
+
* 429 (rate limit) and 5xx errors are retryable
|
|
22
|
+
* 4xx errors (except 429) are NOT retryable
|
|
23
|
+
*/
|
|
24
|
+
isRetryable() {
|
|
25
|
+
if (!this.statusCode)
|
|
26
|
+
return false;
|
|
27
|
+
return this.statusCode === 429 || this.statusCode >= 500;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Authentication/Authorization error (401/403) */
|
|
31
|
+
export class CloudronAuthError extends CloudronError {
|
|
32
|
+
constructor(message = 'Authentication failed. Check CLOUDRON_API_TOKEN.', statusCode = 401) {
|
|
33
|
+
super(message, statusCode, 'AUTH_ERROR');
|
|
34
|
+
this.name = 'CloudronAuthError';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Type guard for CloudronError
|
|
39
|
+
* Usage: if (isCloudronError(error)) { ... }
|
|
40
|
+
*/
|
|
41
|
+
export function isCloudronError(error) {
|
|
42
|
+
return error instanceof CloudronError;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Create appropriate error from HTTP status code
|
|
46
|
+
* Routes 401/403 to CloudronAuthError, others to CloudronError
|
|
47
|
+
*/
|
|
48
|
+
export function createErrorFromStatus(statusCode, message) {
|
|
49
|
+
if (statusCode === 401 || statusCode === 403) {
|
|
50
|
+
return new CloudronAuthError(message, statusCode);
|
|
51
|
+
}
|
|
52
|
+
return new CloudronError(message, statusCode);
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6CAA6C;AAC7C,MAAM,OAAO,aAAc,SAAQ,KAAK;IACtB,UAAU,CAAqB;IAC/B,IAAI,CAAqB;IAEzC,YAAY,OAAe,EAAE,UAAmB,EAAE,IAAa;QAC7D,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,SAAS,CAAC;QAC1C,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,SAAS,CAAC;QAE9B,6CAA6C;QAC7C,IAAI,KAAK,CAAC,iBAAiB,EAAE,CAAC;YAC5B,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAO,KAAK,CAAC;QACnC,OAAO,IAAI,CAAC,UAAU,KAAK,GAAG,IAAI,IAAI,CAAC,UAAU,IAAI,GAAG,CAAC;IAC3D,CAAC;CACF;AAED,mDAAmD;AACnD,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAClD,YACE,OAAO,GAAG,kDAAkD,EAC5D,UAAU,GAAG,GAAG;QAEhB,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;IAClC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,KAAK,YAAY,aAAa,CAAC;AACxC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAkB,EAClB,OAAe;IAEf,IAAI,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,GAAG,EAAE,CAAC;QAC7C,OAAO,IAAI,iBAAiB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;IACD,OAAO,IAAI,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;AAChD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudron MCP Client
|
|
3
|
+
* MVP Phase 2 Implementation
|
|
4
|
+
*/
|
|
5
|
+
export { CloudronClient } from './cloudron-client.js';
|
|
6
|
+
export type { CloudronClientConfig, App, AppManifest, AppsResponse, AppResponse, SystemStatus, } from './types.js';
|
|
7
|
+
export { CloudronError, CloudronAuthError, isCloudronError, createErrorFromStatus, } from './errors.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD,YAAY,EACV,oBAAoB,EACpB,GAAG,EACH,WAAW,EACX,YAAY,EACZ,WAAW,EACX,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudron MCP Client
|
|
3
|
+
* MVP Phase 2 Implementation
|
|
4
|
+
*/
|
|
5
|
+
// Main client
|
|
6
|
+
export { CloudronClient } from './cloudron-client.js';
|
|
7
|
+
// Errors
|
|
8
|
+
export { CloudronError, CloudronAuthError, isCloudronError, createErrorFromStatus, } from './errors.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc;AACd,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAYtD,SAAS;AACT,OAAO,EACL,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,qBAAqB,GACtB,MAAM,aAAa,CAAC"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Cloudron MCP Server
|
|
4
|
+
* Provides tools for managing Cloudron instances via MCP protocol
|
|
5
|
+
*/
|
|
6
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
9
|
+
import { CloudronClient } from './cloudron-client.js';
|
|
10
|
+
import { isCloudronError } from './errors.js';
|
|
11
|
+
// Tool definitions
|
|
12
|
+
const TOOLS = [
|
|
13
|
+
{
|
|
14
|
+
name: 'cloudron_list_apps',
|
|
15
|
+
description: 'List all installed applications on the Cloudron instance. Returns app details including name, domain, status, and health.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {},
|
|
19
|
+
required: [],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'cloudron_get_app',
|
|
24
|
+
description: 'Get detailed information about a specific application by its ID.',
|
|
25
|
+
inputSchema: {
|
|
26
|
+
type: 'object',
|
|
27
|
+
properties: {
|
|
28
|
+
appId: {
|
|
29
|
+
type: 'string',
|
|
30
|
+
description: 'The unique identifier of the application',
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
required: ['appId'],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: 'cloudron_get_status',
|
|
38
|
+
description: 'Get the current status and configuration of the Cloudron instance.',
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: 'object',
|
|
41
|
+
properties: {},
|
|
42
|
+
required: [],
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
];
|
|
46
|
+
// Create server instance
|
|
47
|
+
const server = new Server({
|
|
48
|
+
name: 'cloudron-mcp',
|
|
49
|
+
version: '0.1.0',
|
|
50
|
+
}, {
|
|
51
|
+
capabilities: {
|
|
52
|
+
tools: {},
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
// Lazy-initialize client (validates env vars on first use)
|
|
56
|
+
let client = null;
|
|
57
|
+
function getClient() {
|
|
58
|
+
if (!client) {
|
|
59
|
+
client = new CloudronClient();
|
|
60
|
+
}
|
|
61
|
+
return client;
|
|
62
|
+
}
|
|
63
|
+
// Format app for display
|
|
64
|
+
function formatApp(app) {
|
|
65
|
+
const fqdn = app.location ? `${app.location}.${app.domain}` : app.domain;
|
|
66
|
+
return `${app.manifest.title} (${fqdn})
|
|
67
|
+
ID: ${app.id}
|
|
68
|
+
State: ${app.installationState}
|
|
69
|
+
Health: ${app.health ?? 'unknown'}
|
|
70
|
+
Memory: ${Math.round(app.memoryLimit / 1024 / 1024)} MB`;
|
|
71
|
+
}
|
|
72
|
+
// Handle list tools request
|
|
73
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
74
|
+
tools: TOOLS,
|
|
75
|
+
}));
|
|
76
|
+
// Handle tool calls
|
|
77
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
78
|
+
const { name, arguments: args } = request.params;
|
|
79
|
+
try {
|
|
80
|
+
const cloudron = getClient();
|
|
81
|
+
switch (name) {
|
|
82
|
+
case 'cloudron_list_apps': {
|
|
83
|
+
const apps = await cloudron.listApps();
|
|
84
|
+
const formatted = apps.map(formatApp).join('\n\n');
|
|
85
|
+
return {
|
|
86
|
+
content: [
|
|
87
|
+
{
|
|
88
|
+
type: 'text',
|
|
89
|
+
text: `Found ${apps.length} apps:\n\n${formatted}`,
|
|
90
|
+
},
|
|
91
|
+
],
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
case 'cloudron_get_app': {
|
|
95
|
+
const appId = args.appId;
|
|
96
|
+
const app = await cloudron.getApp(appId);
|
|
97
|
+
return {
|
|
98
|
+
content: [
|
|
99
|
+
{
|
|
100
|
+
type: 'text',
|
|
101
|
+
text: formatApp(app),
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
case 'cloudron_get_status': {
|
|
107
|
+
const status = await cloudron.getStatus();
|
|
108
|
+
return {
|
|
109
|
+
content: [
|
|
110
|
+
{
|
|
111
|
+
type: 'text',
|
|
112
|
+
text: `Cloudron Status:
|
|
113
|
+
Name: ${status.cloudronName}
|
|
114
|
+
Version: ${status.version}
|
|
115
|
+
Admin URL: ${status.adminFqdn}
|
|
116
|
+
Provider: ${status.provider}
|
|
117
|
+
Demo Mode: ${status.isDemo}`,
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
default:
|
|
123
|
+
return {
|
|
124
|
+
content: [{ type: 'text', text: `Unknown tool: ${name}` }],
|
|
125
|
+
isError: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
const message = isCloudronError(error)
|
|
131
|
+
? `Cloudron API Error: ${error.message} (${error.statusCode ?? 'unknown'})`
|
|
132
|
+
: error instanceof Error
|
|
133
|
+
? error.message
|
|
134
|
+
: 'Unknown error occurred';
|
|
135
|
+
return {
|
|
136
|
+
content: [{ type: 'text', text: message }],
|
|
137
|
+
isError: true,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
// Main entry point
|
|
142
|
+
async function main() {
|
|
143
|
+
const transport = new StdioServerTransport();
|
|
144
|
+
await server.connect(transport);
|
|
145
|
+
console.error('Cloudron MCP server running on stdio');
|
|
146
|
+
}
|
|
147
|
+
main().catch((error) => {
|
|
148
|
+
console.error('Fatal error:', error);
|
|
149
|
+
process.exit(1);
|
|
150
|
+
});
|
|
151
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/dist/test.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Integration Test for CloudronClient
|
|
3
|
+
* Tests against real Cloudron instance
|
|
4
|
+
*/
|
|
5
|
+
import { CloudronClient, CloudronError, isCloudronError } from './index.js';
|
|
6
|
+
async function runTests() {
|
|
7
|
+
console.log('=== Cloudron MCP Client Integration Test ===\n');
|
|
8
|
+
// Check environment variables
|
|
9
|
+
const baseUrl = process.env.CLOUDRON_BASE_URL;
|
|
10
|
+
const token = process.env.CLOUDRON_API_TOKEN;
|
|
11
|
+
if (!baseUrl || !token) {
|
|
12
|
+
console.error('❌ Missing environment variables:');
|
|
13
|
+
if (!baseUrl)
|
|
14
|
+
console.error(' - CLOUDRON_BASE_URL not set');
|
|
15
|
+
if (!token)
|
|
16
|
+
console.error(' - CLOUDRON_API_TOKEN not set');
|
|
17
|
+
console.error('\nSet these variables and run again.');
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
console.log(`📡 Connecting to: ${baseUrl}\n`);
|
|
21
|
+
try {
|
|
22
|
+
// Create client
|
|
23
|
+
const client = new CloudronClient();
|
|
24
|
+
console.log('✅ Client created successfully\n');
|
|
25
|
+
// Test 1: List Apps
|
|
26
|
+
console.log('--- Test 1: listApps() ---');
|
|
27
|
+
const apps = await client.listApps();
|
|
28
|
+
console.log(`✅ Found ${apps.length} apps:`);
|
|
29
|
+
for (const app of apps.slice(0, 5)) { // Show first 5
|
|
30
|
+
const fqdn = app.location ? `${app.location}.${app.domain}` : app.domain;
|
|
31
|
+
console.log(` - ${app.manifest.title} (${fqdn})`);
|
|
32
|
+
console.log(` State: ${app.installationState}, Health: ${app.health}`);
|
|
33
|
+
}
|
|
34
|
+
if (apps.length > 5) {
|
|
35
|
+
console.log(` ... and ${apps.length - 5} more\n`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
console.log('');
|
|
39
|
+
}
|
|
40
|
+
// Test 2: Get Single App (if we have any apps)
|
|
41
|
+
if (apps.length > 0) {
|
|
42
|
+
const firstApp = apps[0];
|
|
43
|
+
if (!firstApp) {
|
|
44
|
+
throw new Error('First app is undefined');
|
|
45
|
+
}
|
|
46
|
+
console.log(`--- Test 2: getApp('${firstApp.id}') ---`);
|
|
47
|
+
const app = await client.getApp(firstApp.id);
|
|
48
|
+
console.log(`✅ Retrieved app: ${app.manifest.title}`);
|
|
49
|
+
console.log(` ID: ${app.id}`);
|
|
50
|
+
console.log(` FQDN: ${app.fqdn}`);
|
|
51
|
+
console.log(` Memory: ${app.memoryLimit} bytes`);
|
|
52
|
+
console.log(` Created: ${app.creationTime}\n`);
|
|
53
|
+
}
|
|
54
|
+
// Test 3: Error handling - invalid app ID
|
|
55
|
+
console.log('--- Test 3: Error Handling (invalid app ID) ---');
|
|
56
|
+
try {
|
|
57
|
+
await client.getApp('non-existent-app-id-12345');
|
|
58
|
+
console.log('❌ Expected error but got success');
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (isCloudronError(error)) {
|
|
62
|
+
console.log(`✅ Caught CloudronError as expected`);
|
|
63
|
+
console.log(` Message: ${error.message}`);
|
|
64
|
+
console.log(` Status: ${error.statusCode}`);
|
|
65
|
+
console.log(` Retryable: ${error.isRetryable()}\n`);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
console.log('=== All Tests Passed! ===');
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error('\n❌ Test Failed:');
|
|
75
|
+
if (isCloudronError(error)) {
|
|
76
|
+
console.error(` CloudronError: ${error.message}`);
|
|
77
|
+
console.error(` Status: ${error.statusCode}`);
|
|
78
|
+
console.error(` Code: ${error.code}`);
|
|
79
|
+
}
|
|
80
|
+
else if (error instanceof Error) {
|
|
81
|
+
console.error(` Error: ${error.message}`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.error(' Unknown error:', error);
|
|
85
|
+
}
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
runTests();
|
|
90
|
+
//# sourceMappingURL=test.js.map
|
package/dist/test.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test.js","sourceRoot":"","sources":["../src/test.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudron API TypeScript Definitions
|
|
3
|
+
* MVP scope: listApps + getApp endpoints
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for CloudronClient - enables DI for testing
|
|
7
|
+
*/
|
|
8
|
+
export interface CloudronClientConfig {
|
|
9
|
+
baseUrl: string;
|
|
10
|
+
token: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* App manifest subset containing metadata
|
|
14
|
+
*/
|
|
15
|
+
export interface AppManifest {
|
|
16
|
+
id: string;
|
|
17
|
+
version: string;
|
|
18
|
+
title: string;
|
|
19
|
+
description: string;
|
|
20
|
+
tagline?: string;
|
|
21
|
+
website?: string;
|
|
22
|
+
author?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Cloudron App representation
|
|
26
|
+
*/
|
|
27
|
+
export interface App {
|
|
28
|
+
id: string;
|
|
29
|
+
appStoreId: string;
|
|
30
|
+
installationState: 'pending_install' | 'installed' | 'pending_configure' | 'pending_uninstall' | 'pending_restore' | 'error';
|
|
31
|
+
installationProgress: string;
|
|
32
|
+
runState: 'running' | 'stopped' | 'dead';
|
|
33
|
+
health: 'healthy' | 'unhealthy' | 'unknown';
|
|
34
|
+
location: string;
|
|
35
|
+
domain: string;
|
|
36
|
+
fqdn: string;
|
|
37
|
+
accessRestriction: string | null;
|
|
38
|
+
manifest: AppManifest;
|
|
39
|
+
portBindings: Record<string, number> | null;
|
|
40
|
+
iconUrl: string | null;
|
|
41
|
+
memoryLimit: number;
|
|
42
|
+
creationTime: string;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* API response wrapper for listing apps
|
|
46
|
+
*/
|
|
47
|
+
export interface AppsResponse {
|
|
48
|
+
apps: App[];
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* API response wrapper for single app
|
|
52
|
+
*/
|
|
53
|
+
export interface AppResponse {
|
|
54
|
+
app: App;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* System status response from /api/v1/cloudron/status
|
|
58
|
+
*/
|
|
59
|
+
export interface SystemStatus {
|
|
60
|
+
version: string;
|
|
61
|
+
apiServerOrigin: string;
|
|
62
|
+
adminFqdn: string;
|
|
63
|
+
provider: string;
|
|
64
|
+
cloudronName: string;
|
|
65
|
+
isDemo: boolean;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,iBAAiB,GAAG,WAAW,GAAG,mBAAmB,GAAG,mBAAmB,GAAG,iBAAiB,GAAG,OAAO,CAAC;IAC7H,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;IACzC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAC;IAC5C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,EAAE,WAAW,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAC5C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,GAAG,EAAE,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,GAAG,CAAC;CACV;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@serenichron/mcp-cloudron",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Cloudron instance management - list apps, get status, and manage your self-hosted applications",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"mcp-cloudron": "dist/server.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"start": "node dist/server.js",
|
|
17
|
+
"dev": "tsx watch src/index.ts",
|
|
18
|
+
"test": "tsx src/test.ts",
|
|
19
|
+
"lint": "tsc --noEmit",
|
|
20
|
+
"clean": "rm -rf dist",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"cloudron",
|
|
26
|
+
"model-context-protocol",
|
|
27
|
+
"ai",
|
|
28
|
+
"automation",
|
|
29
|
+
"self-hosted",
|
|
30
|
+
"server-management",
|
|
31
|
+
"claude",
|
|
32
|
+
"anthropic"
|
|
33
|
+
],
|
|
34
|
+
"author": "Serenichron <vlad@serenichron.com>",
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"repository": {
|
|
37
|
+
"type": "git",
|
|
38
|
+
"url": "git+https://github.com/serenichron/mcp-cloudron.git"
|
|
39
|
+
},
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/serenichron/mcp-cloudron/issues"
|
|
42
|
+
},
|
|
43
|
+
"homepage": "https://github.com/serenichron/mcp-cloudron#readme",
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18.0.0"
|
|
46
|
+
},
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/node": "^24.10.2",
|
|
49
|
+
"tsx": "^4.21.0",
|
|
50
|
+
"typescript": "^5.9.3"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@modelcontextprotocol/sdk": "^1.24.3"
|
|
54
|
+
}
|
|
55
|
+
}
|