@selfhost.dev/mcp-server 0.3.0 → 0.4.1
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 +147 -24
- package/dist/auth.d.ts +1 -1
- package/dist/auth.js +3 -3
- package/dist/client.js +1 -1
- package/dist/config.js +1 -1
- package/dist/index.js +29 -4
- package/dist/index.js.map +1 -1
- package/dist/rate-limiter.js +1 -1
- package/dist/tools/billing.js +14 -14
- package/dist/tools/credentials.js +1 -1
- package/dist/tools/database-users.js +9 -9
- package/dist/tools/deployment-domains.d.ts +2 -0
- package/dist/tools/deployment-domains.js +128 -0
- package/dist/tools/deployment-domains.js.map +1 -0
- package/dist/tools/deployment-notifications.d.ts +2 -0
- package/dist/tools/deployment-notifications.js +74 -0
- package/dist/tools/deployment-notifications.js.map +1 -0
- package/dist/tools/deployments.d.ts +2 -0
- package/dist/tools/deployments.js +302 -0
- package/dist/tools/deployments.js.map +1 -0
- package/dist/tools/env-vars.d.ts +2 -0
- package/dist/tools/env-vars.js +121 -0
- package/dist/tools/env-vars.js.map +1 -0
- package/dist/tools/github.d.ts +2 -0
- package/dist/tools/github.js +106 -0
- package/dist/tools/github.js.map +1 -0
- package/dist/tools/hetzner.js +13 -13
- package/dist/tools/instances.js +11 -11
- package/dist/tools/pgbouncer.js +4 -4
- package/dist/tools/pitr.js +16 -16
- package/dist/tools/project-databases.d.ts +2 -0
- package/dist/tools/project-databases.js +169 -0
- package/dist/tools/project-databases.js.map +1 -0
- package/dist/tools/project-services.d.ts +2 -0
- package/dist/tools/project-services.js +93 -0
- package/dist/tools/project-services.js.map +1 -0
- package/dist/tools/projects.d.ts +2 -0
- package/dist/tools/projects.js +141 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/scaling.js +13 -13
- package/dist/types/models.js +1 -1
- package/dist/types/tiers.js +31 -1
- package/dist/types/tiers.js.map +1 -1
- package/package.json +10 -3
package/README.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# SelfHost MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The [SelfHost](https://selfhost.dev) cloud platform, one sentence away inside your AI coding assistant. Spin up production databases, ship apps straight from GitHub, wire up domains and environment variables, and watch builds stream live, all in plain English without ever leaving your editor.
|
|
4
|
+
|
|
5
|
+
SelfHost pairs the power of production-grade managed databases with the effortless, deploy-from-GitHub simplicity of a modern app platform. This [Model Context Protocol](https://modelcontextprotocol.io/) server puts the whole thing at your fingertips.
|
|
6
|
+
|
|
7
|
+
**Two products, one server:**
|
|
8
|
+
|
|
9
|
+
- **Projects** - your apps, shipped. Connect a GitHub repo, click deploy, and it's live: auto-detected builds (Nixpacks, Dockerfile, Docker Compose, or static), auto-deploy on every push, live streaming build logs, environment variables, custom domains, pause and resume to scale to zero, and databases right inside the project. The ease of Railway, Render, and Vercel, with nothing to manage.
|
|
10
|
+
- **Managed Databases** - production-grade database hosting, your way. PostgreSQL, MySQL, and MongoDB on AWS, or Postgres on Hetzner, in our cloud or your own account (BYOC), with backups, point-in-time recovery, autoscaling, alerting, and connection pooling.
|
|
4
11
|
|
|
5
12
|
Works with **Claude Code**, **Cursor**, **Windsurf**, **Cline**, and any MCP-compatible client.
|
|
6
13
|
|
|
@@ -57,7 +64,7 @@ That's it. The server handles authentication, token refresh, and everything else
|
|
|
57
64
|
|
|
58
65
|
### First Run
|
|
59
66
|
|
|
60
|
-
On first use, the MCP server opens your browser to sign in via SelfHost's console. After you authorize, credentials are saved locally (`~/.selfhost/credentials.json`) and auto-refreshed
|
|
67
|
+
On first use, the MCP server opens your browser to sign in via SelfHost's console. After you authorize, credentials are saved locally (`~/.selfhost/credentials.json`) and auto-refreshed - you won't need to sign in again.
|
|
61
68
|
|
|
62
69
|
```
|
|
63
70
|
You: "Show me my databases"
|
|
@@ -70,7 +77,29 @@ Claude: Authenticates → fetches your orgs → selects org → lists instances
|
|
|
70
77
|
|
|
71
78
|
## What Can You Do?
|
|
72
79
|
|
|
73
|
-
|
|
80
|
+
Talk to both products in plain English.
|
|
81
|
+
|
|
82
|
+
### Ship and run apps with Projects
|
|
83
|
+
|
|
84
|
+
Connect a repo, deploy, and it's live - SelfHost takes your code from GitHub to a running app.
|
|
85
|
+
|
|
86
|
+
| You say | What happens |
|
|
87
|
+
|---------|-------------|
|
|
88
|
+
| *"Create a project and deploy my GitHub repo into it"* | Provisions the project, waits until it's ready, auto-detects the build, and deploys the repo |
|
|
89
|
+
| *"Deploy the main branch of my-org/api"* | Creates the deployment, triggers the build, and streams live logs until it's running |
|
|
90
|
+
| *"Turn on auto-deploy so every push ships"* | Enables auto-deploy; future pushes to the branch redeploy automatically |
|
|
91
|
+
| *"Add a private Postgres database to my project"* | Provisions a Postgres database inside the project, with the credentials and visibility you choose |
|
|
92
|
+
| *"Spin up Supabase in this project"* | Deploys the Supabase template alongside your app |
|
|
93
|
+
| *"Set DATABASE_URL on my app and redeploy"* | Updates the env var (without wiping the others) and rolls out the change |
|
|
94
|
+
| *"Point app.example.com at my deployment"* | Attaches the custom domain and returns the exact DNS records to add, then verifies them |
|
|
95
|
+
| *"Show me the build logs for the last deploy"* | Streams the build and container logs for that run |
|
|
96
|
+
| *"Pause my staging app so I stop paying for it"* | Pauses the deployment (scales to zero); resume instantly when you need it |
|
|
97
|
+
| *"Roll back to the last working deploy"* | Re-deploys the commit from the previous successful run |
|
|
98
|
+
| *"Notify my team channel when a deploy fails"* | Binds a notification channel to the app's deploy outcomes |
|
|
99
|
+
|
|
100
|
+
### Manage database infrastructure with Managed Databases
|
|
101
|
+
|
|
102
|
+
Production-grade, standalone database hosting.
|
|
74
103
|
|
|
75
104
|
| You say | What happens |
|
|
76
105
|
|---------|-------------|
|
|
@@ -92,13 +121,13 @@ Claude: Authenticates → fetches your orgs → selects org → lists instances
|
|
|
92
121
|
|
|
93
122
|
### Safety Built In
|
|
94
123
|
|
|
95
|
-
Destructive operations (delete, stop, reboot) require explicit confirmation. The server will always ask before proceeding
|
|
124
|
+
Destructive operations (delete, stop, reboot) require explicit confirmation. The server will always ask before proceeding - you'll never accidentally delete a production database.
|
|
96
125
|
|
|
97
126
|
---
|
|
98
127
|
|
|
99
128
|
## Features
|
|
100
129
|
|
|
101
|
-
###
|
|
130
|
+
### 151 tools across 22 modules
|
|
102
131
|
|
|
103
132
|
Every tool maps to a real API endpoint. No mock data, no shortcuts.
|
|
104
133
|
|
|
@@ -117,7 +146,7 @@ Automatic browser-based sign-in with Firebase. Tokens refresh transparently.
|
|
|
117
146
|
| `reauthenticate` | Sign out and sign in again (switch accounts) |
|
|
118
147
|
|
|
119
148
|
#### Organizations & Team Management
|
|
120
|
-
Multi-tenant
|
|
149
|
+
Multi-tenant - everything is scoped to your org.
|
|
121
150
|
|
|
122
151
|
| Tool | Description |
|
|
123
152
|
|------|-------------|
|
|
@@ -147,7 +176,7 @@ Bring your own AWS account (BYOC) or use SelfHost's managed infrastructure.
|
|
|
147
176
|
| `get_aws_account_info` | AWS account ID and free tier status |
|
|
148
177
|
|
|
149
178
|
#### Networking
|
|
150
|
-
VPCs, subnets, and security groups. Optional
|
|
179
|
+
VPCs, subnets, and security groups. Optional - auto-created during provisioning if not specified.
|
|
151
180
|
|
|
152
181
|
| Tool | Description |
|
|
153
182
|
|------|-------------|
|
|
@@ -237,29 +266,29 @@ PostgreSQL-only. Reduces connection overhead for high-concurrency workloads. Cli
|
|
|
237
266
|
| `disable_pgbouncer` | Drain pool and disable (with confirmation) |
|
|
238
267
|
|
|
239
268
|
#### Database Users
|
|
240
|
-
DBMS-level credentials
|
|
269
|
+
DBMS-level credentials - distinct from the SelfHost platform login. Use for apps and people that need their own DB user.
|
|
241
270
|
|
|
242
271
|
| Tool | Description |
|
|
243
272
|
|------|-------------|
|
|
244
273
|
| `list_database_users` | List users with role, status, target DB, expiry metadata |
|
|
245
274
|
| `create_database_user` | Create user with role (read_only / read_write / admin) and optional connection limit + password expiry |
|
|
246
275
|
| `update_database_user` | Change role, connection limit, or password expiry |
|
|
247
|
-
| `delete_database_user` | Soft-delete user (with confirmation)
|
|
248
|
-
| `rotate_database_user_password` | Rotate password (with confirmation)
|
|
276
|
+
| `delete_database_user` | Soft-delete user (with confirmation) - drops active connections |
|
|
277
|
+
| `rotate_database_user_password` | Rotate password (with confirmation) - new value shown once |
|
|
249
278
|
|
|
250
279
|
#### Scaling
|
|
251
280
|
Manual one-off resize plus auto-scaling policies (reactive metric-based, scheduled cron, and auto start/stop).
|
|
252
281
|
|
|
253
282
|
| Tool | Description |
|
|
254
283
|
|------|-------------|
|
|
255
|
-
| `scale_instance` | Manual resize
|
|
284
|
+
| `scale_instance` | Manual resize - change instance type, volume type, size, IOPS, throughput |
|
|
256
285
|
| `list_scaling_policies` | List policies, optionally filtered to one instance |
|
|
257
|
-
| `create_scaling_policy` | Create policy
|
|
286
|
+
| `create_scaling_policy` | Create policy - reactive metric breach, scheduled cron, or auto start/stop schedule |
|
|
258
287
|
| `update_scaling_policy` | Modify thresholds, schedule, or action details |
|
|
259
288
|
| `delete_scaling_policy` | Remove a policy (with confirmation) |
|
|
260
289
|
|
|
261
290
|
#### Point-in-Time Recovery (PITR)
|
|
262
|
-
PostgreSQL-only, Pro+. Continuous WAL archiving to S3 + restore to any second within the retention window. Restore creates a brand-new instance
|
|
291
|
+
PostgreSQL-only, Pro+. Continuous WAL archiving to S3 + restore to any second within the retention window. Restore creates a brand-new instance - the source is untouched.
|
|
263
292
|
|
|
264
293
|
| Tool | Description |
|
|
265
294
|
|------|-------------|
|
|
@@ -279,18 +308,18 @@ Subscription lifecycle and payment-method linking. All endpoints scoped to the a
|
|
|
279
308
|
| `get_subscription` | Get current subscription (404 = no subscription, on Free) |
|
|
280
309
|
| `create_subscription` | Start a paid subscription (plan goes `pending` → `active` via Razorpay webhook) |
|
|
281
310
|
| `change_subscription` | Upgrade or downgrade plan (downgrades scheduled at cycle end) |
|
|
282
|
-
| `cancel_subscription` | Cancel
|
|
283
|
-
| `link_billing_payment_method` | Initiate Razorpay link
|
|
311
|
+
| `cancel_subscription` | Cancel - keeps access until cycle end (with confirmation) |
|
|
312
|
+
| `link_billing_payment_method` | Initiate Razorpay link - returns short URL to open in browser |
|
|
284
313
|
| `update_billing_contact` | Update billing phone / tax ID / country / state for invoices |
|
|
285
314
|
|
|
286
315
|
#### Hetzner Cloud (Postgres-only)
|
|
287
|
-
Provisioning on Hetzner Cloud as an alternative to AWS. Currently provision / get / status / delete only
|
|
316
|
+
Provisioning on Hetzner Cloud as an alternative to AWS. Currently provision / get / status / delete only - no start / stop / reboot / update / scaling / PITR / pooling yet. Call `list_cloud_providers` at the start of any create-database intent to surface both options to the user.
|
|
288
317
|
|
|
289
318
|
| Tool | Description |
|
|
290
319
|
|------|-------------|
|
|
291
320
|
| `list_cloud_providers` | List available cloud providers (AWS, Hetzner) with capabilities + the create tool to use for each |
|
|
292
321
|
| `list_hetzner_locations` | Hetzner datacenter locations (fsn1, nbg1, hel1, ash, sin) with country + continent |
|
|
293
|
-
| `list_hetzner_server_types` | Hetzner server types (cpx11
|
|
322
|
+
| `list_hetzner_server_types` | Hetzner server types (cpx11-cpx51) with vCPU / RAM / local disk |
|
|
294
323
|
| `create_hetzner_instance` | Provision a Postgres instance on Hetzner Cloud (region, server type, storage size, HA toggle, CIDR allowlist) |
|
|
295
324
|
| `get_hetzner_instance` | Fetch a Hetzner instance's full details by PID |
|
|
296
325
|
| `get_hetzner_instance_status` | Poll provisioning progress (per-step status: network → firewall → ssh_key → server → volume → load_balancer → ansible → finalize) |
|
|
@@ -298,8 +327,102 @@ Provisioning on Hetzner Cloud as an alternative to AWS. Currently provision / ge
|
|
|
298
327
|
|
|
299
328
|
---
|
|
300
329
|
|
|
330
|
+
### PaaS - Projects (app containers)
|
|
331
|
+
A **project** is a per-app container: a provisioned server + Coolify install + wildcard DNS that deployments, databases, and services attach to. Creation is async (~2-5 min) - poll `get_project` until status is `active` before deploying into it.
|
|
332
|
+
|
|
333
|
+
| Tool | Description |
|
|
334
|
+
|------|-------------|
|
|
335
|
+
| `list_projects` | List projects in the org (pid, name, status, public_ip, domain) |
|
|
336
|
+
| `get_project` | Get one project; poll this for provisioning progress (active / failed) |
|
|
337
|
+
| `create_project` | Create a project and start async provisioning (returns status `pending`) |
|
|
338
|
+
| `update_project` | Rename / re-describe a project |
|
|
339
|
+
| `delete_project` | Tear down the server and everything in the project (with confirmation; blocked while provisioning or with running deployments) |
|
|
340
|
+
| `get_project_metrics` | Time-series server + database + deployment metrics from the monitoring agent (start_date/end_date) |
|
|
341
|
+
|
|
342
|
+
### PaaS - Deployments (GitHub apps)
|
|
343
|
+
A **deployment** is an app built from a GitHub repo, living inside an `active` project. Build/run history is returned inline on the deployment.
|
|
344
|
+
|
|
345
|
+
| Tool | Description |
|
|
346
|
+
|------|-------------|
|
|
347
|
+
| `list_deployments` | List apps in the org, each with inline build runs (newest 50) |
|
|
348
|
+
| `get_deployment` | Get one app + runs; poll this for deploy/run progress |
|
|
349
|
+
| `create_deployment` | Deploy a GitHub repo into a project (repo_url, branch, build_pack, port, env_vars, …) |
|
|
350
|
+
| `update_deployment` | Pause/resume, toggle auto-deploy, set ignore_paths / max preview deployments |
|
|
351
|
+
| `update_deployment_build_config` | Change build_pack / base_directory / port / dockerfile / env_vars |
|
|
352
|
+
| `delete_deployment` | Remove the app and its Coolify resources (with confirmation) |
|
|
353
|
+
| `trigger_deploy` | Manually deploy the current branch (new run) |
|
|
354
|
+
| `get_deployment_logs` | Current application/container logs |
|
|
355
|
+
| `get_deployment_health` | Reachability of the deploy URL + attached domains |
|
|
356
|
+
| `get_run_logs` | Full build + container logs for one run (poll until terminal) |
|
|
357
|
+
| `redeploy_run` | Re-run a build from the same commit |
|
|
358
|
+
| `rollback_run` | Re-deploy the commit from a prior successful run |
|
|
359
|
+
|
|
360
|
+
### PaaS - Custom Domains
|
|
361
|
+
| Tool | Description |
|
|
362
|
+
|------|-------------|
|
|
363
|
+
| `add_deployment_domain` | Attach a custom domain to a deployment (returns DNS records to add) |
|
|
364
|
+
| `sync_deployment_domains` | Set the full domain list for a deployment (set primary / remove several) |
|
|
365
|
+
| `remove_deployment_domain` | Remove one domain from a deployment |
|
|
366
|
+
| `verify_custom_domain` | Check DNS (TXT + CNAME) and advance verification → live HTTPS |
|
|
367
|
+
| `list_custom_domains` | List the org's custom-domain verification states |
|
|
368
|
+
|
|
369
|
+
### PaaS - Environment Variables
|
|
370
|
+
| Tool | Description |
|
|
371
|
+
|------|-------------|
|
|
372
|
+
| `list_env_vars` | List a deployment's env vars (values returned in cleartext) |
|
|
373
|
+
| `set_env_vars` | **Replace** the entire env-var set (omitted keys are deleted) |
|
|
374
|
+
| `merge_env_vars` | Add/update env vars without deleting others (safe upsert) |
|
|
375
|
+
| `delete_env_var` | Remove one variable by key |
|
|
376
|
+
|
|
377
|
+
### PaaS - GitHub
|
|
378
|
+
| Tool | Description |
|
|
379
|
+
|------|-------------|
|
|
380
|
+
| `list_github_installations` | Connected GitHub App installations + their accessible repos |
|
|
381
|
+
| `list_repo_branches` | Branches for a repo via an installation |
|
|
382
|
+
| `detect_repo_config` | Auto-detect build_pack / port / monorepo dirs / env-var hints for a repo |
|
|
383
|
+
| `get_github_connect_url` | Get a browser URL to connect GitHub (interactive; then re-list installations) |
|
|
384
|
+
|
|
385
|
+
### PaaS - Project Databases
|
|
386
|
+
Postgres/Redis/MySQL/MongoDB provisioned inside a project (distinct from AWS/Hetzner managed instances).
|
|
387
|
+
|
|
388
|
+
| Tool | Description |
|
|
389
|
+
|------|-------------|
|
|
390
|
+
| `list_project_databases` | List databases attached to a project |
|
|
391
|
+
| `create_project_database` | Provision a Postgres/Redis/MySQL/MongoDB in a project (type-specific credentials) |
|
|
392
|
+
| `delete_project_database` | Delete a project database (exact name match + confirmation) |
|
|
393
|
+
|
|
394
|
+
### PaaS - Project Services (templates)
|
|
395
|
+
| Tool | Description |
|
|
396
|
+
|------|-------------|
|
|
397
|
+
| `list_project_services` | List service-template instances (e.g. Supabase) in a project |
|
|
398
|
+
| `create_project_service` | Deploy a service template (currently `supabase`) into a project |
|
|
399
|
+
| `delete_project_service` | Delete a project service (exact name match + confirmation) |
|
|
400
|
+
|
|
401
|
+
### PaaS - Deployment Notifications
|
|
402
|
+
| Tool | Description |
|
|
403
|
+
|------|-------------|
|
|
404
|
+
| `list_deployment_notification_bindings` | Channels notified on a deployment's deploy outcomes |
|
|
405
|
+
| `bind_deployment_notification_channel` | Notify an org channel (nchan_…) on deploy success/failure |
|
|
406
|
+
| `unbind_deployment_notification_channel` | Stop notifying a channel for a deployment |
|
|
407
|
+
|
|
408
|
+
---
|
|
409
|
+
|
|
301
410
|
## Common Workflows
|
|
302
411
|
|
|
412
|
+
### Deploy an app from GitHub (Projects)
|
|
413
|
+
|
|
414
|
+
```
|
|
415
|
+
You: "Deploy my-org/web to a new project"
|
|
416
|
+
|
|
417
|
+
Claude: Creates a project → polls until it's provisioned and active
|
|
418
|
+
→ detects the build config from the repo (build pack, port)
|
|
419
|
+
→ creates the deployment and triggers the first build
|
|
420
|
+
→ streams the build logs until the app is live
|
|
421
|
+
→ hands you the deploy URL
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Then: *"add a private Postgres to it"*, *"set my env vars"*, *"point app.example.com at it"*, or *"turn on auto-deploy"* to round out the app.
|
|
425
|
+
|
|
303
426
|
### Switch AWS Account (BYOC vs Platform-Managed)
|
|
304
427
|
|
|
305
428
|
```
|
|
@@ -370,12 +493,12 @@ Reference data lookups (regions, instance types, storage types) are unlimited.
|
|
|
370
493
|
| `API_URL` | `https://api.selfhost.dev` | SelfHost API endpoint |
|
|
371
494
|
| `CONSOLE_URL` | `https://console.selfhost.dev` | SelfHost Console URL (for browser auth) |
|
|
372
495
|
| `TIER` | Auto-detected | Override rate limit tier (`FREE`, `STARTER`, `PRO`, `ENTERPRISE`, `ADMIN`) |
|
|
373
|
-
| `FIREBASE_API_KEY` |
|
|
374
|
-
| `FIREBASE_REFRESH_TOKEN` |
|
|
496
|
+
| `FIREBASE_API_KEY` | - | Skip browser auth (CI/headless) |
|
|
497
|
+
| `FIREBASE_REFRESH_TOKEN` | - | Skip browser auth (CI/headless) |
|
|
375
498
|
|
|
376
499
|
### Local Development
|
|
377
500
|
|
|
378
|
-
Both `API_URL` and `CONSOLE_URL` are optional overrides
|
|
501
|
+
Both `API_URL` and `CONSOLE_URL` are optional overrides - they default to the production endpoints when not set.
|
|
379
502
|
|
|
380
503
|
**1. Local Rails API + Local Console**
|
|
381
504
|
|
|
@@ -452,7 +575,7 @@ Set `FIREBASE_API_KEY` and `FIREBASE_REFRESH_TOKEN` environment variables to ski
|
|
|
452
575
|
## Security
|
|
453
576
|
|
|
454
577
|
- **Credentials stored locally** at `~/.selfhost/credentials.json` with `chmod 0600` (owner-only read/write)
|
|
455
|
-
- **JWT auto-refresh**
|
|
456
|
-
- **Sensitive fields stripped**
|
|
457
|
-
- **Destructive operations gated**
|
|
458
|
-
- **No console.log**
|
|
578
|
+
- **JWT auto-refresh** - tokens refresh 5 minutes before expiry, refresh tokens are rotated
|
|
579
|
+
- **Sensitive fields stripped** - passwords, AWS keys, tokens, and secrets are redacted from API responses
|
|
580
|
+
- **Destructive operations gated** - delete, stop, and reboot require explicit `confirm: true`
|
|
581
|
+
- **No console.log** - all logging goes to stderr to avoid corrupting the MCP JSON-RPC stream on stdout
|
package/dist/auth.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export declare function wasAuthPrompted(): Promise<boolean>;
|
|
|
2
2
|
export declare function markAuthPrompted(): Promise<void>;
|
|
3
3
|
/**
|
|
4
4
|
* Returns true if credentials are available (env vars or stored file).
|
|
5
|
-
* No network calls
|
|
5
|
+
* No network calls - just a fast file existence check.
|
|
6
6
|
*/
|
|
7
7
|
export declare function hasCredentials(): Promise<boolean>;
|
|
8
8
|
/**
|
package/dist/auth.js
CHANGED
|
@@ -130,7 +130,7 @@ async function resolveCredentials() {
|
|
|
130
130
|
}
|
|
131
131
|
/**
|
|
132
132
|
* Returns true if credentials are available (env vars or stored file).
|
|
133
|
-
* No network calls
|
|
133
|
+
* No network calls - just a fast file existence check.
|
|
134
134
|
*/
|
|
135
135
|
export async function hasCredentials() {
|
|
136
136
|
if (config.firebaseApiKey && config.firebaseRefreshToken)
|
|
@@ -169,7 +169,7 @@ async function _getValidTokenImpl() {
|
|
|
169
169
|
return jwt;
|
|
170
170
|
}
|
|
171
171
|
catch {
|
|
172
|
-
// Refresh token expired
|
|
172
|
+
// Refresh token expired - re-authenticate via browser
|
|
173
173
|
cachedJwt = null;
|
|
174
174
|
jwtExpiresAt = 0;
|
|
175
175
|
const newCreds = await browserLogin();
|
|
@@ -192,7 +192,7 @@ export async function forceReauth() {
|
|
|
192
192
|
await unlink(config.credentialsPath);
|
|
193
193
|
}
|
|
194
194
|
catch {
|
|
195
|
-
// File may not exist
|
|
195
|
+
// File may not exist - that's fine
|
|
196
196
|
}
|
|
197
197
|
const creds = await browserLogin();
|
|
198
198
|
await saveCredentials(creds.apiKey, creds.refreshToken);
|
package/dist/client.js
CHANGED
|
@@ -63,7 +63,7 @@ export async function apiRequest(path, options = {}) {
|
|
|
63
63
|
};
|
|
64
64
|
}
|
|
65
65
|
catch (error) {
|
|
66
|
-
// Rate limit errors are thrown before fetch
|
|
66
|
+
// Rate limit errors are thrown before fetch - re-throw as-is
|
|
67
67
|
if (error instanceof Error && error.message.includes("Rate limit")) {
|
|
68
68
|
throw error;
|
|
69
69
|
}
|
package/dist/config.js
CHANGED
|
@@ -5,7 +5,7 @@ function log(message) {
|
|
|
5
5
|
const API_URL = process.env.API_URL || "https://api.selfhost.dev";
|
|
6
6
|
const CONSOLE_URL = process.env.CONSOLE_URL || "https://console.selfhost.dev";
|
|
7
7
|
const TIER_OVERRIDE = process.env.TIER;
|
|
8
|
-
// Headless/CI fallback
|
|
8
|
+
// Headless/CI fallback - skip browser login if these are set
|
|
9
9
|
const FIREBASE_API_KEY = process.env.FIREBASE_API_KEY;
|
|
10
10
|
const FIREBASE_REFRESH_TOKEN = process.env.FIREBASE_REFRESH_TOKEN;
|
|
11
11
|
export const config = {
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,14 @@ import { registerScalingTools } from "./tools/scaling.js";
|
|
|
18
18
|
import { registerPitrTools } from "./tools/pitr.js";
|
|
19
19
|
import { registerBillingTools } from "./tools/billing.js";
|
|
20
20
|
import { registerHetznerTools } from "./tools/hetzner.js";
|
|
21
|
+
import { registerProjectTools } from "./tools/projects.js";
|
|
22
|
+
import { registerDeploymentTools } from "./tools/deployments.js";
|
|
23
|
+
import { registerDeploymentDomainTools } from "./tools/deployment-domains.js";
|
|
24
|
+
import { registerEnvVarTools } from "./tools/env-vars.js";
|
|
25
|
+
import { registerGithubTools } from "./tools/github.js";
|
|
26
|
+
import { registerProjectDatabaseTools } from "./tools/project-databases.js";
|
|
27
|
+
import { registerProjectServiceTools } from "./tools/project-services.js";
|
|
28
|
+
import { registerDeploymentNotificationTools } from "./tools/deployment-notifications.js";
|
|
21
29
|
const server = new McpServer({
|
|
22
30
|
name: "selfhost",
|
|
23
31
|
version: "0.1.0",
|
|
@@ -42,14 +50,31 @@ registerAlertTools(server);
|
|
|
42
50
|
registerPgBouncerTools(server);
|
|
43
51
|
// Module 10: Database users (DBMS-level credentials)
|
|
44
52
|
registerDatabaseUserTools(server);
|
|
45
|
-
// Module 11: Scaling
|
|
53
|
+
// Module 11: Scaling - manual + auto-scaling policies + auto start/stop
|
|
46
54
|
registerScalingTools(server);
|
|
47
55
|
// Module 12: Point-in-Time Recovery (Postgres, Pro+)
|
|
48
56
|
registerPitrTools(server);
|
|
49
|
-
// Module 13: Billing
|
|
57
|
+
// Module 13: Billing - subscriptions + payment-method linking
|
|
50
58
|
registerBillingTools(server);
|
|
51
|
-
// Module 14: Hetzner Cloud
|
|
59
|
+
// Module 14: Hetzner Cloud - Postgres-only provision/get/status/delete + provider discovery
|
|
52
60
|
registerHetznerTools(server);
|
|
61
|
+
// ─── PaaS / Apps surface (/api/v1/platform/...) ──────────────────────────────
|
|
62
|
+
// Module 15: Projects - CoolifyProject app-container lifecycle + metrics
|
|
63
|
+
registerProjectTools(server);
|
|
64
|
+
// Module 16: Deployments - GitHub-repo apps, build runs, deploy/redeploy/rollback, logs, health
|
|
65
|
+
registerDeploymentTools(server);
|
|
66
|
+
// Module 17: Custom domains - deployment-scoped add/sync/remove + org DNS verification
|
|
67
|
+
registerDeploymentDomainTools(server);
|
|
68
|
+
// Module 18: Environment variables - list / set (replace) / merge / delete
|
|
69
|
+
registerEnvVarTools(server);
|
|
70
|
+
// Module 19: GitHub - installations (+repos), branches, repo config detection, connect URL
|
|
71
|
+
registerGithubTools(server);
|
|
72
|
+
// Module 20: Project databases - Postgres/Redis/MySQL/MongoDB inside a project
|
|
73
|
+
registerProjectDatabaseTools(server);
|
|
74
|
+
// Module 21: Project services - service templates (Supabase) inside a project
|
|
75
|
+
registerProjectServiceTools(server);
|
|
76
|
+
// Module 22: Deployment notifications - bind/unbind org channels to deploy outcomes
|
|
77
|
+
registerDeploymentNotificationTools(server);
|
|
53
78
|
// Server utility tools
|
|
54
79
|
server.tool("reauthenticate", "Clear stored credentials and sign in again (use to switch accounts or fix auth issues)", {}, async () => {
|
|
55
80
|
try {
|
|
@@ -78,7 +103,7 @@ async function main() {
|
|
|
78
103
|
if (!(await hasCredentials()) && !(await wasAuthPrompted())) {
|
|
79
104
|
markAuthPrompted().catch(() => { });
|
|
80
105
|
getValidToken().catch(() => {
|
|
81
|
-
// Timeout or error
|
|
106
|
+
// Timeout or error - user can retry via any tool call
|
|
82
107
|
});
|
|
83
108
|
}
|
|
84
109
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC1G,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC1G,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,6BAA6B,EAAE,MAAM,+BAA+B,CAAC;AAC9E,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,mCAAmC,EAAE,MAAM,qCAAqC,CAAC;AAE1F,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,UAAU;IAChB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,yBAAyB;AACzB,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE1B,oCAAoC;AACpC,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAElC,8BAA8B;AAC9B,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAEhC,wDAAwD;AACxD,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAEhC,+BAA+B;AAC/B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAE9B,8BAA8B;AAC9B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAE9B,gCAAgC;AAChC,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE5B,mCAAmC;AACnC,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAE3B,0DAA0D;AAC1D,sBAAsB,CAAC,MAAM,CAAC,CAAC;AAE/B,qDAAqD;AACrD,yBAAyB,CAAC,MAAM,CAAC,CAAC;AAElC,wEAAwE;AACxE,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,qDAAqD;AACrD,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAE1B,8DAA8D;AAC9D,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,4FAA4F;AAC5F,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,gFAAgF;AAEhF,yEAAyE;AACzE,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAE7B,gGAAgG;AAChG,uBAAuB,CAAC,MAAM,CAAC,CAAC;AAEhC,uFAAuF;AACvF,6BAA6B,CAAC,MAAM,CAAC,CAAC;AAEtC,2EAA2E;AAC3E,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE5B,2FAA2F;AAC3F,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAE5B,+EAA+E;AAC/E,4BAA4B,CAAC,MAAM,CAAC,CAAC;AAErC,8EAA8E;AAC9E,2BAA2B,CAAC,MAAM,CAAC,CAAC;AAEpC,oFAAoF;AACpF,mCAAmC,CAAC,MAAM,CAAC,CAAC;AAE5C,uBAAuB;AACvB,MAAM,CAAC,IAAI,CAAC,gBAAgB,EAAE,wFAAwF,EAAE,EAAE,EAAE,KAAK,IAAI,EAAE;IACrI,IAAI,CAAC;QACH,OAAO,CAAC,KAAK,EAAE,CAAC;QAChB,MAAM,WAAW,EAAE,CAAC;QACpB,OAAO;YACL,OAAO,EAAE,CAAC;oBACR,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE,oJAAoJ;iBAC3J,CAAC;SACH,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,6BAA6B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC;IACxH,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,KAAK,UAAU,IAAI;IACjB,MAAM,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IAC9C,MAAM,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAExC,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,kBAAkB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEhC,iGAAiG;IACjG,IAAI,CAAC,CAAC,MAAM,cAAc,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,eAAe,EAAE,CAAC,EAAE,CAAC;QAC5D,gBAAgB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACnC,aAAa,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;YACzB,sDAAsD;QACxD,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,MAAM,CAAC,GAAG,CAAC,gBAAgB,GAAG,EAAE,CAAC,CAAC;IAClC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/dist/rate-limiter.js
CHANGED
|
@@ -43,7 +43,7 @@ class RateLimiter {
|
|
|
43
43
|
this.tier = tier;
|
|
44
44
|
this.isAdmin = tier === "ADMIN";
|
|
45
45
|
if (this.isAdmin) {
|
|
46
|
-
config.log("Admin tier set
|
|
46
|
+
config.log("Admin tier set - rate limits disabled.");
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
const tierConfig = TIER_CONFIGS[tier];
|
package/dist/tools/billing.js
CHANGED
|
@@ -2,15 +2,15 @@ import { z } from "zod";
|
|
|
2
2
|
import { apiRequest } from "../client.js";
|
|
3
3
|
import { session } from "../session.js";
|
|
4
4
|
/**
|
|
5
|
-
* Billing
|
|
5
|
+
* Billing - subscription lifecycle + payment method linking.
|
|
6
6
|
*
|
|
7
7
|
* Endpoints:
|
|
8
|
-
* - GET /organizations/:pid/billing/subscription
|
|
9
|
-
* - POST /organizations/:pid/billing/subscriptions
|
|
10
|
-
* - PATCH /organizations/:pid/billing/subscriptions
|
|
11
|
-
* - DELETE /organizations/:pid/billing/subscriptions
|
|
12
|
-
* - POST /organizations/:pid/billing/link
|
|
13
|
-
* - PATCH /organizations/:pid/billing/contact
|
|
8
|
+
* - GET /organizations/:pid/billing/subscription - current subscription
|
|
9
|
+
* - POST /organizations/:pid/billing/subscriptions - create (first time)
|
|
10
|
+
* - PATCH /organizations/:pid/billing/subscriptions - change plan (up/downgrade)
|
|
11
|
+
* - DELETE /organizations/:pid/billing/subscriptions - cancel
|
|
12
|
+
* - POST /organizations/:pid/billing/link - initiate Razorpay link
|
|
13
|
+
* - PATCH /organizations/:pid/billing/contact - update contact / tax info
|
|
14
14
|
*
|
|
15
15
|
* All endpoints are org-scoped via the path. The org PID is taken from the
|
|
16
16
|
* MCP session by default; pass `organization_id` to target a different org.
|
|
@@ -55,7 +55,7 @@ export function registerBillingTools(server) {
|
|
|
55
55
|
return {
|
|
56
56
|
content: [{
|
|
57
57
|
type: "text",
|
|
58
|
-
text: "Free is the default
|
|
58
|
+
text: "Free is the default - no subscription needed. Use `change_subscription` with billing_plan=free to downgrade an existing paid subscription.",
|
|
59
59
|
}],
|
|
60
60
|
};
|
|
61
61
|
}
|
|
@@ -79,12 +79,12 @@ export function registerBillingTools(server) {
|
|
|
79
79
|
}
|
|
80
80
|
return {
|
|
81
81
|
content: [
|
|
82
|
-
{ type: "text", text: `Subscription create requested for plan \`${billing_plan}\`. The lifecycle state will move from \`pending\` to \`active\` once Razorpay confirms
|
|
82
|
+
{ type: "text", text: `Subscription create requested for plan \`${billing_plan}\`. The lifecycle state will move from \`pending\` to \`active\` once Razorpay confirms - poll \`get_subscription\`.` },
|
|
83
83
|
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
84
84
|
],
|
|
85
85
|
};
|
|
86
86
|
});
|
|
87
|
-
server.tool("change_subscription", "Change an existing subscription's plan (upgrade or downgrade). Upgrades apply immediately and prorate; downgrades are scheduled at the end of the current billing cycle. A downgrade may return 422 DOWNGRADE_BLOCKED if the org has resources above the target plan's caps (e.g. >3 instances on Starter)
|
|
87
|
+
server.tool("change_subscription", "Change an existing subscription's plan (upgrade or downgrade). Upgrades apply immediately and prorate; downgrades are scheduled at the end of the current billing cycle. A downgrade may return 422 DOWNGRADE_BLOCKED if the org has resources above the target plan's caps (e.g. >3 instances on Starter) - surface the BE error message to the user.", {
|
|
88
88
|
organization_id: z.string().optional(),
|
|
89
89
|
billing_plan: z.enum(PLANS).describe("Target plan"),
|
|
90
90
|
}, async ({ organization_id, billing_plan }) => {
|
|
@@ -144,7 +144,7 @@ export function registerBillingTools(server) {
|
|
|
144
144
|
}
|
|
145
145
|
return {
|
|
146
146
|
content: [
|
|
147
|
-
{ type: "text", text: "Subscription cancellation scheduled
|
|
147
|
+
{ type: "text", text: "Subscription cancellation scheduled - org will move to `cancelling` until cycle end, then `cancelled`." },
|
|
148
148
|
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
149
149
|
],
|
|
150
150
|
};
|
|
@@ -193,12 +193,12 @@ export function registerBillingTools(server) {
|
|
|
193
193
|
}
|
|
194
194
|
return {
|
|
195
195
|
content: [
|
|
196
|
-
{ type: "text", text: "Razorpay link initiated. Open the `short_url` in a browser to add a card / UPI. The MCP can't complete the checkout
|
|
196
|
+
{ type: "text", text: "Razorpay link initiated. Open the `short_url` in a browser to add a card / UPI. The MCP can't complete the checkout - it's a browser-only flow." },
|
|
197
197
|
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
198
198
|
],
|
|
199
199
|
};
|
|
200
200
|
});
|
|
201
|
-
server.tool("update_billing_contact", "Update billing contact info on an already-linked org. Doesn't re-run Razorpay
|
|
201
|
+
server.tool("update_billing_contact", "Update billing contact info on an already-linked org. Doesn't re-run Razorpay - only persists DB overrides for invoices.", {
|
|
202
202
|
organization_id: z.string().optional(),
|
|
203
203
|
billing_contact_phone: z.string().optional(),
|
|
204
204
|
tax_id: z.string().optional()
|
|
@@ -224,7 +224,7 @@ export function registerBillingTools(server) {
|
|
|
224
224
|
return {
|
|
225
225
|
content: [{
|
|
226
226
|
type: "text",
|
|
227
|
-
text: "No changes to apply
|
|
227
|
+
text: "No changes to apply - pass at least one of billing_contact_phone / tax_id / country_code / state_code.",
|
|
228
228
|
}],
|
|
229
229
|
};
|
|
230
230
|
}
|
|
@@ -15,7 +15,7 @@ When selecting credentials for instance creation:
|
|
|
15
15
|
- Filter by cloud_provider matching the user's chosen provider (e.g. "aws")
|
|
16
16
|
- Only use credentials with status "active"
|
|
17
17
|
- is_platform_managed=true → SelfHost's cloud account (no VPC needed)
|
|
18
|
-
- is_platform_managed=false → user's own cloud account (BYOC
|
|
18
|
+
- is_platform_managed=false → user's own cloud account (BYOC - VPC required, use list_vpcs)
|
|
19
19
|
- Present the user with a choice between platform-managed and their own credentials`, {
|
|
20
20
|
organization_id: z.string().optional().describe("Organization PID (defaults to active org)"),
|
|
21
21
|
}, async ({ organization_id }) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { apiRequest } from "../client.js";
|
|
3
3
|
/**
|
|
4
|
-
* Database users
|
|
4
|
+
* Database users - DBMS-level credentials (distinct from the platform login).
|
|
5
5
|
*
|
|
6
6
|
* Endpoints:
|
|
7
7
|
* - GET /aws/v1/instances/:id/database_users
|
|
@@ -70,12 +70,12 @@ export function registerDatabaseUserTools(server) {
|
|
|
70
70
|
}
|
|
71
71
|
return {
|
|
72
72
|
content: [
|
|
73
|
-
{ type: "text", text: `Database user \`${username}\` create requested. Status will transition from \`pending\` to \`active\` once applied
|
|
73
|
+
{ type: "text", text: `Database user \`${username}\` create requested. Status will transition from \`pending\` to \`active\` once applied - poll \`list_database_users\`.` },
|
|
74
74
|
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
75
75
|
],
|
|
76
76
|
};
|
|
77
77
|
});
|
|
78
|
-
server.tool("update_database_user", "Update a database user
|
|
78
|
+
server.tool("update_database_user", "Update a database user - change role, connection limit, or password expiry. Username and target database are immutable (delete + recreate to change them).", {
|
|
79
79
|
instance_id: z.string().min(1),
|
|
80
80
|
user_id: z.string().min(1).describe("Database user PID (from list_database_users)"),
|
|
81
81
|
role: z.enum(ROLES).optional(),
|
|
@@ -94,7 +94,7 @@ export function registerDatabaseUserTools(server) {
|
|
|
94
94
|
return {
|
|
95
95
|
content: [{
|
|
96
96
|
type: "text",
|
|
97
|
-
text: "No changes to apply
|
|
97
|
+
text: "No changes to apply - pass at least one of role / connection_limit / password_expiry_days.",
|
|
98
98
|
}],
|
|
99
99
|
};
|
|
100
100
|
}
|
|
@@ -114,7 +114,7 @@ export function registerDatabaseUserTools(server) {
|
|
|
114
114
|
}
|
|
115
115
|
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
116
116
|
});
|
|
117
|
-
server.tool("delete_database_user", "Soft-delete a database user. Existing connections opened by this user are terminated. The record is preserved for audit
|
|
117
|
+
server.tool("delete_database_user", "Soft-delete a database user. Existing connections opened by this user are terminated. The record is preserved for audit - contact support to recover.", {
|
|
118
118
|
instance_id: z.string().min(1),
|
|
119
119
|
user_id: z.string().min(1),
|
|
120
120
|
username: z.string().optional().describe("Username for the confirmation message (cosmetic)"),
|
|
@@ -142,9 +142,9 @@ export function registerDatabaseUserTools(server) {
|
|
|
142
142
|
}],
|
|
143
143
|
};
|
|
144
144
|
}
|
|
145
|
-
return { content: [{ type: "text", text: "Database user delete requested
|
|
145
|
+
return { content: [{ type: "text", text: "Database user delete requested - status will move to `deleting` and then disappear from the list." }] };
|
|
146
146
|
});
|
|
147
|
-
server.tool("rotate_database_user_password", "Rotate the password for a database user. The new password is generated server-side and returned ONCE in the response. SECURITY: save it immediately
|
|
147
|
+
server.tool("rotate_database_user_password", "Rotate the password for a database user. The new password is generated server-side and returned ONCE in the response. SECURITY: save it immediately - there is no way to retrieve it later. Existing connections using the old password are terminated.", {
|
|
148
148
|
instance_id: z.string().min(1),
|
|
149
149
|
user_id: z.string().min(1),
|
|
150
150
|
confirm: z.boolean().describe("Must be true. Old password is invalidated immediately; apps and scripts must pick up the new value."),
|
|
@@ -153,7 +153,7 @@ export function registerDatabaseUserTools(server) {
|
|
|
153
153
|
return {
|
|
154
154
|
content: [{
|
|
155
155
|
type: "text",
|
|
156
|
-
text: `⚠️ About to ROTATE the password for database user ${user_id} on instance ${instance_id}.\n\nThe new password is shown ONCE in the response
|
|
156
|
+
text: `⚠️ About to ROTATE the password for database user ${user_id} on instance ${instance_id}.\n\nThe new password is shown ONCE in the response - save it before doing anything else.\nApps and scripts using the old password will lose connections immediately.\n\nCall again with confirm=true to proceed.`,
|
|
157
157
|
}],
|
|
158
158
|
};
|
|
159
159
|
}
|
|
@@ -172,7 +172,7 @@ export function registerDatabaseUserTools(server) {
|
|
|
172
172
|
}
|
|
173
173
|
return {
|
|
174
174
|
content: [
|
|
175
|
-
{ type: "text", text: "🔑 New password generated. Copy it now
|
|
175
|
+
{ type: "text", text: "🔑 New password generated. Copy it now - it will not be shown again." },
|
|
176
176
|
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
177
177
|
],
|
|
178
178
|
};
|