@hoststack.dev/mcp 0.10.1 → 0.11.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 CHANGED
@@ -87,22 +87,22 @@ If `HOSTSTACK_API_KEY` is set in your shell, it gets baked into the snippet; oth
87
87
 
88
88
  60 tools, grouped by resource:
89
89
 
90
- | Category | Read | Write |
91
- | ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
92
- | **projects** | `list_projects`, `get_project` | `create_project`, `update_project` |
93
- | **services** | `list_services`, `get_service`, `get_service_metrics`, `get_service_metrics_history`, `get_service_logs`, `get_service_logs_bulk` | `create_service`, `create_dev_environment`, `update_service`, `update_service_config`, `suspend_service`, `resume_service` |
94
- | **deploys** | `list_deploys`, `get_deploy`, `get_deploy_logs`, `diagnose_deploy` | `trigger_deploy`, `cancel_deploy` |
95
- | **environments** | `list_environments` | `create_environment`, `delete_environment`, `promote_deploy` |
96
- | **databases** | `list_databases`, `get_database`, `get_database_cluster`, `query_database` | `update_database`, `upgrade_database_to_ha` (use the dashboard for create/delete/credentials) |
97
- | **volumes** | `list_volumes` | `create_volume`, `update_volume`, `delete_volume` |
98
- | **domains** | `list_domains` | `add_domain`, `verify_domain`, `remove_domain` |
99
- | **dns** | `list_dns_zones`, `list_dns_records`, `get_dns_record` | `create_dns_record`, `update_dns_record`, `delete_dns_record` |
100
- | **env-vars** | `list_env_vars` | `set_env_var`, `delete_env_var`, `bulk_set_env_vars` |
101
- | **cron** | `list_cron_executions`, `get_cron_execution` | — |
102
- | **notifications** | `list_notification_channels` | `create_notification_channel`, `update_notification_channel`, `delete_notification_channel`, `test_notification_channel` |
103
- | **alerts** | `list_alerts` | — |
104
- | **activity-log** | `list_activity_log` | — |
105
- | **meta** | `get_me` | — |
90
+ | Category | Read | Write |
91
+ | ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
92
+ | **projects** | `list_projects`, `get_project` | `create_project`, `update_project` |
93
+ | **services** | `list_services`, `get_service`, `get_service_metrics`, `get_service_metrics_history`, `get_service_logs`, `get_service_logs_bulk` | `create_service`, `create_dev_environment`, `update_service`, `update_service_config`, `suspend_service`, `resume_service` |
94
+ | **deploys** | `list_deploys`, `get_deploy`, `get_deploy_logs`, `diagnose_deploy` | `trigger_deploy`, `cancel_deploy` |
95
+ | **environments** | `list_environments` | `create_environment`, `delete_environment`, `promote_deploy` |
96
+ | **databases** | `list_databases`, `get_database`, `get_database_cluster`, `query_database` | `update_database`, `upgrade_database_to_ha` (use the dashboard for create/delete/credentials) |
97
+ | **volumes** | `list_volumes` | `create_volume`, `update_volume`, `delete_volume` |
98
+ | **domains** | `list_domains` | `add_domain`, `verify_domain`, `remove_domain` |
99
+ | **dns** | `list_dns_zones`, `list_dns_records`, `get_dns_record` | `create_dns_record`, `update_dns_record`, `delete_dns_record` |
100
+ | **env-vars** | `list_env_vars` | `set_env_var`, `delete_env_var`, `bulk_set_env_vars` |
101
+ | **cron** | `list_cron_executions`, `get_cron_execution` | — |
102
+ | **notifications** | `list_notification_channels` | `create_notification_channel`, `update_notification_channel`, `delete_notification_channel`, `test_notification_channel` |
103
+ | **alerts** | `list_alerts` | — |
104
+ | **activity-log** | `list_activity_log` | — |
105
+ | **meta** | `get_me` | — |
106
106
 
107
107
  A few design notes worth knowing as a caller:
108
108
 
@@ -747,6 +747,36 @@ defineTool({
747
747
  });
748
748
  }
749
749
  });
