fleethost-mcp 0.1.0__tar.gz
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.
- fleethost_mcp-0.1.0/PKG-INFO +57 -0
- fleethost_mcp-0.1.0/README.md +47 -0
- fleethost_mcp-0.1.0/pyproject.toml +21 -0
- fleethost_mcp-0.1.0/setup.cfg +4 -0
- fleethost_mcp-0.1.0/src/fleet_mcp/__init__.py +3 -0
- fleethost_mcp-0.1.0/src/fleet_mcp/__main__.py +3 -0
- fleethost_mcp-0.1.0/src/fleet_mcp/server.py +230 -0
- fleethost_mcp-0.1.0/src/fleethost_mcp.egg-info/PKG-INFO +57 -0
- fleethost_mcp-0.1.0/src/fleethost_mcp.egg-info/SOURCES.txt +11 -0
- fleethost_mcp-0.1.0/src/fleethost_mcp.egg-info/dependency_links.txt +1 -0
- fleethost_mcp-0.1.0/src/fleethost_mcp.egg-info/entry_points.txt +2 -0
- fleethost_mcp-0.1.0/src/fleethost_mcp.egg-info/requires.txt +2 -0
- fleethost_mcp-0.1.0/src/fleethost_mcp.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fleethost-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for Fleet hosting platform — deploy apps and databases from any MCP-compatible agent
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: mcp>=1.6.0
|
|
9
|
+
Requires-Dist: httpx>=0.28.0
|
|
10
|
+
|
|
11
|
+
# fleethost-mcp
|
|
12
|
+
|
|
13
|
+
MCP server for [Fleet](https://fleethost.space) — deploy applications and databases from any MCP-compatible agent (Claude CLI, Cline, opencode, etc.).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install fleethost-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
Add to your agent's MCP config:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"fleet": {
|
|
29
|
+
"command": "fleethost-mcp",
|
|
30
|
+
"args": []
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
1. Start a conversation with your agent
|
|
39
|
+
2. Say: "Deploy my app to Fleet"
|
|
40
|
+
3. Agent will ask for your Fleet credentials once
|
|
41
|
+
4. Token is cached for future sessions
|
|
42
|
+
|
|
43
|
+
## Tools
|
|
44
|
+
|
|
45
|
+
| Tool | Description |
|
|
46
|
+
|------|-------------|
|
|
47
|
+
| `login` | Authenticate with your Fleet account |
|
|
48
|
+
| `deploy_app` | Deploy a new application |
|
|
49
|
+
| `list_apps` | List all your applications |
|
|
50
|
+
| `get_app_status` | Get live deployment status |
|
|
51
|
+
| `get_app_logs` | Fetch deployment or runtime logs |
|
|
52
|
+
| `redeploy_app` | Trigger a redeploy |
|
|
53
|
+
| `update_envs` | Set environment variables |
|
|
54
|
+
| `deploy_database` | Deploy a database (PostgreSQL, MySQL, MongoDB, Redis) |
|
|
55
|
+
| `list_databases` | List all your databases |
|
|
56
|
+
| `get_vps_info` | View VPS info and storage usage |
|
|
57
|
+
| `get_user_info` | View your Fleet profile |
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# fleethost-mcp
|
|
2
|
+
|
|
3
|
+
MCP server for [Fleet](https://fleethost.space) — deploy applications and databases from any MCP-compatible agent (Claude CLI, Cline, opencode, etc.).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install fleethost-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
Add to your agent's MCP config:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"mcpServers": {
|
|
18
|
+
"fleet": {
|
|
19
|
+
"command": "fleethost-mcp",
|
|
20
|
+
"args": []
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
1. Start a conversation with your agent
|
|
29
|
+
2. Say: "Deploy my app to Fleet"
|
|
30
|
+
3. Agent will ask for your Fleet credentials once
|
|
31
|
+
4. Token is cached for future sessions
|
|
32
|
+
|
|
33
|
+
## Tools
|
|
34
|
+
|
|
35
|
+
| Tool | Description |
|
|
36
|
+
|------|-------------|
|
|
37
|
+
| `login` | Authenticate with your Fleet account |
|
|
38
|
+
| `deploy_app` | Deploy a new application |
|
|
39
|
+
| `list_apps` | List all your applications |
|
|
40
|
+
| `get_app_status` | Get live deployment status |
|
|
41
|
+
| `get_app_logs` | Fetch deployment or runtime logs |
|
|
42
|
+
| `redeploy_app` | Trigger a redeploy |
|
|
43
|
+
| `update_envs` | Set environment variables |
|
|
44
|
+
| `deploy_database` | Deploy a database (PostgreSQL, MySQL, MongoDB, Redis) |
|
|
45
|
+
| `list_databases` | List all your databases |
|
|
46
|
+
| `get_vps_info` | View VPS info and storage usage |
|
|
47
|
+
| `get_user_info` | View your Fleet profile |
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fleethost-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "MCP server for Fleet hosting platform — deploy apps and databases from any MCP-compatible agent"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"mcp>=1.6.0",
|
|
10
|
+
"httpx>=0.28.0",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[project.scripts]
|
|
14
|
+
fleet-mcp = "fleet_mcp:main"
|
|
15
|
+
|
|
16
|
+
[build-system]
|
|
17
|
+
requires = ["setuptools>=75.0", "wheel"]
|
|
18
|
+
build-backend = "setuptools.build_meta"
|
|
19
|
+
|
|
20
|
+
[tool.setuptools.packages.find]
|
|
21
|
+
where = ["src"]
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
from mcp.server.fastmcp import FastMCP
|
|
8
|
+
|
|
9
|
+
FLEET_API_URL = os.environ.get("FLEET_API_URL", "https://fleet-host.fastapicloud.dev")
|
|
10
|
+
TOKEN_FILE = Path.home() / ".config" / "fleet-mcp" / "token"
|
|
11
|
+
|
|
12
|
+
mcp = FastMCP("fleet-mcp")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _load_token() -> str | None:
|
|
16
|
+
if TOKEN_FILE.exists():
|
|
17
|
+
return TOKEN_FILE.read_text().strip()
|
|
18
|
+
return None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _save_token(token: str):
|
|
22
|
+
TOKEN_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
23
|
+
TOKEN_FILE.write_text(token)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _get_headers() -> dict:
|
|
27
|
+
token = _load_token()
|
|
28
|
+
if not token:
|
|
29
|
+
raise RuntimeError(
|
|
30
|
+
"Not authenticated. Please use the `login` tool first with your Fleet email and password."
|
|
31
|
+
)
|
|
32
|
+
return {
|
|
33
|
+
"Authorization": f"Bearer {token}",
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
"Accept": "application/json",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _api_call(method: str, path: str, **kwargs) -> dict:
|
|
40
|
+
url = f"{FLEET_API_URL}{path}"
|
|
41
|
+
with httpx.Client(timeout=60.0, verify=False) as client:
|
|
42
|
+
resp = client.request(method, url, **kwargs)
|
|
43
|
+
if resp.status_code == 401:
|
|
44
|
+
raise RuntimeError(
|
|
45
|
+
"Authentication expired or invalid. Please use the `login` tool again."
|
|
46
|
+
)
|
|
47
|
+
resp.raise_for_status()
|
|
48
|
+
return resp.json()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@mcp.tool()
|
|
52
|
+
def login(email: str, password: str) -> str:
|
|
53
|
+
"""Authenticate with Fleet using your email and password. The token is cached for future sessions."""
|
|
54
|
+
payload = {"email": email, "password": password}
|
|
55
|
+
data = _api_call("POST", "/api/login", json=payload)
|
|
56
|
+
token = data.get("access_token")
|
|
57
|
+
if not token:
|
|
58
|
+
return f"Login failed: {data}"
|
|
59
|
+
_save_token(token)
|
|
60
|
+
return "Successfully authenticated with Fleet. Token cached for future sessions."
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@mcp.tool()
|
|
64
|
+
def deploy_app(
|
|
65
|
+
repo_url: str,
|
|
66
|
+
name: str,
|
|
67
|
+
branch: str = "main",
|
|
68
|
+
port: int = 3000,
|
|
69
|
+
env_vars: str | None = None,
|
|
70
|
+
build_command: str | None = None,
|
|
71
|
+
start_command: str | None = None,
|
|
72
|
+
custom_domain: str | None = None,
|
|
73
|
+
install_command: str | None = None,
|
|
74
|
+
use_build_cache: bool = True,
|
|
75
|
+
) -> str:
|
|
76
|
+
"""Deploy a new application to Fleet from a GitHub repository.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
repo_url: Full HTTPS clone URL of the GitHub repo (e.g. https://github.com/owner/repo.git)
|
|
80
|
+
name: A name for your application
|
|
81
|
+
branch: Git branch to deploy (default: main)
|
|
82
|
+
port: Internal port your app listens on (default: 3000)
|
|
83
|
+
env_vars: JSON string of environment variables as key-value pairs (e.g. [{"key":"NODE_ENV","value":"production"}])
|
|
84
|
+
build_command: Custom build command (e.g. npm run build)
|
|
85
|
+
start_command: Custom start command (e.g. npm start)
|
|
86
|
+
custom_domain: Custom domain (DNS must already point to your VPS)
|
|
87
|
+
install_command: Custom install command (e.g. npm install)
|
|
88
|
+
use_build_cache: Whether to use build cache (default: true)
|
|
89
|
+
"""
|
|
90
|
+
payload = {
|
|
91
|
+
"repo_url": repo_url,
|
|
92
|
+
"name": name,
|
|
93
|
+
"branch": branch,
|
|
94
|
+
"port": port,
|
|
95
|
+
"use_build_cache": use_build_cache,
|
|
96
|
+
}
|
|
97
|
+
if env_vars:
|
|
98
|
+
try:
|
|
99
|
+
payload["env_vars"] = json.loads(env_vars)
|
|
100
|
+
except json.JSONDecodeError:
|
|
101
|
+
return f"Invalid JSON for env_vars: {env_vars}"
|
|
102
|
+
if build_command:
|
|
103
|
+
payload["build_command"] = build_command
|
|
104
|
+
if start_command:
|
|
105
|
+
payload["start_command"] = start_command
|
|
106
|
+
if custom_domain:
|
|
107
|
+
payload["custom_domain"] = custom_domain
|
|
108
|
+
if install_command:
|
|
109
|
+
payload["install_command"] = install_command
|
|
110
|
+
|
|
111
|
+
data = _api_call("POST", "/api/apps/deploy", json=payload, headers=_get_headers())
|
|
112
|
+
return json.dumps(data, indent=2)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
@mcp.tool()
|
|
116
|
+
def list_apps() -> str:
|
|
117
|
+
"""List all your deployed applications and their current status."""
|
|
118
|
+
data = _api_call("GET", "/api/apps", headers=_get_headers())
|
|
119
|
+
if not data.get("apps"):
|
|
120
|
+
return "No applications deployed yet."
|
|
121
|
+
result = []
|
|
122
|
+
for app in data["apps"]:
|
|
123
|
+
result.append(f"- {app['name']} ({app['status']}) — {app.get('domain', 'no domain')}")
|
|
124
|
+
return "\n".join(result)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
@mcp.tool()
|
|
128
|
+
def get_app_status(app_id: int) -> str:
|
|
129
|
+
"""Get the live deployment status of an application.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
app_id: The numeric ID of the application
|
|
133
|
+
"""
|
|
134
|
+
data = _api_call("GET", f"/api/apps/{app_id}/status", headers=_get_headers())
|
|
135
|
+
return json.dumps(data, indent=2)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
@mcp.tool()
|
|
139
|
+
def get_app_logs(app_id: int, log_type: str = "deployment") -> str:
|
|
140
|
+
"""Fetch logs for an application.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
app_id: The numeric ID of the application
|
|
144
|
+
log_type: Type of logs to fetch — 'deployment' for build logs, 'runtime' for live app logs
|
|
145
|
+
"""
|
|
146
|
+
data = _api_call(
|
|
147
|
+
"GET", f"/api/apps/{app_id}/logs?log_type={log_type}", headers=_get_headers()
|
|
148
|
+
)
|
|
149
|
+
return data.get("logs", json.dumps(data, indent=2))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@mcp.tool()
|
|
153
|
+
def redeploy_app(app_id: int, force: bool = False) -> str:
|
|
154
|
+
"""Trigger a redeploy of an existing application.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
app_id: The numeric ID of the application to redeploy
|
|
158
|
+
force: If true, force a rebuild without cache
|
|
159
|
+
"""
|
|
160
|
+
params = f"?force={'true' if force else 'false'}"
|
|
161
|
+
data = _api_call("POST", f"/api/apps/{app_id}/redeploy{params}", headers=_get_headers())
|
|
162
|
+
return data.get("message", json.dumps(data, indent=2))
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
@mcp.tool()
|
|
166
|
+
def update_envs(app_id: int, env_vars: str) -> str:
|
|
167
|
+
"""Set environment variables for an application. Replaces all existing variables.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
app_id: The numeric ID of the application
|
|
171
|
+
env_vars: JSON string of environment variables, e.g. [{"key":"DATABASE_URL","value":"postgres://..."}]
|
|
172
|
+
"""
|
|
173
|
+
try:
|
|
174
|
+
envs = json.loads(env_vars)
|
|
175
|
+
except json.JSONDecodeError:
|
|
176
|
+
return f"Invalid JSON: {env_vars}"
|
|
177
|
+
data = _api_call(
|
|
178
|
+
"POST", f"/api/apps/{app_id}/envs", json={"envs": envs}, headers=_get_headers()
|
|
179
|
+
)
|
|
180
|
+
return data.get("message", json.dumps(data, indent=2))
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
@mcp.tool()
|
|
184
|
+
def deploy_database(
|
|
185
|
+
name: str,
|
|
186
|
+
db_type: str = "postgresql",
|
|
187
|
+
password: str | None = None,
|
|
188
|
+
) -> str:
|
|
189
|
+
"""Deploy a new database to Fleet.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
name: A name for your database
|
|
193
|
+
db_type: Type of database — postgresql, mysql, mongodb, or redis
|
|
194
|
+
password: Optional password. If blank, Fleet auto-generates a secure one.
|
|
195
|
+
"""
|
|
196
|
+
payload = {"name": name, "db_type": db_type}
|
|
197
|
+
if password:
|
|
198
|
+
payload["password"] = password
|
|
199
|
+
data = _api_call("POST", "/api/databases/deploy", json=payload, headers=_get_headers())
|
|
200
|
+
return json.dumps(data, indent=2)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
@mcp.tool()
|
|
204
|
+
def list_databases() -> str:
|
|
205
|
+
"""List all your deployed databases and their status."""
|
|
206
|
+
data = _api_call("GET", "/api/databases", headers=_get_headers())
|
|
207
|
+
if not data.get("databases"):
|
|
208
|
+
return "No databases deployed yet."
|
|
209
|
+
result = []
|
|
210
|
+
for db in data["databases"]:
|
|
211
|
+
result.append(f"- {db['name']} ({db['db_type']}) — {db.get('status', 'unknown')}")
|
|
212
|
+
return "\n".join(result)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
@mcp.tool()
|
|
216
|
+
def get_vps_info() -> str:
|
|
217
|
+
"""View your VPS information including IP address, specs, and storage usage."""
|
|
218
|
+
data = _api_call("GET", "/api/vps/info", headers=_get_headers())
|
|
219
|
+
return json.dumps(data, indent=2)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
@mcp.tool()
|
|
223
|
+
def get_user_info() -> str:
|
|
224
|
+
"""View your Fleet account profile and usage summary."""
|
|
225
|
+
data = _api_call("GET", "/api/user/me", headers=_get_headers())
|
|
226
|
+
return json.dumps(data, indent=2)
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def main():
|
|
230
|
+
mcp.run()
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fleethost-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for Fleet hosting platform — deploy apps and databases from any MCP-compatible agent
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: mcp>=1.6.0
|
|
9
|
+
Requires-Dist: httpx>=0.28.0
|
|
10
|
+
|
|
11
|
+
# fleethost-mcp
|
|
12
|
+
|
|
13
|
+
MCP server for [Fleet](https://fleethost.space) — deploy applications and databases from any MCP-compatible agent (Claude CLI, Cline, opencode, etc.).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install fleethost-mcp
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Configuration
|
|
22
|
+
|
|
23
|
+
Add to your agent's MCP config:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"fleet": {
|
|
29
|
+
"command": "fleethost-mcp",
|
|
30
|
+
"args": []
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
1. Start a conversation with your agent
|
|
39
|
+
2. Say: "Deploy my app to Fleet"
|
|
40
|
+
3. Agent will ask for your Fleet credentials once
|
|
41
|
+
4. Token is cached for future sessions
|
|
42
|
+
|
|
43
|
+
## Tools
|
|
44
|
+
|
|
45
|
+
| Tool | Description |
|
|
46
|
+
|------|-------------|
|
|
47
|
+
| `login` | Authenticate with your Fleet account |
|
|
48
|
+
| `deploy_app` | Deploy a new application |
|
|
49
|
+
| `list_apps` | List all your applications |
|
|
50
|
+
| `get_app_status` | Get live deployment status |
|
|
51
|
+
| `get_app_logs` | Fetch deployment or runtime logs |
|
|
52
|
+
| `redeploy_app` | Trigger a redeploy |
|
|
53
|
+
| `update_envs` | Set environment variables |
|
|
54
|
+
| `deploy_database` | Deploy a database (PostgreSQL, MySQL, MongoDB, Redis) |
|
|
55
|
+
| `list_databases` | List all your databases |
|
|
56
|
+
| `get_vps_info` | View VPS info and storage usage |
|
|
57
|
+
| `get_user_info` | View your Fleet profile |
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/fleet_mcp/__init__.py
|
|
4
|
+
src/fleet_mcp/__main__.py
|
|
5
|
+
src/fleet_mcp/server.py
|
|
6
|
+
src/fleethost_mcp.egg-info/PKG-INFO
|
|
7
|
+
src/fleethost_mcp.egg-info/SOURCES.txt
|
|
8
|
+
src/fleethost_mcp.egg-info/dependency_links.txt
|
|
9
|
+
src/fleethost_mcp.egg-info/entry_points.txt
|
|
10
|
+
src/fleethost_mcp.egg-info/requires.txt
|
|
11
|
+
src/fleethost_mcp.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
fleet_mcp
|