management MCP/CLI cannot migrate a workspace's compute provider (canvas can) — add migrate-provider #5

Open
opened 2026-06-15 01:23:54 +00:00 by devops-engineer · 1 comment
Member

Gap

The canvas UI can migrate a workspace's compute provider cross-cloud (AWS↔Hetzner↔GCP) — it calls the control-plane migrate-provider endpoint. The management MCP server and molecule CLI cannot: there is no tool/command that triggers a provider migration, so the management surface is inconsistent with what the product already exposes.

Evidence the MCP/CLI can't do it today:

  • MCP update_workspace (server/src/tools/workspaces.ts) exposes name/role/tier/parent_id but no provider/compute field.
  • move_agent is org-structure only; restart_workspace has no provider param.
  • The CLI workspace command group (internal/cmd/workspace*.go) has no migrate verb.

This is a real capability gap, filed against the SSOT-derived tooling chain (OpenAPI → MCP → CLI → docs).

The CP contract (source-verified against molecule-controlplane)

Route (admin surface, gated by AdminGateCP_ADMIN_API_TOKEN):

POST /api/v1/admin/workspaces/{id}/migrate-provider     (alias: /cp/admin/...)
GET  /api/v1/admin/workspaces/{id}/migration-status     (and GET on the POST path)

Handler: internal/handlers/admin_workspace_migrate_provider.goMigrateWorkspaceProvider / GetWorkspaceMigrationStatus. Router: internal/router/router.go.

Request body:

{
  "from": "aws",            // required: aws|hetzner|gcp
  "to":   "hetzner",        // required: aws|hetzner|gcp (must differ from `from`)
  "from_instance_id": "...",// required for non-AWS sources; optional for AWS (tag-resolved, cp#711)
  "org_id":  "...",         // optional hint; resolved from tenant_resources for non-AWS when omitted
  "runtime": "...",         // optional hint; resolved likewise
  "confirm": true           // REQUIRED — refuses without it
}

Responses:

  • 202 {"status":"migration_started","workspace_id","from","to","note"} — runs async (~15-20 min, detached goroutine).
  • 400 — bad/same provider, missing from_instance_id (non-AWS), or confirm not true.
  • 409 — a migration is already in progress for this workspace.
  • 503 — migrator/data-persistence not wired in this env.

GET status → 200 {"migration": <MigrationStatus>, "terminal": bool}. State machine: snapshotting → snapshotted → provisioning_target → target_healthy → retiring_source → completed; terminal = completed | failed | rolled_back.

Auth: CP admin bearer (cpAdminBearer), exactly like POST /api/v1/admin/workspaces/{id}/env. The tenant Org API Key has no standing on the CP — this is a CP-admin operation, modeled alongside the other cpAdminBearer admin ops in management.yaml.

Plan (SSOT-first)

  1. Add the migrate-provider + migration-status operations to the OpenAPI SSOT workspace-server/docs/openapi/management.yaml in molecule-core (request/response/status schemas). [PR in molecule-core]
  2. MCP server: add migrate_workspace_provider + get_workspace_migration_status tools (CP-admin-bearer call path) derived from the spec. Unit tests. [PR in molecule-mcp]
  3. CLI: add molecule workspace migrate-provider --to <p> [--from <p>] <id> + migration-status <id>, via the existing cpAdminClient() path. Tests + --help. [PR in molecule-cli]
  4. Docs: document the capability in platform-management-api (reference + tasks). [PR in docs]

Closes the canvas/management-surface inconsistency.

## Gap The **canvas UI** can migrate a workspace's compute provider cross-cloud (AWS↔Hetzner↔GCP) — it calls the control-plane `migrate-provider` endpoint. The **management MCP server and `molecule` CLI cannot**: there is no tool/command that triggers a provider migration, so the management surface is inconsistent with what the product already exposes. Evidence the MCP/CLI can't do it today: - MCP `update_workspace` (`server/src/tools/workspaces.ts`) exposes `name/role/tier/parent_id` but **no `provider`/`compute` field**. - `move_agent` is org-structure only; `restart_workspace` has no provider param. - The CLI `workspace` command group (`internal/cmd/workspace*.go`) has no migrate verb. This is a real capability gap, filed against the SSOT-derived tooling chain (OpenAPI → MCP → CLI → docs). ## The CP contract (source-verified against `molecule-controlplane`) Route (admin surface, gated by `AdminGate` → `CP_ADMIN_API_TOKEN`): ``` POST /api/v1/admin/workspaces/{id}/migrate-provider (alias: /cp/admin/...) GET /api/v1/admin/workspaces/{id}/migration-status (and GET on the POST path) ``` Handler: `internal/handlers/admin_workspace_migrate_provider.go` → `MigrateWorkspaceProvider` / `GetWorkspaceMigrationStatus`. Router: `internal/router/router.go`. Request body: ```json { "from": "aws", // required: aws|hetzner|gcp "to": "hetzner", // required: aws|hetzner|gcp (must differ from `from`) "from_instance_id": "...",// required for non-AWS sources; optional for AWS (tag-resolved, cp#711) "org_id": "...", // optional hint; resolved from tenant_resources for non-AWS when omitted "runtime": "...", // optional hint; resolved likewise "confirm": true // REQUIRED — refuses without it } ``` Responses: - `202 {"status":"migration_started","workspace_id","from","to","note"}` — runs async (~15-20 min, detached goroutine). - `400` — bad/same provider, missing `from_instance_id` (non-AWS), or `confirm` not true. - `409` — a migration is already in progress for this workspace. - `503` — migrator/data-persistence not wired in this env. GET status → `200 {"migration": <MigrationStatus>, "terminal": bool}`. State machine: `snapshotting → snapshotted → provisioning_target → target_healthy → retiring_source → completed`; terminal = `completed | failed | rolled_back`. Auth: **CP admin bearer** (`cpAdminBearer`), exactly like `POST /api/v1/admin/workspaces/{id}/env`. The tenant Org API Key has no standing on the CP — this is a CP-admin operation, modeled alongside the other `cpAdminBearer` admin ops in `management.yaml`. ## Plan (SSOT-first) 1. Add the `migrate-provider` + `migration-status` operations to the OpenAPI SSOT `workspace-server/docs/openapi/management.yaml` in `molecule-core` (request/response/status schemas). [PR in molecule-core] 2. MCP server: add `migrate_workspace_provider` + `get_workspace_migration_status` tools (CP-admin-bearer call path) derived from the spec. Unit tests. [PR in molecule-mcp] 3. CLI: add `molecule workspace migrate-provider --to <p> [--from <p>] <id>` + `migration-status <id>`, via the existing `cpAdminClient()` path. Tests + `--help`. [PR in molecule-cli] 4. Docs: document the capability in `platform-management-api` (reference + tasks). [PR in docs] Closes the canvas/management-surface inconsistency.
Member

Claimed by Kimi (Engineer-A) for implementation. PR incoming.

Claimed by Kimi (Engineer-A) for implementation. PR incoming.
Sign in to join this conversation.
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-mcp#5