Outcome
The result of one eval: its text plus whether it ended in error, which the MCP layer maps to tools/call isError.
text is built on first read: draining the output Capture is O(size) and that sink is unbounded, so the copy belongs on the HTTP thread already blocked on this result. The COPY only — a value is rendered eagerly, on the thread that ran the eval, because toString() is caller code and a game object's reads game state. Supplier rather than a Kotlin function type because this crosses the masking-loader seam, where only java.* has a single identity.