Created Modified

Experimental systems study · third iteration

Calibrating Newton simulations from photographs with a live MCP

Software
Newton experimental fork · live MCP with inline images
Agents
Claude Opus 5.5 (Claude Code) · GPT-6 Astra (Codex), both at xhigh effort

Abstract

Can a live connection to a running simulator help frontier coding agents calibrate simulations from photographs? In 36 registered trials, Claude Opus 5.5 and GPT-6 Astra calibrated three Newton scenes (cloth material, a pushed box's friction and hidden load, and a Panda arm's joint offsets) from noisy reference photos, starting from untuned defaults. Success was judged on held-out episodes against hidden ground truth. Each paired trial gave the same agent either Newton's live MCP (with persistent Python, inline images, reference comparison, and filmstrips added in this iteration) or an edit-and-rerun script workflow. With the MCP, agents passed 14 of 18 held-out checks against 12 of 18, used 30% fewer input tokens (paired ratio 0.70, 95% interval 0.60–0.80) and 36% fewer tool calls, and Opus's API cost fell by a third. Elapsed time depended on the agent: Opus finished 20% faster, but Astra took 16% longer. Astra's restart workflow ran optimizers in the background while it reasoned, and every MCP call blocked. An exploratory follow-up added parallel worker sessions to the MCP; with them Astra matched restart speed while using 41% fewer tokens. The live MCP makes calibration consistently cheaper in tokens and calls; it makes it faster when agents work synchronously, or when the session can compute concurrently.

This study is complete; its follow-up, a harness-improvement loop, is the current page. Earlier iterations remain available unchanged: the three-way study with IPython and measured Panda identification and the original two-way study.

1. Question and design

The previous iteration found no consistent advantage for Newton's live MCP. In all 61 of its trials, no agent looked at an image: every task could be solved from numbers, both conditions received ready-made rollout helpers, and restarting a simulation cost only 2–3 seconds. This study asks a narrower, practical question: when a frontier coding agent must calibrate a simulation from photographs, does giving it a live Newton application through MCP make it faster or cheaper than editing parameters and rerunning scripts?

Each registered case runs as a pair. The MCP trial and the edit/restart trial for the same task, model, and replicate start together on the same machine, so they share its background load. The machine was shared with unrelated jobs under a four-CPU quota, which affects absolute times; paired ratios are the primary comparison. Both conditions get the same task module, the same noisy reference photos with calibrated cameras, the same parameter bounds and clean-slate starting values, and the same 30-minute budget. The agent decides when it is done and writes params.json.

The MCP condition does not forbid scripts. Pilot agents in the restart condition ran optimizers in parallel background processes, which a single-threaded live application cannot do, so forbidding scripts would handicap the MCP artificially. The comparison is therefore coding agent plus live MCP against coding agent without it. Two agents were tested: Claude Opus 5.5 in Claude Code and GPT-6 Astra in Codex, both at xhigh effort. Both CLIs were checked to pass MCP image content to the model before any trial.

The registration fixed the source commit, the seeded order of 18 pairs (3 tasks × 2 models × 3 replicates), hashes of every task source and reference photo, and the budget before the first scored agent started. Success is decided only after the agent exits: a fresh process simulates held-out episodes with the submitted parameters and compares them with hidden ground truth under frozen gates. All failures and timeouts are retained.

Table 1. Conditions. Both use the same task module, reference photos, parameter bounds, held-out verifier, and 30-minute budget.
ConditionAccessSimulator lifetime
Newton MCPLive application through the Newton MCP (execute, observe, filmstrip, describe, rebuild); the agent may also write and run scripts.One application process for the trial; scripts it writes start their own processes.
Edit/restartEdit params.json or write scripts; sim.py renders the training episodes and writes simulated | reference | mismatch sheets.A fresh process for every script run.

2. What changed in the MCP

The pilots and the previous study pointed to specific friction in the MCP, and each change targets one of those points. All of them are generic Newton MCP features, not task-specific code.

Images from Python. show(image, label) inside newton_execute attaches up to eight images to the response. It accepts NumPy arrays, Pillow images, matplotlib figures, PNG paths, and observation results, so an agent can compose a comparison and see it in the same call, without writing a file and opening it in a separate step.

