---
title: "List a suite's eval cases"
method: GET
path: "/projects/{projectId}/eval-suites/{suiteId}/cases"
tags: ["Eval runs"]
---

# List a suite's eval cases

`GET /projects/{projectId}/eval-suites/{suiteId}/cases`

Every case in the suite, in the public steps-first shape.

## Path parameters

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

## Response `200`

The suite's cases.

- EvalCasePage
  - `items` EvalCase[], required
    - `id` string, required
    - `declaredId` string — The case's effective declared id. Absent on cases authored before declared identity existed.
    - `title` string, required
    - `steps` EvalTestStep[], required — Ordered test steps. A `prompt` step is a model turn; a single model-free `toolCall` step is a render-check; `assert` steps hold the expectations.
      - `id` string, required
      - `kind` 'prompt' | 'toolCall' | 'interact' | 'assert', required
      - `prompt` string — User message (`kind: prompt`).
      - `serverName` string — Server that owns the tool (`kind: toolCall`).
      - `toolName` string — Tool name (`kind: toolCall` / `interact`).
      - `arguments` object — Tool-call arguments (`kind: toolCall`).
      - `action` object — Widget action (`kind: interact`).
      - `assertion` object — Predicate or widget assertion (`kind: assert`).
    - `expectedOutput` string
    - `iterations` integer, required
    - `repetitions` integer — Trials this case runs under verdict policy 2, overriding the suite default. Absent means the case inherits it. NOT a second spelling of `iterations`: that one is the legacy count, which the legacy resolver reads as a FLOOR (`max(iterations, suite.minimumIterations)`) and which a policy-2 case still reports for compatibility. This one is exact.
    - `passThreshold` number — Fraction of this case's trials that must pass, overriding the suite default. Absent means the case inherits it. Never derived from the suite's `minimumAccuracy`, which is a PERCENT under a different resolver.
    - `isNegative` boolean, required — When true, the case passes if NO tools are called.
    - `scenario` string
    - `intent` string — Optional authored analytics grouping label. Must be already trimmed; absent means unlabelled.
    - `models` object[], required
      - `model` string, required
      - `provider` string
    - `matchOptions` object — Absent when the case sets none — omitted from the response rather than sent as `null`.
    - `checks` object — Absent when the case sets none — omitted from the response rather than sent as `null`.
      - `mode` 'inherit' | 'replace' | 'extend'
      - `list` object[]
    - `import` EvalCaseImportClaim — What a converter CLAIMED about one imported case. `exact` is CONVERTER-CLAIMED exact — the converter says it applied a structural mapping rule, cited in `note`. MCPJam has NOT verified semantic equivalence, so user-facing copy must say "claimed exact", never "verified" or "accepted". Claim-only: who approved an approximation, when, and why is a PER-RUN decision frozen on the run (`ImportEligibility.approvedApproximationReceipts`), never stored on the case — an approval that lived on a case would outlive the run it was granted for and the edit that invalidated it. Approval and internal keys are rejected with 400, never stripped.
      - `status` 'exact' | 'approximated' | 'unsupported' | 'unresolved', required — `exact`: the converter claims a 1:1 structural mapping, and must cite it in `note`. `approximated`: behaviour was intentionally approximated; a human must approve it for EVERY run. `unsupported`: the source behaviour cannot currently be represented. `unresolved`: a deterministic reference does not resolve against the live target. A selected `unsupported` or `unresolved` case cannot run.
      - `sourceCaseKey` string — The case's identity in the source system, when it had one.
      - `note` string — Why the status is what it is — the mapping rule cited, or what was lost. REQUIRED when `status` is `exact`.
    - `createdAt` number, nullable
    - `updatedAt` number, nullable
  - `nextCursor` string, nullable

## Other responses

- `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.
- `429` — Per-key rate limit exceeded (60 requests/minute sustained, bursts up to 10). Honor `Retry-After` and back off with jitter.
- `500` — Something failed on MCPJam's side.
- `502` — Could not connect to the target MCP server.

## Changes

- **2026-08-27** `d9a00becd476` — 1 info
  - added the optional property `items/items/intent` to the response with the `200` status
- **2026-08-26** `e81e8ba8baae` — 1 info
  - added the optional property `items/items/import` to the response with the `200` status
- **2026-08-24** `c479eeceb7a3` — 2 info
  - added the optional property `items/items/passThreshold` to the response with the `200` status
  - added the optional property `items/items/repetitions` to the response with the `200` status
- **2026-08-19** `879ca349c804` — 1 info
  - added the optional property `items/items/declaredId` to the response with the `200` status
- **2026-08-09** `c5f6167955e4` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/mcpjam/apis/mcpjam-api/changes/projects/:projectId/eval-suites/:suiteId/cases/get.md)

---

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