npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@uphealth/mcp-server

v1.1.4

Published

Uphealth Signal — the adaptive health-messaging engine for apps and agents. Drive federally-sourced, audience-safe cued health-message streams from any MCP client — local stdio via npx, or the hosted mcp.uphealth.us endpoint. Not medical advice.

Readme

Uphealth MCP Server (Track A A4)

The adaptive health-messaging engine for apps and agents — federally-sourced, audience-safe. Not medical advice.

Wraps the api.uphealth.us cued-stream API as agent-callable Model Context Protocol tools. The agent can call lookup_health_fact with zero setup — no key to get one already-public federal health fact, then configure a free up_sandbox_… key to drive an adaptive cued patient stream with the 4 keyed tools.

Locks captured in docs/spec_track_a_a4_mcp_server.md:

  • SDK — TypeScript via @modelcontextprotocol/sdk (flipped from Python at 2026-05-22 build-kickoff revalidation)
  • Tool surface — 5 tools: a no-key lookup_health_fact (one already-public federal fact per question, zero setup) + 4 keyed tools (create_patient_stream / get_next_cued_message / read_stream_state / list_sandbox_topics)
  • Auth — Bearer-token passthrough (MCP server is stateless thin proxy; Rails validates). lookup_health_fact is the sole exception — it needs no key; the per-tool policy still 401s every keyed tool without one.
  • Corpus — sandbox only at v1
  • Hostnamemcp.uphealth.us subdomain (Option A locked)
  • Transport — Streamable HTTP

Local dev

nvm use            # picks Node 22 from .nvmrc
npm install
cp .env.example .env
npm run dev        # tsx hot-reload of src/index.ts

The dev server listens on :3001. Point an MCP client at http://localhost:3001/mcp with Authorization: Bearer <a valid up_sandbox_… token from api.uphealth.us>.

Build + run (production)

npm ci             # full install — typescript (the compiler) is a devDependency
npm run build      # tsc → dist/
node dist/index.js # systemd does this via bin/mcp-server-systemd.sh

Tests

npm test           # vitest run; mocks global fetch

Environment

See .env.example for the full list. Required: RAILS_API_BASE_URL. Optional with defaults: MCP_SERVER_PORT (3001), NODE_ENV (development), LOG_LEVEL (info).

Deployment (co-located on the .us droplet at mcp.uphealth.us)

Per spec §6.1 lock 2026-05-22, the MCP server runs as a Node process co-located with Rails on the existing .us droplet (164.92.77.128, $14/mo s-1vcpu-2gb-amd). No separate droplet — the MCP server is a thin Node proxy (< 50 MB RAM, no DB connection, no state) so resource pressure on Rails is negligible. The existing bin/deploy cron handles MCP rebuilds when files under mcp-server/ change.

A separate companion droplet remains a v2 option if MCP traffic exceeds Rails on the shared droplet OR an enterprise buyer requires isolation. See spec §6.1 for the migration path.

One-time provisioning sequence

The provisioning steps live on the existing .us droplet (164.92.77.128). Eric does the DO panel step (#2 DNS); the rest run via SSH.

  1. Install Node 22 LTS (only step that adds new software; the .us droplet currently runs Ruby + Rails only). Install via the NodeSource apt repo so node + npm land at /usr/bin/ on the system PATH:
    curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
    apt install -y nodejs          # Node 22 + npm at /usr/bin/{node,npm}
    node --version                 # expect v22.x
    which node npm                 # expect /usr/bin/node  /usr/bin/npm

    A system-PATH install is required, not nvm: (a) the systemd unit's ExecStart=/usr/bin/node is an absolute path, and (b) the bin/deploy auto-rebuild hook gates on command -v npm, which the cron environment only resolves for a /usr/bin install. Plain apt install nodejs (without the NodeSource repo) ships an EOL Node on Ubuntu; nvm puts node under ~/.nvm where neither the absolute ExecStart nor the cron PATH will find it.

  2. Add DNS — Eric adds A record mcp.uphealth.us → 164.92.77.128 via DO Networking → Domains → uphealth.us (same IP as the existing uphealth.us / www.uphealth.us / api.uphealth.us records; we're co-locating). Propagation typically minutes.
  3. Configure env — copy mcp-server/.env.example to /root/uphealth-us/mcp-server/.env.production; set RAILS_API_BASE_URL=https://api.uphealth.us and NODE_ENV=production. chmod 600 since it's root-only.
  4. Initial buildcd /root/uphealth-us/mcp-server && npm ci && npm run build (full install — typescript is a devDependency the build needs — then tscdist/; this is exactly what bin/mcp-server-systemd.sh runs on every subsequent deploy). Verify dist/index.js exists. Do NOT use npm ci --omit=dev here: it skips the compiler and the build silently fails (see the comment block in bin/mcp-server-systemd.sh documenting the [email protected] fall-through).
  5. Install systemd unitcp /root/uphealth-us/config/systemd/uphealth-mcp-server.service /etc/systemd/system/systemctl daemon-reloadsystemctl enable --now uphealth-mcp-serversystemctl status uphealth-mcp-server to verify "active (running)". Logs via journalctl -u uphealth-mcp-server -f.
  6. nginx vhostcp /root/uphealth-us/mcp-server/ops/nginx-vhost.conf /etc/nginx/sites-available/uphealth-us-mcpln -s /etc/nginx/sites-available/uphealth-us-mcp /etc/nginx/sites-enabled/nginx -t (must pass) → systemctl reload nginx.
  7. Cert SAN extensioncertbot --nginx --expand -d uphealth.us -d www.uphealth.us -d api.uphealth.us -d mcp.uphealth.us. Existing cert at /etc/letsencrypt/live/uphealth.us/ gains the new SAN; auto-renewal via the certbot timer continues.
  8. Auto-deploy cron is already running on /root/uphealth-us/bin/deploy per the existing .us setup. The bin/deploy extension (PR #424) detects changes under mcp-server/ and runs bin/mcp-server-systemd.sh automatically. No new cron entry needed.

After step 8, subsequent pushes that touch mcp-server/ trigger npm ci && npm run build && systemctl restart uphealth-mcp-server automatically (via bin/mcp-server-systemd.sh).

Smoke verification (post-deploy)

Mirror the A1 PR C 6-step smoke against the MCP server using @modelcontextprotocol/inspector:

npx @modelcontextprotocol/inspector \
  --transport streamable-http \
  --url https://mcp.uphealth.us/mcp \
  --header "Authorization: Bearer <up_sandbox_…>"

Then in the inspector UI:

  1. create_patient_stream with template_id: "general_wellness_daily" → returns stream_id + first_cue
  2. get_next_cued_message WITHOUT feedback → returns isError: true with the moat-explainer message
  3. get_next_cued_message WITH valid feedback → returns next cue
  4. get_next_cued_message again with same idempotency_key + same feedback → returns the cached cue (idempotent)
  5. read_stream_state → returns current state + events_count
  6. list_sandbox_topics → returns 5 topic labels

Pass criteria: all 6 steps green; the moat error in step 2 includes the phrase "structural, not a bug".

Registry submission (at A4 launch)

Per docs/spec_track_a_a4_mcp_server.md §9 and future_roadmap.md §3 A4 strategic context, submit at launch to:

  • Anthropic MCP registry
  • Claude Desktop MCP directory
  • Third-party catalogs (mcp.so, mcpservers.com if active at launch time)

Captures the 5-month MCP-positioning window. Don't defer.