@hoststack.dev/mcp 0.22.0 → 0.24.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
@@ -97,7 +97,7 @@ use by hand — an MCP client is what should be launching it.
97
97
 
98
98
  ## Tool inventory
99
99
 
100
- 107 tools. The headings are the registry's own categories rather than a friendlier regrouping, so the build can diff this table against the registry and fail when the two disagree — which is how an earlier version of it came to advertise a total from three releases back and send agents to the dashboard for a `create_database` that had already shipped.
100
+ 108 tools. The headings are the registry's own categories rather than a friendlier regrouping, so the build can diff this table against the registry and fail when the two disagree — which is how an earlier version of it came to advertise a total from three releases back and send agents to the dashboard for a `create_database` that had already shipped.
101
101
 
102
102
  | Category | Read | Write |
103
103
  | ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -105,7 +105,7 @@ use by hand — an MCP client is what should be launching it.
105
105
  | **services** | `list_services`, `get_service`, `get_service_metrics`, `get_service_metrics_history`, `list_dev_environments`, `list_templates` | `create_service`, `create_dev_environment`, `create_standalone_dev_environment`, `spin_up_dev_environment`, `resize_dev_environment`, `delete_dev_environment`, `update_service`, `update_service_config`, `suspend_service`, `resume_service`, `delete_service` |
106
106
  | **logs** | `get_service_logs`, `get_service_logs_bulk` | — |
107
107
  | **deploys** | `list_deploys`, `get_deploy`, `get_deploy_logs`, `diagnose_deploy` | `trigger_deploy`, `cancel_deploy` |
108
- | **environments** | `list_environments` | `create_environment`, `delete_environment`, `promote_deploy` |
108
+ | **environments** | `list_environments` | `create_environment`, `update_environment`, `delete_environment`, `promote_deploy` |
109
109
  | **databases** | `list_databases`, `get_database`, `get_database_cluster`, `query_database` | `create_database`, `update_database`, `delete_database`, `suspend_database`, `resume_database`, `restart_database`, `upgrade_database_to_ha`, `upgrade_database_version` |
110
110
  | **volumes** | `list_volumes` | `create_volume`, `update_volume`, `delete_volume` |
111
111
  | **resource-links** | `list_managed_resources`, `list_service_resources` | `link_resource_to_service`, `unlink_resource_from_service` |
@@ -8,7 +8,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
8
  import { HostStack } from "@hoststack.dev/sdk";
9
9
 
10
10
  // src/version.ts
11
- var MCP_VERSION = true ? "0.22.0" : "0.0.0-dev";
11
+ var MCP_VERSION = true ? "0.24.0" : "0.0.0-dev";
12
12
  var USER_AGENT = `hoststack-mcp/${MCP_VERSION}`;
13
13
 
14
14
  // src/api-client.ts
@@ -2131,6 +2131,61 @@ defineTool({
2131
2131
  });
2132
2132
  }
2133
2133
  });