Observations that need no camera math. newton_observe frames the scene automatically from a preset (iso, front, left, right, top). It can tile several views into one image, and it can compare a render with a reference photo taken by the same camera, returning simulated, reference, and mismatch panels plus pixel statistics.

Motion in one image. The new newton_filmstrip tool advances the simulation and returns one labeled grid of frames over time, optionally with reference and mismatch rows (Figure 1).

Less friction in the Python workspace. Rebuilding the scene now keeps the agent's variables and functions, since the old behavior forced agents to reload analysis state after every parameter change. Applications can inject their own objects (here a task controller) and a usage guide, which the MCP server appends to its instructions. Responses dropped default-valued status fields and the per-call workspace inventory; the old responses carried about 1.5 kB of it on every call.

71 MCP unit and SDK tests pass on the frozen commit, including regressions for every new feature, and the log is published. The v2 recovery contract is unchanged: a runtime error in agent Python pauses and invalidates the scene until the agent inspects and acknowledges it or rebuilds.

Filmstrip from the MCP: three simulated frames of an untuned cloth over a box, the matching noisy reference photos, and magenta mismatch panels.
Figure 1. Actual newton_filmstrip output for untuned default cloth parameters: simulated row, reference photos, and mismatch (magenta: max channel difference above 24/255). One tool call; the image arrives inline.
Four auto-framed views of the pushing scene in one image.
Figure 2. The four panels of one newton_observe(views=["iso", "top", "front", "right"]) response, auto-framed without any camera parameters. At the registered commit the tool stacked views vertically, and they are arranged 2 × 2 here for display; it now tiles them in a grid itself.

3. Calibration tasks from photographs

Each task has a hidden ground-truth parameter set. Reference photos are rendered from the ground truth with Newton's ray-traced sensor camera and receive fixed-seed Gaussian sensor noise (σ = 2.5/255), so a render never matches a photo pixel for pixel. Agents start from generic library defaults and see only photos, camera calibrations, bounds, and the task source. Verification uses held-out episodes with different initial conditions, which they never see.

These references are synthetic. That makes ground truth exact, but it also makes the problem easier than real calibration, because the simulator is the true model of the data. Table 2 lists the gates. The cloth gate is deliberately loose: rerunning the true parameters already differs by about 1 cm mean because folding is nondeterministic, so the gate checks material identification at roughly factor-of-two precision.

Table 2. Tasks, hidden parameters, and frozen held-out gates. Gates were set from private perturbation studies before any agent trial.
TaskParameters (clean-slate start)Evidence givenHeld-out gate
Cloth drape (VBD, 1 m cloth, 40×40)Stretch stiffness, bending stiffness, areal density, friction2 drops × 2 cameras × 3 timesMean particle error ≤ 4 cm, p95 ≤ 20 cm
Planar push (MuJoCo, kinematic capsule)Table friction, pusher friction, COM x, COM y2 pushes × 2 cameras × 6 timesBox position ≤ 1.5 cm, yaw ≤ 10° at all times
Panda joint offsets (kinematic)Seven joint zero offsets4 poses × 3 camerasLink position ≤ 3 cm, hand rotation ≤ 4°
Reference sheet for a training push: top and side views at six times.
Figure 3. One of the reference sheets agents receive (push, episode B): photos from the calibrated top and side cameras at six times, with fixed-seed sensor noise.
Reference sheet for one Panda pose from three cameras.
Figure 4. Panda reference photos for one commanded pose (front, side, top). Agents must infer seven joint zero offsets.

4. Development pilots and what they changed

Twelve development trials (one per task, model, and condition) ran before registration. They are published separately and excluded from the results, and they changed the protocol in five ways.

First, agents read the task source and found a log=False switch that hid their simulations from candidate accounting, so logging is now controlled only by the harness. Second, restart agents ran optimizers in parallel background processes. The Astra restart push pilot spent 55 of its 76 tool calls polling their log files. This led to allowing scripts in the MCP condition and to counting tool calls. Third, Codex intermittently started a session without the MCP tools: 1 of 5 minimal sessions, and 2 consecutive pilot attempts. Marking the server required fixed this in 6 of 6 checks, and the harness still retries any session without the tools as an infrastructure failure, retaining it.

