Skip to main content
Complete flag tables for every mcpjam command. For guides and recipes, see the individual command pages. Account-bound Cloud commands live under mcpjam cloud. Local MCP testing stays at the top level (mcpjam server, mcpjam oauth login, …). Credential flags --api-key / --api-url are declared on mcpjam cloud and work before or after descendants. Hosted readiness stays at the root and still takes leaf --api-key. See Migrating to CLI 4.0.

Global flags


server commands

All server commands accept the shared connection flags below, plus command-specific options.

Shared connection flags

Transport selection is inferred from --url vs --command when --transport is omitted. Use --transport http|stdio when you want an explicit validation step. For stdio targets, child processes inherit the parent shell environment by default. -e/--env adds or overrides child env values, and structured debug artifacts only record the explicit env keys you passed on the command line. --credentials-file cannot be combined with individual token flags (--access-token, --oauth-access-token, --refresh-token, --client-id, --client-secret). The CLI rejects conflicting auth sources upfront.

server probe

No additional flags beyond shared connection flags.

server doctor

server info

No additional flags.

server validate

No additional flags.

server ping

No additional flags.

server capabilities

No additional flags.

server export

No additional flags.

tools commands

tools list

Uses shared connection flags, plus: When --host is set, the output includes a host field and a toolsDroppedVisibility count. Hosts that opt out of visibility filtering (e.g. cursor) keep all tools.

tools call

Plus shared connection flags. Without --ui, tools call returns the raw tool result. When that result is a JSON object (the usual MCP CallToolResult), the default JSON output also includes _durationMs — wall-clock milliseconds spent in the tool call itself, excluding connection setup and the --host visibility probe, so it measures the same window as the durationMs returned by POST /v1/projects/{projectId}/servers/{serverId}/tools/call. Arrays and non-objects are left unchanged so a list-shaped payload is not rewritten. --reporter keeps its own durationMs, which is end-to-end (connection setup plus the call, stopped before validation, Inspector render, and debug I/O), and does not get _durationMs. With --ui, it opens Inspector by default in a TTY and returns a compact envelope with result, inspectorBrowserUrl, and inspectorRender status. Object-shaped result values carry _durationMs; the envelope root does not. inspectorRender.status is rendered when Inspector accepted the render, skipped when the tool succeeded but Inspector had no active browser client, an unsatisfied render precondition, or a render timeout, and error for non-recoverable render command failures. inspectorRender.remediation is always present and is one of open_browser, retry, reconnect_server, or none. Skipped renders are emitted as a stable root warning plus inspectorRender.warning, both with the shape { code, message, remediation, browserUrl?, hasActiveClient?, inspectorStarted? }. Stable skipped-render codes are no_active_client, timeout, disconnected_server, and unsupported_in_mode. Skipped renders keep the tool-call exit code unless --require-render is set; tool failures, validation failures, non-skippable render command errors, and --require-render skipped renders all exit nonzero. --attach-only is an exception to the skipped-render rule for no_active_client: by default a missing browser client yields inspectorRender.status = "skipped" with inspectorRender.remediation = "open_browser", but when --attach-only is set, no_active_client is treated as non-skippable, surfaces as a root error (not a downgraded warning), and exits nonzero like other non-skippable render failures. --inspector-url points to the Inspector backend/API; pass --frontend-url when you already know the browser/client URL and want to skip health-advertised frontend checks and local dev port discovery. Use --no-open when browser automation already opened inspectorBrowserUrl; use --attach-only when startup, browser opening, and discovery should all be disallowed. Default non-TTY --ui runs do not open a browser unless --open is passed. When --open is in effect (default in TTYs, opt-in elsewhere), the App Builder URL and the initial browser-client wait progress are emitted to stderr unless --quiet is set, regardless of whether stderr is a TTY; only the elapsed-seconds heartbeat is gated on stderr being a TTY. The Inspector path injects the completed tool result through renderToolResult; it does not call the tool a second time. Fresh tabs do not hydrate the injected render state; use the active Inspector client that received the render. Use --debug-out for the full render envelope including params and command responses. --ui cannot be combined with --reporter.

Reading tools call --ui output as an agent

Treat the tool result and the Inspector render as separate outcomes. An exit code of 0 means the tool call succeeded and no hard render error occurred; it does not, by itself, prove the UI rendered. Confirm UI delivery with inspectorRender.status === "rendered". If inspectorRender.status === "skipped", branch on inspectorRender.remediation or the stable root warning.code. If --require-render is set, the same skipped-render issue moves from root warning to root error and the command exits with code 1.

resources commands

resources list

Uses shared connection flags, plus:

resources read

Plus shared connection flags.

resources templates

Uses shared connection flags, plus:

prompts commands

prompts list

Uses shared connection flags, plus:

prompts get

Plus shared connection flags.

xaa commands

xaa run

Run the Cross-App Access (ID-JAG) debugger: self-issue an ID-JAG, redeem it at the target authorization server (RFC 7523), and call the MCP server with the resulting access token. See the XAA Debugger guide for the trust setup, registration strategies, and CI usage.

Registration strategies

Confidential CIMD (--client-auth private-key-jwt)

