> ## Documentation Index
> Fetch the complete documentation index at: https://mcpjam-mintlify-docs-update-pr-4615-1788458430079.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# List run iterations

> Per-iteration results: actual tool calls, structured token usage, and latency. Cursor-paginated.



## OpenAPI

````yaml /reference/openapi.json get /projects/{projectId}/eval-runs/{runId}/iterations
openapi: 3.1.0
info:
  title: MCPJam API
  version: 1.0.0-preview
  description: >-
    Programmatic access to MCP servers saved in your MCPJam projects — live
    diagnostics (validate, inspect, export) and operations: call tools, render
    prompts, run eval suites asynchronously and poll their results, and import
    OAuth tokens.


    **The API is in preview**: the surface may change while we finish the
    design. Error `code` values are stable; error `message` strings are not.
    Write clients that ignore unknown response fields.
  contact:
    name: MCPJam
    url: https://github.com/MCPJam/inspector/issues
servers:
  - url: https://app.mcpjam.com/api/v1
    description: Hosted MCPJam
security:
  - bearerAuth: []
tags:
  - name: Agent browsers
    description: >-
      Isolated cloud browser sessions for coding agents. Requires authenticated
      project membership and a configured desktop runtime.
  - name: Clients
    description: >-
      Clients — the named, reusable configurations that define how MCPJam
      connects to and talks to your MCP servers. The original `/hosts` paths
      remain as deprecated, ID-only compatibility aliases with their original
      DTOs and their original (tokenless) write contracts; every alias response
      carries `Deprecation: true`. New integrations should use `/clients`.
  - name: Environments
    description: >-
      Project environments: named, live-editable execution bundles (one host, an
      optional standalone server group, optionally pinned skills and plugin
      versions) that eval suites and journeys run against. Distinct from Sandbox
      images, which are Computer base images. Reads require project membership;
      every write requires project admin.
  - name: Plugins
    description: >-
      Agent Plugins imported into a project — read-only inventory and version
      detail.
  - name: Skills
    description: >-
      Cloud Skills: authored SKILL.md files stored in a project. Read-only here.
      Environments pin skills by id (`skillSelection.skillIds`) and eval runs
      pin them with `--compose-skill`, so this surface exists to give an
      unattended caller those ids; authoring is an app flow behind a beta gate.
  - name: Sandbox images
    description: >-
      Custom Computer images: a digest-pinned Dockerfile built into an immutable
      image your project's computers boot from.
  - name: Server diagnostics
    description: Connect-level health checks against a saved MCP server.
  - name: Primitives
    description: 'The server''s MCP primitives: tools, prompts, and resources.'
  - name: Export
    description: Full-server snapshots for diffing and CI.
  - name: Execution
    description: 'Run the server''s primitives: call tools, render prompts.'
  - name: Eval runs
    description: >-
      Asynchronous eval suite runs: create with 202, poll status, iterations,
      and traces.
  - name: Conformance runs
    description: >-
      Ingest MCP spec-conformance results from the SDK/CLI into project-owned
      history. Distinct from Eval runs (authored LLM cases) and from directory
      readiness.
  - name: Server connections
    description: >-
      Connect an MCP server URL to a project, authorizing in a browser when the
      server requires it.
  - name: OAuth
    description: 'Bring-your-own OAuth: import externally obtained tokens for a server.'
  - name: Scenarios
    description: >-
      Read-only access to the scenarios published from a project: listing,
      settings, attached servers, and share links.
  - name: Catalog
    description: >-
      Discover the resources the other routes operate on: your account,
      projects, servers, eval suites, and chat sessions.
  - name: Tunnels
    description: >-
      Relay tunnels that expose local MCP servers through a public URL,
      registered as first-class project servers (the `mcpjam cloud tunnel` CLI
      flow).
  - name: Agent
    description: >-
      Headless agent turns over the public API: send a message history, the
      server runs one assistant turn with project-scoped workspace tools (eval
      reads + suite creation) on a pinned hosted model, and returns the reply
      plus created-resource references.
  - name: Swarms
    description: >-
      Personas, journeys and swarm containers — the authoring half of Swarms —
      plus the model-backed generation that drafts them.
  - name: Swarm runs
    description: >-
      Launching journeys and reading what they produced. Launching SPENDS — see
      the per-operation notes.
  - name: Swarm insights
    description: >-
      What a swarm run revealed. The scorecard and findings are deterministic
      and free; requesting wave insights runs models and draws on your shared
      daily ledger.
  - name: User testing
    description: >-
      Publishing an environment for real visitors, and controlling who can reach
      it. Several of these NARROW access and take effect immediately.
  - name: Directory readiness
    description: >-
      Grade a saved server against a publisher's listing requirements:
      Anthropic's connector directory or OpenAI's plugin directory. Reported as
      lane status and coverage, never as a numeric score, and excluded from
      `pooledConformanceScore`. Deterministic grading is free; model-backed
      experience observations are an explicit opt-in that consumes MCPJam
      credits and can never decide a verdict.
  - name: Registry
    description: >-
      Search the scraped MCP directories (Claude, ChatGPT, and any future
      source), list curated/org registry cards, and install them into a project.
      Install writes a `servers` row and provenance — it does not open a live
      session. There is no catalog-uninstall route: delete the project server
      instead. Directory reads require a bearer (including minted guest tokens)
      but do not materialize a user. Card/connection reads and all writes are
      authed-non-guest.