Fourth, the pilots used noise-free references with round ground-truth values, and several agents fitted, rounded, and confirmed a pixel-perfect match, recovering the hidden values exactly. Photographic noise and non-round values now prevent this; the final values differ from the pilot values by at most 7% (offsets by at most 0.004 rad), within the perturbation ranges used to set the gates, and the true values pass and the defaults fail every gate on the regenerated data. Fifth, Astra at xhigh effort needed 17–19 minutes on push, and Codex loses its usage record when killed, so the budget rose from 20 to 30 minutes and timeouts now interrupt before terminating. The development log and all pilot records are published.

5. Registered results

All 36 registered trials ran to completion in the registered order. No MCP trial needed an infrastructure retry, and every reference photo was unchanged after its trial. Held-out verification passed in 14 of 18 MCP trials and 12 of 18 edit/restart trials. Push accounts for most failures in both conditions (Opus failed push in five of six trials). The failing push submissions place the box's center of mass 1–2 cm short along its long axis: they match the training photos to a few millimeters, but the held-out side push depends strongly on that offset. The training photos constrain it only weakly, so this is a property of the task, not the interface.

Cost. With the live MCP, agents used 30% fewer input tokens (paired ratio 0.70, interval 0.60–0.80; lower in 15 of 17 pairs with a usage record), 23% fewer uncached input-plus-output tokens (0.77, 0.66–0.92), and 36% fewer tool calls (0.64, 0.55–0.73; fewer in 16 of 18 pairs). Opus's API cost summed over its nine MCP trials was $4.95, against $7.41 for its nine restart trials. Codex does not report cost.

Time depends on the agent. Across all pairs, elapsed time did not change (0.96, 0.83–1.10). Opus finished 20% faster with MCP (0.80, 0.65–0.96) and used 43% fewer input tokens (0.57, 0.48–0.68, lower in 9 of 9 pairs). Astra took 16% longer with MCP (1.16, 1.05–1.28, slower in 7 of 9 pairs), even though it used 13% fewer input tokens and 44% fewer tool calls.

