Get or create an unnamed environment for a composed stack
GET-OR-CREATE an UNNAMED, content-addressed environment for a composed stack — a host plus an optional server group, model override, computer image and pinned skills.
Distinct from POST /environments, which mints a NAMED row that lands in the project’s environment list forever. A composed stack is a throwaway: the caller wants to run this exact combination, not to add a permanent entry someone else has to reason about.
Deduplicated by a server-side fingerprint of the stack, so the same stack always returns the same environment. created says which happened — the status is 200 either way, because get-or-create cannot honestly answer 201 on the dedupe path.
A deployment that predates ad-hoc environments answers 400 with details.reason: "ADHOC_UNAVAILABLE".
Requires project membership (admin only when the stack pins plugin versions). Promote one to a named environment with POST /environments/{environmentId}/name.
Authorizations
MCPJam API key (sk_…). Create one at Settings → API keys. Guest sessions cannot use the API, and API keys cannot manage other API keys.
Path Parameters
ID of the hosted project that contains the server.
Body
A composed stack: the same execution axes a named environment carries, minus the name.
The host the stack runs as.
Standalone server group to pin. Omit to use the host's own servers.
Model to run instead of the host's pinned one. Stored verbatim.
An explicit pinned skill selection. Cannot be empty — clear the field instead (send null on update) to mean "no pinned skills".
Pinning plugin versions requires project ADMIN; the rest of a stack needs only membership.
1Project-shared sandbox image to pin, so runs boot a fresh computer from it.
Response
The environment for this stack, created or reused.
An UNNAMED, content-addressed environment: a composed client/model/computer/skills stack rather than a saved entry in the project's environment list. Its own shape rather than ProjectEnvironment with a nullable name, because that schema's name is required and every environment listing filters ad-hoc rows out precisely so that promise holds.
false when the same stack had already been composed. The only way to tell a first compose from a repeat — the status line cannot, because get-or-create answers 200 either way.