paths:
  /projects/{projectId}/eval-runs/{runId}/iterations:
    get:
      tags:
        - Eval runs
      summary: List run iterations
      description: >-
        Per-iteration results: actual tool calls, structured token usage, and
        latency. Cursor-paginated.
      operationId: listEvalRunIterations
      parameters:
        - $ref: '#/components/parameters/projectId'
        - $ref: '#/components/parameters/runId'
        - name: limit
          in: query
          required: false
          description: Page size, 1–200. Defaults to 50.
          schema:
            type: integer
            minimum: 1
            maximum: 200
            default: 50
        - name: cursor
          in: query
          required: false
          description: Opaque cursor from a previous response's `nextCursor`.
          schema:
            type: string
      responses:
        '200':
          description: One page of iterations.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EvalIterationPage'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    projectId:
      name: projectId
      in: path
      required: true
      description: ID of the hosted project that contains the server.
      schema:
        type: string
    runId:
      name: runId
      in: path
      required: true
      description: Eval run ID, as returned by `POST /eval-runs`.
      schema:
        type: string
  schemas:
    EvalIterationPage:
      type: object
      required:
        - items
      properties:
        items:
          type: array
          items:
            $ref: '#/components/schemas/EvalIteration'
        nextCursor:
          type: string
          description: Opaque cursor for the next page. Omitted on the last page.
    EvalIteration:
      type: object
      required:
        - id
        - iterationNumber
        - status
        - expectedToolCalls
        - actualToolCalls
      properties:
        id:
          type: string
        testCaseId:
          type:
            - string
            - 'null'
          description: >-
            The STORED case row's database id. Changes if the case is recreated
            and means nothing outside this deployment; see `caseId` for the
            declared one.
        caseId:
          type: string
          description: >-
            The case's SDK-DECLARED id, read from the iteration's frozen
            `testCaseSnapshot` — the durable, author-chosen identity that
            survives the case row being recreated. ABSENT on a UI-authored case
            (which never declared one) and on runs predating declared ids;
            absence is not an error. Distinct from `testCaseId`, which is this
            deployment's row id, and NOT a join key into
            `verdictSummary.cases[].caseId`, which is a separately encoded
            identity the platform mints from whichever spelling the run knew.
        title:
          type:
            - string
            - 'null'
        iterationNumber:
          type: integer
        status:
          type: string
          description: >-
            LIFECYCLE, not verdict: how far the trial got, never how it graded.
            A trial that ran normally and graded badly is `completed` with
            `result: "failed"`, so reading `status === "failed"` as "the case
            failed" counts harness noise as server defects. `failed` is an
            execution failure, `setup_failed` means the environment never came
            up, `timed_out` means the budget expired, `skipped` means it was
            deliberately not run, `cancelled` means it was withdrawn mid-flight
            (and is excluded from validity denominators). Treat an unrecognised
            value as non-terminal-unknown rather than as a failure.
          enum:
            - pending
            - running
            - completed
            - failed
            - cancelled
            - timed_out
            - setup_failed
            - skipped
        result:
          type:
            - string
            - 'null'
          description: >-
            Task verdict for the trial, independent of `status`. `null` until
            the trial is graded — including on a terminal trial that never
            produced a gradeable outcome (`setup_failed`, `skipped`).
          enum:
            - passed
            - failed
            - null
        model:
          type:
            - string
            - 'null'
        provider:
          type:
            - string
            - 'null'
        startedAt:
          type:
            - number
            - 'null'
          description: Epoch milliseconds.
        durationMs:
          type:
            - number
            - 'null'
          description: Wall-clock duration; `null` until terminal.
        tokensUsed:
          type:
            - number
            - 'null'
        usage:
          type:
            - object
            - 'null'
          description: >-
            Structured token usage (input/output/cached/reasoning) when
            available, plus `estimatedCostUsd` and the `costBasis` it was priced
            from.


            `estimatedCostUsd` ABSENT means no cost was observed — never that
            the trial was free. `costBasis.reason` says which: `no_pricing` (not
            an MCPJam-billed model, e.g. your own API key),
            `harness_mixed_models` (a harness turn mixes models and carries no
            per-model split, so its cost arrives with billed attribution
            instead), or `no_tokens`.


            `costBasis.source` is `gateway_pricing` when MCPJam priced its own
            token counts, and `sdk_runner` when the figure came from your runner
            — real, but neither computed nor verified by MCPJam.
          additionalProperties: true
        actualToolCalls:
          type: array
          items:
            type: object
            additionalProperties: true
        expectedToolCalls:
          type: array
          items:
            type: object
            additionalProperties: true
        error:
          type:
            - string
            - 'null'
        scores:
          type:
            - array
            - 'null'
          description: >-
            Per-scorer verdicts for this iteration. `null` when the run predates
            scoring, or when the stored payload failed validation at the
            boundary — partially-trusted score data is never projected.
          items:
            $ref: '#/components/schemas/ScoreResult'
        evaluationConfig:
          description: >-
            The scorer definitions `scores` were produced under. Present exactly
            when `scores` is: results carry only a `definitionHash`, so without
            this a caller cannot tell a gating failure from an advisory one.
          oneOf:
            - $ref: '#/components/schemas/EvaluationConfigSnapshot'
            - type: 'null'
        scoreIntegrity:
          type:
            - string
            - 'null'
          description: >-
            Set when the backend downgraded this iteration's verdict because its
            gating score evidence was malformed.
          enum:
            - score_integrity_invalid
            - null
        stageResults:
          type: array
          description: >-
            The user-value chain rows for this trial, in chain order, from a
            derivation that validated.
          items:
            $ref: '#/components/schemas/StageResultRow'
        firstFailedStage:
          type: string
          enum:
            - connection
            - discovery
            - selection
            - call
            - response
            - userValue
          description: >-
            Where the chain stopped — A LOCATION, NOT A CAUSE. It names the
            first link that failed, never why it failed: the why is `reason` on
            that stage's row (see `StageResultRow.reason`), and neither this nor
            the `failureCategory` bucket on its own authorizes proposing a
            change to the server. Absent when nothing failed — and absent on a
            trial that never reached a stage at all, such as a setup abort or an
            evaluator error, which still carries a `failureCategory`.
            `connection` — the server was reachable and the session initialized.
            `discovery` — its tools and resources were listed and readable.
            `selection` — the model chose the right tool for the request. `call`
            — the call was made with usable arguments. `response` — the server
            returned data the model could use. `userValue` — the user's actual
            request was satisfied.
        failureCategory:
          type: string
          enum:
            - setup
            - metadata
            - selection
            - arguments
            - serverData
            - userValue
            - evaluator
          description: >-
            The bucket this trial is grouped under — A BUCKET, NOT A DIAGNOSIS.
            Present without `firstFailedStage` for a trial that never reached a
            stage. `setup` — setup: the harness or environment never got to the
            test. `metadata` — tool metadata: tool names, descriptions or
            schemas misled the model. `selection` — tool selection: the model
            picked the wrong tool, or none. `arguments` — call arguments: the
            right tool, called wrongly. `serverData` — server data: the server
            answered, with data the model could not use. `userValue` — user
            value: everything mechanical worked and the user still was not
            served. `evaluator` — evaluator: the grader itself failed, so the
            run says nothing about the server — never folded into the others,
            because counting a broken judge as a server defect poisons every
            rate derived from it.
        stageAnalyzerVersion:
          type: integer
          minimum: 0
        stageResultsUnverified:
          type: boolean
          enum:
            - true
        frictionSignals:
          $ref: '#/components/schemas/EvalTrialFrictionSignals'
        frictionSignalsUnverified:
          type: boolean
          enum:
            - true
          description: >-
            The server stored a friction document that failed validation. The
            signals themselves are withheld rather than partially trusted.
        suspectedConditionVerdict:
          $ref: '#/components/schemas/EvalSuspectedConditionVerdict'
        suspectedConditionUnverified:
          type: boolean
          enum:
            - true
          description: >-
            The server stored a suspected-condition verdict that failed
            validation. The verdict is withheld rather than partially trusted.
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: >-
            Stable, machine-readable error code. New codes may be added over
            time; treat unknown codes as non-retryable failures unless the HTTP
            status says otherwise.
          enum:
            - UNAUTHORIZED
            - FORBIDDEN
            - NOT_FOUND
            - CONFLICT
            - VALIDATION_ERROR
            - RATE_LIMITED
            - FEATURE_NOT_SUPPORTED
            - SERVER_UNREACHABLE
            - TIMEOUT
            - OAUTH_REQUIRED
            - INTERNAL_ERROR
        message:
          type: string
          description: >-
            Human-readable description. May change between releases — don't
            match on it.
        details:
          type: object
          description: Optional, unstructured context bag.
          additionalProperties: true
    ScoreResult:
      type: object
      description: >-
        One scorer's verdict for one iteration. `passed` is DERIVED as `value >=
        passThreshold` — never asserted by the scorer or the model.
      required:
        - scorerId
        - scorerVersion
        - definitionHash
        - status
        - passThreshold
        - deterministic
      properties:
        scorerId:
          type: string
          maxLength: 128
        scorerVersion:
          type: string
        definitionHash:
          type: string
          description: >-
            Joins this result to its definition in
            `evaluationConfig.definitions`.
        status:
          type: string
          description: >-
            `error` is never a low score — a crashed judge is not a disagreeing
            judge. `not_applicable` never gates and is excluded from aggregation
            denominators, which is what distinguishes it from `skipped`.
          enum:
            - scored
            - error
            - skipped
            - not_applicable
        value:
          type: number
          minimum: 0
          maximum: 1
          description: Present only when `status` is `scored`.
        passThreshold:
          type: number
          minimum: 0
          maximum: 1
        passed:
          type: boolean
          description: >-
            Derived as `value >= passThreshold`; present only when `status` is
            `scored`.
        rationale:
          type: string
          maxLength: 2000
        evidence:
          type: array
          maxItems: 20
          items:
            type: string
            maxLength: 300
        deterministic:
          type: boolean
        model:
          type: string
        promptHash:
          type: string
        error:
          type: string
          maxLength: 500
          description: Present only when `status` is `error`.
        scope:
          type: object
          description: >-
            Absent means case-level; `{kind:"turn",promptIndex}` means the check
            was authored on a single turn.
          additionalProperties: true
    EvaluationConfigSnapshot:
      type: object
      description: >-
        The scorer definitions a run graded with, plus their hash. Changing
        scorer configuration changes this hash but NOT the case identity — a
        threshold edit must not fork a scenario's history.
      required:
        - hash
        - definitions
      properties:
        hash:
          type: string
          description: >-
            `evaluationConfigHash` over the resolved definitions.
            Order-independent — the hash sorts internally.
        definitions:
          type: array
          items:
            $ref: '#/components/schemas/ResolvedScoreDefinition'
    StageResultRow:
      type: object
      description: >-
        One user-value stage's verdict for one trial, from a derivation that
        validated. Six of these make a chain, always in chain order, and the
        order is normative: `notReached` is derived from position, so
        re-ordering them changes which stages a failure is said to have blocked.
      required:
        - stage
        - state
      properties:
        stage:
          type: string
          enum:
            - connection
            - discovery
            - selection
            - call
            - response
            - userValue
          description: >-
            Which link of the user-value chain this row is a verdict on. The
            order is NORMATIVE: a run walks the six in sequence, and
            `notReached` is derived from position — every stage after the first
            failed one never ran. `connection` — the server was reachable and
            the session initialized. `discovery` — its tools and resources were
            listed and readable. `selection` — the model chose the right tool
            for the request. `call` — the call was made with usable arguments.
            `response` — the server returned data the model could use.
            `userValue` — the user's actual request was satisfied.
        state:
          type: string
          enum:
            - passed
            - failed
            - notReached
            - notMeasured
            - notApplicable
          description: >-
            What this stage did. The three non-verdicts stay three different
            facts on purpose: collapsing them is how "we never checked" gets
            read as "it passed". `passed` — measured, and it passed. `failed` —
            measured, and it failed. `notReached` — it never ran (an earlier
            stage failed), so there was nothing to decide. `notMeasured` — this
            run captured nothing that could decide it, so the stage is not
            measured. `notApplicable` — the stage is not applicable to this case
            at all.
        reason:
          type: string
          enum:
            - noSpanChannel
            - noEvidenceCaptured
            - matchVerdictUnavailable
            - traceAbsent
            - executorEmitsNoSpans
            - blockedByPolicy
            - evaluatorError
            - providerError
            - setupAborted
            - connectFailed
            - toolsListFailed
            - egressUnverified
            - lifecycleStopped
            - notAuthored
            - earlierStageFailed
            - missingToolCall
            - unexpectedToolCall
            - argumentMismatch
            - toolError
            - protocolError
            - renderFailed
            - predicateFailed
            - observed
            - impliedByLaterEvidence
            - judgeObserved
            - judgePartial
            - judgeFailed
            - judgePending
            - judgeNotRequested
          description: >-
            Why this stage landed where it did. A CLOSED vocabulary — render
            what arrives, never widen it. Each entry completes "…because
            <reason>". `noSpanChannel` — this run captures no evidence channel
            for that stage. `noEvidenceCaptured` — nothing eligible for that
            stage was captured. `matchVerdictUnavailable` — extra tool calls
            were captured but the run did not report whether its match options
            tolerate them. `traceAbsent` — the iteration recorded no trace.
            `executorEmitsNoSpans` — the executor emitted no spans.
            `blockedByPolicy` — a policy blocked the run before it could be
            measured. `evaluatorError` — the evaluator itself failed, so the run
            says nothing about the server. `providerError` — the model provider
            failed the call, so this stage was never measured. `setupAborted` —
            the environment was never prepared, so the test never began.
            `connectFailed` — the configured server was reached and initialize
            failed there. `toolsListFailed` — initialize succeeded and listing
            tools failed. `egressUnverified` — the connection failed with no
            evidence that our own network egress works. `lifecycleStopped` — the
            run was stopped mid-flight. `notAuthored` — the case asserts nothing
            this stage could decide. `earlierStageFailed` — an earlier stage
            failed. `missingToolCall` — an expected tool call was never made.
            `unexpectedToolCall` — a tool call was made that the case did not
            expect. `argumentMismatch` — the call arguments did not match what
            the case expects. `toolError` — the server reported a tool error.
            `protocolError` — the call never produced a result. `renderFailed` —
            the widget did not render. `predicateFailed` — a check on the result
            did not hold. `observed` — the evidence was inspected and the stage
            held. `impliedByLaterEvidence` — a later stage's success implies it.
            `judgeObserved` — the LLM judge scored at or above the threshold.
            `judgePartial` — the LLM judge scored inside the partial band — at
            or above the floor, below the threshold. `judgeFailed` — the LLM
            judge scored below the partial floor. `judgePending` — an LLM judge
            verdict is owed and has not arrived. `judgeNotRequested` — no LLM
            judge verdict was ever owed.
        evidence:
          type: object
          properties:
            spanIds:
              type: array
              items:
                type: string
              maxItems: 5
            promptIndexes:
              type: array
              items:
                type: integer
              maxItems: 5
            predicateReasons:
              type: array
              items:
                type: string
                maxLength: 500
              maxItems: 5
          additionalProperties: false
    EvalTrialFrictionSignals:
      type: object
      description: >-
        Observable patterns in one trial's tool calls. REPORT-ONLY: nothing here
        decided the trial's `result`, and every pattern has a benign reading.
        `state` is `notMeasured` when the trial could not be looked at at all;
        `identifierSignals.state` is separate because a trial whose tool results
        were not retained still has measurable retries but cannot be asked
        whether an identifier went unused. An ABSENT document means the trial
        predates the measurement — never read it as zero.
      required:
        - version
        - state
        - callCount
        - resultAvailableCount
        - timedCallCount
        - identifierSignals
        - signals
      properties:
        version:
          type: integer
          enum:
            - 1
          description: >-
            Derivation semantics version. Bumped when a counting RULE changes,
            even if the shape does not.
        state:
          type: string
          enum:
            - measured
            - notMeasured
        notMeasuredReason:
          type: string
          enum:
            - noToolCalls
            - resultsUnavailable
            - orderingUnknown
            - evidenceIncomplete
            - truncated
          description: >-
            Present only when `state` is `notMeasured`. `noToolCalls` — no tool
            calls to look at. `resultsUnavailable` — tool results were not
            retained. `orderingUnknown` — the calls cannot be placed in a causal
            order. `evidenceIncomplete` — the evidence for this trial has a
            known hole. `truncated` — too many tool calls to measure.
        callCount:
          type: integer
          minimum: 0
        resultAvailableCount:
          type: integer
          minimum: 0
        timedCallCount:
          type: integer
          minimum: 0
        identifierSignals:
          type: object
          description: >-
            Whether the two identifier-dependent kinds were measured at all.
            `notMeasured` here beside `state: measured` above is the normal
            shape for a run whose tool results were not retained: the retries
            were measured, the identifiers were never looked for.
          required:
            - state
          properties:
            state:
              type: string
              enum:
                - measured
                - notMeasured
            reason:
              type: string
              description: >-
                Why the identifier kinds were not measured. `noToolCalls` — no
                tool calls to look at. `resultsUnavailable` — tool results were
                not retained. `orderingUnknown` — the calls cannot be placed in
                a causal order. `evidenceIncomplete` — the evidence for this
                trial has a known hole. `truncated` — too many tool calls to
                measure.
              enum:
                - noToolCalls
                - resultsUnavailable
                - orderingUnknown
                - evidenceIncomplete
                - truncated
        signals:
          type: array
          maxItems: 24
          items:
            $ref: '#/components/schemas/EvalFrictionSignal'
          description: >-
            Ordered by the call that made each pattern observable. Empty on a
            `measured` document means nothing fired; empty on a `notMeasured`
            one means nothing was looked for.
    EvalSuspectedConditionVerdict:
      type: object
      description: >-
        Which server-controlled condition is SUSPECTED of contributing to one
        observed friction pattern, from an advisory per-trial judge. REPORT-ONLY
        and NEVER a claim about cause: nothing here entered the trial’s
        `result`, its stage chain or its `failureCategory`, and only a
        controlled rewrite that changes the suspected response and holds the
        rest comparable could establish causation. ABSENT means no judge ran —
        the trial predates it, nothing was flagged, or the deployment has it
        off.
      required:
        - status
        - gradingKey
        - signalKind
        - informationCallIndex
        - observedAtCallIndex
        - judgeTemplateVersion
        - judgeTemplateHash
        - model
        - generatedAt
      properties:
        status:
          type: string
          enum:
            - scored
            - skipped
            - error
          description: >-
            `scored` — a verdict was produced. `skipped` — the judge did not
            reach this trial; `reason` says why. `error` — the pass threw for
            this trial. A skipped or errored trial carries NO condition, so “we
            never looked” is never rendered as “we looked and could not say”.
        reason:
          type: string
          enum:
            - spendBlocked
            - traceIncomplete
            - noEvidence
            - cap
          description: >-
            Present only when `status` is `skipped`. `spendBlocked` — the
            internal-LLM spend gate refused the call. `traceIncomplete` — a
            referenced trace blob could not be read. `noEvidence` — the judge’s
            window could not be built, most often because the information call’s
            result never reached the trace. `cap` — the run had more flagged
            trials than the per-run cap.
        condition:
          type: string
          enum:
            - unclear
            - idBuriedInPayload
            - idNameCollision
            - missingQueryEcho
            - silentTruncation
            - ambiguousErrorSemantics
            - missingUnits
            - responseWasClear
            - descriptionMisleading
          description: >-
            Which server-controlled condition is SUSPECTED of contributing. A
            CLOSED vocabulary. SUSPECTED, not established: the judge saw one
            window of one trial and named a plausible contributor, and only a
            controlled rewrite could turn that into a claim about cause.
            `unclear` — could not attribute: the judge could not identify a
            condition from what it was shown, which is also where a
            low-confidence or unsupported verdict is demoted to.
            `idBuriedInPayload` — identifier buried in payload: the identifier a
            later call needed was not where a caller would look for it.
            `idNameCollision` — identifier name collision: two different
            identifiers share a name, or one name means different things across
            tools. `missingQueryEcho` — response does not echo the query: a
            caller cannot tell a narrowed result from a fresh one.
            `silentTruncation` — response truncated without saying so.
            `ambiguousErrorSemantics` — error text does not say whether to
            retry. `missingUnits` — value has no stated unit. `responseWasClear`
            — the response was clear: the server's output does not explain the
            pattern. This is the honest negative and a real answer.
            `descriptionMisleading` — tool description points the wrong way.
        confidence:
          type: string
          enum:
            - low
            - medium
            - high
          description: >-
            How sure the judge was. `low` — low confidence: never reaches a
            reader as a named condition, because a low-confidence verdict is
            demoted to `unclear` before it is persisted. `medium` — medium
            confidence. `high` — high confidence.
        remediation:
          type: string
          maxLength: 300
          description: >-
            ONE sentence naming a lever the SERVER OWNER controls. Absent for
            `unclear` and `responseWasClear`, which name no server problem to
            remediate, and absent from any verdict whose remediation named no
            server lever — that verdict is demoted to `unclear`.
        evidence:
          type: object
          description: >-
            Where in the window the judge was pointing. Dropped rather than
            guessed when it fell outside the window or named the wrong tool; the
            verdict survives, the pointer does not.
          required:
            - callIndex
            - toolName
          properties:
            callIndex:
              type: integer
              minimum: 0
            toolName:
              type: string
            fieldPath:
              type: string
              maxLength: 120
        gradingKey:
          type: string
        signalKind:
          type: string
          description: The friction signal that triggered the judge.
        informationCallIndex:
          type: integer
          minimum: 0
          description: >-
            Where the information was surfaced. The judge saw calls 0 through
            `observedAtCallIndex` and nothing after.
        observedAtCallIndex:
          type: integer
          minimum: 0
          description: >-
            The call that made the pattern observable, and the judge’s evidence
            bound.
        judgeTemplateVersion:
          type: integer
          minimum: 1
        judgeTemplateHash:
          type: string
        model:
          type: string
        generatedAt:
          type: integer
          minimum: 0
    ResolvedScoreDefinition:
      type: object
      description: >-
        A scorer definition with every semantic default resolved. This is the
        form that is hashed, so an omitted `onError` and an
        explicitly-configured default digest identically.
      required:
        - scorerId
        - idSource
        - scorerVersion
        - implementationHash
        - deterministic
        - passThreshold
        - role
        - onError
        - onSkipped
      properties:
        scorerId:
          type: string
          maxLength: 128
        idSource:
          type: string
          description: >-
            `generated` ids are positional and UNSTABLE across config edits;
            only `explicit` ids may be referenced by a gate policy or tracked
            across runs.
          enum:
            - explicit
            - generated
        scorerVersion:
          type: string
        implementationHash:
          type: string
          description: >-
            Digest of what the scorer actually does — the canonicalized
            predicate, or the judge prompt plus template version. Required so
            two judges with different prompts cannot hash identically.
        label:
          type: string
          description: Presentation only; deliberately excluded from the hash.
        deterministic:
          type: boolean
        passThreshold:
          type: number
          minimum: 0
          maximum: 1
        role:
          type: string
          description: Only `gating` scorers decide the iteration's verdict.
          enum:
            - gating
            - advisory
        onError:
          type: string
          description: >-
            What an `error` status does to a gating iteration. Defaults to
            `fail`.
          enum:
            - fail
            - ignore
        onSkipped:
          type: string
          description: >-
            What a `skipped` status does to a gating iteration. Separate from
            `onError`: a crashed judge and a judge that never ran are different
            failures.
          enum:
            - fail
            - ignore
        model:
          type: string
        scope:
          type: object
          additionalProperties: true
    EvalFrictionSignal:
      type: object
      description: >-
        One observed pattern in a trial's tool calls. Identifier kinds carry
        `informationCallIndex` (where the identifiers appeared) and
        `observedAtCallIndex` (the later call that made the pattern visible);
        adjacency kinds carry `callIndex` and `priorCallIndex`. Every index
        addresses `actualToolCalls` on the same iteration.
      required:
        - kind
        - toolName
      properties:
        kind:
          type: string
          enum:
            - identifierSurfacedUnused
            - searchRepeatedAfterIdentifier
            - identicalRetry
            - changedRetry
            - paginationContinuation
          description: >-
            Which observable pattern this is. A CLOSED vocabulary; a reader that
            does not know a member must not guess at it. Every member has a
            benign reading, so none of them is a verdict about the trial.
            `identifierSurfacedUnused` — Identifiers surfaced, none used later:
            a result carried identifiers and no later call passed one, which is
            also what a search that already answered the question looks like.
            `searchRepeatedAfterIdentifier` — Same tool searched again after
            identifiers: the tool that surfaced them was called again with a
            different question, which is also what a sensible refinement looks
            like. `identicalRetry` — Repeated with identical arguments: the same
            call ran twice byte for byte, which is what recovery after a
            transient error looks like. `changedRetry` — Same tool called again
            with changed arguments: ordinary exploration, and most useful work
            looks like this. `paginationContinuation` — Pagination continued:
            only the pagination keys changed, which is a cursor doing its job
            and is never counted as a repeat.
        toolName:
          type: string
        toolCallId:
          type: string
        informationCallIndex:
          type: integer
          minimum: 0
        observedAtCallIndex:
          type: integer
          minimum: 0
        callIndex:
          type: integer
          minimum: 0
        priorCallIndex:
          type: integer
          minimum: 0
        afterError:
          type: boolean
          description: Whether the call this one repeats returned an error.
        identifierKeyPaths:
          type: array
          maxItems: 8
          items:
            type: string
          description: >-
            Where in the result the identifiers were found (`results[].id`). KEY
            PATHS ONLY — an identifier VALUE never leaves the deployment.
        identifierCount:
          type: integer
          minimum: 1
        laterCallCount:
          type: integer
          minimum: 2
        repeatCallIndexes:
          type: array
          minItems: 1
          maxItems: 8
          items:
            type: integer
            minimum: 0
        paginationKeys:
          type: array
          minItems: 1
          maxItems: 4
          items:
            type: string
            enum:
              - cursor
              - nextCursor
              - page
              - pageToken
              - offset
              - after
              - before
              - start
              - limit
  responses:
    Unauthorized:
      description: >-
        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.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            badKey:
              summary: Invalid or revoked key
              value:
                code: UNAUTHORIZED
                message: Invalid API key
            oauthRequired:
              summary: Target server needs an OAuth grant
              value:
                code: OAUTH_REQUIRED
                message: Server requires OAuth authorization
    Forbidden:
      description: Key is valid but not allowed to do this.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: FORBIDDEN
            message: You do not have access to this project
    NotFound:
      description: Unknown project, server, or resource.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: NOT_FOUND
            message: Server not found
    RateLimited:
      description: >-
        Per-key rate limit exceeded (60 requests/minute sustained, bursts up to
        10). Honor `Retry-After` and back off with jitter.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: RATE_LIMITED
            message: API key rate limit exceeded. Slow down and retry.
    InternalError:
      description: Something failed on MCPJam's side.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          example:
            code: INTERNAL_ERROR
            message: Unexpected internal error
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        MCPJam API key (`sk_…`). Create one at [Settings → API
        keys](https://app.mcpjam.com/settings/api-keys). Guest sessions cannot
        use the API, and API keys cannot manage other API keys.

````