An MCP server over JSON-RPC 2.0. Eleven tools, one per intent, every answer carrying its uncertainty and its basis. A refusal comes back as a successful result — never an error to retry.
01
{
"mcpServers": {
"lisgen": {
"command": "lisgen-mcp",
"args": ["--store", "~/.lisgen/record.db"]
}
}
}Read lisgen://capabilities before calling anything. It states what the system can and cannot do, with the measurement behind each boundary.
02
Record one observation, bound to an entity and the instrument that produced it. The only way data enters the record.
entity · measurand · value · instrument
Compare a new value against THIS person's own threshold, not a population reference range.
entity · measurand · new_value
Direction and rate over this person's own history, with the slope's uncertainty. Needs at least 3 observations.
entity · measurand
Ranks this person's organs against EACH OTHER. Never against a population percentile.
organ_ages · chronological_age
Rate of aging from repeated DunedinPACE measurements. Static biological-age-in-years is refused.
pace_values
Within-person change with a stated false-alarm rate. Never a diagnosis.
values · own_threshold
Repeated on/off cycles; the person is their own control. The stronger design -- prefer it when the intervention can be switched off. A small effect needs ~40 cycles.
measurand · cycles
For interventions that cannot be switched off. Weaker evidence than a crossover and carries explicit confounding risk.
measurand · pre · post
Ranks candidates by decision-relevant information per unit cost. Can answer 'nothing -- already settled'.
candidates · decision_threshold
Regulatory evidence for one gene in this person's measured graph. Abstains when the gene/tissue combination was never assayed -- absence of measurement is not absence of regulation.
gene
The capability surface with the measurement behind each boundary. Read before asking anything genomic.
no arguments
03
Why
If a boundary came back as a JSON-RPC error, an agent would retry it, and a retried refusal eventually gets rephrased into something that answers. So refusals return with isError: false and the reason in the content — the model reads them as the answers they are.
Catalogue
Each carries the specific study that forbids the claim. Read lisgen://refusals and you get the whole list with reasons — so your agent can learn the limits before it hits one.
// asking for something the evidence forbids
{ "name": "did_it_move", "arguments": { "measurand": "biological_age_years", ... } }
// comes back as a SUCCESSFUL result
{ "isError": false,
"structuredContent": {
"kind": "refusal",
"confidence": "refused",
"refusals": ["Static clocks estimate a cross-sectional age with noise on the
order of +/- 9 years, against interventions that move things over 3 months."] } }04
Name this server as the resource when requesting a token. We reject anything minted for another service, and refuse wildcards.
Without a subject the server cannot tell whose record a request touches — the gap the confused deputy exploits.
A token received here is never forwarded upstream. Forwarding makes this server a deputy with your agent's full authority.
A write needs health:write. A session is bound to one member and refuses another's record even with a valid token.