Janus and MCP as a client interaction model
June 13, 2026
Ok so Janus is going live soon. The application is updated to the extent I’m satisfied with, Hermes has been stable (unchanged) for almost a calendar year. It did dawn on me though that “adding an MCP server” to Janus would be valuable:
In practice
The below is an exerpt from conversations with claude code with the MCP service running from the GUI
i have a model at ~/Documents/models/acop.mod. Is there a run history for it?
Called janus 2 times (ctrl+o to expand)
● Yes — acop.mod has a run log with 16 runs. Here's the history (newest first):
┌───────┬──────────────────────────┬───────┬──────────┬──────────────┬──────┐
│ # │ Timestamp │ Cores │ Mode │ Status │ Exit │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 1 │ 2026-06-08 19:23 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 2 │ 2026-06-08 19:22 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 3 │ 2025-12-08 23:38 │ 2 │ parallel │ ❌ failed │ 111 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 4 │ 2025-12-08 22:54 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 5 │ 2025-12-08 22:49 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 6 │ 2025-12-08 22:40 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 7 │ 2025-12-08 20:58 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 8 │ 2025-12-08 20:56 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 9 │ 2025-12-08 19:50 │ 1 │ serial │ ✅d completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 10 │ 2025-12-02 20:06 │ 1 │ serial │ ✅ completed │ 0 │
├───────┼──────────────────────────┼───────┼──────────┼──────────────┼──────┤
│ 11–16 │ 2025-11-30 (21:56–22:08) │ 1 │ serial │ ✅ completed │ 0 │
└───────┴──────────────────────────┴───────┴──────────┴──────────────┴──────┘
All runs used the command nonmem acop.mod. 15 of 16 completed successfully; the one failure was the parallel (2-core) run on 2025-12-08 at 23:38, which exited with code 111.
Want me to pull the details or output files for any specific run — e.g., dig into that failed parallel run (019b0167…) to see what went wrong?
✻ Cooked for 14s
❯ Can you see what files are stored with run 10?
Called janus (ctrl+o to expand)
● Run 10 (019ae1be…, 2025-12-02 20:06) stores 7 files:
┌────────┬──────────────────────────────────────────┐
│ Key │ What it is │
├────────┼──────────────────────────────────────────┤
│ mod │ The model input file │
├────────┼──────────────────────────────────────────┤
│ lst │ NONMEM output/results listing │
├────────┼──────────────────────────────────────────┤
│ ext │ Parameter estimates (iterations + final) │
├────────┼──────────────────────────────────────────┤
│ phi │ Individual Bayesian/EBE parameters │
├────────┼──────────────────────────────────────────┤
│ xml │ Structured run results │
├────────┼──────────────────────────────────────────┤
│ stdout │ Captured standard output │
├────────┼──────────────────────────────────────────┤
│ stderr │ Captured standard error │
└────────┴──────────────────────────────────────────┘
A couple of notable bits of metadata on this run:
- Description: "Testing things"
- Signed: ✅ yes, by darrell.breeden@pharmalytica.io
Want me to pull the contents of any of these — e.g., the lst or ext to see the parameter estimates?
✻ Cogitated for 9s
❯ Can you run it again? Same parameters as run 10
Called janus (ctrl+o to expand)
● Launched — same config as run 10 (1 core, serial, local). New run id: 019ec225-f49a-7d8c-af6f-4c2ce5a6f0a1, status running. Let me poll for completion.
Called janus (ctrl+o to expand)
● ✅ Done — the run completed successfully.
┌───────────┬────────────────────────────────────────────────────────────┐
│ │ │
├───────────┼────────────────────────────────────────────────────────────┤
│ Run id │ 019ec225-f49a-7d8c-af6f-4c2ce5a6f0a1 │
├───────────┼────────────────────────────────────────────────────────────┤
│ Status │ completed (exit code 0) │
├───────────┼────────────────────────────────────────────────────────────┤
│ Config │ 1 core, serial, local — matching run 10 │
├───────────┼────────────────────────────────────────────────────────────┤
│ Timestamp │ 2026-06-13 14:02 │
├───────────┼────────────────────────────────────────────────────────────┤
│ Files │ mod, lst, ext, phi, xml, stdout, stderr — same 7 as run 10 │
├───────────┼────────────────────────────────────────────────────────────┤
│ Signed │ ✅ by darrell.breeden@januspk.com │
└───────────┴────────────────────────────────────────────────────────────┘
It produced the identical set of output files as run 10. This is now the newest entry in acop.mod's run log (17 runs total).
Want me to compare the new parameter estimates (ext) against run 10's to confirm they match?
Can you list the stored `mod` file from that run(019ec225-f49a-7d8c-af6f-4c2ce5a6f0a1)?
Called janus (ctrl+o to expand)
● Here's the stored mod file from run 019ec225… (728 bytes, complete):
$PROBLEM PK model 1 cmt base
$INPUT ID TIME MDV EVID DV AMT SEX WT ETN
$DATA acop.csv IGNORE=@
$SUBROUTINES ADVAN2 TRANS2
$PK
ET=1
IF(ETN.EQ.3) ET=1.3
KA = THETA(1)
CL = THETA(2)*((WT/70)**0.75)* EXP(ETA(1))
V = THETA(3)*EXP(ETA(2))
SC=V
$THETA
(0, 3) ; KA
(0, 4) ; CL
(0, 12) ; V2
(0.02) ; RUVp
(1) ; RUVa
$OMEGA
0.06 ; iiv CL
0.2 ; iiv V2
$SIGMA
1 FIX
$ERROR
IPRED = F
IRES = DV-IPRED
W = IPRED*THETA(4) + THETA(5)
IF (W.EQ.0) W = 1
IWRES = IRES/W
Y= IPRED+W*ERR(1)
$TABLE ID TIME DV PRED IPRED CWRES NOAPPEND NOPRINT ONEHEADER FILE=sdtab001
$TABLE ID ETA1 ETA2 CL V KA NOAPPEND NOPRINT ONEHEADER FIRSTONLY FILE=patab001
$EST METHOD=1 INTERACTION MAXEVAL=9999 SIG=3 PRINT=5 NOABORT POSTHOC
$COV
It's a one-compartment (ADVAN2/TRANS2) PK model with first-order absorption — 5 thetas (KA, CL, V2, and proportional + additive residual error), IIV on CL and V2, FOCE with interaction. Want me to diff this against
the mod stored in run 10 to confirm the model was unchanged between the two runs?
✻ Cooked for 14s
❯ Yeah let's confirm that
Called janus (ctrl+o to expand)
● Not a match — the model was edited between the two runs. Here are the differences:
┌────────────────┬───────────────────────────┬────────────────────────────────┐
│ Section │ Run 10 (019ae1be…, 572 B) │ New run (019ec225…, 728 B) │
├────────────────┼───────────────────────────┼────────────────────────────────┤
│ $THETA KA │ (0, 2) │ (0, 3) │
├────────────────┼───────────────────────────┼────────────────────────────────┤
│ $THETA CL │ (0, 3) │ (0, 4) │
├────────────────┼───────────────────────────┼────────────────────────────────┤
│ $THETA V2 │ (0, 10) │ (0, 12) │
├────────────────┼───────────────────────────┼────────────────────────────────┤
│ $OMEGA iiv CL │ 0.05 │ 0.06 │
├────────────────┼───────────────────────────┼────────────────────────────────┤
│ $TABLE records │ none │ two added (sdtab001, patab001) │
└────────────────┴───────────────────────────┴────────────────────────────────┘
So between run 10 and now, someone bumped the initial estimates for KA, CL, V2 and the IIV-CL omega, and added the two $TABLE outputs. Everything else — $PROBLEM, $INPUT, $DATA, $SUBROUTINES, $PK, the residual-error
thetas, $SIGMA, $ERROR, $EST, $COV — is byte-identical.
The realization
After I had added the MCP server I realized “Wait, if I have this, why have the GUI be a dependency for it?”. So after a big refactor (to effectively move the entirety of the execution engine into a library), Janus can run purely as an MCP server.
In fact both can co-exist with the two managing locks between themselves. So you can have both the MCP server executing things and the GUI at the same time.