When --registration cimd --client-auth private-key-jwt is used, the CLI loads or generates a local EC P-256 key pair (stored in ~/.mcpjam). The public key is encoded into a reflector URL on app.mcpjam.com, which becomes the client_id. The CLI signs a client_assertion with the private key at token-redemption time; the private key never leaves the machine.
For a cloud authorization server, expose the inspector origin through a tunnel and pass the public origin as --issuer-base-url — see making the issuer reachable. Key rotation: the key is the identity. Deleting ~/.mcpjam/xaa-client-private.pem or changing the XAA_CLIENT_PRIVATE_KEY environment variable generates a new client_id; any RAS-side allowlisting must be updated after rotation.

oauth commands

oauth login

oauth conformance

oauth conformance-suite

oauth metadata

oauth proxy / oauth debug-proxy


protocol commands

protocol conformance

Use --format json|human for raw output and --reporter json-summary|junit-xml for CI reports.

protocol conformance-suite


apps commands

Shared connection flags

Apps commands share the same transport inference rules as the rest of the CLI: --url implies HTTP, --command implies stdio, and --transport is an optional explicit override.

apps conformance

MCP Apps server-side conformance checks. Uses shared connection flags plus: Use --format json|human for raw output and --reporter json-summary|junit-xml for CI reports.

apps conformance-suite


compat command

Check whether an MCP server’s tools and widgets work on each AI host. Uses shared server connection flags (see server commands) plus:
The result includes a per-host verdict (works, degraded, blocked, or unknown), a findings list explaining each verdict, and a top-level summary count. When the tool list is truncated (more than 50 pages), verdicts that would otherwise be works are downgraded to unknown.

cloud clients commands

Manage the clients saved in your hosted MCPJam projects — the named, reusable configurations that define how MCPJam connects to and talks to your MCP servers. Every clients command that contacts Cloud requires an sk_ API key (via --api-key or the MCPJAM_API_KEY environment variable) or a prior mcpjam cloud login. clients templates is the exception: it prints the built-in template list from the bundled SDK and needs no credential. mcpjam cloud hosts … still works as a command alias, and every command accepts --host as a deprecated spelling of --client. Passing both --client and --host is a usage error rather than a silent precedence rule.

Editing safely: configId and expectedConfigId

A client’s config is immutable and content-addressed: configId identifies the exact settings, so the same id means byte-identical settings. Every config edit takes the configId you last read as expectedConfigId, and a rename takes the name you last read as expectedName. If someone else edited the client since you read it, the write is refused with a 409 naming the current value instead of silently reverting their edit. The loop is always the same:
On a conflict, re-run get and retry with the fresh value.

Shared platform flags

cloud clients templates

List the built-in templates usable with mcpjam cloud clients create --template. No additional flags.

cloud clients list

Clients that exist only as the private backing of a User Testing scenario are omitted, matching the Clients tab.

cloud clients get

Returns the resolved config, the configId every edit takes, and impact — the live environments, scenario attachments and active legacy journeys a config edit would follow.

cloud clients create

Provide either --template or --file/--json, not both.

cloud clients update

Use either --set/--unset or --file/--json, not both. Prefer --set: a whole-config replacement composed from a stale read reverts anything that landed in between.

--set field types

Values are parsed by the FIELD, never guessed from what the value looks like — so --set systemPrompt='{"a":1}' sets that literal string, and a --set temperature=0.2x typo fails locally instead of reaching the API as a string. Object-valued fields are whole-object replacements, not merges. To change a deep knob, read the client, overlay the sub-object, and send the whole object back.

cloud clients servers

This REPLACES the server set: every server you leave out is detached.

cloud clients duplicate

cloud clients delete


cloud environments commands

Manage project environments in your hosted MCPJam projects. A project environment is a named, live-editable execution bundle — one host, optionally a standalone server group, optionally a pinned skill selection and pinned plugin versions — that eval suites and journeys run against.
A project environment is not a Computer sandbox image (those are mcpjam cloud images), and not the STDIO environment variables you pass with --env.
All environments commands require an sk_ API key (via --api-key or the MCPJAM_API_KEY environment variable) or a prior mcpjam cloud login. Reading requires project membership; creating, updating, archiving, and restoring require project admin — a key bound to a non-admin gets a FORBIDDEN error on those.

Shared platform flags

The revision workflow

Environments use optimistic concurrency. Every write takes --expected-revision, the revision you last read:
If someone else changed the environment in between, the write fails with a CONFLICT error (HTTP 409) instead of overwriting their edit — re-read it and retry. CONFLICT also covers a duplicate name and archive-state errors (archiving something already archived, editing something archived), so read the message.

cloud environments list

cloud environments get

cloud environments resolve

Preview what the environment resolves to right now: the host’s current config, the closed server set, and the pinned plugin versions. Fails with CONFLICT when the environment can’t currently produce a runnable configuration (for example a pinned plugin was disabled); details.code carries the specific reason.

cloud environments create

* --name and --host-id may instead be supplied inside --file/--json; explicit flags override the same key in the JSON body. Use the JSON body for the structured fields that have no flag — serverAttachmentId, skillSelection, and pluginVersionIds:

cloud environments update

Only the fields you pass change. To clear serverAttachmentId, skillSelection, or pluginVersionIds, send an explicit null in the JSON body — an empty array is rejected, it is not a way to clear:

cloud environments archive

Archiving is reversible and frees the name for a new environment; the row is kept.

cloud environments restore

Fails with CONFLICT if another live environment took the name while this one was archived. Plugin pins whose version no longer exists at all are dropped on restore — compare the returned pluginVersionIds against what you archived.

