---
id: w1/m24/t004
title: Surfaces — MCP deploy stack form; validate-all-then-apply; REST mapping documented
worker: worker1
status: todo
estimate: 30m
depends_on: [w1/m24/t003]
---

## Objective

The agent path: MCP `deploy` (`{repo, branch?, bexYaml}`) accepts the stack form and returns the set of created resources (services pollable to Ready via `get_service`/`list_deploys`, databases via their status). Partial-failure contract enforced at the verb: all validation runs **before** any write — one invalid entry rejects everything with a per-entry error list; nothing half-created. Document the REST mapping (stack deploys ride the same webhook/upsert paths; no bespoke `/v1/deploy`) in docs/ADR006-bex-api.md + docs/ADR017-deploy-from-chat.md.

## Context

- MCP fragment: `lego/backend/internal/apps/mcp.go` (`deploy` from w2/m2/t002); return shape must stay backward-compatible for single-service calls (list-of-one vs bare object — decide, document).
- GraphQL: no stack mutation (the dashboard has no consumer; DO_NOT_DO picker ban) — record the omission.

## Files

- `lego/backend/internal/apps/mcp.go`
- `docs/ADR006-bex-api.md`, `docs/ADR017-deploy-from-chat.md`

## Acceptance criteria

- [ ] MCP `deploy` with a 3-resource file returns 3 pollable objects; an invalid third entry rejects all three with per-entry errors; single-service calls behave exactly as before.

## Out of scope

- Dashboard anything; a `/blueprints` REST resource (untracked-low, documented in t006).
