From b424c1de5191e41baefee4928392057cdedc3ecc Mon Sep 17 00:00:00 2001 From: byteworthy Date: Thu, 14 May 2026 18:05:23 -0500 Subject: [PATCH] fix(mcp): replace compare_payers with compare_practice_to_community MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The backend /api/v1/public/payer-scorecard/compare/ is NOT a "compare two payers" endpoint — it is an email-gated "compare YOUR practice metrics against the network aggregate for ONE payer + specialty" lead-capture endpoint (Django view docstring confirms). The old compare_payers tool sent {payer_a, payer_b} and got 400 "Valid email is required." Every invocation failed silently. Rename to compare_practice_to_community. Update schema to require email + payer + specialty + optional your_denial_rate / your_days_to_pay / your_appeal_win_rate (matches Django view fields verified at upstream/api/v1/public/payer_scorecard.py:31-37). Also adds .env.example (was missing; README told users to copy it and there was nothing to copy). Build + 9 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) --- .env.example | 16 ++++++- README.md | 2 +- src/index.ts | 4 +- src/tools/compare_payers.ts | 22 --------- src/tools/compare_practice_to_community.ts | 52 ++++++++++++++++++++++ 5 files changed, 69 insertions(+), 27 deletions(-) delete mode 100644 src/tools/compare_payers.ts create mode 100644 src/tools/compare_practice_to_community.ts diff --git a/.env.example b/.env.example index 6252180..1b6027f 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,14 @@ -UPSTREAM_API_KEY=dev_your_key_here -UPSTREAM_BASE_URL=https://api.upstream.cx +# Upstream MCP — environment configuration template. +# Copy to `.env` and fill in real values. Never commit `.env`. + +# Required: your Upstream API key (free tier available at upstream.cx/developers). +# Format: lz_live_... or lz_test_... — generated at app.upstream.cx/settings/api-keys +UPSTREAM_API_KEY= + +# Optional: override the API base URL. Default is https://api.upstream.cx. +# Set this when developing against a local Django dev server (http://localhost:8000) +# or against a Vercel preview. +# UPSTREAM_API_BASE_URL=https://api.upstream.cx + +# Optional: per-request timeout in milliseconds. Default 30000 (30s). +# UPSTREAM_REQUEST_TIMEOUT_MS=30000 diff --git a/README.md b/README.md index 93cc4fc..18fde73 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ Free API key (500 calls per month, no credit card): [upstream.cx/developers/keys | Tool | Tier | What it does | |---|---|---| | `get_payer_scorecard` | `[Paid]` | A to F grade and denial rate for a payer by specialty. Includes top denial codes, payment timing percentiles, and historical appeal success rates. | -| `compare_payers` | `[Paid]` | Side by side comparison of two payers on denial rates, payment timing, and appeal success. | +| `compare_practice_to_community` | `[Free, lead-capture]` | Compare your practice's payer-specific metrics (denial rate, days-to-pay, appeal win rate) against the Upstream network aggregate for that payer + specialty. Requires email — saved as a lead. Returns delta metrics + risk-adjusted CTA. | | `check_payer_behavior` | `[Paid]` | Behavioral risk score and cluster classification (Aggressive Denier, Slow Payer, Prompt Payer, Underpayer). Includes recent policy changes and the specific dates of detection. | ### Reimbursement diff --git a/src/index.ts b/src/index.ts index ddde400..18e4539 100644 --- a/src/index.ts +++ b/src/index.ts @@ -13,7 +13,7 @@ import { lookupDenialCode } from './tools/lookup_denial_code.js'; import { lookupFeeSchedule } from './tools/lookup_fee_schedule.js'; import { scanClaim } from './tools/scan_claim.js'; import { getPayerScorecard } from './tools/get_payer_scorecard.js'; -import { comparePayers } from './tools/compare_payers.js'; +import { comparePracticeToCommunity } from './tools/compare_practice_to_community.js'; import { checkPayerBehavior } from './tools/check_payer_behavior.js'; import { getIndustrySignals } from './tools/get_industry_signals.js'; import { checkPriorAuthReadiness } from './tools/check_prior_auth_readiness.js'; @@ -27,7 +27,7 @@ const tools = [ lookupFeeSchedule, scanClaim, getPayerScorecard, - comparePayers, + comparePracticeToCommunity, checkPayerBehavior, getIndustrySignals, checkPriorAuthReadiness, diff --git a/src/tools/compare_payers.ts b/src/tools/compare_payers.ts deleted file mode 100644 index 4948d54..0000000 --- a/src/tools/compare_payers.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { UpstreamAPIClient } from '../client.js'; - -export const comparePayers = { - name: 'compare_payers', - description: - 'Compare two payers side by side on denial rates, payment timing, and appeal success. ' + - "Useful when choosing network participation or explaining a payer's behavior relative to peers.", - inputSchema: { - type: 'object', - properties: { - payer_a: { type: 'string', description: 'First payer name' }, - payer_b: { type: 'string', description: 'Second payer name' }, - }, - required: ['payer_a', 'payer_b'], - }, - async execute(client: UpstreamAPIClient, args: { payer_a: string; payer_b: string }) { - return client.post('/api/v1/public/payer-scorecard/compare/', { - payer_a: args.payer_a, - payer_b: args.payer_b, - }); - }, -}; diff --git a/src/tools/compare_practice_to_community.ts b/src/tools/compare_practice_to_community.ts new file mode 100644 index 0000000..3f61d68 --- /dev/null +++ b/src/tools/compare_practice_to_community.ts @@ -0,0 +1,52 @@ +import { UpstreamAPIClient } from '../client.js'; + +export const comparePracticeToCommunity = { + name: 'compare_practice_to_community', + description: + "Compare your practice's payer-specific metrics (denial rate, days-to-pay, appeal " + + 'win rate) against the Upstream network aggregate for that payer + specialty. ' + + 'Lead-capture endpoint — requires email. Returns delta metrics and a risk-adjusted CTA.', + inputSchema: { + type: 'object', + properties: { + email: { + type: 'string', + description: 'Work email — saved as a lead and returned with results', + }, + payer: { + type: 'string', + description: 'Payer name to compare against (e.g. "UnitedHealthcare", "Aetna")', + }, + specialty: { + type: 'string', + description: 'Specialty for the community aggregate (e.g. "ABA", "PT/OT", "dental")', + }, + your_denial_rate: { + type: 'number', + description: 'Your practice denial rate as a decimal (e.g. 0.18 = 18%)', + }, + your_days_to_pay: { + type: 'number', + description: 'Average days from claim submission to payment for your practice', + }, + your_appeal_win_rate: { + type: 'number', + description: 'Your appeal win rate as a decimal (e.g. 0.62 = 62%)', + }, + }, + required: ['email', 'payer', 'specialty'], + }, + async execute( + client: UpstreamAPIClient, + args: { + email: string; + payer: string; + specialty: string; + your_denial_rate?: number; + your_days_to_pay?: number; + your_appeal_win_rate?: number; + }, + ) { + return client.post('/api/v1/public/payer-scorecard/compare/', args); + }, +};