cloud environments ensure-adhoc

Get or create an unnamed environment for a composed stack. Deduplicated by content: the same stack always returns the same environment, with created: false on the second call. Ad-hoc environments do not appear in environments list — they exist so a one-off combination can be run and reproduced without adding a name to the project’s list. Requires project membership, not admin (pinning plugin versions still requires admin).

cloud environments name

Promote an ad-hoc environment to a named one in place — the same id every existing run already points at, so history stays attached. Fails with CONFLICT if the environment already has a name.

What can be pinned

Both pin fields are narrower than they look:
  • skillSelection accepts project-shared skills only. Personal skills, skills with supporting files or extra frontmatter, and plugin-component skills are all rejected.
  • pluginVersionIds accepts a plugin version only when its plugin is installed and enabled, the version is ready, at most one version per plugin is pinned, and none of the version’s skills carry supporting files.

cloud images commands

Manage custom Computer sandbox images in your hosted MCPJam projects. An image is defined by a blueprint — YAML with a digest-pinned base image, initialize steps baked into the image at build time, and maintenance / knowledge text delivered to the agent at runtime (never executed automatically):
All images commands require an sk_ API key (via --api-key or the MCPJAM_API_KEY environment variable) or a prior mcpjam cloud login.

Shared platform flags

cloud images list

cloud images get

cloud images validate

Lint a blueprint without saving it. Prints ok plus the resolved base digest, or structured errors with the YAML path of each violation.

cloud images create

cloud images edit

cloud images build

Trigger an image build for the sandbox image (async). Poll images logs to check build status.

cloud images logs

Show a sandbox image’s builds (newest first) with their log preview.

cloud images use

Boot your computer from this sandbox image. This rebuilds the computer — installed files are wiped.

cloud images reset

Reset your computer to its current image, wiping mutable state.

cloud images promote

Share a personal-draft sandbox image with the whole project. Requires project admin permissions.

cloud images delete

Permanently delete a sandbox image from a project.

cloud skills commands

List and read the Cloud Skills in your hosted MCPJam projects. These commands exist to close a gap: three flags across the CLI take a skill ID (eval run --compose-skill, eval cases run --compose-skill, environments ensure-adhoc --skill) and until now there was no way to discover those IDs without opening the web app. Authoring stays in the app — these commands are read-only. All skills commands require an sk_ API key (via --api-key or the MCPJAM_API_KEY environment variable) or a prior mcpjam cloud login.

Shared platform flags

cloud skills list

List the skills visible to you in a project — the project-shared ones plus your own personal drafts. Each row includes a pinnability field that says whether the skill’s ID is usable with --compose-skill and environment skillSelection, and why not if it isn’t.

cloud skills get

Show one skill, including its SKILL.md body.

inspector commands

inspector open

Start or attach to the local Inspector and open the UI.

inspector start

Start the local Inspector in the background without opening a browser.

inspector stop

Stop the local Inspector if it is running.

cloud tunnel

Expose a local MCP server through an MCPJam relay tunnel and register it as a server in your hosted project, so evals and scenarios can target it. Requires an sk_ API key or a prior mcpjam cloud login. The tunnel stays up until Ctrl-C; the server record outlives the session (calls fail fast at the edge until you re-run, which revives the same URL slug with a fresh secret).
With --format json, a single machine-readable startup object (public URL, server ID, slug, project) is written to stdout; ongoing status goes to stderr in both formats.
The public tunnel URL embeds a bearer secret and is stored on the project server record so the platform can call it. Every re-run rotates the secret and disconnects any previous tunnel session for the same server.

readiness hosted commands

Grade a saved server against a publisher’s directory as the platform reaches it — through the saved server row and the authorize exchange. This is the hosted half of readiness check: it answers a different question (what the platform sees, not what your machine sees), can optionally spend credits for model observations, and leaves a persistent record. All readiness hosted commands require an sk_ API key (via --api-key or the MCPJAM_API_KEY environment variable) or a prior mcpjam cloud login.

Shared platform flags

readiness start claude

Start a hosted readiness run that grades a saved server against Anthropic’s connector-directory rules. Returns immediately with a run id; poll with readiness status.

readiness start openai

Start a hosted readiness run that grades a saved server against OpenAI’s app-directory rules. --submission-mode is required and never inferred — omitting it would silently report the package lane as not-applicable.

readiness status

Read one hosted readiness run. The response carries three independent axes: status (whether the run finished), overallStatus (the grade — a completed run can be not-ready), and llmObservations (whether the optional model pass ran).

readiness list

List hosted readiness runs, newest first.

readiness cancel

Stop a hosted readiness run that is still going. The run’s real terminal state arrives on a later readiness status — this response reports the request, not the outcome.

readiness report

Read a finished run’s findings, ordered most-consequential-first and capped. truncated and totalFindings indicate when you are seeing a subset.

cloud eval commands

All eval commands accept the shared platform flags below.

Shared platform flags

cloud eval create

Create a runnable eval suite from authored test cases (does not run it).

cloud eval list

List the eval suites saved in a project.

cloud eval run