2134
+ defineTool({
2135
+ name: "update_environment",
2136
+ category: "environments",
2137
+ description: [
2138
+ "Rename an environment, change whether it is protected, or make it the project's default.",
2139
+ "",
2140
+ "When to use: correcting a name, turning protection on for an env that has become production-like, or promoting a different env to default. Everything else about an environment is fixed at creation \u2014 `type` in particular cannot be changed, because the hostname suffix it drives is already baked into every service in the env.",
2141
+ "",
2142
+ "Inputs:",
2143
+ " - project_id: project publicId.",
2144
+ " - environment_id: environment publicId or numeric id.",
2145
+ " - name (optional): new name, 1\u201364 chars.",
2146
+ " - is_protected (optional): require admin role for destructive actions in this env.",
2147
+ " - is_default (optional): make this the project default. See below.",
2148
+ "",
2149
+ 'is_default is a MOVE, not a flag. Setting it true demotes whichever env is currently default, because a project has exactly one \u2014 and for the same reason you cannot set it false: that would leave the project with none, and every create that omits an envId falls back to the default, so the next `create_service` would fail with "Project has no Production environment". To change which env is default, set is_default true on the one you want; the old one is demoted for you.',
2150
+ "",
2151
+ "Returns: { environment: Environment }.",
2152
+ "",
2153
+ 'Example: update_environment({ project_id: "prj_abc", environment_id: "env_xyz", name: "Staging EU" }) \u2192 { environment: { publicId: "env_xyz", name: "Staging EU" } }'
2154
+ ].join("\n"),
2155
+ input: {
2156
+ project_id: z11.string().describe("Project publicId."),
2157
+ environment_id: z11.union([z11.string(), z11.number()]).describe("Environment publicId or numeric id."),
2158
+ name: z11.string().min(1).max(64).optional().describe("New name (1\u201364 chars)."),
2159
+ is_protected: z11.boolean().optional().describe("Require admin role for destructive actions in this env."),
2160
+ is_default: z11.boolean().optional().describe(
2161
+ "Make this the project's default, demoting the current one. Cannot be set false \u2014 promote a different env instead."
2162
+ )
2163
+ },
2164
+ handler: async (args2, ctx) => {
2165
+ const teamId = await ctx.resolveTeamId();
2166
+ const input = {};
2167
+ if (args2.name !== void 0) input.name = args2.name;
2168
+ if (args2.is_protected !== void 0) input.isProtected = args2.is_protected;
2169
+ if (args2.is_default !== void 0) input.isDefault = args2.is_default;
2170
+ if (Object.keys(input).length === 0) {
2171
+ return respondError(
2172
+ "Nothing to update. Pass at least one of name, is_protected or is_default."
2173
+ );
2174
+ }
2175
+ const response = await ctx.hoststack.environments.update(
2176
+ teamId,
2177
+ args2.project_id,
2178
+ args2.environment_id,
2179
+ input
2180
+ );
2181
+ const data = { environment: shape(response.environment) };
2182
+ const fields = Object.keys(input).join(", ");
2183
+ return respond({
2184
+ summary: `Updated ${fields} on environment ${response.environment.name}.`,
2185
+ data
2186
+ });
2187
+ }
2188
+ });
2134
2189
  defineTool({
2135
2190
  name: "delete_environment",
2136
2191
  category: "environments",
@@ -3965,6 +4020,7 @@ defineTool({
3965
4020
  ' - type: "web_service" | "private_service" | "worker" | "cron_job" | "static_site".',
3966
4021
  " - docker_image (optional): pre-built image ref to deploy instead of building from source.",
3967
4022
  " - github_repo_id (optional): connect a previously-linked GitHub repo by numeric id.",
4023
+ " - git_repo_url (optional): a PUBLIC https git URL, for a repo that is not connected through GitHub. Private repos do not work here \u2014 they need a provider connection, because this field carries no credentials and embedding them in the URL is rejected. Mutually exclusive with github_repo_id and docker_image.",
3968
4024
  ' - branch (optional): git branch (default "main").',
3969
4025
  " - install_command / build_command / start_command (optional): build/run shell commands. start_command is required for web/private services without a docker_image.",
3970
4026
  " - cron_schedule (optional): cron expression \u2014 required for cron_job.",
@@ -3990,6 +4046,9 @@ defineTool({
3990
4046
  "Pre-built APPLICATION image ref. Mutually exclusive with github_repo_id. Not for databases \u2014 use create_database for postgres/redis/mysql/mariadb/mongodb."
3991
4047
  ),
3992
4048
  github_repo_id: z19.number().int().positive().optional().describe("Linked GitHub repo numeric id. Mutually exclusive with docker_image."),
4049
+ git_repo_url: z19.string().max(2048).optional().describe(
4050
+ "Public https git URL. No embedded credentials \u2014 private repos need a provider connection. Mutually exclusive with github_repo_id and docker_image."
4051
+ ),
3993
4052
  branch: z19.string().max(200).optional().describe('Git branch (default "main").'),
3994
4053
  install_command: z19.string().max(1e3).optional().describe("Install shell command."),
3995
4054
  build_command: z19.string().max(1e3).optional().describe("Build shell command."),
@@ -4021,6 +4080,7 @@ defineTool({
4021
4080
  };
4022
4081
  if (args2.docker_image !== void 0) input.dockerImage = args2.docker_image;
4023
4082
  if (args2.github_repo_id !== void 0) input.githubRepoId = args2.github_repo_id;
4083
+ if (args2.git_repo_url !== void 0) input.gitRepoUrl = args2.git_repo_url;
4024
4084
  if (args2.branch !== void 0) input.branch = args2.branch;
4025
4085
  if (args2.install_command !== void 0) input.installCommand = args2.install_command;
4026
4086
  if (args2.build_command !== void 0) input.buildCommand = args2.build_command;
@@ -4685,6 +4745,11 @@ defineTool({
4685
4745
  " - scale_cpu_threshold, scale_memory_threshold (optional): integer 10\u2013100 \u2014 autoscale trigger percentage.",
4686
4746
  " - scale_requests_per_sec_threshold (optional): integer 1\u201310000 \u2014 autoscale on request rate instead of (or alongside) CPU and memory. Pass null to stop scaling on request rate.",
4687
4747
  " - build_timeout_seconds (optional): integer 60\u20131800 \u2014 how long a build may run before it is killed. Raise it for a service whose build legitimately takes longer than the default; pass null to go back to the default.",
4748
+ " - plan (optional): move the service to a different size tier. This is the supported way to grow past the current tier's ceiling \u2014 memory_mb and cpu_shares are CLAMPED to the tier, so raising them alone does nothing once you are at the top of it. Memory and CPU apply to the running container where possible; disk grows on the next recreate. Changing tier changes what the service costs.",
4749
+ " - docker_image (optional): repoint an image-backed service at a different image. Takes effect on the next deploy \u2014 this writes the reference, it does not pull. Pass null to clear it.",
4750
+ " - cron_schedule (optional): the schedule for a cron_job service. Pass null to clear it.",
4751
+ ' - publish_path (optional): the directory a static_site publishes (e.g. "dist"). Pass null to clear it.',
4752
+ ' - runtime (optional): runtime hint ("node" | "bun" | "python" | \u2026), normally auto-detected from the repo. Set it when the detection is wrong.',
4688
4753
  ` - log_filter_rules (optional): list of { pattern, action } rules applied at read time \u2014 to get_service_logs (tail AND count) and to the dashboard's live stream alike. Pattern matches the message by case-insensitive substring, literally (a % or _ is not a wildcard); action is "drop" (filter out) or "downgrade" (flip stderr \u2192 stdout so it stops looking like an error). Stored lines are never altered, so removing a rule re-exposes everything it was hiding. Pass [] to clear all rules. Capped at 50 rules.`,
4689
4754
  "",
4690
4755
  "Returns: { service?: Service, config?: ServiceConfig } \u2014 whichever rows were touched.",
@@ -4727,6 +4792,15 @@ defineTool({
4727
4792
  scale_memory_threshold: z19.number().int().min(10).max(100).optional().describe("Autoscale memory trigger percentage (10\u2013100)."),
4728
4793
  scale_requests_per_sec_threshold: z19.number().int().min(1).max(1e4).nullable().optional().describe("Autoscale request-rate trigger (1\u201310000 req/s). null stops using it."),
4729
4794
  build_timeout_seconds: z19.number().int().min(60).max(1800).nullable().optional().describe("Kill a build that runs longer than this (60\u20131800s). null = default."),
4795
+ plan: z19.enum(SERVICE_PLANS).optional().describe(
4796
+ "Move to a different size tier. memory_mb and cpu_shares are clamped to the tier, so this is what raises the ceiling. Changes cost."
4797
+ ),
4798
+ docker_image: z19.string().max(500).nullable().optional().describe(
4799
+ "Repoint an image-backed service. Applies on the next deploy. null clears it."
4800
+ ),
4801
+ cron_schedule: z19.string().max(100).nullable().optional().describe("Cron expression for a cron_job service. null clears it."),
4802
+ publish_path: z19.string().max(500).nullable().optional().describe('Static-site output directory, e.g. "dist". null clears it.'),
4803
+ runtime: z19.string().max(50).optional().describe("Runtime hint (node/bun/python/\u2026). Normally auto-detected."),
4730
4804
  log_filter_rules: z19.array(
4731
4805
  z19.object({
4732
4806
  pattern: z19.string().min(1).max(200),
@@ -4750,6 +4824,10 @@ defineTool({
4750
4824
  if (args2.auto_deploy !== void 0) serviceUpdate["autoDeploy"] = args2.auto_deploy;
4751
4825
  if (args2.health_check_path !== void 0)
4752
4826
  serviceUpdate["healthCheckPath"] = args2.health_check_path;
4827
+ if (args2.plan !== void 0) serviceUpdate["plan"] = args2.plan;
4828
+ if (args2.cron_schedule !== void 0) serviceUpdate["cronSchedule"] = args2.cron_schedule;
4829
+ if (args2.publish_path !== void 0) serviceUpdate["publishPath"] = args2.publish_path;
4830
+ if (args2.runtime !== void 0) serviceUpdate["runtime"] = args2.runtime;
4753
4831
  const configUpdate = {};
4754
4832
  if (args2.health_check_enabled !== void 0)
4755
4833
  configUpdate["healthCheckEnabled"] = args2.health_check_enabled;
@@ -4785,6 +4863,7 @@ defineTool({
4785
4863
  configUpdate["scaleRequestsPerSecThreshold"] = args2.scale_requests_per_sec_threshold;
4786
4864
  if (args2.build_timeout_seconds !== void 0)
4787
4865
  configUpdate["buildTimeoutSeconds"] = args2.build_timeout_seconds;
4866
+ if (args2.docker_image !== void 0) configUpdate["dockerImage"] = args2.docker_image;
4788
4867
  if (args2.log_filter_rules !== void 0) {
4789
4868
  configUpdate["logFilterRules"] = args2.log_filter_rules;
4790
4869
  }