Skip to main content
Glama
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.