Start an eval run of an existing suite, or upload a versioned suite file and run it. Provide either --suite or --file, not both. By default the command prints a launch receipt and returns immediately. --wait polls every launched run to a terminal state. Exit codes (--wait only). Without --wait this command’s exit code is unchanged: 0 on any launch, 1 on a partial or wholly failed fan-out. --wait owns a separate six-code contract — a caller who asked this process to sit and watch a run to completion is asking it to say how the run went: No infrastructure condition ever maps to 1 — see the same rule under eval gate below. A multi-target launch merges these worst-of across every waited run, in the order 1 > 3 > 4 > 5 > 0: a real verdict failure is never masked by a sibling’s infrastructure noise, and a credential failure (which may be why other targets show no verdict) outranks a plain connection failure. This six-code contract is new and deliberately different from eval gate’s four codes below — see that command’s own doc for why the two are not unified. An invalid suite file exits 2 either way — eval validate still exits 1 for the same contract failure, because it is a verdict on the file and this command is not.

Composing a target instead of naming one

--compose-host <id-or-name> builds an execution stack for this run instead of naming a saved environment, refined by --compose-computer, --compose-model, --compose-server-group and --compose-skill. The stack becomes an unnamed, content-addressed environment (the same one environments ensure-adhoc produces), so composing the same stack twice reuses one environment.
This edits the suite. The composed environment is appended to the suite’s environment list — deliberately, because an environment the suite does not list is one nobody can re-run from the app afterwards. The result reports both writes (composed.environment.created, composed.attachment.attached) even when the launch itself fails, so you always know what changed.
Any --compose-* flag alongside --environment, --host, --server or --all-targets is a usage error: compose builds the stack the run uses, so naming a target alongside it describes two different runs.

Which target runs

Fan-out is explicit and never inferred. Choosing for you would be choosing how much to spend, so:
  • nothing attached → the suite’s saved server selection runs (unchanged);
  • exactly one attached environment or host → that one runs automatically, and the run is stamped with its configuration;
  • several attached → the run fails with TARGET_REQUIRED, listing every choice. Name one with --environment / --host, several by repeating the flag, or run all of them with --all-targets.
--all-targets expands one axis: attached environments if the suite has any, otherwise attached hosts — never a cross product, because an environment already resolves a host. It starts one paid run per target, launched as a single group that occupies one concurrency slot rather than N. --environment / --host and --server are mutually exclusive: an environment or host supplies a closed server set that an override cannot change.
--refresh-snapshot changes the suite, not just this run: it re-derives and stores the suite’s host-config snapshot, so every future run uses the new one. It is rejected on any multi-target launch — several runs racing to write one snapshot would leave the suite pinned to whichever finished last.

Output and exit codes

With --format json, stdout is exactly one JSON document — the launch receipt, with nothing appended — so CI can parse it directly. In human format the CLI prints a View: link per started run, a Started N/M runs (group …) summary when several launched, and a Failed: <target> — <code>: <message> line per failure. With --wait, the default output contains the launch receipt and completed runs. --reporter replaces that output with the canonical structured report. --out writes the same report atomically, including on failed-run and post-completion reporting-error paths, before the command sets its exit code. Without --wait, a partial or wholly failed fan-out exits 1; with --wait it exits 4 (see the exit-code table above). A per-target failure does not abort its siblings, so exiting 0 would let a pipeline read “1 of 3 runs never started” as a clean launch.

--file: upload and run a suite file

