medprice
README.md
# medprice
medprice is a small local bridge to FineRx's hosted MCP
server, a prescription-price service for the US: it knows
what a medicine costs with a free discount card at the
major pharmacy chains, which stores sit near a ZIP code,
and what a medicine sold under a foreign brand name is
called in the US.
The bridge keeps no drug or price data of its own. It
serves the upstream server's tool list locally, exactly
as captured from the live endpoint, and forwards each
tool call upstream, returning the result untouched.
## Labelled subset: 18 of 19 tools
The live capture held 19 tools. This rebuild serves 18
of them. One tool is deliberately omitted:
- `email_savings_card` — **omitted**. It sends email to
an arbitrary address supplied by the caller, an
external-sending action outside this server's
price-read core, so it is excluded under the program's
safety rule. It is not registered, not forwarded, and
the test suite asserts its absence from both the local
registry and the served MCP tools/list.
One nearby tool is kept on purpose:
- `get_savings_card` — **kept**. It returns the FineRx
program's own free discount card: the shared program
codes printed on every card the service distributes
publicly, with usage steps. That is published program
data, not a user's payment-card data, and it creates
no payment instrument — a read like the price reads
around it.
## Tools
- `compare_prices` — one medicine's card price at US
pharmacy chains, near a place. Optional: `drug`,
`strength`, `form`, `quantity`, `zip`, `ndc`, `locale`,
`channel`, `compare_to`.
- `ui_prices` — the same price answer for a package and
place picked inside the FineRx card. Required: `slug`.
- `find_nearby_pharmacies` — pharmacy stores within
30 miles, per chain, with the card price when a drug
is given. All arguments optional.
- `ui_nearby` — nearby pharmacies for the package on
screen, called by the card itself. All optional.
- `get_transfer_steps` — how to move a prescription to
another chain. All arguments optional.
- `compare_basket` — card prices for several medicines
at once, and which chain was seen pricing the whole
list. Required: `drugs`.
- `ui_basket` — the same basket for another place,
called by the card itself. Required: `slugs`.
- `open_price_finder` — open the FineRx search inside
the card. Optional: `query`, `locale`.
- `ui_suggest` — medicines matching what is being typed
in the FineRx search. Required: `q`.
- `get_savings_card` — the free FineRx discount card:
its codes, how to use it, how to keep it. See the
subset note above. All arguments optional.
- `search_drugs` — find a medicine by name (brand,
generic, misspelled or in another script) and get its
slug. Required: `query`.
- `get_drug` — strengths, forms and pack sizes of one
medicine that have a card price. Required: `slug`.
- `get_dataset_info` — what FineRx covers: chains,
freshness, store counts, terms. No arguments.
- `get_prescription_options` — routes to filling a
prescription, including having none yet. All optional.
- `find_us_equivalent` — what a medicine from another
country is in the US, and its card price here.
Required: `brand`.
- `find_us_equivalents` — the same for several foreign
medicines at once. Required: `brands`.
- `ui_equivalent` — one foreign brand picked in the
FineRx search, called by the card itself. Required:
`brand_slug`.
- `foreign_brands_for_drug` — what a US drug is called
abroad. Required: `slug`.
## Configuration
- `FINERX_MCP_URL` (optional) — override the upstream
endpoint. Defaults to `https://www.finerxfinder.com/mcp`.
(The override hook is this rebuild's own labelled
reconstruction.)
- `FINERX_API_KEY` (optional) — when set, every
upstream request carries an
`Authorization: Bearer <key>` header. When it is not
set, no auth header is sent. (This forwarding is also
a labelled reconstruction; the original surface was
captured keyless.)
### Forwarding mechanics
On the first tool call the client opens a streamable
HTTP session with the upstream: a JSON-RPC `initialize`
request (protocolVersion `2025-03-26`, clientInfo name
`medprice`), then a `notifications/initialized`
notification, then the `tools/call` request carrying
the caller's arguments unchanged. When the upstream
answers `initialize` with an `Mcp-Session-Id` header,
that value rides on every later request of the session,
which is reused for the life of the process. Replies
may arrive as plain JSON or as server-sent events;
both are read.
Successful upstream results pass through verbatim,
including any `isError` flag the upstream sets.
Failures — a JSON-RPC error, a non-2xx status, an
unreadable response, or a request that cannot be
completed — come back as an `isError` result whose
text starts with `medprice error:` (this rendering
is this rebuild's own labelled reconstruction).
## CLI
Each tool is also a subcommand taking one JSON argument
string (omit it for tools that take none):
```bash
npx @reneturcios/medprice search_drugs '{"query":"lisinopril"}'
npx @reneturcios/medprice compare_prices '{"drug":"lisinopril","zip":"94110"}'
npx @reneturcios/medprice compare_basket '{"drugs":["lisinopril","metformin"]}'
npx @reneturcios/medprice find_us_equivalent '{"brand":"No-Spa"}'
npx @reneturcios/medprice get_dataset_info
npx @reneturcios/medprice --version
```
Exit codes: `0` on success, `1` on an `isError`
result, `2` on a usage error.
## MCP server
```bash
npx -y @reneturcios/medprice mcp
```
MCP client config:
```json
{
"mcpServers": {
"medprice": {
"command": "npx",
"args": ["-y", "@reneturcios/medprice", "mcp"]
}
}
}
```
## Docker
```bash
docker run -i ghcr.io/cloudcorprecords/medprice
docker run --rm ghcr.io/cloudcorprecords/medprice --version
```
The container's default command is `mcp`, so the first
form is a stdio MCP server; any other arguments reach
the CLI normally.
## Development
```bash
npm install
npm run build
npm test
npm run dev
```
The test suite runs entirely against a stubbed
JSON-RPC upstream — no live network calls.
## License
MIT — see `LICENSE`.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessOutdated data