@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/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { HostStack } from "@hoststack.dev/sdk";
4
4
 
5
5
  // src/version.ts
6
- var MCP_VERSION = true ? "0.22.0" : "0.0.0-dev";
6
+ var MCP_VERSION = true ? "0.24.0" : "0.0.0-dev";
7
7
  var USER_AGENT = `hoststack-mcp/${MCP_VERSION}`;
8
8
 
9
9
  // src/api-client.ts
@@ -2132,6 +2132,61 @@ defineTool({
2132
2132
  });
2133
2133
  }
2134
2134
  });
2135
+ defineTool({
2136
+ name: "update_environment",
2137
+ category: "environments",
2138
+ description: [
2139
+ "Rename an environment, change whether it is protected, or make it the project's default.",
2140
+ "",
2141
+ "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.",
2142
+ "",
2143
+ "Inputs:",
2144
+ " - project_id: project publicId.",
2145
+ " - environment_id: environment publicId or numeric id.",
2146
+ " - name (optional): new name, 1\u201364 chars.",
2147
+ " - is_protected (optional): require admin role for destructive actions in this env.",
2148
+ " - is_default (optional): make this the project default. See below.",
2149
+ "",
2150
+ '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.',
2151
+ "",
2152
+ "Returns: { environment: Environment }.",
2153
+ "",
2154
+ 'Example: update_environment({ project_id: "prj_abc", environment_id: "env_xyz", name: "Staging EU" }) \u2192 { environment: { publicId: "env_xyz", name: "Staging EU" } }'
2155
+ ].join("\n"),
2156
+ input: {
2157
+ project_id: z11.string().describe("Project publicId."),
2158
+ environment_id: z11.union([z11.string(), z11.number()]).describe("Environment publicId or numeric id."),
2159
+ name: z11.string().min(1).max(64).optional().describe("New name (1\u201364 chars)."),
2160
+ is_protected: z11.boolean().optional().describe("Require admin role for destructive actions in this env."),
2161
+ is_default: z11.boolean().optional().describe(
2162
+ "Make this the project's default, demoting the current one. Cannot be set false \u2014 promote a different env instead."
2163
+ )
2164
+ },
2165
+ handler: async (args, ctx) => {
2166
+ const teamId = await ctx.resolveTeamId();
2167
+ const input = {};
2168
+ if (args.name !== void 0) input.name = args.name;
2169
+ if (args.is_protected !== void 0) input.isProtected = args.is_protected;
2170
+ if (args.is_default !== void 0) input.isDefault = args.is_default;
2171
+ if (Object.keys(input).length === 0) {
2172
+ return respondError(
2173
+ "Nothing to update. Pass at least one of name, is_protected or is_default."
2174
+ );
2175
+ }
2176
+ const response = await ctx.hoststack.environments.update(
2177
+ teamId,
2178
+ args.project_id,
2179
+ args.environment_id,
2180
+ input
2181
+ );
2182
+ const data = { environment: shape(response.environment) };
2183
+ const fields = Object.keys(input).join(", ");
2184
+ return respond({
2185
+ summary: `Updated ${fields} on environment ${response.environment.name}.`,
2186
+ data
2187
+ });
2188
+ }
2189
+ });
2135
2190
  defineTool({
2136
2191
  name: "delete_environment",
2137
2192
  category: "environments",
@@ -3966,6 +4021,7 @@ defineTool({
3966
4021
  ' - type: "web_service" | "private_service" | "worker" | "cron_job" | "static_site".',
3967
4022
  " - docker_image (optional): pre-built image ref to deploy instead of building from source.",
3968
4023
  " - github_repo_id (optional): connect a previously-linked GitHub repo by numeric id.",
4024
+ " - 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.",
3969
4025
  ' - branch (optional): git branch (default "main").',
3970
4026
  " - install_command / build_command / start_command (optional): build/run shell commands. start_command is required for web/private services without a docker_image.",
3971
4027
  " - cron_schedule (optional): cron expression \u2014 required for cron_job.",
@@ -3991,6 +4047,9 @@ defineTool({
3991
4047
  "Pre-built APPLICATION image ref. Mutually exclusive with github_repo_id. Not for databases \u2014 use create_database for postgres/redis/mysql/mariadb/mongodb."
3992
4048
  ),
3993
4049
  github_repo_id: z19.number().int().positive().optional().describe("Linked GitHub repo numeric id. Mutually exclusive with docker_image."),
4050
+ git_repo_url: z19.string().max(2048).optional().describe(
4051
+ "Public https git URL. No embedded credentials \u2014 private repos need a provider connection. Mutually exclusive with github_repo_id and docker_image."
4052
+ ),
3994
4053
  branch: z19.string().max(200).optional().describe('Git branch (default "main").'),
3995
4054
  install_command: z19.string().max(1e3).optional().describe("Install shell command."),
3996
4055
  build_command: z19.string().max(1e3).optional().describe("Build shell command."),
@@ -4022,6 +4081,7 @@ defineTool({
4022
4081
  };
4023
4082
  if (args.docker_image !== void 0) input.dockerImage = args.docker_image;
4024
4083
  if (args.github_repo_id !== void 0) input.githubRepoId = args.github_repo_id;
4084
+ if (args.git_repo_url !== void 0) input.gitRepoUrl = args.git_repo_url;
4025
4085
  if (args.branch !== void 0) input.branch = args.branch;
4026
4086
  if (args.install_command !== void 0) input.installCommand = args.install_command;
4027
4087
  if (args.build_command !== void 0) input.buildCommand = args.build_command;
@@ -4686,6 +4746,11 @@ defineTool({
4686
4746
  " - scale_cpu_threshold, scale_memory_threshold (optional): integer 10\u2013100 \u2014 autoscale trigger percentage.",
4687
4747
  " - 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.",
4688
4748
  " - 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.",
4749
+ " - 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.",
4750
+ " - 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.",
4751
+ " - cron_schedule (optional): the schedule for a cron_job service. Pass null to clear it.",
4752
+ ' - publish_path (optional): the directory a static_site publishes (e.g. "dist"). Pass null to clear it.',
4753
+ ' - runtime (optional): runtime hint ("node" | "bun" | "python" | \u2026), normally auto-detected from the repo. Set it when the detection is wrong.',
4689
4754
  ` - 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.`,
4690
4755
  "",
4691
4756
  "Returns: { service?: Service, config?: ServiceConfig } \u2014 whichever rows were touched.",
@@ -4728,6 +4793,15 @@ defineTool({
4728
4793
  scale_memory_threshold: z19.number().int().min(10).max(100).optional().describe("Autoscale memory trigger percentage (10\u2013100)."),
4729
4794
  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."),
4730
4795
  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."),
4796
+ plan: z19.enum(SERVICE_PLANS).optional().describe(
4797
+ "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."
4798
+ ),
4799
+ docker_image: z19.string().max(500).nullable().optional().describe(
4800
+ "Repoint an image-backed service. Applies on the next deploy. null clears it."
4801
+ ),
4802
+ cron_schedule: z19.string().max(100).nullable().optional().describe("Cron expression for a cron_job service. null clears it."),
4803
+ publish_path: z19.string().max(500).nullable().optional().describe('Static-site output directory, e.g. "dist". null clears it.'),
4804
+ runtime: z19.string().max(50).optional().describe("Runtime hint (node/bun/python/\u2026). Normally auto-detected."),
4731
4805
  log_filter_rules: z19.array(
4732
4806
  z19.object({
4733
4807
  pattern: z19.string().min(1).max(200),
@@ -4751,6 +4825,10 @@ defineTool({
4751
4825
  if (args.auto_deploy !== void 0) serviceUpdate["autoDeploy"] = args.auto_deploy;
4752
4826
  if (args.health_check_path !== void 0)
4753
4827
  serviceUpdate["healthCheckPath"] = args.health_check_path;
4828
+ if (args.plan !== void 0) serviceUpdate["plan"] = args.plan;
4829
+ if (args.cron_schedule !== void 0) serviceUpdate["cronSchedule"] = args.cron_schedule;
4830
+ if (args.publish_path !== void 0) serviceUpdate["publishPath"] = args.publish_path;
4831
+ if (args.runtime !== void 0) serviceUpdate["runtime"] = args.runtime;
4754
4832
  const configUpdate = {};
4755
4833
  if (args.health_check_enabled !== void 0)
4756
4834
  configUpdate["healthCheckEnabled"] = args.health_check_enabled;
@@ -4786,6 +4864,7 @@ defineTool({
4786
4864
  configUpdate["scaleRequestsPerSecThreshold"] = args.scale_requests_per_sec_threshold;
4787
4865
  if (args.build_timeout_seconds !== void 0)
4788
4866
  configUpdate["buildTimeoutSeconds"] = args.build_timeout_seconds;
4867
+ if (args.docker_image !== void 0) configUpdate["dockerImage"] = args.docker_image;
4789
4868
  if (args.log_filter_rules !== void 0) {
4790
4869
  configUpdate["logFilterRules"] = args.log_filter_rules;
4791
4870
  }