eval run --file reads the versioned suite file (schemaVersion: "1"), authenticates, then validates. A contract-invalid file exits 2 after the auth request — it does not start a run. eval validate on the same bytes still exits 1: that command is a verdict on the file; this one is not. The file’s suite.id is the declared suite identity. The first run creates a file-owned suite stamped with that id; later runs of the same id in the same project update that suite rather than creating a second one. A UI-authored suite has no declared id, so no file can claim it. Resolve is never by name. File passThreshold is a fraction; the hosted suite grades on a percent. The conversion refuses rather than approximates. File repetitions above 10 are refused by name (REPETITIONS_CAP) and are not clamped. Cases are synced in batches of at most 100 (create_eval_cases). Every declared case is created or updated, including disabled: true rows. A case the file no longer declares is deleted from the hosted suite before launch. A case the file still declares but marks disabled: true is kept, with its history — it is simply left out of the launch, so parking a flaky test does not destroy its past results and re-enabling it later resumes the same case. The run is scoped to the enabled cases either way. A file with no enabled cases is refused (NO_ENABLED_CASES) rather than launching the whole persisted suite. --case may only name an enabled case. A later run updates existing cases by declared id and creates new ones. An enabled case that overrides passThreshold is refused: hosted grading is suite-wide. A disabled case with the same override is ignored, matching how repetitions are checked. Authored defaults.toolPolicy and non-empty defaults.validity gates are refused at hosted CLI launch (TOOL_POLICY_UNSUPPORTED / the corresponding validity refusal). Hosted platform-authored suites do not currently have a backend tool-policy field or enforcement path, so the CLI does not upload a suite that would claim those guarantees. When supported by an eval runner, toolPolicy is enforced at execution time with denied tools kept visible but blocked; server annotations are advisory and UNTRUSTED. File defaults.repetitions is inherited per case and is not uploaded as a suite minIterations floor. Authored defaults.systemPrompt and defaults.temperature are uploaded as execution defaults; omitted fields stay omitted so the platform applies its own defaults. target.hosts and target.environment are attached before launch. A file environment takes precedence over file hosts for that launch, while an explicit CLI target takes precedence over both. When an explicit CLI target is provided (for example --host), the file’s target.hosts are not synchronized to the suite’s persisted host attachments — the suite keeps whatever hosts it already has. Host attachment synchronization only runs when no explicit CLI target overrides the file. Environment attachment synchronization is unaffected and always runs. Without --idempotency-key, the CLI derives one from the file’s SHA-256, declared suite id, project, target, and every run-affecting knob (--iterations, --case, --min-pass-rate, --exclude-skills, --match-options, --environment / --host / --server / --all-targets, --refresh-snapshot, compose flags, and the normalized --allow-approximated set with its --approval-reason). Repeating the same file with the same knobs returns the run it already started; changing a knob starts a new one. The approval set is sorted and keyed by AUTHORED case id, so --allow-approximated a b and --allow-approximated b a are the same run while approving nothing is a different one. --notes is not part of the key.
Imported cases: live tool resolution, and per-run approval
Every file run performs the same live check eval validate --project performs, before it writes anything. It is not opt-in and there is no flag to skip it. A file with no deterministic toolCall steps asks no question and pays no round trip. What happens when a deterministic reference does not resolve depends on the case: Each target is checked on its own server set. --host is checked against that host’s configured servers rather than the file’s, because that is the set the run connects — validating target.servers would approve a tool the host cannot reach. A host the FILE declares uses its own servers list when it declares one (those are attached to the host before launch) and the host’s configured set when the field is omitted. An explicitly empty servers: [] is a real, empty set — it clears the attachment before launch — and is validated as such, never as an omitted field. A step that pins serverId is resolved by id; serverName is a display fallback and never overrides it. If the run’s target set cannot be enumerated before the suite exists (--all-targets, --compose-*), or a host does not report a server set, or a host pins a server the project no longer has, the launch refuses rather than assuming the references are fine. --case accepts a hosted row id, which does not exist yet when this check runs. A selector this stage cannot map is therefore treated as possibly naming any enabled case, so an unresolved reference still refuses; the launcher resolves the selector itself a moment later. A selected approximated case refuses unless this invocation approves it:
Checked before anything is billed, each with its own message: approving a native case (nothing to approve), a claimed-exact one (needs no approval), an unsupported or unresolved one (approval covers a case whose behaviour was approximated, not one whose behaviour is missing), a disabled or unselected one (the run will not execute it), an unknown id, or the same id twice. The flags are refused outright with --suite: a hosted suite’s cases are not the ones this invocation authored, so an authored-id selector has nothing to resolve against. The approval belongs to the run, never to the case. You supply an id and a reason and nothing else — the approver and the timestamp are derived by the server and frozen into that run’s own snapshot, because a caller-supplied approver would file one person’s approval under another’s name and a caller-supplied timestamp could be backdated past the edit that invalidated the claim. Nothing persists: edit the suite, re-sync, or launch again, and the flags are required again. Scheduled runs and GitHub-App runs cannot approve anything. A scheduled suite containing a selected approximation is refused by platform policy, which is the intended behaviour — an unattended job is exactly the caller that must not be able to wave one through. --file pointing at create-API JSON (no schemaVersion) is a usage error that names eval create --file. The converse is also true: eval create --file on a versioned suite file names eval run --file. Export of a file-owned suite writes declaredId as suite.id. Export of a UI suite still writes the Convex id; running that file back is the ownership refusal. When the run targets an attached project environment (eval environments set), it executes against that environment’s resolved host config, closed server set, and pinned plugin versions instead of the suite’s saved selection. Every run records the environment and the exact revision it used, so eval status can answer “which configuration did this run actually execute against?” long after the environment has been edited.

cloud eval status

Get the status and summary of an eval run. The response carries a judges block with each advisory grader’s state and per-case grades. status: null means that judge was never requested for the run — different from a judge that ran and graded nothing. In --format human, each judge that actually graded gets a one-line summary.

cloud eval judge

Grade a finished eval run with LLM as Judge. Spends your organization’s model budget. Returns a pending receipt; read the grades from eval status. A run’s grading config is pinned when the run starts, so turning the judge on for the suite does not reach a run that was already recorded — --enable is what grades it, and it changes nothing beyond that run. Passing neither --judge-model nor --judge-threshold grades with the suite’s own config, clearing any override a previous request left on the run.

cloud eval iterations

List per-iteration results for an eval run (pass/fail, tool calls, tokens, latency). Results are paginated. --project is optional. Selection follows --project → input selector → MCPJAM_PROJECT → nearest project link → automatic newest accessible project.

cloud eval gate

