fix(api): harden task automations for MCP/API clients#3044
Merged
Conversation
Three related hardening fixes for the automation endpoints that customers hit through the MCP server. 1. create-version no longer 500s on a malformed body. The endpoint used an inline, untyped @Body() that the global ValidationPipe could not see, so a missing version/scriptKey reached Prisma and threw a non-null violation (raw 500). Add a validated, documented CreateVersionDto and map Prisma failures to clean responses: duplicate version -> 409, missing -> 404. 2. Bake a finite default request timeout (x-speakeasy-timeout = 120s) into the generated SDK and MCP server. Without it the generated request functions resolve their timeout to -1 ("no timeout"), so a hung upstream call leaves the MCP fetch dangling forever and the client marks the whole connection unhealthy. 120s covers our slowest endpoints while staying under the ALB's 300s idle timeout. 3. Hide the two automation-authoring tools (create-automation, create-version) from the MCP surface. A working automation needs its evidence script generated, and that step lives only in the enterprise-api browser chat, so over MCP these POSTs only ever create an empty shell plus a version row pointing at a script that was never generated. Disable them via the generation overlay until script generation is a first-class endpoint; the HTTP endpoints stay live for the web UI. openapi.json is edited surgically (root key only) to avoid clobbering the open uploads PR (#3042); the full create-version body appears on the next regen. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
1 issue found across 9 files
Confidence score: 4/5
- This PR is likely safe to merge with minimal risk, since the only reported issue is moderate in severity (5/10) and limited to DTO input validation.
- In
apps/api/src/tasks/automations/dto/create-version.dto.ts,scriptKeycurrently allows whitespace-only values, which can let invalid keys pass validation and lead to avoidable downstream handling errors. - Because the impact is concrete but scoped to one validation path (not a clear system-wide break), this is better treated as a follow-up fix than a merge blocker.
- Pay close attention to
apps/api/src/tasks/automations/dto/create-version.dto.ts- tightenscriptKeyvalidation to reject blank/whitespace-only input.
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
Contributor
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Workflows to automatically generate PRs for you. |
@isnotempty() treats a whitespace-only string (" ", "\t\n") as valid, so a blank scriptKey could pass validation and persist a version row whose script can never be fetched at runtime. Trim the value first (type-guarded so non-strings still hit @IsString) so a blank collapses to "" and @isnotempty rejects it; legitimate keys are normalized. Issue identified by cubic on PR #3044. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rdening # Conflicts: # apps/mcp-server/.speakeasy/mcp-uploads-overlay.yaml
Contributor
|
🎉 This PR is included in version 3.72.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Three related hardening fixes for the task automation endpoints — the ones customers reach through the MCP server. Surfaced while triaging Nicole's report (automations behaving badly over MCP). Each is small and safe; none changes the web UI flow.
1.
create-versionreturned a raw 500 on a bad body → now a clean 4xxPOST /v1/tasks/{taskId}/automations/{automationId}/versionsused an inline, untyped@Body(). The globalValidationPipecan't see an inline type, so a request missingversion/scriptKeysailed through to Prisma and threw a non-null constraint violation → 500. It was also invisible in the OpenAPI spec (no documented request body).CreateVersionDto(validated withclass-validator, documented with@ApiProperty+@ApiBody). Missing/invalid fields now fail at validation → 400.(automation, version)→ 409 Conflict; missing automation (FKP2003/P2025) → 404 Not Found. Unexpected errors are rethrown untouched (no masking real 500s).2. The MCP server could hang forever on a slow call → finite request timeout
Speakeasy-generated request functions resolve their timeout to
operationTimeoutMs || clientTimeoutMs || -1, and-1means "no timeout". A slow/hung upstream call left the MCP server's fetch dangling indefinitely; the client eventually marked the whole connection unhealthy (the wedging customers saw).x-speakeasy-timeout: 120000at the OpenAPI document root, both in the generator (applyPublicOpenApiMetadata) and surgically inopenapi.json. The SDK now aborts a stuck request and returns a clean error instead of hanging.comp-privateinfra/modules/loadbalancer.ts).3. Automation-authoring tools are dead-ends over MCP → hidden from the MCP surface
Creating a working automation requires generating its evidence-collection script, and that step lives only in the enterprise-api browser chat (an AI tool writes
.draft.jsto S3; publish copies it to.vN.js). Neither the public API nor MCP can produce that script. So over MCP,create-automationandcreate-versiononly ever create an empty shell + a version row pointing at a script that was never generated — a dead end that confuses agents.x-speakeasy-mcp.disabled: true). The HTTP endpoints stay live for the web UI, which drives the full flow. Read/list/update automation tools remain available over MCP.Tests
automations.service.spec.ts— createVersion success + P2002→409, P2003/P2025→404, unexpected→rethrow.create-version.dto.spec.ts— DTO rejects missingversion/scriptKey,version < 1, emptyscriptKey;changelogoptional.openapi-docs.spec.ts— asserts the document root carriesx-speakeasy-timeout./v1/policies"SOC 2" SEO-copy assertion inopenapi-docs.spec.tsfails onmainalready (curated copy drifted ind8ce45093) — unrelated to this PR.Notes for the reviewer
openapi.jsonis touched surgically (root key only) to avoid clobbering the open uploads PR fix(api): accept presigned s3Key for MCP uploads (attachment/document/evidence) #3042. The fullcreate-versionrequest body will appear on the next natural spec regeneration.mcp-uploads-overlay.yaml. Whichever merges second will hit a trivial conflict — keep both appended action blocks.bun run typecheckhas pre-existing failures in unrelated spec files (variables/risks/timelines/offboarding/training/sync-gws). This PR's files typecheck clean.🤖 Generated with Claude Code
Summary by cubic
Hardens task automation endpoints for MCP/API: adds input validation to prevent 500s, sets a 120s SDK/MCP request timeout to avoid hangs, and hides dead-end automation creation over MCP.
create-version: useCreateVersionDtowith OpenAPI body; reject missing/invalid fields and whitespace-onlyscriptKey; map Prisma P2002→409 and P2003/P2025→404; unexpected errors rethrow.x-speakeasy-timeout: 120000at the OpenAPI root so generated SDK/MCP calls abort instead of hanging; under the ALB’s 300s idle timeout.x-speakeasy-mcp.disabled; HTTP endpoints remain for the web UI.Written for commit 56c42df. Summary will update on new commits.