WebMCP tool results
The browser adapter returns the SDK's JSON result envelope, including diagnostics,
confirmation previews, HTTP metadata and verification outcomes. Results have a
UTF-8 JSON limit (maxResultBytes, default 1 MiB). Exceeding a limit returns a
failure; output is never silently clipped. A rendering failure after an API call
cannot undo the call. Inspect API state before retrying consequential operations.
Streaming and declared binary responses reject before HTTP by default. Secret response fields and values shown only once remain blocked with every result policy. Use trusted SDK application code for those outputs.
Bounded SSE collection
For an operation with an SDK stream descriptor, explicitly enable collection:
const registration = await registerTungstenWebMcp({
core, manifest, backend,
streamCollection: {
maxEvents: 100,
maxBytes: 256 * 1024,
maxDurationMs: 10_000,
},
});
Every limit is required and must be a positive safe integer; duration is at most
2,147,483,647 ms. maxResultBytes must exceed 1024 for collection. The adapter
uses ClientCore.stream, so SDK authentication, SSE Accept headers, validation,
confirmation and idempotency remain authoritative. Streaming macros are rejected.
Success is { ok: true, value: events, reconnects }. Each event retains its SDK
value, event, id, retry and meta. An SDK failure retains its diagnostic
and adds partial (previous events) and reconnects. Adapter count, byte and
duration failures also return partial. Partial output is incomplete and is not
an instruction to retry. Adapter interruption of a mutation uses OUTCOME_UNKNOWN
and directs the caller to inspect API state. SDK diagnostics retain their original
classification and effect guidance.
The byte budget counts UTF-8 JSON event envelopes and separators. The outer result
budget reserves 1024 bytes for envelope/diagnostic overhead. The SDK separately
bounds individual SSE events with ClientOptions.maxEventBytes; configure that
limit for the upstream API. Collection ends only on complete stream termination;
reaching a count limit while another event arrives is a failure. Time limits and
caller abort cancel the SDK reader. Caller abort leaves registration available;
registration disposal cancels active calls and unregisters owned tools.
JSON Lines/NDJSON responses use ClientCore.call and its array result envelope,
not SSE collection. Configure SDK response validation as strict when malformed
JSON Lines must fail rather than produce the SDK's default warning. With an
explicit result policy, non-SSE HTTP bodies are bounded while reading by the
adapter's maxResultBytes (or the declared binary policy's maxBytes).
Binary output
Small, reviewed binary outputs can be converted to JSON base64:
binaryResults: { mode: "base64", maxBytes: 64 * 1024 }
The result value is { kind: "binary", encoding: "base64", mediaType, byteLength, data }, retaining the outer SDK envelope. Base64 expansion must fit the JSON
result budget. The HTTP reader checks both declared Content-Length and actual
received bytes, cancels on overflow, and never retries an oversized response.
Applications can instead render an expiring download handle:
binaryResults: {
mode: "download",
maxBytes: 256 * 1024,
async render({ bytes, mediaType, operation, signal }) {
return applicationDownloads.create({ bytes, mediaType, operation, signal });
// { url: "https://downloads.example.test/opaque-handle", expiresAt: epochMs }
},
}
The adapter accepts HTTPS URLs without embedded credentials and future integer
expiry timestamps. The JSON value is { kind: "download", mediaType, byteLength, url, expiresAt }. The application must enforce expiry, access control and its
content policy; a timestamp alone does not expire a URL. The renderer receives
an AbortSignal and should cancel its own work. No browser Blob URLs are generated,
and secret-bearing outputs never reach the renderer. Invalid handles and binary
limits return explicit failures with guidance about possible API effects.