MCP JSON captures and assertions
The MCP inspector can return a public value from one tool call for use in later steps. Captures are retained in evidence. Keep credentials in private bindings or owner-only token files.
Declare api in your flow frontmatter and
connect its private binding:
providers: api: MCPCapture a scalar
Section titled “Capture a scalar”Use your binding alias as the receiver. call_value takes the same tool and
arguments as call, with a required RFC 6901 JSON Pointer:
api.call_value tool="create_record" arguments="{\"title\":\"test record\"}" select="/id" -> record_idapi.call tool="get_record" arguments="{\"id\":\"${record_id}\"}" expect="{\"isError\":false,\"json\":[{\"pointer\":\"/id\",\"equals\":\"${record_id}\"}]}"The tools and paths above are examples; use the names and response shape of your server. Each command calls its tool once. A failed selection never repeats the first call. A lost reply may have run the tool and is recorded as unknown.
Selection reads structuredContent when present. Otherwise it joins text blocks
with newlines and parses the result as JSON. The empty pointer selects the root;
/a~1b selects member a/b, and /a~0b selects member a~b.
The selected value must be a string, number or boolean, at most 4 KiB, without control characters or a binding private value. Null, objects, arrays, missing paths, non-JSON text, tool errors and JSON-RPC refusals fail the step and return nothing. A malformed or private pointer is refused before contact. Repeated object members make the source ambiguous and produce no capture.
Every capture is an RFL string. Numbers preserve their response JSON spelling;
booleans return true or false. ${record_id} can enter a later JSON string
value as escaped text, including when it contains quotes or backslashes. It
cannot be inserted as a JSON member name or an unquoted numeric value. See
references in JSON arguments.
call_value accepts positive-result checks such as textIncludes,
textExcludes, redacted and json. It always requires a non-error tool result;
use call to assert isError: true or a JSON-RPC refusal.
Assert JSON
Section titled “Assert JSON”The json expectation takes 1–32 assertions. Each supplies a pointer and
exactly one operator:
| Operator | Operand and meaning |
|---|---|
exists | Boolean: whether the pointer resolves. A present null exists. |
equals | String, number, boolean or null, with exact decimal number comparison. |
type | string, number, boolean, null, array or object. |
count | Exact integer 0–10,000: array elements or object members. |
includes | Literal substring of a string target. |
api.call tool="get_record" arguments="{\"id\":\"${record_id}\"}" expect="{\"isError\":false,\"json\":[{\"pointer\":\"/enabled\",\"equals\":true},{\"pointer\":\"/members\",\"count\":2},{\"pointer\":\"/deleted_at\",\"equals\":null}]}"Tool calls and gateway helpers assert against structuredContent, or the only
text block parsed as JSON. Unlike scalar selection, JSON assertions do not join
several text blocks. read_resource uses its only text entry; get_prompt uses
the {description, messages} envelope. No usable JSON, repeated members or a
source that cannot be checked fails every assertion with source-unavailable
evidence. json cannot be combined with rpcError.
All assertions are evaluated. Evidence records their pointers, operators, pass
flags and fixed failure reasons, without target or operand values. A target
string containing a private value or terminal controls cannot satisfy equals
or includes. Private pointers and operands are refused before the request for
every operator, including numeric equivalents and boolean/null spellings.
Comparator numbers allow at most 1,000 mantissa digits, 1,024 bytes total, and
six significant exponent digits after sign and leading zeros. Host admission is
a separate limit: its parsed number must be finite and have absolute value at
most 9,007,199,254,740,991. That admission can round or underflow, but comparison
retains the original spelling. For example, 1e-400 is admitted and differs
from zero in an exact comparison.
Check absence and binding-secret exposure
Section titled “Check absence and binding-secret exposure”api.call tool="whoami" expect="{\"isError\":false,\"textExcludes\":[\"other-user-marker\"],\"redacted\":false}"textExcludes searches the complete result or error’s decoded string values
and member names, including metadata, annotations, embedded resources and error
data. It also decodes JSON string literals nested inside strings, up to four
layers. Searches are exact and case-sensitive and happen before truncation,
after private binding values and terminal controls have been removed.
Absence by itself can hold on an error or empty reply. Pair it with the intended
result expectation. It cannot detect a binding secret that redaction removed;
"redacted": false fails when a binding private value or stripped terminal
control occurred anywhere in the complete reply. Neither check proves absence
under arbitrary encodings such as base64 or percent encoding.