Protocol CompanyA physics verifier for Super Intelligence
Zero-Trust Physics

Documentation

Zero-Trust Physics is a physics verifier for Super Intelligence (SI). SI agents ask it questions about real hardware, and every answer comes with a cryptographic proof, so any agent can run the question again and get the same thing. When a question goes past what a model was tested for, the answer stops there and says why.

The address

https://mcp.zerotrustphysics.com/mcp

Open to any agent. There is no account and no sign-in.

Connect an agent

Claude

Open Customize, then Connectors, then Add custom connector. Enter the address. Where it asks about sign-in, choose No sign-in. Select Add. In a chat, open the + menu, choose Connectors, and turn it on.

Claude Code

claude mcp add --transport http zero-trust-physics https://mcp.zerotrustphysics.com/mcp

Any other agent

Add the address as a remote Model Context Protocol server with no authentication.

By hand

The address speaks the Model Context Protocol over HTTP: one POST, one JSON answer. Each request stands alone. There is no session and no stream.

curl -s https://mcp.zerotrustphysics.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

A script that uses Python’s built-in web client must name itself in a User-Agent header. Without one the network in front of the address answers 403.

Something to paste

Connect to https://mcp.zerotrustphysics.com/mcp and read what is there. Then
tell me what it is, and why it might matter to me.

The tools

Read what is served

list_cards
Every model that steps through time, each with one sentence and one word for how it did against its measurements.
list_solvers
Every field solver, the same way.
describe_card
One model in full: inputs, units, ranges, the names of its stops, how it was tested, and a worked request. With "form": "short" it is one page.
describe_solver
The same for one solver.
find_model
From a plain description of a real thing to the models that fit, with what each was tested on and how it did.
cite
How to cite the verifier, the paper, and the people whose measurements a model stands on, as text and BibTeX.

Ask

verify_step
One step of one model, with its cryptographic proof.
run_trajectory
A run under a changing load, with its cryptographic proof.
solve
One solution of a field solver, with its cryptographic proof.
run_dataset
A planned set of runs, or of solves, under one proof.
validate_series
A run, or a set of solves, compared with measurements you send. The answer is the error in numbers.
find_flip
The place where an outcome changes, with the run on each side and the proof of each.

Confirm a proof

verify_tape
Confirms a run’s proof. Send the request as it was sent and the proof it came back with.
verify_solution
The same for a solution.
verify_dataset
The same for a dataset.
verify_receipt
Confirms that a copy of an answer is byte for byte what was sent.

In an answer the proof of a run is named run_seal, of a solution solution_seal, and of a dataset dataset_seal. Each is 64 characters.

One question and its answer

An agent asks how hard a battery pack can be pushed for ten minutes. This is the run at 71.44 amps.

curl -s https://mcp.zerotrustphysics.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -o answer.json \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"run_trajectory","arguments":{"domain":"energy","card":"battery_sag","initial":{"soc":1.0},"dt_s":0.1,"segments":[{"steps":6000,"load":{"current_a":71.44}}],"record_every":6000}}}'

The answer is one block of text inside result.content. Its main parts:

"outcome": "completed"
"steps_landed": 6000
"final_state": { "t_s": 6.000000000000679e2, "soc": 4.587878787877244e-1,
                 "terminal_v": 3.600029381817893e1,
                 "cutoff_margin_v": 2.9381817893181505e-4, ... }
"run_seal": "6bd7e54b83c71da84eda74f3314416d619bbbce112186aa548085cb5a4ba0d34"

The pack holds for the ten minutes and ends 0.0003 volts above its cutoff.

The same question at 71.45 amps stops 0.2 seconds before the end:

"outcome": "refused"
"reject": "UndervoltageCutoff"
"reject_detail": "Physical Failure: the pack reached the 36.0 V cutoff
  (UndervoltageCutoff). The run is sealed to step 5998. The state at step 5999
  was refused and is not sealed."
"steps_landed": 5998
"run_seal": "68c3bc0e9f1469d239ec4e00795d03eaf58063d704c7535ad6f533222672a83e"

The pack is a generic 12-cell model, here to show what an answer looks like. It has not been compared with a measurement.

When a model stops

A model answers inside the range it was tested for. At the edge it stops and says why. One Panasonic cell was tested at one current. Asked for 5 amps, it answers:

Physical Failure: 'held_current_a' 5 A is above 2.90065 A, the inclusive
maximum of the cell_18650pf card (CurrentNotCompared). That state is not sealed.

A stop before anything is computed is one sentence and has no proof. A run that starts and stops part way keeps its proof up to the last step that landed.

Confirm a proof

By asking again

Send verify_tape the request and its run_seal:

{"request": { ...the run_trajectory request as sent... },
 "run_seal": "6bd7e54b83c71da84eda74f3314416d619bbbce112186aa548085cb5a4ba0d34"}

The answer begins "holds": true. With one character of the proof changed it begins "holds": false, "cause": "run_seal".

With no engine

Three small programs confirm a proof from a saved answer. They need Python and nothing else.

git clone https://github.com/johnkruze/zero-trust-physics
python3 zero-trust-physics/verify_run.py answer.json

run_seal:      holds  6bd7e54b83c71da84eda74f3314416d619bbbce112186aa548085cb5a4ba0d34
result: every proof holds

Keep the answer byte for byte. One added line break at the end of the file changes its last proof line.

The engine’s own source, to build it and get the same proofs: https://github.com/johnkruze/zero-trust-physics-engine

Limits

The address states these when an agent connects.

Requests
300 a minute from one address, then HTTP 429 with Retry-After. 16 in flight at once and 4 from one address, then 429. A request body up to 4,194,304 bytes, then 413.
A run
Up to 1,000,000 steps and 10,000 recorded states.
A dataset
Up to 300 runs, 1,000,000 steps in all and 10,000 recorded states. It comes back in the answer and is stored nowhere.
A set of solves
Up to 64, and fewer of a slow solver: 5 of step_flow_armaly, 15 of tokamak_dt_beam_target, 15 of ablator_slab, 30 of atom_dft.
One thing at a time
One address computes one thing at a time. A solve, a dataset and a run of more than 10,000 steps are long work, and one piece of long work runs at a time. When the address is busy the answer is “Too many concurrent physics tasks.” Nothing waits. Send it again.
Time
An answer is waited for 60 seconds. Long work is stopped there. Send a smaller request.
A search
find_flip runs up to 64 runs, 1,000,000 steps in all or 64 solves, and starts no new run after 20 seconds.
In Claude
Claude reads a tool’s answer up to about 150,000 characters. Ask for few recorded states: a large record_every, or a readout.

If something goes wrong

“Too many concurrent physics tasks.”
The address was busy. Send it again.
HTTP 429
Wait the seconds named, then send again.
HTTP 403 from a Python script
Give the script a User-Agent header.
HTTP 413
The request is over 4,194,304 bytes.
An answer that stops and says why
The sentence names the limit. The model’s description gives its range.

More help: Support

Where the rest is

The site
https://zerotrustphysics.com
For an agent
https://zerotrustphysics.com/llms.txt
Each real thing
https://zerotrustphysics.com/things/
The paper
https://doi.org/10.5281/zenodo.23305697
Programs and source
https://github.com/johnkruze/zero-trust-physics

John Kruze, Protocol Company · 13 October 2026