750
+ defineTool({
751
+ name: "upgrade_database_version",
752
+ category: "databases",
753
+ description: [
754
+ "Upgrade a standalone managed database (postgres or redis) to a newer engine version in place. The agent dumps the live data, recreates the container at the target version under the same DNS name, and restores \u2014 so connection URLs stay valid and services do NOT need a redeploy. The database is briefly unavailable (seconds) during the cut-over; on any failure the original container is rolled back automatically.",
755
+ "",
756
+ "`version` must be a supported, strictly-newer version for the engine (postgres: 18/17/16/15, redis: 8/7/6). Downgrades are rejected. Returns 400 for unsupported engines (mysql/mariadb/mongodb upgrades are not implemented yet), for HA (Patroni) clusters, or if the database is not currently `available`.",
757
+ "",
758
+ "When to use: a customer wants to move to a newer Postgres/Redis major version. Check get_database first \u2014 the `version` field shows the current version; compare against the engine latest.",
759
+ "",
760
+ "Inputs:",
761
+ " - database_id: publicId of the postgres/redis database to upgrade.",
762
+ ' - version: target engine version (e.g. "18" for postgres, "8" for redis).',
763
+ "",
764
+ 'Returns: 202 Accepted. The upgrade is async \u2014 poll get_database until `version` matches the target and `status === "available"` to confirm.',
765
+ "",
766
+ 'Example: upgrade_database_version({ database_id: "db_abc", version: "18" }) \u2192 { ok: true }'
767
+ ].join("\n"),
768
+ input: {
769
+ database_id: z5.string().describe("Database publicId (e.g. db_abc) to upgrade."),
770
+ version: z5.string().describe('Target engine version, e.g. "18" for postgres or "8" for redis.')
771
+ },
772
+ handler: async (args2, ctx) => {
773
+ const teamId = await ctx.resolveTeamId();
774
+ await ctx.hoststack.databases.upgradeVersion(teamId, args2.database_id, args2.version);
775
+ return respond({
776
+ summary: `Version upgrade to v${args2.version} started for ${args2.database_id}. Poll get_database until version=${args2.version} and status=available to confirm.`
777
+ });
778
+ }
779
+ });
750
780
  defineTool({
751
781
  name: "get_database_cluster",
752
782
  category: "databases",
@@ -1986,7 +2016,9 @@ defineTool({
1986
2016
  },
1987
2017
  handler: async (args2, ctx) => {
1988
2018
  const teamId = await ctx.resolveTeamId();
1989
- const input = { name: args2.name };
2019
+ const input = {
2020
+ name: args2.name
2021
+ };
1990
2022
  if (args2.description !== void 0) input.description = args2.description;
1991
2023
  if (args2.region !== void 0) input.region = args2.region;
1992
2024
  const response = await ctx.hoststack.projects.create(teamId, input);
@@ -2062,7 +2094,7 @@ defineTool({
2062
2094
 
2063
2095
  // src/tools/services.ts
2064
2096
  import { z as z13 } from "zod";
2065
- var DEV_ENV_IMAGE = "hoststack/dev-env:claude";
2097
+ var DEV_ENV_IMAGE = "hoststack/dev-env:latest";
2066
2098
  var DEV_ENV_VOLUME = { name: "workspace", mountPath: "/workspace", sizeGb: 10 };
2067
2099
  var SERVICE_TYPES = [
2068
2100
  "web_service",
@@ -2291,11 +2323,85 @@ defineTool({
2291
2323
  const deploy = await ctx.hoststack.deploys.trigger(teamId, service.id);
2292
2324
  const deployId = deploy.deploy?.id ?? null;
2293
2325
  return respond({
2294
- summary: `Created AI dev environment "${name}" (${service.publicId})${volumeAttached ? " with a /workspace volume" : ""} \u2014 deploying. Open its Terminal tab once running.`,
2326
+ summary: `Created AI dev environment "${name}" (${service.publicId})${volumeAttached ? " with a /workspace volume" : ""} \u2014 deploying. Open it in the dashboard's Development section (or the service's Terminal tab) once running.`,
2295
2327
  data: { service: shapeService(service), volumeAttached, deployId }
2296
2328
  });
2297
2329
  }
2298
2330
  });
2331
+ defineTool({
2332
+ name: "spin_up_dev_environment",
2333
+ category: "services",
2334
+ description: [
2335
+ "Spin up an agentic dev environment FROM an existing service so you can reproduce a bug, fix it, view it, and ship it. Creates a dev box (Claude/Codex/OpenCode + MCPs) that RUNS a clone of the app: the repo is auto-cloned into /workspace, the service env-vars are copied, and its linked database is cloned (so the box never touches the prod DB). The box gets an unguessable public dev URL and seamless `git push`.",
2336
+ "",
2337
+ 'When to use: "spin up a dev environment for <service>", "I found a bug on <service>, give me a box to fix it". Distinct from create_dev_environment, which makes a BARE box not tied to any app.',
2338
+ "",
2339
+ "Inputs:",
2340
+ ' - service_id: the source service to debug \u2014 numeric id or publicId ("svc_\u2026").',
2341
+ " - include_database_clone (optional): clone the linked database so the app runs on a copy of real data (default true).",
2342
+ ' - name (optional): dev box name (default "<source>-dev").',
2343
+ "",
2344
+ "Returns: { service, devUrl, deployId }. Once it is live: open the Terminal tab, run `claude`, start the dev server (it must bind $PORT), and view the app at https://<devUrl>. Tear it all down later with delete_dev_environment.",
2345
+ "",
2346
+ 'Example: spin_up_dev_environment({ service_id: "svc_api" }) \u2192 a dev box running a clone of the api service (repo + env-vars + cloned DB) with a public dev URL.'
2347
+ ].join("\n"),
2348
+ input: {
2349
+ service_id: z13.union([z13.number().int().positive(), z13.string()]).describe("Source service to debug \u2014 numeric id or publicId."),
2350
+ include_database_clone: z13.boolean().optional().describe("Clone the linked database so the app runs on copied data (default true)."),
2351
+ name: z13.string().min(1).max(100).optional().describe('Dev box name (default "<source>-dev").')
2352
+ },
2353
+ handler: async (args2, ctx) => {
2354
+ const teamId = await ctx.resolveTeamId();
2355
+ const serviceId = await ctx.hoststack.resolveId(args2.service_id, {
2356
+ kind: "service",
2357
+ teamId
2358
+ });
2359
+ const opts = {};
2360
+ if (args2.include_database_clone !== void 0)
2361
+ opts.includeDatabaseClone = args2.include_database_clone;
2362
+ if (args2.name !== void 0) opts.name = args2.name;
2363
+ const result = await ctx.hoststack.services.spinUpDevEnvironment(teamId, serviceId, opts);
2364
+ return respond({
2365
+ summary: `Spun up dev environment "${result.service.name}" (${result.service.publicId}) \u2014 deploying. Once live: open the Terminal tab, run \`claude\`, start the dev server on $PORT, and view it at https://${result.devUrl}. \`git push\` works from inside.`,
2366
+ data: {
2367
+ service: shapeService(result.service),
2368
+ devUrl: result.devUrl,
2369
+ deployId: result.deployId
2370
+ }
2371
+ });
2372
+ }
2373
+ });
2374
+ defineTool({
2375
+ name: "delete_dev_environment",
2376
+ category: "services",
2377
+ description: [
2378
+ "Tear down an agentic dev environment in one call: removes the dev box AND cascade-deletes its cloned database, its /workspace volume, and the auto-created `development` environment if it is now empty.",
2379
+ "",
2380
+ 'When to use: "delete / tear down the dev environment", once you have shipped the fix and no longer need the box.',
2381
+ "",
2382
+ "Inputs:",
2383
+ " - service_id: the dev box to tear down \u2014 numeric id or publicId.",
2384
+ "",
2385
+ "Returns: { ok: true }. Irreversible \u2014 the cloned database and workspace volume are deleted.",
2386
+ "",
2387
+ 'Example: delete_dev_environment({ service_id: "svc_api_dev" }) \u2192 removes the dev box, its cloned database, and the /workspace volume.'
2388
+ ].join("\n"),
2389
+ input: {
2390
+ service_id: z13.union([z13.number().int().positive(), z13.string()]).describe("The dev box to tear down \u2014 numeric id or publicId.")
2391
+ },
2392
+ handler: async (args2, ctx) => {
2393
+ const teamId = await ctx.resolveTeamId();
2394
+ const serviceId = await ctx.hoststack.resolveId(args2.service_id, {
2395
+ kind: "service",
2396
+ teamId
2397
+ });
2398
+ await ctx.hoststack.services.tearDownDevEnvironment(teamId, serviceId);
2399
+ return respond({
2400
+ summary: "Dev environment torn down \u2014 box, cloned database, /workspace volume, and empty development environment removed.",
2401
+ data: { ok: true }
2402
+ });
2403
+ }
2404
+ });
2299
2405
  defineTool({
2300
2406
  name: "get_service",
2301
2407
  category: "services",