Apply a pass/fail policy to an eval run. Add --wait to poll an in-progress run before evaluating it. Report files are flushed before gate exit codes are set, including failed and incomplete gate outcomes. --baseline / --baseline-sha. Either flag fetches the same run comparison cloud eval compare uses and folds a regression verdict into the same report and exit code as the threshold flags above — either one alone enables the pass-rate regression gate with its default tuning; the four tuning flags need a baseline to mean anything and are a usage error without one. A case set that changed, was added or removed, or ran an unequal iteration count between the two runs makes the whole-run pass-rate and p95-latency gates non-gateable (exit 3) rather than a silent pass or a misread regression; the deterministic per-case regression gate is exempt and can still fail (exit 1) on a matching case. The two are mutually exclusive — passing both is a usage error (exit 2). There is deliberately no single flag that guesses which kind you meant: a Convex run ID is an opaque string with no documented format, and an abbreviated commit SHA is indistinguishable from one by construction, so the kind is named by the flag rather than inferred. A commit SHA passed to --baseline is rejected with a pointer to --baseline-sha instead of being sent as a doomed run lookup. A SHA that matches no completed run in the suite is not an error: it is the ordinary “no baseline” outcome, incomplete (exit 3), which means the comparison established nothing — never a regression. When the SHA matched more than one eligible run, or the lookup was truncated before it could prove uniqueness, the gate report’s baseline provenance records baselineMatchCount alongside baselineMatchCountTruncated; the count is a floor, not a total, so the two are always read together. An absent count means the match was unambiguous. Baseline provenance records both what was requested and what it resolved to — requestedBaselineKind, requestedBaselineRunId or requestedBaselineCommitSha, the backend-echoed resolvedBaselineCommitSha, and the resolved baseRunId — so an archived report can answer “which run did commit X compare against?” without the invocation that produced it. There is no automatic baseline selection: a baseline is compared only when one is pinned. Gate waivers. A run whose gate failed can be overridden by an authorized user, on the record, until an expiry they name — see cloud eval gate waive below. When a waiver is in force, eval gate reports the outcome as waived and exits 0. waived is deliberately not the same as passed. The run keeps its own failed result, the failing verdicts stay in the report, and the waiver — who granted it, why, and until when — is named in every output format: the human report, json-summary, junit-xml (as a <skipped> element on the gate testcase, which does not fail the build and does not render as a clean green row), and html (its own badge and section, neither green nor red). Only a real verdict failure can be waived. An incomplete gate — a cancelled run, a --wait timeout, a network failure, non-gateable score evidence — keeps exit 3 no matter what waiver is on the run: a waiver granted because the evals regressed is not consent to ship on an infrastructure failure. A usage_error keeps exit 2 for the same reason. The CLI also re-derives the waiver’s expiry itself rather than trusting the platform’s active flag, so a lapsed waiver cannot keep a gate green. Exit codes. eval gate is the command that fails a build, so it is the one that maps a verdict onto an exit code. It keeps four: Incomplete import evidence is exit 3, decided first. When the platform reports the run’s importEligibility as incomplete (or gateable: false under any status), eval gate returns 3 before any verdict is computed and before a waiver is considered. That ordering is the point: import completeness is evidence ELIGIBILITY, not a measurement of the server, so it is never exit 1 — the run has not said the server regressed, it has said its own evidence cannot be relied on. A waiver cannot override it either, for the same reason it cannot override a cancelled run: a waiver granted because the evals regressed is not consent to ship on evidence nobody finished reviewing. Fix it by re-running with the approvals the cases need, or with the unsupported cases excluded. The baseline is checked too. A --baseline / --baseline-sha gate rests on two runs, so eval gate reads the resolved baseline run’s own importEligibility and returns 3 when the baseline cannot gate — the compare response reports counters, not provenance, so the baseline is fetched by id rather than assumed sound. Without that, a baseline whose own approximations were never approved could still produce a confident “no regression”. A baseline run that cannot be read at all is also 3: “we could not look” is not “it is fine”. A run whose eligibility is legacy (no imported cases at all — every native run) or eligible goes through the ordinary verdict logic unchanged. A server that reports no eligibility at all behaves exactly as it did before the field existed. No infrastructure condition ever maps to 1. A job that fails a release because a network call flaked, and reports it as a regression, teaches people to ignore the gate — so retry on 3, and treat 1 as a real finding about the server. These four are deliberately not the same set eval run --wait uses (see that command above): gate’s exit 3 means “incomplete / non-gateable”, and remapping it to the six-code scheme would invert pipelines that already retry on 3. This is a deliberate compatibility exception for v1 — a six-code migration for gate is deferred behind a future opt-in flag, kept here so the exception stays documented rather than silently diverging.

cloud eval gate waive

Override a failing run’s gate until an expiry you name. Requires the manage tier, enforced by the platform — whoever launched the run gets no exception for having launched it. This does not make the run pass. The run keeps its result, and the waiver is reported by both things that read the gate: the GitHub Check Run and eval gate itself.
The reason is stored unredacted, for the life of the suite. It is readable by anyone who can see the suite and has no independent retention window. Never paste secrets, tokens, or customer data into it. The CLI prints this notice before it accepts a reason.
A bare number is rejected: --expires-in 7 is ambiguous between seven minutes and seven days, and the difference is a gate that reopens before lunch or three weeks later. The 30-day cap is enforced by the platform, so the refusal names the cap and what to do instead. Waiving a run that already has a waiver in force is a conflict, not a second waiver: the existing one is reported back and is left untouched, because two active waivers would make “which reason is on the check” a race.

cloud eval gate unwaive

Revoke a waiver, putting the gate and the GitHub Check Run back.
Idempotent. A second revoke reports the original revocation rather than restamping it — that is a success, not an error, and it preserves the record of who actually ended the waiver. An already-expired waiver can still be revoked; the audit trail distinguishes “this was wrong” from “this ran out”.

cloud eval trace

Fetch the full trace for one eval iteration (complete message history and spans). Can be large. --project is optional. Selection follows --project → input selector → MCPJAM_PROJECT → nearest project link → automatic newest accessible project.

cloud eval get

Show an eval suite’s full settings.