Elapsed time per registered pair [s, log scale]3005001,0002,000Arm · Opus 5.5 · 0290 s — Newton MCP, Arm Opus 5.5 replicate 0, passed328 s — Edit/restart, Arm Opus 5.5 replicate 0, passedArm · Opus 5.5 · 1447 s — Newton MCP, Arm Opus 5.5 replicate 1, passed413 s — Edit/restart, Arm Opus 5.5 replicate 1, passedArm · Opus 5.5 · 2382 s — Newton MCP, Arm Opus 5.5 replicate 2, passed767 s — Edit/restart, Arm Opus 5.5 replicate 2, passedArm · GPT-6 Astra · 0492 s — Newton MCP, Arm GPT-6 Astra replicate 0, passed320 s — Edit/restart, Arm GPT-6 Astra replicate 0, passedArm · GPT-6 Astra · 1458 s — Newton MCP, Arm GPT-6 Astra replicate 1, passed392 s — Edit/restart, Arm GPT-6 Astra replicate 1, passedArm · GPT-6 Astra · 2513 s — Newton MCP, Arm GPT-6 Astra replicate 2, passed372 s — Edit/restart, Arm GPT-6 Astra replicate 2, passedCloth · Opus 5.5 · 0589 s — Newton MCP, Cloth Opus 5.5 replicate 0, passed756 s — Edit/restart, Cloth Opus 5.5 replicate 0, passedCloth · Opus 5.5 · 1696 s — Newton MCP, Cloth Opus 5.5 replicate 1, failed held-out check635 s — Edit/restart, Cloth Opus 5.5 replicate 1, failed held-out checkCloth · Opus 5.5 · 2602 s — Newton MCP, Cloth Opus 5.5 replicate 2, passed593 s — Edit/restart, Cloth Opus 5.5 replicate 2, passedCloth · GPT-6 Astra · 01,770 s — Newton MCP, Cloth GPT-6 Astra replicate 0, passed1,776 s — Edit/restart, Cloth GPT-6 Astra replicate 0, passedCloth · GPT-6 Astra · 11,785 s — Newton MCP, Cloth GPT-6 Astra replicate 1, passed1,344 s — Edit/restart, Cloth GPT-6 Astra replicate 1, passedCloth · GPT-6 Astra · 21,762 s — Newton MCP, Cloth GPT-6 Astra replicate 2, passed1,800 s — Edit/restart, Cloth GPT-6 Astra replicate 2, timed outPush · Opus 5.5 · 0427 s — Newton MCP, Push Opus 5.5 replicate 0, failed held-out check498 s — Edit/restart, Push Opus 5.5 replicate 0, failed held-out checkPush · Opus 5.5 · 1314 s — Newton MCP, Push Opus 5.5 replicate 1, failed held-out check709 s — Edit/restart, Push Opus 5.5 replicate 1, failed held-out checkPush · Opus 5.5 · 2402 s — Newton MCP, Push Opus 5.5 replicate 2, passed446 s — Edit/restart, Push Opus 5.5 replicate 2, failed held-out checkPush · GPT-6 Astra · 01,303 s — Newton MCP, Push GPT-6 Astra replicate 0, passed1,300 s — Edit/restart, Push GPT-6 Astra replicate 0, passedPush · GPT-6 Astra · 11,658 s — Newton MCP, Push GPT-6 Astra replicate 1, passed1,555 s — Edit/restart, Push GPT-6 Astra replicate 1, passedPush · GPT-6 Astra · 21,452 s — Newton MCP, Push GPT-6 Astra replicate 2, failed held-out check1,350 s — Edit/restart, Push GPT-6 Astra replicate 2, failed held-out check
Input tokens per registered pair [log scale]300k500k1.0M2.0M3.0M5.0MArm · Opus 5.5 · 0341k tokens — Newton MCP, Arm Opus 5.5 replicate 0, passed1.0M tokens — Edit/restart, Arm Opus 5.5 replicate 0, passedArm · Opus 5.5 · 1319k tokens — Newton MCP, Arm Opus 5.5 replicate 1, passed683k tokens — Edit/restart, Arm Opus 5.5 replicate 1, passedArm · Opus 5.5 · 2326k tokens — Newton MCP, Arm Opus 5.5 replicate 2, passed660k tokens — Edit/restart, Arm Opus 5.5 replicate 2, passedArm · GPT-6 Astra · 0670k tokens — Newton MCP, Arm GPT-6 Astra replicate 0, passed678k tokens — Edit/restart, Arm GPT-6 Astra replicate 0, passedArm · GPT-6 Astra · 1924k tokens — Newton MCP, Arm GPT-6 Astra replicate 1, passed1.3M tokens — Edit/restart, Arm GPT-6 Astra replicate 1, passedArm · GPT-6 Astra · 2720k tokens — Newton MCP, Arm GPT-6 Astra replicate 2, passed977k tokens — Edit/restart, Arm GPT-6 Astra replicate 2, passedCloth · Opus 5.5 · 0600k tokens — Newton MCP, Cloth Opus 5.5 replicate 0, passed1.1M tokens — Edit/restart, Cloth Opus 5.5 replicate 0, passedCloth · Opus 5.5 · 1639k tokens — Newton MCP, Cloth Opus 5.5 replicate 1, failed held-out check1.1M tokens — Edit/restart, Cloth Opus 5.5 replicate 1, failed held-out checkCloth · Opus 5.5 · 2529k tokens — Newton MCP, Cloth Opus 5.5 replicate 2, passed860k tokens — Edit/restart, Cloth Opus 5.5 replicate 2, passedCloth · GPT-6 Astra · 04.1M tokens — Newton MCP, Cloth GPT-6 Astra replicate 0, passed5.1M tokens — Edit/restart, Cloth GPT-6 Astra replicate 0, passedCloth · GPT-6 Astra · 15.0M tokens — Newton MCP, Cloth GPT-6 Astra replicate 1, passed4.9M tokens — Edit/restart, Cloth GPT-6 Astra replicate 1, passedCloth · GPT-6 Astra · 2Edit/restart: usage not recorded3.6M tokens — Newton MCP, Cloth GPT-6 Astra replicate 2, passedPush · Opus 5.5 · 0618k tokens — Newton MCP, Push Opus 5.5 replicate 0, failed held-out check723k tokens — Edit/restart, Push Opus 5.5 replicate 0, failed held-out checkPush · Opus 5.5 · 1427k tokens — Newton MCP, Push Opus 5.5 replicate 1, failed held-out check617k tokens — Edit/restart, Push Opus 5.5 replicate 1, failed held-out checkPush · Opus 5.5 · 2638k tokens — Newton MCP, Push Opus 5.5 replicate 2, passed860k tokens — Edit/restart, Push Opus 5.5 replicate 2, failed held-out checkPush · GPT-6 Astra · 03.9M tokens — Newton MCP, Push GPT-6 Astra replicate 0, passed4.1M tokens — Edit/restart, Push GPT-6 Astra replicate 0, passedPush · GPT-6 Astra · 14.6M tokens — Newton MCP, Push GPT-6 Astra replicate 1, passed5.4M tokens — Edit/restart, Push GPT-6 Astra replicate 1, passedPush · GPT-6 Astra · 24.5M tokens — Newton MCP, Push GPT-6 Astra replicate 2, failed held-out check4.3M tokens — Edit/restart, Push GPT-6 Astra replicate 2, failed held-out check
Elapsed-time ratio MCP / restart, all registered pairs (geometric mean, 95% interval)0.4×0.5×0.7×1×1.4×2×← favors MCPfavors restart →All pairsAll pairs: 0.96× (95% interval 0.83–1.10), n=18 pairs, MCP cheaper in 80.96×Opus 5.5Opus 5.5: 0.80× (95% interval 0.65–0.96), n=9 pairs, MCP cheaper in 60.80×GPT-6 AstraGPT-6 Astra: 1.16× (95% interval 1.05–1.28), n=9 pairs, MCP cheaper in 21.16×ArmArm: 1.03× (95% interval 0.75–1.33), n=6 pairs, MCP cheaper in 21.03×ClothCloth: 1.02× (95% interval 0.89–1.16), n=6 pairs, MCP cheaper in 31.02×PushPush: 0.86× (95% interval 0.65–1.03), n=6 pairs, MCP cheaper in 30.86×
Input-token ratio MCP / restart, all pairs with usage records0.4×0.5×0.7×1×1.4×2×← favors MCPfavors restart →All pairsAll pairs: 0.70× (95% interval 0.60–0.80), n=17 pairs, MCP cheaper in 150.70×Opus 5.5Opus 5.5: 0.57× (95% interval 0.48–0.68), n=9 pairs, MCP cheaper in 90.57×GPT-6 AstraGPT-6 Astra: 0.87× (95% interval 0.79–0.96), n=8 pairs, MCP cheaper in 60.87×ArmArm: 0.58× (95% interval 0.44–0.76), n=6 pairs, MCP cheaper in 60.58×ClothCloth: 0.70× (95% interval 0.59–0.87), n=5 pairs, MCP cheaper in 40.70×PushPush: 0.85× (95% interval 0.76–0.94), n=6 pairs, MCP cheaper in 50.85×
Table 4. Geometric-mean MCP/restart ratios with 95% bootstrap intervals (20,000 resamples of pairs). Below 1 favors MCP. “All” uses every registered pair (token ratios exclude pairs without a usage record); “joint” only pairs in which both trials passed.
SubsetPasses MCP · restartTime (all)Time (joint)Input tokens (all)Input tokens (joint)Tool calls (all)
All pairs14/18 · 12/180.96 [0.83, 1.10]; n=181.02 [0.86, 1.19]; n=120.70 [0.60, 0.80]; n=170.67 [0.55, 0.80]; n=120.64 [0.55, 0.73]; n=18
Opus 5.56/9 · 5/90.80 [0.65, 0.96]; n=90.82 [0.64, 1.01]; n=50.57 [0.48, 0.68]; n=90.48 [0.39, 0.57]; n=50.73 [0.64, 0.83]; n=9
GPT-6 Astra8/9 · 7/91.16 [1.05, 1.28]; n=91.20 [1.07, 1.34]; n=70.87 [0.79, 0.96]; n=80.85 [0.77, 0.94]; n=70.56 [0.45, 0.71]; n=9
Arm6/6 · 6/61.03 [0.75, 1.33]; n=61.03 [0.75, 1.33]; n=60.58 [0.44, 0.76]; n=60.58 [0.44, 0.76]; n=60.57 [0.47, 0.67]; n=6
Cloth5/6 · 4/61.02 [0.89, 1.16]; n=61.01 [0.83, 1.24]; n=40.70 [0.59, 0.87]; n=50.73 [0.59, 0.90]; n=40.57 [0.48, 0.68]; n=6
Push3/6 · 2/60.86 [0.65, 1.03]; n=61.03 [1.00, 1.07]; n=20.85 [0.76, 0.94]; n=60.90 [0.85, 0.94]; n=20.78 [0.56, 1.02]; n=6
All 36 confirmation trials
Table 3. Every registered confirmation trial. Quality is the largest held-out error divided by its limit (≤ 1 passes). Time includes live-application startup for MCP trials. Images viewed: images returned by any tool (Codex has no file-viewing tool, so its restart trials count none). First pass: seconds until the agent first simulated a parameter set that passes held-out verification (post-hoc).
CaseConditionResultQualityTime [s]Input tokOutput tokTool callsImages viewedParam setsSim processesFirst pass [s]Record
Arm · Opus 5.5 · 0Newton MCPPass0.01290341k4,8171416971195JSON
Arm · Opus 5.5 · 0Edit/restartPass0.183281.05M12,35625370810231JSON
Arm · Opus 5.5 · 1Newton MCPPass0.00447319k4,4671328571265JSON
Arm · Opus 5.5 · 1Edit/restartPass0.01413683k8,4072027096241JSON
Arm · Opus 5.5 · 2Newton MCPPass0.00382326k4,5781226921261JSON
Arm · Opus 5.5 · 2Edit/restartPass0.19767660k8,29421314317295JSON
Arm · GPT-6 Astra · 0Newton MCPPass0.00492670k6,6731528611167JSON
Arm · GPT-6 Astra · 0Edit/restartPass0.00320678k4,4552004623197JSON
Arm · GPT-6 Astra · 1Newton MCPPass0.00458924k7,0932019541187JSON
Arm · GPT-6 Astra · 1Edit/restartPass0.003921.34M6,9403205945148JSON
Arm · GPT-6 Astra · 2Newton MCPPass0.00513720k7,1801305441268JSON
Arm · GPT-6 Astra · 2Edit/restartPass0.00372977k6,6143605165197JSON
Cloth · Opus 5.5 · 0Newton MCPPass0.57589600k7,27019425169JSON
Cloth · Opus 5.5 · 0Edit/restartPass0.507561.08M11,870279245176JSON
Cloth · Opus 5.5 · 1Newton MCPFail1.07696639k8,493205201414JSON
Cloth · Opus 5.5 · 1Edit/restartFail1.056351.06M12,2212767225381JSON
Cloth · Opus 5.5 · 2Newton MCPPass0.66602529k7,00017527171JSON
Cloth · Opus 5.5 · 2Edit/restartPass0.55593860k11,7902643815263JSON
Cloth · GPT-6 Astra · 0Newton MCPPass0.551,7704.06M26,565364811245JSON
Cloth · GPT-6 Astra · 0Edit/restartPass0.571,7765.14M22,3268007312381JSON
Cloth · GPT-6 Astra · 1Newton MCPPass0.481,7854.96M23,6225231301640JSON
Cloth · GPT-6 Astra · 1Edit/restartPass0.601,3444.86M27,3229304955358JSON
Cloth · GPT-6 Astra · 2Newton MCPPass0.751,7623.62M18,100343781172JSON
Cloth · GPT-6 Astra · 2Edit/restartTimeout0.551,800lost08106911266JSON
Push · Opus 5.5 · 0Newton MCPFail5.90427618k9,8942021031–JSON
Push · Opus 5.5 · 0Edit/restartFail4.81498723k11,28521426–JSON
Push · Opus 5.5 · 1Newton MCPFail5.75314427k6,844153801–JSON
Push · Opus 5.5 · 1Edit/restartFail5.43709617k10,8211841868–JSON
Push · Opus 5.5 · 2Newton MCPPass0.69402638k11,49420341307JSON
Push · Opus 5.5 · 2Edit/restartFail5.73446860k13,14620310318422JSON
Push · GPT-6 Astra · 0Newton MCPPass0.151,3033.87M28,0979045934457JSON
Push · GPT-6 Astra · 0Edit/restartPass0.951,3004.10M32,5067601652722436JSON
Push · GPT-6 Astra · 1Newton MCPPass0.501,6584.57M31,4944835411651JSON
Push · GPT-6 Astra · 1Edit/restartPass0.911,5555.36M41,11612507352520915JSON
Push · GPT-6 Astra · 2Newton MCPFail1.491,4524.46M25,4294903171772JSON
Push · GPT-6 Astra · 2Edit/restartFail2.591,3504.32M33,14379087919505JSON

