A coding agent can write a pricer in minutes and change one in seconds. Ask it where a number comes from and it reads the source and tells you what the code probably does. That is an answer about the code, not about the run.
For a pricer the difference matters. The price depends on constants nobody passed in, on branches taken at this input point and not another, on a day-count denominator three files away. Reading the source finds some of them. The run contains all of them.
aadc-mcp is a local MCP server that gives the agent the run.
What the server does
It runs over stdio inside your own Python environment. When the agent asks for a script to be traced, the script runs with recording on and leaves a record of every value it computed, each tied to the library source line that computed it. The agent then asks the record questions in a small fixed grammar: the constants, the decisions and their margins, where a value was computed, the formula behind it, and a replay at new inputs. It narrates the answers. Every number and every file:line it quotes is the engine’s output.
python3 -m venv aadc-env && . aadc-env/bin/activate
pip install "aadc-mcp[quantlib]" # QuantLib 1.41 with source tracing: Linux x86-64, macOS on Apple silicon
aadc-mcp --check # what runs on this machine, before you register anything
claude mcp add aadc -- "$VIRTUAL_ENV/bin/aadc-mcp"
The last line registers the server with Claude Code; other MCP clients take the same command in their own configuration.
A real session recorded on 4 November 2026 in a fresh environment: install, check, register, then four questions in Claude Code. Waits are shown as time-lapse.
An unmodified European call
The bundled european_option example is an ordinary QuantLib script with no tracing calls: a one-year call, spot 100, strike 105, a 3% flat rate, 20% volatility, priced with the analytic engine. It prints NPV 7.1280646692617395.
Traced, the record holds 685 entries. 613 of them (89%) are attributed to a QuantLib source line, across 268 lines in 29 files. It contains 71 constant leaves and 38 frozen-branch sites: comparisons whose outcome was fixed at record time.
Which decisions were closest to going the other way? The agent asks for the branches ordered by margin, the signed distance from the comparison’s threshold at record time:
| Decision | Margin |
|---|---|
comparison.hpp:71, in close | 0 |
errorfunction.cpp:210 | 0.0043 |
blackcalculator.cpp:77, in initialize | 0.2 |
The zero is an equality test that held exactly. Equality is decided true at zero, so any move off it can flip the outcome. The second sits in QuantLib’s error function, and a small enough change in its argument switches it. These are the places to look first when the price behaves differently at another input.
Where was 7.1280646692617395 computed? find returns six exact matches. One is the marked output; the line that computed the value is blackcalculator.cpp:198, in BlackCalculator::value. The record gives the formula behind it with its recorded inputs, each at its own line:
0.9704455335485082 × (103.04545339535169 × 0.5024132586078933 + (−0.4231071949364934) × 105)
The discount factor comes from interestrate.hpp:70, the forward from analyticeuropeanengine.cpp:70, and the strike 105 is a constant at blackcalculator.cpp:198. None of that required reading the source.
The Greeks
For sensitivities, the script records explicitly with its inputs marked. This is the core of the bundled european_greeks example:
f = aadc.Functions()
f.start_recording(trace=True, trace_inputs_as_random=False)
active = {name: aadc.idouble(v) for name, v in values.items()} # spot, rate, dividend, vol
handles = {name: x.mark_as_input() for name, x in active.items()}
# ... the same QuantLib objects, built on the active values ...
npv = option.NPV()
out = npv.mark_as_output()
f.stop_recording()
ws = f.create_workspace()
for name, handle in handles.items():
ws.set_val(handle, values[name])
ws.forward()
ws.set_diff(out, 1.0)
ws.reverse() # price and all four sensitivities
One reverse pass gives the price and all four sensitivities. In the recorded run: dNPV/dspot 0.5024132586078933, dNPV/drate 43.113261191527585, dNPV/ddividend −50.24132586078933, dNPV/dvol 39.893498130685984.
Open european_greeks and reprice at spot 101. The server can keep the recording process alive as a session. The agent sets the spot leaf to 101 and replays: 7.6404151728880825. Every recorded decision was re-checked and none flipped, so the value is exact: a fresh pricing at spot 101 gives the same digits.
In the clip the agent first tried the same replay on the saved record. That replay came back withheld, naming errorfunction.cpp:200: a decision the saved file cannot re-check. The agent opened the live session and got the exact answer. A replay the record cannot vouch for comes back without a number and with the decision that stopped it.
A what-if on an untouched script is not a Greek
Tracing an unmodified script records every value the script created as a constant inside the library. In european_option, the volatility 0.2 is one leaf, at simplequote.hpp:69, and its square, 0.04, is a separate leaf at blackvoltermstructure.hpp:263. Setting the first to 0.202 leaves the price at 7.1280646692617395, while a fresh run at 0.202 prices 7.207851149315401. The record is right about what ran; the square was computed before the recording saw it.
So the traced script is the instrument for code-flow questions: constants, decisions, origins. For what-ifs and Greeks, mark the input and record explicitly, as above. The tool descriptions the agent reads say which route answers which question, and the agent in the clip followed them.
Try it
pip install aadc-mcp
Then ask your agent to run check_environment, and run_example("european_option"). The server ships six examples, the verbs reference and the how-tos the agent reads. The package is on PyPI; the tracer behind it is described on the AADC Tracer page.
AADC runs here as Community Edition: free for non-commercial and academic use; commercial use, including evaluation inside a company, needs a licence from MatLogica.
Implemented using AADC, a commercial adjoint AD compiler (matlogica.com).