cloud eval validate

Validate a local eval suite file — the versioned declarative document that describes a suite, its defaults and its cases (schemaVersion: "1", YAML canonical, JSON accepted, conventionally .mcpjam/evals/*.yaml). Offline by default: without --project this command builds no API client, reads no API key and never touches the network. Passing --project is the only thing that changes that, and it is keyed off the FLAG — a linked directory or an MCPJAM_PROJECT in the environment never turns the offline command into a networked one. Input is capped at 1,048,576 bytes (1 MiB) of UTF-8 and is never truncated — a file over the cap is rejected outright. Under --format json, stdout carries this envelope whether the file is valid or not:
Findings are deterministically ordered and carry no timestamps, so two runs over the same bytes produce byte-identical output. An unreadable or missing path is a usage error and goes to stderr in the CLI’s standard error envelope rather than as findings — nothing was read, so there is nothing to report about. What “valid” does not mean, without --project. The offline check judges the file against the suite-file contract. It does not re-resolve tool names, server references or fixtures against a project’s live discovery, so a file that validates here can still fail to run.

--project: resolving the names against a real project

With --project, the command authenticates, resolves the named project, and checks every deterministic toolCall step against the live tool inventory of the targets the file would run on. Structural findings are unchanged and the live half is additive, under its own key:
Three properties of the live check are worth knowing before you rely on it:
  • Only toolCall steps count. A tool named in prompt text is a hint the model may or may not act on, and an assert step is an expectation a case may legitimately fail at run time. Treating either as a deterministic reference would make a negative test unwritable.
  • Per target, never over their union. A file that runs against several targets must resolve in all of them; a union would green-light a case that fails on two targets out of three.
  • Auth and network failures are command errors, not findings. “Your file names a tool that does not exist” and “we could not look” send you to two different places, so they are never reported as the same thing.
A completed live check with unresolved references is a verdict on the file and exits 1, like any other contract failure. A failure to authenticate, reach the project, or list a server’s tools is a command error on stderr.

cloud eval export

Write a hosted eval suite to a local suite file. The default path uses the suite’s id, not its display name: an id is stable and path-safe, so a rename does not leave a second file behind. Fail-closed. A suite file cannot express everything a hosted suite can, and this command refuses rather than writing a file that describes a different test than the dashboard runs. When any part of a suite is not representable it emits UNSUPPORTED_SUITE_EXPORT findings, exits 1, and writes no file at all — not a partial one, not one with a warning comment. Every finding names the field it is about, so the command’s output is the authoritative list; the constructs that refuse today include:
  • several attached project environments, or legacy servers combined with an attached environment (the suite file can name one environment);
  • a pinned sandbox image;
  • automatic LLM-as-judge grading, non-default match options, and an iterations floor that raises a case above its own count;
  • a compare-across-models case, a scenario-bound case, and cases that name different model providers (a suite file carries one suite-level provider);
  • replace/extend check overrides, a case that inherits the suite’s checks while also carrying its own, and any suite check the predicate contract does not recognise;
  • a suite with no execution model, no minimum accuracy, no name, no runnable server or environment target, or no cases; a case with no steps; and a suite or case id that is not an opaque id;
  • a suite that serializes past the 1 MiB suite-file limit — the size is a property of the suite, and this never truncates.
Case identity is never freshly minted: a case exports under its declared id, or under its platform row id, or it refuses. Exporting the same suite twice produces the same case ids. The file is written through a sibling temp file and a rename, so an interrupted write leaves the previous file exactly as it was.

cloud eval update

Edit an eval suite’s settings (only the flags you pass change).

cloud eval checks list

List the repositories whose pull requests run an eval suite, plus the repositories the MCPJam GitHub App can reach. available: false means GitHub Checks is not enabled for the organization at all, so connecting a repository will not help. connectable: null means the App could not be asked (GitHub unavailable, or no installation) — different from an empty list, which would mean it reaches nothing.

cloud eval checks connect

Run this suite on every pull request to a repository. Affects everyone who opens a pull request on that repository, and with fail-closed it can block their merges. --outage-policy has no default on purpose: it decides what happens to other people’s pull requests during an MCPJam outage, and it is not editable from this command afterwards. Retargeting a repository at a different suite, pausing it, and disconnecting all live in the app’s Settings → Integrations, where every connected repository is visible at once.

cloud eval delete

Permanently delete an eval suite (and its cases and runs).

cloud eval schedule

Enable or disable scheduled runs for a suite. Pass either --enable or --disable (not both). A scheduled run launches exactly one run, so a suite with several attached environments must pin one with --environment; a suite with exactly one defaults to it. --environment is rejected with --disable: disabling preserves the existing pin, so accepting one there would silently do nothing.

cloud eval environments subcommands

Attach or detach the project environments an eval suite runs against. Attaching is what makes eval run --environment available for the suite.

cloud eval environments set

Replace the suite’s attached environments (this sets the whole list, in order).
Rejected if it would strand an enabled schedule pinned to an environment being removed — repoint the schedule (eval schedule --enable --environment ...) or disable it first.

cloud eval environments clear

Detach every environment, reverting the suite to its saved server selection. Subject to the same schedule guard as set: rejected if the suite has an enabled schedule pinned to one of the environments being removed. Repoint the schedule or disable it first.

cloud eval cases subcommands

cloud eval cases list

List a suite’s test cases.

cloud eval cases get

Show one test case.

cloud eval cases run

Run a single case as a persisted, fully-queryable run — inspect it with eval iterations / eval steps like any other run. Every --compose-* flag behaves exactly as it does for eval run — see Composing a target instead of naming one. Target selection follows the same rules (Which target runs), except that a single case run targets ONE thing — there is no --all-targets here.

cloud eval cases create

Add a test case to a suite (definition via --file/--json).

cloud eval cases update

Edit a test case (definition via --file/--json).

cloud eval cases delete

Permanently delete a test case.

cloud eval cases generate

AI-generate test cases from the suite’s tools (spends credits).

mcp command

mcp

Run MCPJam as an MCP server over stdio so MCP clients (Claude Desktop, Claude Code, Cursor, …) can connect to, exercise, and debug other MCP servers. See MCPJam as an MCP server for the exposed tools and client setup.
The command takes no flags of its own. The global --timeout <ms> flag sets the default per-request timeout against target servers, and --quiet suppresses the startup notice on stderr. Stdout carries only JSON-RPC; never pipe other output into it.

telemetry commands

Telemetry commands inspect and configure anonymous CLI telemetry. They never emit telemetry events themselves.

telemetry status

Shows the effective telemetry state, install ID state, state file path, debug mode, and disable reason when disabled. This command does not create an install ID.

telemetry disable

Persistently disables anonymous CLI telemetry by writing enabled: false to the telemetry state file. If no install ID exists yet, this command does not create one.

telemetry enable

Persistently enables anonymous CLI telemetry. If no install ID exists yet, this command creates a random install UUID.

cloud workspace

mcpjam cloud is the account-bound namespace. Log in, link a project, then run evals, tunnels, and the rest of the Cloud groups.

Cloud account session

See cloud login / logout / whoami below. Pin the current Git worktree (or --here cwd) to a Cloud project by writing .mcpjam/project.json. No secrets. Bare link ignores an existing file when choosing what to pin.

cloud status

Zero-network. Prints credential source, deployment URL, and the project selector that Cloud commands would use (flag / env / link / automatic). API keys are redacted. The report includes credential.valid (true / false / null) and deployment.valid. null means no credential is configured and is a successful informational status. An invalid explicit --api-key or --api-url still emits the complete JSON report, sets ok: false, includes an error string, and exits 1. Other Cloud commands reject those same values with exit 2 and no report.

cloud organizations list

List organizations and their ids. An sk_ key sees only its own. Use the id with mcpjam cloud projects list --org <id>.

cloud projects list

cloud sessions list

List Playground chat sessions in the selected project. Same project-selection rule as other Cloud commands.

cloud sessions send

Send one message to a project’s MCP servers and print the reply plus the raw tool calls, per-call latency and token usage — the telemetry a participant in the conversation cannot see. This spends model credits on every call. --idempotency-key is required and must be stable for the intent, not regenerated per attempt. It is what makes a retry safe: with the same key, a turn that already completed is replayed rather than re-run and re-billed. A fresh key per attempt deduplicates nothing. Omit --session to start a conversation; pass the sessionId the command returns to continue one. Configuration is fixed at the first turn, so --model, --environment, --server, --system-prompt and --tool-mode are refused alongside --session rather than silently repinning the session. read_only filters on a hint the SERVER asserts, so it is a policy this host applies rather than a guarantee it can verify. A server is free to annotate a mutating tool as read-only.

cloud sessions show

Print a session’s metadata and a window of its raw messages. Message index values are absolute transcript positions — the same indices cloud sessions trace spans reference, so the two outputs join on that number. A transcript that could not be read reports transcriptUnavailable: true and a null messageCount — never 0, which would claim the conversation is empty.

cloud sessions trace

Print a session’s per-turn execution spans: per-tool-call latency, token usage, and indices into the transcript. Returns the latest turn by default rather than the whole session — a session’s spans are the largest thing the API emits, and the turn you just took is the one you are debugging. A turn whose spans could not be read reports spansUnavailable: true rather than an empty spans array: “made no calls” and “could not fetch” are opposite conclusions.

cloud login / logout / whoami

These commands manage your MCPJam platform session. login opens a browser for OAuth and stores the session locally; logout removes it; whoami shows the account behind the current credentials.

cloud login

The MCPJAM_API_URL environment variable is equivalent to --api-url. An invalid value in either source is a hard error (exit 2). URL resolution order for cloud commands after login:
  1. Explicit --api-url flag
  2. MCPJAM_API_URL environment variable
  3. The apiUrl stored with the OAuth session (only when the stored login is the credential; sk_ API keys do not inherit the stored URL)
  4. Production default (https://app.mcpjam.com/api/v1)
Login output fields: After a successful login, the result includes: Account details (email and plan) are fetched from the platform after the OAuth exchange completes. If the lookup fails, login still succeeds and a warning is printed to stderr (suppressed with --quiet).

cloud logout

No additional flags. Removes the stored MCPJam session. When MCPJAM_API_KEY is set to an active sk_ key, logout prints a warning to stderr (human format only) noting that the CLI remains authenticated via the environment variable even after the stored session is cleared. JSON output is unaffected.

cloud whoami


Exit codes

Codes above 2 are reserved for outcomes a script should act on differently — not merely for naming a failure. See MCP Tasks for the full tasks watch mapping.