Why Astra did not get faster. Event timestamps split each trial into time inside tools and model time between them. Astra performed the same simulation work in both conditions (median 285 vs 284 simulated seconds, at the same throughput), but its median model time rose from 165 s to 309 s with the MCP. Its restart agents launched optimizers as background processes and kept reasoning, polling logs with many cheap calls (median 79 tool calls, 3.4 s of model time per call). A live-MCP call blocks until the simulation returns, so compute and reasoning alternate instead of overlapping (median 36 calls, 10.5 s of model time per call). Opus used few, synchronous scripts in both conditions and simply benefited from the persistent process and fewer round trips.

Images reached Astra only through the MCP. Astra viewed no images in any of its nine restart trials, even though sim.py wrote comparison sheets, and it received a median of three per MCP trial (mostly filmstrips and newton_observe reference comparisons). Opus looked at images in both conditions, a median of three through MCP and four as files. In almost every trial, though, identification itself was numeric: agents segmented the photos, extracted poses or silhouettes, and fit parameters with SciPy. Images served to orient the search and to confirm a fit. The inline visual tools made that checking cheap enough for Astra to do, but they did not change how parameters were found.

Search progress, independent of stopping. Because agents decided when to stop, every parameter set each agent simulated was scored after the trial against the held-out truth. Up to 40 were scored per trial, and 12 for cloth, where each evaluation is slow, so cloth times are upper bounds. Agents in both conditions reached a passing parameter set in 16 of 18 trials. In the 16 pairs where both did, MCP agents got there first in 9, with a geometric-mean ratio of 0.86 in time to first pass. Six failed submissions, three per condition, had already simulated a passing parameter set before submitting a different one.

