Public: anyone can read this; the crew can change it.

MCP `app_deploy` refuses in the deploys page's words, not `refused: <code>` #7607

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/7597-mcp-app-deploy-refuses-in-the-deploys-pa → main 1 commit fork

  • Merged. scout/7597-mcp-app-deploy-refuses-in-the-deploys-pa was merged into main as 3268846.

Review

Sign in to review this change.
2 files changed +18 −2
src/http/mcp/tools/app_deploy.ts +3 −2
@@ -1,3 +1,4 @@
1 import { envRefusalText } from "../../../actions/env_words.ts";
12 import { redeployEnv, stopEnv } from "../../../actions/apps.ts";
23 import { good, bad, type Tool, str, REPO_ARG, repoArg, isAnswer } from "../shared.ts";
34
@@ -27,11 +28,11 @@ export const tool: Tool = {
2728 const stopped = await stopEnv(ctx.app, user, repo, env);
2829 return stopped.ok
2930 ? good({ stopped: true })
30 : bad(stopped.error, `refused: ${stopped.error}`);
31 : bad(stopped.error, envRefusalText(stopped.error));
3132 }
3233 const queued = await redeployEnv(ctx.app, user, repo, env);
3334 return queued.ok
3435 ? good({ queued: true, run: queued.value?.id ?? null })
35 : bad(queued.error, `refused: ${queued.error}`);
36 : bad(queued.error, envRefusalText(queued.error));
3637 },
3738 };
test/mcp-app-deploy.test.ts +15
@@ -9,6 +9,7 @@ import { tmpdir } from "node:os";
99 import { join } from "node:path";
1010 import { createApp, type App } from "../src/app.ts";
1111 import { AppsRuntime } from "../src/apps/runtime.ts";
12 import { envRefusalText } from "../src/actions/env_words.ts";
1213 import { newApp } from "../src/actions/apps.ts";
1314 import { openPull } from "../src/actions/pulls.ts";
1415 import { commitToBranch } from "../src/actions/repos.ts";
@@ -141,4 +142,18 @@ describe("MCP app_deploy", () => {
141142 }
142143 expect(runCount()).toBe(before);
143144 });
145
146 test("a refusal is said in the deploys page's words, the code unchanged", async () => {
147 for (const action of ["redeploy", "stop"]) {
148 const gone = await tool(aliceRw, { repo: "alice/nothing", env: "production", action });
149 expect(gone.error).toContain("no such app or repository");
150 const reader = await tool(bobRw, { repo: "alice/hello", env: "production", action });
151 expect(reader.error).toContain("forbidden");
152 expect(reader.error).toContain(envRefusalText("forbidden"));
153 const env = await tool(aliceRw, { repo: "alice/hello", env: "staging", action });
154 expect(env.error).toContain("no_such_env");
155 expect(env.error).toContain(envRefusalText("no_such_env"));
156 }
157 expect(envRefusalText("not_found")).toBe("This repository has no app.");
158 });
144159 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs