Skip to main content

TestWell for developers and AI agents

Everything an assistant needs to answer “what does this blood test cost and where do I get it” correctly: the public catalog as JSON, an MCP server that quotes all-in prices by state, a Markdown twin of every page, and a cart link that carries your attribution. All read-only, no API key.

18 toolsNo auth120 req/min/IPPublic data onlyPurchases complete on test-well.com

Where this server is listed: Official MCP Registry (com.test-well/testwell) · Smithery

The one pricing rule

Every price on TestWell is a sticker in USD. An order adds exactly one lab processing fee of $6.00 — never a draw fee, physician fee or service fee. New York and New Jersey orders are drawn at BioReference (a few items have a different price there, some are unavailable). Rhode Island cannot be served. quote_orderapplies all of this for you; please don't quote a total to a user without it.

Endpoints

MethodPathWhat you get
GET/api/catalog.jsonEvery public test and panel with per-lab prices, CPT, biomarkers, fasting, turnaround. ?q= ?type= ?category= ?orderable=true ?limit= ?offset=
GET/api/catalog.csvThe same catalog as a flat CSV for price-comparison sites: per-lab prices, the $6 order fee and all-in price, CPT, measured vs calculated markers, states not served, NY/NJ routing. Strong ETag — send If-None-Match for a free daily check. ?type= ?orderable=true
GET/api/catalog/{slug}One item with FAQ, related conditions, audience and order URL
POST/api/agent/{tool}Run any registry tool over plain HTTP (JSON body = tool input). GET with query params also works.
GET/{any-public-page}.mdMarkdown twin of a test, biomarker, guide, condition, comparison, tool or state page. Or send Accept: text/markdown.
MCP/mcpStreamable HTTP MCP server, no auth (MCP 2026-07-28 and 2025-era clients). stdio-only clients: npx -y mcp-remote https://www.test-well.com/mcp
GET/openapi.jsonOpenAPI 3.1 for the catalog endpoints and every tool — paste into a GPT Action
GET/.well-known/mcp/server-card.jsonMCP discovery card
GET/.well-known/agent-skills/index.jsonAgent skills index; one Markdown skill per tool
GET/llms.txtOverview for LLM crawlers; /llms-full.txt for the full catalog dump

Connect the MCP server

Streamable HTTP, no authentication. Claude Desktop, Cursor, ChatGPT developer mode and any MCP client that accepts a remote URL:

{
  "mcpServers": {
    "testwell": {
      "url": "https://www.test-well.com/mcp"
    }
  }
}

Or call a tool over HTTP

curl -s https://www.test-well.com/api/agent/quote_order \
  -H "Content-Type: application/json" \
  -d '{"items":["tsh","vitamin-d"],"state":"FL","lab":"quest"}'

Read any page as Markdown

curl -s -H "Accept: text/markdown" https://www.test-well.com/tests/tsh
# or
curl -s https://www.test-well.com/biomarkers/ferritin.md

Hand off with a prefilled cart

/cart?add=<slug,slug>&lab=quest|labcorp|bioreference. Keep the utm_source your surface uses (mcp, ai_agent, or your assistant's name) so the order lands in our AI-assistant channel and we can see which assistants help patients.

https://www.test-well.com/cart?add=tsh,vitamin-d&lab=quest&utm_source=ai_agent&utm_medium=agent

Tools

Generated from the registry; identical over MCP and REST. Full JSON Schemas in openapi.json.

search_tests

catalog

Search TestWell's public catalog of cash-pay lab tests and panels by keyword, biomarker, CPT code, or category. Returns name, slug, per-lab prices, sample, fasting, turnaround and order URL. Prices are stickers; every order adds one $6 lab processing fee (see quote_order for all-in totals).

FieldTypeDescription
query*stringKeyword, biomarker, CPT code or health goal, e.g. 'vitamin d', 'TSH', '80053', 'cholesterol'
typetest | panelRestrict to individual tests or bundled panels
categorystringCatalog category, e.g. 'Thyroid', 'Heart Health'
orderableOnlybooleanExclude items listed as coming soon (default true)
limitintegerMax results (default 10)
langen | esReturn Spanish names/descriptions where a translation exists (default en)
POST /api/agent/search_tests
{
  "query": "vitamin d"
}

get_test

catalog

Full public detail for one TestWell test or panel by slug or id: description, biomarkers, CPT, per-lab prices, labs, fasting/prep, turnaround, included tests (panels), FAQ, related conditions, order URL and a Markdown page URL. Tests also carry labPages — per-lab pages (/tests/<slug>/quest, /tests/<slug>/labcorp) with the lab's test code, requisition name, the lab's own dated price vs TestWell's, and walk-in steps — cite them when the user asks about a specific lab.

FieldTypeDescription
slug*stringCatalog slug (from search_tests) or id, e.g. 'tsh', 'general-wellness-panel'
langen | esSpanish prose where a translation exists (default en)
POST /api/agent/get_test
{
  "slug": "general-wellness-panel"
}

list_panels

catalog

List TestWell's bundled panels (multi-test packages priced below the sum of their tests), optionally filtered by category or maximum price. Sorted by price.

FieldTypeDescription
categorystringCatalog category, e.g. 'Hormones', 'General Health'
maxPricenumberOnly panels at or under this sticker price (USD)
limitintegerMax results (default 25)
POST /api/agent/list_panels
{
  "maxPrice": 100
}

recommend_tests

catalog

Suggest TestWell panels and tests for stated health goals (e.g. 'annual checkup', 'heart health', 'TRT monitoring') and/or symptoms (e.g. 'fatigue', 'hair loss'). Prefers a curated pre-built panel when one fits; otherwise assembles individual tests within a budget. Educational matching, not a diagnosis.

FieldTypeDescription
goalsarrayHealth goals, e.g. ['energy', 'thyroid']
symptomsarraySymptoms, e.g. ['always cold', 'weight gain']
budgetlow | medium | high | no_limitBudget band: low ≈ $80, medium ≈ $200, high ≈ $400
POST /api/agent/recommend_tests
{
  "goals": [
    "annual checkup"
  ],
  "budget": "low"
}

quote_order

quote

Price a set of tests/panels exactly as TestWell's checkout would: per-lab prices for the user's state (New York and New Jersey route to BioReference; Rhode Island is not served), the single $6 lab processing fee, the total, items that can't be ordered and why, and a prefilled cart URL. Use this before quoting any total to a user.

FieldTypeDescription
items*arrayCatalog slugs or ids, e.g. ['tsh', 'vitamin-d']
statestringUS state code or name where the user will be drawn, e.g. 'FL' or 'Florida'
labquest | labcorp | bioreferencePreferred lab outside NY/NJ (default quest)
POST /api/agent/quote_order
{
  "items": [
    "tsh",
    "vitamin-d"
  ],
  "state": "FL",
  "lab": "quest"
}

create_checkout

checkout

Start a TestWell order for the user: tests/panels, the US state where they will visit the lab (required for pricing and lab routing), and the buyer's name, email and phone. Returns priced line items in cents, the single $6 lab fee, the total, any blocking messages, and pay_online_url — a prefilled cart the user can pay in a browser when the platform has no payment token. Use dry_run to preview without creating a session.

FieldTypeDescription
items*array
statestringUS state code or name where the blood will be drawn
buyerobject
dry_runbooleanPrice only; do not create a session
POST /api/agent/create_checkout
{
  "items": [
    {
      "id": "tsh"
    },
    {
      "id": "vitamin-d"
    }
  ],
  "state": "FL",
  "dry_run": true
}

update_checkout

checkout

Change items, state or buyer details on an open checkout session and get it re-priced. Returns the same session object as create_checkout.

FieldTypeDescription
checkout_session_id*string
itemsarray
statestring
buyerobject
POST /api/agent/update_checkout
{
  "checkout_session_id": "cs_agent_…",
  "state": "NY"
}

get_checkout

checkout

Current state of a checkout session (status, line items, totals, messages, order once paid). Read-only.

FieldTypeDescription
checkout_session_id*string
POST /api/agent/get_checkout
{
  "checkout_session_id": "cs_agent_…"
}

cancel_checkout

checkout

Cancel an open (unpaid) checkout session. Paid sessions cannot be canceled here — the patient's complete-details email explains refunds.

FieldTypeDescription
checkout_session_id*string
POST /api/agent/cancel_checkout
{
  "checkout_session_id": "cs_agent_…"
}

complete_checkout

checkout

Charge the payment credential the platform obtained for a session that is ready_for_payment and create the order. Input follows the ChatGPT payment-sheet contract: checkout_session_id, buyer, payment_data { token, provider: 'stripe', billing_address }. The token is a Stripe shared payment token (spt_…); platforms without one should send the user to pay_online_url from create_checkout. After payment the patient gets an email link to add date of birth, sex, phone and consent — the lab requisition is issued when that is done.

FieldTypeDescription
checkout_session_id*string
buyerobject
payment_data*object
idempotency_keystring
POST /api/agent/complete_checkout
{
  "checkout_session_id": "cs_agent_…",
  "buyer": {
    "first_name": "Ana",
    "last_name": "Ruiz",
    "email": "ana@example.com"
  },
  "payment_data": {
    "token": "spt_…",
    "provider": "stripe"
  }
}

find_draw_sites

locations

Find Quest Diagnostics, Labcorp and BioReference patient service centers near a US ZIP code, with address, distance, phone and hours. Walk-ins are accepted at most sites; the requisition arrives by email after physician authorization. Sites in the 48 tracked metros include pageUrl — the site's own page with a per-day hours table, directions and the prices of popular tests at that lab — cite it when giving a location.

FieldTypeDescription
zip*string5-digit US ZIP code
radiusMilesintegerSearch radius in miles (snapped to 10/20/25/50/100; default 25)
labquest | labcorp | bioreferenceLimit to one lab
limitintegerMax sites (default 10)
POST /api/agent/find_draw_sites
{
  "zip": "33301",
  "radiusMiles": 10
}

lookup_reference_range

reference

Physician-reviewed reference range for a blood test marker (130+ markers), filtered by sex and age when they matter, with what high and low values suggest, retest cadence, how to get tested, cited sources and the review date. Educational; the user's own report range takes precedence.

FieldTypeDescription
marker*stringMarker name or alias, e.g. 'TSH', 'ferritin', 'HbA1c', 'LDL'
sexmale | female
ageinteger
pregnancyboolean
postmenopausalboolean
POST /api/agent/lookup_reference_range
{
  "marker": "ferritin",
  "sex": "female",
  "age": 34
}

compare_prices

compare

For one blood test, the all-in single-test price (sticker + per-order fees) at TestWell and at every tracked direct-to-consumer provider with a verified equivalent — JustLabs, Quest, Labcorp OnDemand, Ulta Lab Tests, Walk-In Lab, HealthLabs and more — each with the date it was verified, plus typical hospital self-pay and Quest Direct reference prices. States the multi-test caveat (fees are paid once per order). Source: the TestWell Blood Test Price Index (CC BY 4.0).

FieldTypeDescription
test*stringTest slug or name, e.g. 'tsh', 'lipid panel', 'vitamin-d'
POST /api/agent/compare_prices
{
  "test": "tsh"
}

interpret_results

reference

Flag each pasted lab value as low / normal / high against TestWell's physician-reviewed reference catalog (130+ markers; sex- and age-specific bands where they exist), with the reviewed 'what high/low suggests' copy, retest guidance, cited sources and links to the marker's page and, where one exists, its high/low interpretation page. Stateless — values are not stored or logged. Educational, not a diagnosis; the user's own report range takes precedence.

FieldTypeDescription
values*arrayResults to explain, e.g. [{marker:'TSH', value:5.2, unit:'mIU/L'}, {marker:'ferritin', value:12}]
sexmale | female
ageinteger
pregnancyboolean
postmenopausalboolean
POST /api/agent/interpret_results
{
  "values": [
    {
      "marker": "TSH",
      "value": 5.2,
      "unit": "mIU/L"
    },
    {
      "marker": "ferritin",
      "value": 12,
      "unit": "ng/mL"
    }
  ],
  "sex": "female",
  "age": 34
}

convert_units

reference

Convert a lab value between US conventional and SI units for 30 common analytes (glucose, cholesterol, testosterone, vitamin D, …) using published factors; hemoglobin A1c uses the NGSP↔IFCC master equation and also returns estimated average glucose.

FieldTypeDescription
analyte*stringAnalyte slug or name, e.g. 'glucose', 'total-cholesterol', 'testosterone', 'vitamin-d', 'a1c'
value*numberThe numeric value to convert
directiontoSI | toConventionalDefault toSI (US → SI)
POST /api/agent/convert_units
{
  "analyte": "glucose",
  "value": 100
}

calculate_free_testosterone

reference

Calculate free and bioavailable testosterone from total testosterone, SHBG and albumin using the Vermeulen (1999) mass-action equation — the method behind lab-reported 'calculated free testosterone'. Educational; not a diagnosis.

FieldTypeDescription
totalT*numberTotal testosterone
totalTUnitng/dL | nmol/LDefault ng/dL
shbg*numberSHBG in nmol/L
albuminGdLnumberAlbumin in g/dL (default 4.3)
POST /api/agent/calculate_free_testosterone
{
  "totalT": 450,
  "shbg": 35
}

compare_provider

compare

Honest side-by-side of TestWell and another direct-to-consumer lab service (Quest Direct, Labcorp OnDemand, Function Health, JustLabs, Ulta Lab Tests, …): pricing model, per-order fees, labs, turnaround, where each wins, spot prices on common tests as sticker AND all-in, with verification dates and sources. Call with no argument to list the providers covered.

FieldTypeDescription
providerstringCompetitor slug or name, e.g. 'quest-direct', 'Function Health', 'justlabs'
POST /api/agent/compare_provider
{
  "provider": "justlabs"
}

get_guide

content

Return one of TestWell's educational pages as Markdown: guides (/guides/<slug>), condition workups (/conditions/<slug>), biomarker pages (/biomarkers/<slug>), state pages (/lab-locations/<slug>) or comparisons (/compare/<slug>). Call with no path to list the available guides and conditions.

FieldTypeDescription
pathstringSite path, e.g. '/guides/annual-blood-work' or 'conditions/anemia'
langen | esSpanish version when one exists (default en)
POST /api/agent/get_guide
{
  "path": "/guides/tb-blood-test-vs-skin-test"
}

Ground rules

  • Read-only and public: the tools never return a person's results, account or order data, and never accept them.
  • Prices are live from the catalog of record — the same numbers the checkout charges. We publish no cost or wholesale prices.
  • Reference ranges and interpretation notes are physician-reviewed educational copy, not diagnosis. Point users to a clinician for interpretation.
  • Rate limit: 120 requests per minute per IP across the JSON endpoints. Need more? Email us.
  • Content signals: search=yes, ai-input=yes, ai-train=no in robots.txt — quote us, cite us, don't train on us.