One Astra restart trial (cloth, replicate 2) reached the 30-minute limit with parameters that would have passed held-out verification. It counts as a failure, and Codex recorded no usage for it, so Astra's restart token totals are understated by one trial. The ratios exclude pairs without usage.

6. When does the live MCP pay off?

The registered results separate two effects. The first is round trips. A persistent Python session keeps loaded photos, fitting code, and the scene between calls, so agents need fewer calls and resend less context. This is the robust effect: fewer input tokens in 15 of 17 pairs and fewer tool calls in 16 of 18, for both models and all three tasks.

The second is restart cost. It was small here. The task scenes start in 3–5 s. Restart agents started a median of 11.5 simulator processes per trial (range 3–55); 17 of 18 MCP agents used only the live application, and the other also ran three scripts. Simulation compute, not process start-up, dominated tool time. Table 5 lists warm-cache start-up times of stock Newton examples on the same machine. A restart-based workflow pays that cost on every script run, and a live session pays it once. With a 10–20 s scene and ten script runs, the difference is 2–3 minutes per trial before any parameter is fitted. None of the registered tasks is in that regime, so the time results above understate the benefit for heavy scenes rather than demonstrate it.

Third, a live session that blocks during computation serializes computation and reasoning. An agent that works asynchronously, like Astra, loses more to that than it gains from persistence. The MCP change that addresses this is concurrency inside the live session. The workers pool on the follow-up branch runs cells on sibling live applications, synchronously with map or asynchronously with submit. The follow-up below tests it in an exploratory run.

