stillshort
README.md
# stillshort
An MCP server that follows medicines in the FDA drug shortage register and
answers the only question anybody asks twice, has anything changed since I last
looked.
python demo.py --offline the frozen records, repeatable
python demo.py the live register
python -m unittest discover -s tests -t .
## What it does
Three tools, because a voice interface cannot hold more than three verbs.
watch follow a substance, and hear where it stands now
watching read the list back, forget one, or forget all of it
changed what moved since each one was last read
The register keys a shortage on `generic_name`, and that field carries the
dosage form inside the same string, `Clonazepam Tablet` rather than
`Clonazepam`. Nobody says that out loud, so a spoken name is matched against
the leading substance and the forms that came back are reported separately.
A substance can hold two hundred lines, one per package. Reading them is not an
answer. What comes back is one reading per status, how many packages, how many
suppliers, and the most useful note the register carries.
## What it refuses to do
It does not suggest a substitute, it does not say whether to worry, and it does
not translate a status into advice. Every answer that carries a shortage
carries the register's own words back with it, verbatim,
> Do not rely on openFDA to make decisions regarding medical care. While we
> make every effort to ensure that data is accurate, you should assume all
> results are unvalidated.
When the register cannot be reached, it says so and adds nothing to the list.
A silent server is worse than one that admits it could not look, because the
caller reads silence as good news.
## Where the data live
The watchlist is plain JSON under `~/.stillshort`, or wherever
`STILLSHORT_HOME` points. Nothing leaves the machine, nothing is encrypted, and
`watching` with `forget all` empties it in one call. An encrypted file the
owner cannot read is worse than a readable one they can delete.
## Two things the register does that will bite the next person
`related_info` is one free text field carrying two unrelated things. `Estimated
supply: August 2026` is an answer. `Marketed by Advagen Pharma Ltd.` is not,
and read out loud it sounds like one. A supply note wins whenever there is one.
`update_date` is written `MM/DD/YYYY`, which does not sort as text. `12/01/2025`
sorts above `01/05/2026` character by character, so comparing these as strings
picks the wrong latest entry, and only across a year boundary, which is when
nobody is looking. There is a test for exactly that.
## Fixtures
`tests/fixtures` holds real answers from the register, saved 2026-09-05, so the
shapes under test are the shapes the service really sends. The bench never
touches the network.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues