---
title: "Attach one environment to a suite (atomic append)"
method: POST
path: "/projects/{projectId}/eval-suites/{suiteId}/environments"
tags: ["Eval suites"]
---

# Attach one environment to a suite (atomic append)

`POST /projects/{projectId}/eval-suites/{suiteId}/environments`

APPEND one project environment to the suite's attachments, if it is not already there.

Distinct from `PATCH /eval-suites/{suiteId}` with `environmentIds`, which REPLACES the whole list. An append built on the replace door is a read-modify-write across two round trips, and a concurrent attach landing in between is silently DETACHED. The compose-and-run path attaches on every launch, which makes that race ordinary rather than theoretical, so the append happens inside one transaction instead.

Idempotent: attaching an already-attached environment reports `attached: false` and changes nothing, which is what lets a retried launch converge instead of erroring. Subject to the same cap, membership and schedule-pin rules as the replace door — growing a single-environment suite to two is exactly the edit that strands an enabled unpinned schedule.

## Path parameters

- `projectId` string, required
- `suiteId` string, required

## Request body

- EvalSuiteEnvironmentAttachRequest
  - `environmentId` string, required

## Response `200`

The suite's attachments after the call.

- EvalSuiteEnvironmentAttached
  - `suiteId` string, required
  - `attached` boolean, required — `false` when it was ALREADY attached — a no-op, not a failure, which is what lets a retried compose-and-run converge.
  - `environmentIds` string[], required — The suite's attachments after the call, in attach order.

## Other responses

- `400` — Malformed body or parameters.
- `401` — Missing, invalid, revoked, or orphaned key (`UNAUTHORIZED`) — or the **target MCP server** needs an OAuth grant (`OAUTH_REQUIRED`), which is a property of the server, not your key.
- `403` — Key is valid but not allowed to do this.
- `404` — Unknown project, server, or resource.
- `500` — Something failed on MCPJam's side.
- `502` — Could not connect to the target MCP server.

---

[API](https://skmtc.net/mcpjam/apis/mcpjam-api.md) · [All operations](https://skmtc.net/mcpjam/apis/mcpjam-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/mcpjam/mcpjam-api/revisions/ece7d99ceaf3/schema)