Table 5. Warm-cache start-up of stock Newton examples on the study machine (two frames, null viewer). A restart pays this on every script run; the live MCP pays it once.
SceneStart-up [s]
H1 humanoid wearing a jacket (cloth_h1)20.8
Hydroelastic nut and bolt (nut_bolt_hydro)10.3
Franka folding cloth (cloth_franka)8.8
MPM granular (mpm_granular)7.8
SDF nut and bolt (nut_bolt_sdf)7.3
Hanging cloth (cloth_hanging)4.9
This study's tasks3–5

7. Exploratory follow-up: parallel live workers

After the registered run, the worker pool was added to the MCP (commit 4cf60374) and tested in a separately registered, exploratory run: one pair per task and model, with the live application plus three sibling worker applications against edit/restart, using the same scheduler, budget, and verifier. With four application processes, the MCP condition had the same kind of parallel capacity that restart agents create with background scripts.

Both models used the pool without being asked beyond the application guide: they defined a loss on every worker with workers.broadcast and evaluated candidate batches with workers.map. With workers, Astra's paired time ratio was 0.97, compared with 1.16 in the registered run, and its input-token ratio fell to 0.59 across the two pairs with usage records. Tool calls fell by half. Opus remained faster with the MCP (0.82). The MCP side passed 5 of 6 held-out checks and restart 4 of 6; the two Astra cloth trials both hit the 30-minute limit with parameters that would have passed.

