@selfhost.dev/mcp-server 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -2
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/auth.js +0 -11
- package/dist/tools/auth.js.map +1 -1
- package/dist/tools/billing.d.ts +2 -0
- package/dist/tools/billing.js +248 -0
- package/dist/tools/billing.js.map +1 -0
- package/dist/tools/database-users.d.ts +2 -0
- package/dist/tools/database-users.js +181 -0
- package/dist/tools/database-users.js.map +1 -0
- package/dist/tools/hetzner.d.ts +2 -0
- package/dist/tools/hetzner.js +263 -0
- package/dist/tools/hetzner.js.map +1 -0
- package/dist/tools/instances.js +58 -85
- package/dist/tools/instances.js.map +1 -1
- package/dist/tools/pgbouncer.d.ts +2 -0
- package/dist/tools/pgbouncer.js +155 -0
- package/dist/tools/pgbouncer.js.map +1 -0
- package/dist/tools/pitr.d.ts +2 -0
- package/dist/tools/pitr.js +196 -0
- package/dist/tools/pitr.js.map +1 -0
- package/dist/tools/scaling.d.ts +2 -0
- package/dist/tools/scaling.js +290 -0
- package/dist/tools/scaling.js.map +1 -0
- package/dist/types/tiers.js +28 -1
- package/dist/types/tiers.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Works with **Claude Code**, **Cursor**, **Windsurf**, **Cline**, and any MCP-com
|
|
|
10
10
|
|
|
11
11
|
### Prerequisites
|
|
12
12
|
|
|
13
|
-
- A [SelfHost.dev](https://selfhost.dev) account
|
|
13
|
+
- A [SelfHost.dev](https://selfhost.dev) account
|
|
14
14
|
- **Node.js 18+** or **Bun**
|
|
15
15
|
|
|
16
16
|
### Install
|
|
@@ -81,6 +81,14 @@ Claude: Authenticates → fetches your orgs → selects org → lists instances
|
|
|
81
81
|
| *"Fork my production database for testing"* | Creates an independent clone with a new password |
|
|
82
82
|
| *"What's my estimated monthly cost for an r6i.xlarge with 500GB gp3?"* | Calculates itemized cost breakdown |
|
|
83
83
|
| *"Tune shared_buffers on my instance"* | Previews defaults, applies the override, syncs to replicas |
|
|
84
|
+
| *"Enable PgBouncer on my prod DB with 200 max clients"* | Configures connection pooling, clients connect on port 6432 |
|
|
85
|
+
| *"Add a read-only database user for the reporting app"* | Creates a DBMS-level credential with the right grants |
|
|
86
|
+
| *"Restore my prod database to 14:30 yesterday into a new instance"* | Sets up a point-in-time recovery from WAL + base backups |
|
|
87
|
+
| *"Scale my instance to r6i.2xlarge and 1TB"* | Issues a manual scale, polls the resize event |
|
|
88
|
+
| *"Auto-stop my staging DB at 7pm weekdays"* | Creates a scheduled scaling policy with start/stop times |
|
|
89
|
+
| *"Upgrade my org to the Pro plan"* | Confirms billing state, creates or changes the subscription |
|
|
90
|
+
| *"Spin up a Postgres instance on Hetzner in Helsinki"* | Confirms provider, walks through Hetzner location + server type, provisions on Hetzner Cloud |
|
|
91
|
+
| *"What cloud providers can I use?"* | Lists AWS and Hetzner with their capabilities so you can pick |
|
|
84
92
|
|
|
85
93
|
### Safety Built In
|
|
86
94
|
|
|
@@ -90,7 +98,7 @@ Destructive operations (delete, stop, reboot) require explicit confirmation. The
|
|
|
90
98
|
|
|
91
99
|
## Features
|
|
92
100
|
|
|
93
|
-
###
|
|
101
|
+
### 111 tools across 14 modules
|
|
94
102
|
|
|
95
103
|
Every tool maps to a real API endpoint. No mock data, no shortcuts.
|
|
96
104
|
|
|
@@ -218,6 +226,76 @@ Monitor your databases and get notified when things go wrong.
|
|
|
218
226
|
| `delete_notification_channel` | Remove channel (with confirmation) |
|
|
219
227
|
| `test_notification_channel` | Send test notification |
|
|
220
228
|
|
|
229
|
+
#### Connection Pooling (PgBouncer)
|
|
230
|
+
PostgreSQL-only. Reduces connection overhead for high-concurrency workloads. Clients connect on port 6432 once enabled.
|
|
231
|
+
|
|
232
|
+
| Tool | Description |
|
|
233
|
+
|------|-------------|
|
|
234
|
+
| `get_pgbouncer` | Get current pooling config (or null if never configured) |
|
|
235
|
+
| `enable_pgbouncer` | Enable pooling with pool mode, max client conn, pool sizes |
|
|
236
|
+
| `reconfigure_pgbouncer` | Apply new settings on an enabled instance (PATCH-style) |
|
|
237
|
+
| `disable_pgbouncer` | Drain pool and disable (with confirmation) |
|
|
238
|
+
|
|
239
|
+
#### Database Users
|
|
240
|
+
DBMS-level credentials — distinct from the SelfHost platform login. Use for apps and people that need their own DB user.
|
|
241
|
+
|
|
242
|
+
| Tool | Description |
|
|
243
|
+
|------|-------------|
|
|
244
|
+
| `list_database_users` | List users with role, status, target DB, expiry metadata |
|
|
245
|
+
| `create_database_user` | Create user with role (read_only / read_write / admin) and optional connection limit + password expiry |
|
|
246
|
+
| `update_database_user` | Change role, connection limit, or password expiry |
|
|
247
|
+
| `delete_database_user` | Soft-delete user (with confirmation) — drops active connections |
|
|
248
|
+
| `rotate_database_user_password` | Rotate password (with confirmation) — new value shown once |
|
|
249
|
+
|
|
250
|
+
#### Scaling
|
|
251
|
+
Manual one-off resize plus auto-scaling policies (reactive metric-based, scheduled cron, and auto start/stop).
|
|
252
|
+
|
|
253
|
+
| Tool | Description |
|
|
254
|
+
|------|-------------|
|
|
255
|
+
| `scale_instance` | Manual resize — change instance type, volume type, size, IOPS, throughput |
|
|
256
|
+
| `list_scaling_policies` | List policies, optionally filtered to one instance |
|
|
257
|
+
| `create_scaling_policy` | Create policy — reactive metric breach, scheduled cron, or auto start/stop schedule |
|
|
258
|
+
| `update_scaling_policy` | Modify thresholds, schedule, or action details |
|
|
259
|
+
| `delete_scaling_policy` | Remove a policy (with confirmation) |
|
|
260
|
+
|
|
261
|
+
#### 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 — the source is untouched.
|
|
263
|
+
|
|
264
|
+
| Tool | Description |
|
|
265
|
+
|------|-------------|
|
|
266
|
+
| `get_pitr` | Current config + restore window (oldest / latest restorable moments) |
|
|
267
|
+
| `enable_pitr` | Set up WAL archiving to an S3 bucket with retention days |
|
|
268
|
+
| `configure_pitr` | Toggle between `enabled` (resume) and `disabled` (pause) |
|
|
269
|
+
| `retry_pitr` | Retry after an `error` state (e.g. fix IAM, then retry) |
|
|
270
|
+
| `trigger_pitr_base_backup` | Run a one-off base backup now |
|
|
271
|
+
| `list_pitr_base_backups` | List historical base backups with status + timestamps |
|
|
272
|
+
| `restore_pitr` | Restore to a target time into a new instance (with confirmation) |
|
|
273
|
+
|
|
274
|
+
#### Billing & Subscriptions
|
|
275
|
+
Subscription lifecycle and payment-method linking. All endpoints scoped to the active org.
|
|
276
|
+
|
|
277
|
+
| Tool | Description |
|
|
278
|
+
|------|-------------|
|
|
279
|
+
| `get_subscription` | Get current subscription (404 = no subscription, on Free) |
|
|
280
|
+
| `create_subscription` | Start a paid subscription (plan goes `pending` → `active` via Razorpay webhook) |
|
|
281
|
+
| `change_subscription` | Upgrade or downgrade plan (downgrades scheduled at cycle end) |
|
|
282
|
+
| `cancel_subscription` | Cancel — keeps access until cycle end (with confirmation) |
|
|
283
|
+
| `link_billing_payment_method` | Initiate Razorpay link — returns short URL to open in browser |
|
|
284
|
+
| `update_billing_contact` | Update billing phone / tax ID / country / state for invoices |
|
|
285
|
+
|
|
286
|
+
#### Hetzner Cloud (Postgres-only)
|
|
287
|
+
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
|
+
|
|
289
|
+
| Tool | Description |
|
|
290
|
+
|------|-------------|
|
|
291
|
+
| `list_cloud_providers` | List available cloud providers (AWS, Hetzner) with capabilities + the create tool to use for each |
|
|
292
|
+
| `list_hetzner_locations` | Hetzner datacenter locations (fsn1, nbg1, hel1, ash, sin) with country + continent |
|
|
293
|
+
| `list_hetzner_server_types` | Hetzner server types (cpx11–cpx51) with vCPU / RAM / local disk |
|
|
294
|
+
| `create_hetzner_instance` | Provision a Postgres instance on Hetzner Cloud (region, server type, storage size, HA toggle, CIDR allowlist) |
|
|
295
|
+
| `get_hetzner_instance` | Fetch a Hetzner instance's full details by PID |
|
|
296
|
+
| `get_hetzner_instance_status` | Poll provisioning progress (per-step status: network → firewall → ssh_key → server → volume → load_balancer → ansible → finalize) |
|
|
297
|
+
| `delete_hetzner_instance` | Tear down a Hetzner instance and all associated resources (with confirmation) |
|
|
298
|
+
|
|
221
299
|
---
|
|
222
300
|
|
|
223
301
|
## Common Workflows
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,12 @@ import { registerInstanceTools } from "./tools/instances.js";
|
|
|
12
12
|
import { registerPgConfigTools } from "./tools/pg-config.js";
|
|
13
13
|
import { registerBackupTools } from "./tools/backups.js";
|
|
14
14
|
import { registerAlertTools } from "./tools/alerts.js";
|
|
15
|
+
import { registerPgBouncerTools } from "./tools/pgbouncer.js";
|
|
16
|
+
import { registerDatabaseUserTools } from "./tools/database-users.js";
|
|
17
|
+
import { registerScalingTools } from "./tools/scaling.js";
|
|
18
|
+
import { registerPitrTools } from "./tools/pitr.js";
|
|
19
|
+
import { registerBillingTools } from "./tools/billing.js";
|
|
20
|
+
import { registerHetznerTools } from "./tools/hetzner.js";
|
|
15
21
|
const server = new McpServer({
|
|
16
22
|
name: "selfhost",
|
|
17
23
|
version: "0.1.0",
|
|
@@ -32,6 +38,18 @@ registerPgConfigTools(server);
|
|
|
32
38
|
registerBackupTools(server);
|
|
33
39
|
// Module 8: Alerts & Notifications
|
|
34
40
|
registerAlertTools(server);
|
|
41
|
+
// Module 9: PgBouncer connection pooling (Postgres, paid)
|
|
42
|
+
registerPgBouncerTools(server);
|
|
43
|
+
// Module 10: Database users (DBMS-level credentials)
|
|
44
|
+
registerDatabaseUserTools(server);
|
|
45
|
+
// Module 11: Scaling — manual + auto-scaling policies + auto start/stop
|
|
46
|
+
registerScalingTools(server);
|
|
47
|
+
// Module 12: Point-in-Time Recovery (Postgres, Pro+)
|
|
48
|
+
registerPitrTools(server);
|
|
49
|
+
// Module 13: Billing — subscriptions + payment-method linking
|
|
50
|
+
registerBillingTools(server);
|
|
51
|
+
// Module 14: Hetzner Cloud — Postgres-only provision/get/status/delete + provider discovery
|
|
52
|
+
registerHetznerTools(server);
|
|
35
53
|
// Server utility tools
|
|
36
54
|
server.tool("reauthenticate", "Clear stored credentials and sign in again (use to switch accounts or fix auth issues)", {}, async () => {
|
|
37
55
|
try {
|
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;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/auth.js
CHANGED
|
@@ -40,17 +40,6 @@ export function registerAuthTools(server) {
|
|
|
40
40
|
server.tool("create_or_login_user", "Create your account or log in (called automatically on first use). Returns user profile.", {}, async () => {
|
|
41
41
|
const result = await apiRequest("/users", { method: "POST", toolName: "create_or_login_user", skipOrgInjection: true });
|
|
42
42
|
if (!result.success) {
|
|
43
|
-
if (result.statusCode === 403) {
|
|
44
|
-
return {
|
|
45
|
-
content: [{
|
|
46
|
-
type: "text",
|
|
47
|
-
text: `Platform access denied. ${result.message}\nSelfHost is invite-only. Ask an existing user to send you an invite, or join the waitlist.`,
|
|
48
|
-
}],
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
if (result.statusCode === 409) {
|
|
52
|
-
return { content: [{ type: "text", text: `Already on the waitlist. ${result.message}` }] };
|
|
53
|
-
}
|
|
54
43
|
return { content: [{ type: "text", text: `Login failed (${result.statusCode}): ${result.message}` }] };
|
|
55
44
|
}
|
|
56
45
|
const user = result.data;
|
package/dist/tools/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/tools/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,SAAS,cAAc,CAAC,IAAU;IAChC,OAAO,CAAC,OAAO,CAAC;QACd,EAAE,EAAE,IAAI,CAAC,EAAE;QACX,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,WAAW,EAAE,IAAI,CAAC,YAAY;QAC9B,OAAO,EAAE,IAAI,CAAC,cAAc,KAAK,CAAC,CAAC;KACpC,CAAC,CAAC;IACH,wEAAwE;AAC1E,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,6FAA6F,EAC7F,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,MAAM,UAAU,CAAO,gBAAgB,EAAE,EAAE,QAAQ,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QAClH,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,+BAA+B,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;QACvH,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAK,CAAC;QAC1B,cAAc,CAAC,IAAI,CAAC,CAAC;QAErB,MAAM,KAAK,GAAa;YACtB,GAAG,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,GAAG;YACpD,mBAAmB,IAAI,CAAC,cAAc,EAAE;YACxC,mBAAmB,IAAI,CAAC,cAAc,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,EAAE;SAC5F,CAAC;QAEF,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,2FAA2F,CAAC,CAAC;QAC9G,CAAC;aAAM,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC;YACnC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,oGAAoG,CAAC,CAAC;QACvH,CAAC;QAED,OAAO;YACL,OAAO,EAAE;gBACP,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACxC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;aACtD;SACF,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,0FAA0F,EAC1F,EAAE,EACF,KAAK,IAAI,EAAE;QACT,MAAM,MAAM,GAAG,MAAM,UAAU,CAAO,QAAQ,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC9H,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/tools/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { apiRequest } from "../client.js";
|
|
3
|
+
import { session } from "../session.js";
|
|
4
|
+
/**
|
|
5
|
+
* Billing — subscription lifecycle + payment method linking.
|
|
6
|
+
*
|
|
7
|
+
* Endpoints:
|
|
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
|
+
*
|
|
15
|
+
* All endpoints are org-scoped via the path. The org PID is taken from the
|
|
16
|
+
* MCP session by default; pass `organization_id` to target a different org.
|
|
17
|
+
*
|
|
18
|
+
* Note: actually entering card details happens in a browser (Razorpay
|
|
19
|
+
* checkout). `link_billing_payment_method` returns the short URL the user
|
|
20
|
+
* needs to open; it does not complete the payment flow from here.
|
|
21
|
+
*/
|
|
22
|
+
const PLANS = ["free", "starter", "pro", "enterprise"];
|
|
23
|
+
function resolveOrgId(organization_id) {
|
|
24
|
+
return organization_id || session.getActiveOrgId();
|
|
25
|
+
}
|
|
26
|
+
const noOrgMessage = "No organization selected. Call `select_organization` first or pass an organization_id.";
|
|
27
|
+
export function registerBillingTools(server) {
|
|
28
|
+
server.tool("get_subscription", "Get the current billing subscription for an organization. Returns 404 (success=false, statusCode=404) for orgs that have never subscribed (i.e. on Free from day one). Response includes billing_plan, lifecycle_state (pending | active | past_due | cancelling | cancelled | paused | revoked), next_billing_date, and Razorpay metadata.", {
|
|
29
|
+
organization_id: z.string().optional()
|
|
30
|
+
.describe("Org PID (defaults to active org)"),
|
|
31
|
+
}, async ({ organization_id }) => {
|
|
32
|
+
const orgId = resolveOrgId(organization_id);
|
|
33
|
+
if (!orgId) {
|
|
34
|
+
return { content: [{ type: "text", text: noOrgMessage }] };
|
|
35
|
+
}
|
|
36
|
+
const result = await apiRequest(`/organizations/${orgId}/billing/subscription`, {
|
|
37
|
+
toolName: "get_subscription",
|
|
38
|
+
skipOrgInjection: true,
|
|
39
|
+
});
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
return {
|
|
42
|
+
content: [{
|
|
43
|
+
type: "text",
|
|
44
|
+
text: `Failed to get subscription (${result.statusCode}): ${result.message}`,
|
|
45
|
+
}],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
return { content: [{ type: "text", text: JSON.stringify(result.data, null, 2) }] };
|
|
49
|
+
});
|
|
50
|
+
server.tool("create_subscription", "Start a paid subscription on an organization that doesn't have one yet. BE optimistically flips org.billing_plan + lifecycle_state=`pending`, then awaits the Razorpay `subscription.activated` webhook to move it to `active`. If the org isn't already linked (no payment method), call `link_billing_payment_method` first.", {
|
|
51
|
+
organization_id: z.string().optional(),
|
|
52
|
+
billing_plan: z.enum(PLANS).describe("Target plan (starter | pro | enterprise)"),
|
|
53
|
+
}, async ({ organization_id, billing_plan }) => {
|
|
54
|
+
if (billing_plan === "free") {
|
|
55
|
+
return {
|
|
56
|
+
content: [{
|
|
57
|
+
type: "text",
|
|
58
|
+
text: "Free is the default — no subscription needed. Use `change_subscription` with billing_plan=free to downgrade an existing paid subscription.",
|
|
59
|
+
}],
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const orgId = resolveOrgId(organization_id);
|
|
63
|
+
if (!orgId) {
|
|
64
|
+
return { content: [{ type: "text", text: noOrgMessage }] };
|
|
65
|
+
}
|
|
66
|
+
const result = await apiRequest(`/organizations/${orgId}/billing/subscriptions`, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
body: { organization: { billing_plan } },
|
|
69
|
+
toolName: "create_subscription",
|
|
70
|
+
skipOrgInjection: true,
|
|
71
|
+
});
|
|
72
|
+
if (!result.success) {
|
|
73
|
+
return {
|
|
74
|
+
content: [{
|
|
75
|
+
type: "text",
|
|
76
|
+
text: `Failed to create subscription (${result.statusCode}): ${result.message}`,
|
|
77
|
+
}],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
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 — poll \`get_subscription\`.` },
|
|
83
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
84
|
+
],
|
|
85
|
+
};
|
|
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) — surface the BE error message to the user.", {
|
|
88
|
+
organization_id: z.string().optional(),
|
|
89
|
+
billing_plan: z.enum(PLANS).describe("Target plan"),
|
|
90
|
+
}, async ({ organization_id, billing_plan }) => {
|
|
91
|
+
const orgId = resolveOrgId(organization_id);
|
|
92
|
+
if (!orgId) {
|
|
93
|
+
return { content: [{ type: "text", text: noOrgMessage }] };
|
|
94
|
+
}
|
|
95
|
+
const result = await apiRequest(`/organizations/${orgId}/billing/subscriptions`, {
|
|
96
|
+
method: "PATCH",
|
|
97
|
+
body: { organization: { billing_plan } },
|
|
98
|
+
toolName: "change_subscription",
|
|
99
|
+
skipOrgInjection: true,
|
|
100
|
+
});
|
|
101
|
+
if (!result.success) {
|
|
102
|
+
return {
|
|
103
|
+
content: [{
|
|
104
|
+
type: "text",
|
|
105
|
+
text: `Failed to change subscription (${result.statusCode}): ${result.message}`,
|
|
106
|
+
}],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
content: [
|
|
111
|
+
{ type: "text", text: `Subscription change requested to \`${billing_plan}\`. Upgrades apply immediately; downgrades are scheduled at cycle end.` },
|
|
112
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
113
|
+
],
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
server.tool("cancel_subscription", "Cancel the active subscription. BE moves the org to `cancelling` for the rest of the current billing cycle, then `cancelled` (which drops to Free with reduced caps). Resources above Free caps remain reachable but new ones cannot be created.", {
|
|
117
|
+
organization_id: z.string().optional(),
|
|
118
|
+
confirm: z.boolean().describe("Must be true to proceed. Cancellation takes effect at the end of the current billing cycle."),
|
|
119
|
+
}, async ({ organization_id, confirm }) => {
|
|
120
|
+
if (!confirm) {
|
|
121
|
+
return {
|
|
122
|
+
content: [{
|
|
123
|
+
type: "text",
|
|
124
|
+
text: `⚠️ About to CANCEL the subscription on the active org. You'll keep access until the end of the current billing cycle, then drop to Free.\n\nCall again with confirm=true to proceed.`,
|
|
125
|
+
}],
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const orgId = resolveOrgId(organization_id);
|
|
129
|
+
if (!orgId) {
|
|
130
|
+
return { content: [{ type: "text", text: noOrgMessage }] };
|
|
131
|
+
}
|
|
132
|
+
const result = await apiRequest(`/organizations/${orgId}/billing/subscriptions`, {
|
|
133
|
+
method: "DELETE",
|
|
134
|
+
toolName: "cancel_subscription",
|
|
135
|
+
skipOrgInjection: true,
|
|
136
|
+
});
|
|
137
|
+
if (!result.success) {
|
|
138
|
+
return {
|
|
139
|
+
content: [{
|
|
140
|
+
type: "text",
|
|
141
|
+
text: `Failed to cancel subscription (${result.statusCode}): ${result.message}`,
|
|
142
|
+
}],
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
content: [
|
|
147
|
+
{ type: "text", text: "Subscription cancellation scheduled — org will move to `cancelling` until cycle end, then `cancelled`." },
|
|
148
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
server.tool("link_billing_payment_method", "Initiate Razorpay payment-method linking. Returns a `short_url` the user must open in a browser to add a card / UPI. Until they do, paid features stay locked. `billing_contact_phone` is required; tax_id / country_code / state_code are optional and only used for invoices.", {
|
|
153
|
+
organization_id: z.string().optional(),
|
|
154
|
+
billing_contact_phone: z.string().min(1)
|
|
155
|
+
.describe("Required by Razorpay (E.164 preferred, e.g. +14155551234)"),
|
|
156
|
+
billing_email: z.string().email().optional()
|
|
157
|
+
.describe("Defaults to the current user's email on the BE if omitted"),
|
|
158
|
+
tax_id: z.string().optional()
|
|
159
|
+
.describe("GSTIN / VAT / equivalent for invoices"),
|
|
160
|
+
country_code: z.string().optional()
|
|
161
|
+
.describe("ISO 3166-1 alpha-2, e.g. IN, US, GB"),
|
|
162
|
+
state_code: z.string().optional()
|
|
163
|
+
.describe("ISO 3166-2 region code, e.g. KA for Karnataka"),
|
|
164
|
+
}, async ({ organization_id, billing_contact_phone, billing_email, tax_id, country_code, state_code }) => {
|
|
165
|
+
const orgId = resolveOrgId(organization_id);
|
|
166
|
+
if (!orgId) {
|
|
167
|
+
return { content: [{ type: "text", text: noOrgMessage }] };
|
|
168
|
+
}
|
|
169
|
+
const orgFields = {
|
|
170
|
+
billing_contact_phone,
|
|
171
|
+
};
|
|
172
|
+
if (billing_email)
|
|
173
|
+
orgFields.billing_email = billing_email;
|
|
174
|
+
if (tax_id)
|
|
175
|
+
orgFields.tax_id = tax_id;
|
|
176
|
+
if (country_code)
|
|
177
|
+
orgFields.country_code = country_code;
|
|
178
|
+
if (state_code)
|
|
179
|
+
orgFields.state_code = state_code;
|
|
180
|
+
const result = await apiRequest(`/organizations/${orgId}/billing/link`, {
|
|
181
|
+
method: "POST",
|
|
182
|
+
body: { organization: orgFields },
|
|
183
|
+
toolName: "link_billing_payment_method",
|
|
184
|
+
skipOrgInjection: true,
|
|
185
|
+
});
|
|
186
|
+
if (!result.success) {
|
|
187
|
+
return {
|
|
188
|
+
content: [{
|
|
189
|
+
type: "text",
|
|
190
|
+
text: `Failed to start billing link (${result.statusCode}): ${result.message}`,
|
|
191
|
+
}],
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
return {
|
|
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 — it's a browser-only flow." },
|
|
197
|
+
{ type: "text", text: JSON.stringify(result.data, null, 2) },
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
});
|
|
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
|
+
organization_id: z.string().optional(),
|
|
203
|
+
billing_contact_phone: z.string().optional(),
|
|
204
|
+
tax_id: z.string().optional()
|
|
205
|
+
.describe("Pass empty string to clear"),
|
|
206
|
+
country_code: z.string().optional(),
|
|
207
|
+
state_code: z.string().optional(),
|
|
208
|
+
}, async ({ organization_id, billing_contact_phone, tax_id, country_code, state_code }) => {
|
|
209
|
+
const orgId = resolveOrgId(organization_id);
|
|
210
|
+
if (!orgId) {
|
|
211
|
+
return { content: [{ type: "text", text: noOrgMessage }] };
|
|
212
|
+
}
|
|
213
|
+
const orgFields = {};
|
|
214
|
+
if (billing_contact_phone !== undefined && billing_contact_phone.length > 0) {
|
|
215
|
+
orgFields.billing_contact_phone = billing_contact_phone;
|
|
216
|
+
}
|
|
217
|
+
if (tax_id !== undefined)
|
|
218
|
+
orgFields.tax_id = tax_id;
|
|
219
|
+
if (country_code !== undefined)
|
|
220
|
+
orgFields.country_code = country_code;
|
|
221
|
+
if (state_code !== undefined)
|
|
222
|
+
orgFields.state_code = state_code;
|
|
223
|
+
if (Object.keys(orgFields).length === 0) {
|
|
224
|
+
return {
|
|
225
|
+
content: [{
|
|
226
|
+
type: "text",
|
|
227
|
+
text: "No changes to apply — pass at least one of billing_contact_phone / tax_id / country_code / state_code.",
|
|
228
|
+
}],
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
const result = await apiRequest(`/organizations/${orgId}/billing/contact`, {
|
|
232
|
+
method: "PATCH",
|
|
233
|
+
body: { organization: orgFields },
|
|
234
|
+
toolName: "update_billing_contact",
|
|
235
|
+
skipOrgInjection: true,
|
|
236
|
+
});
|
|
237
|
+
if (!result.success) {
|
|
238
|
+
return {
|
|
239
|
+
content: [{
|
|
240
|
+
type: "text",
|
|
241
|
+
text: `Failed to update billing contact (${result.statusCode}): ${result.message}`,
|
|
242
|
+
}],
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return { content: [{ type: "text", text: "Billing contact updated." }] };
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=billing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"billing.js","sourceRoot":"","sources":["../../src/tools/billing.ts"],"names":[],"mappings":"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"}
|