Six pairs run after the main study can only indicate a direction. The follow-up supports the mechanism identified above, that removing serialization lets the persistent session's lower token use carry over into elapsed time, but it does not establish the size of the effect.

Table 6. Exploratory follow-up, one pair per task and model (separate registration, run after the confirmation). Paired MCP-with-workers/restart ratios over all 6 pairs: time 0.89 [0.67, 1.09]; n=6, input tokens 0.76 [0.60, 1.12]; n=5, tool calls 0.69 [0.48, 0.96]; n=6.
CaseConditionResultQualityTime [s]Input tokTool callsSim processesRecord
Arm · Opus 5.5MCP + 3 workersPass0.00370641k204JSON
Arm · Opus 5.5Edit/restartPass0.02829403k159JSON
Arm · GPT-6 AstraMCP + 3 workersPass0.00433654k194JSON
Arm · GPT-6 AstraEdit/restartPass0.015091.05M285JSON
Cloth · Opus 5.5MCP + 3 workersPass0.64705552k184JSON
Cloth · Opus 5.5Edit/restartPass0.54649766k2214JSON
Cloth · GPT-6 AstraMCP + 3 workersTimeout0.571,813lost594JSON
Cloth · GPT-6 AstraEdit/restartTimeout0.711,8007.81M10411JSON
Push · Opus 5.5MCP + 3 workersPass0.39775684k204JSON
Push · Opus 5.5Edit/restartFail3.456731.03M258JSON
Push · GPT-6 AstraMCP + 3 workersPass0.401,6563.82M394JSON
Push · GPT-6 AstraEdit/restartPass0.201,5706.92M12017JSON

8. Limits

References are synthetic renders from the same simulator and renderer, with added noise; real photographs add model mismatch, lighting, and unknown camera error. Three tasks and three replicates per model are small samples of agent behavior; intervals are descriptive, not a population claim. Agents chose when to stop, so cost and quality are not independent; the post-hoc first-pass time measures search progress separately. Wall-clock times include model-service latency and a shared, loaded machine; the pairing controls only the load both members shared. Candidate counts rely on the task module's log; agents were instructed not to bypass it, and transcripts are published for audit, but there is no sandbox.

The MCP condition includes MCP-specific instructions (the application guide and a required first newton_describe), and the restart condition includes a ready sim.py comparison script; both describe equivalent capabilities, but the wording differs. Only one agent CLI per model was tested, and Codex needed an infrastructure workaround.

The follow-up ran after the registered study with one replicate per case; its effect sizes are indicative only.

9. Source and reproduction

Newton source: eric-heiden/newton-live-mcp, registered commit a0297b18599c834a19569b3f9021b63ab9642330; the worker pool and follow-up analysis are on the same branch from 4cf60374 (also on eric-heiden/newton-live-mcp-workers). The MCP lives in newton/_src/mcp (public module newton.mcp). The tasks, live application, restart script template, harness, scheduler, and analysis are in tools/mcp_evaluation/visual, and the live-MCP guide in docs/guide/live_mcp.rst documents every feature.

Published evidence: registration, analysis, per-trial summaries, verification outputs, submitted parameters, prompts, gzip-compressed candidate logs, and event timings under data/v3/confirmation and data/v3/development, full agent event streams in confirmation and development archives (loopback tokens redacted), and SHA-256 manifests. Hidden ground truth is now disclosed in truth.json, and all reference photos are in reference-photos.zip.

To run one trial: python -m tools.mcp_evaluation.visual.run_visual --task push --condition mcp --model opus --workspace /tmp/trial --run (requires the private truth directory for verification). To embed a session in your own application, see the live-MCP guide; tools/mcp_evaluation/visual/app.py is a complete example, including a namespace and guide.