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

@uscreentv/mcp

v0.3.0

Published

Uscreen MCP server — exposes Uscreen primitives (catalog, entitlement, sandbox, checkout) as tools for Claude Desktop, Cursor, Windsurf, and other MCP clients

Readme

@uscreentv/mcp

MCP server for Uscreen — exposes the Uscreen analytics surface as tools that AI assistants like Claude Desktop, Cursor, and Windsurf can call directly.

Status: alpha. v1 ships read-only analytics + user-detail primitives backed by the public developer/v1/* API. Catalog, entitlement, sandbox, and checkout primitives are planned and will land as their backing endpoints ship.

What it does

Once installed in your MCP-compatible client, this server lets an AI assistant answer questions about your Uscreen business in plain English:

  • "What's my MRR?"get_store_metrics returns the canonical top-line number, same as your Bullet dashboard.
  • "What's working in my catalog this month?"list_top_content ranks videos by watch time.
  • "How is video 1234 trending?"get_content_performance returns a daily series for one piece of content.
  • "How many new signups in the last 7 days?"get_subscriber_growth with a trial-vs-paid split.
  • "Which of my plans is driving revenue?"get_revenue_breakdown per-plan, sorted by MRR.
  • "What's going on with [email protected]?"find_user_by_email then get_user, list_user_emails, list_user_views, list_user_comments, list_user_payments for a full activity drill-down.
  • "Did Sarah's churn coincide with a failed charge?"list_user_payments with status=overdue or status=unpaid.
  • "Is Sarah about to churn?"get_user and read current_plan.cancel_at_period_end (true means they clicked cancel; the sub stays active until next_billing_at).
  • "When does Sarah's trial end?"get_user and read current_plan.trial_ends_at.
  • "Show me users whose trials end this week."list_users and filter by current_plan.trial_ends_at within the window. Cohort prompts work without the per-user round-trip because current_plan rides on the list rows.
  • "Who's about to churn?"list_users and filter by current_plan.cancel_at_period_end: true.
  • "Did Sarah ever pay, or only trial?"get_user and check plan_history rows: any is_trial: false row means they reached the paid phase. Or list_user_payments for the definitive answer (any status: "paid" row).
  • "Show me everyone who signed up this week."list_users with a days=7 window.
  • "What can this key do?"whoami returns the workspace identity and the granted scope list.

In Uscreen vocabulary, a user is anyone in your CRM — leads, paid subscribers, and one-time buyers. The shipped get_subscriber_growth tool keeps its existing name; the user_* tools are the broader CRM-record surface.

All tools are primitives, not workflows. Agents chain them freely; Uscreen does not prescribe flows.

Install

Prerequisites

  • Node 20+ (22+ recommended).
  • A Uscreen developer API key. Generate one from Bullet → Settings → Developers → Apps. Tokens look like usc_sk_live_<32 chars> and are shown exactly once at creation — copy them then.

Install as an npm package

npm install -g @uscreentv/mcp

Or run directly without install:

npx -y @uscreentv/mcp

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent on Windows / Linux:

{
  "mcpServers": {
    "uscreen": {
      "command": "npx",
      "args": ["-y", "@uscreentv/mcp"],
      "env": {
        "USCREEN_API_KEY": "usc_sk_live_..."
      }
    }
  }
}

Restart Claude Desktop. The Uscreen tools appear in the tools menu.

Cursor

Open Cursor Settings → MCP → Add new MCP server:

  • Name: Uscreen
  • Type: stdio
  • Command: npx -y @uscreentv/mcp
  • Environment: USCREEN_API_KEY=usc_sk_live_...

Windsurf

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "uscreen": {
      "command": "npx",
      "args": ["-y", "@uscreentv/mcp"],
      "env": { "USCREEN_API_KEY": "usc_sk_live_..." }
    }
  }
}

Tools

Each tool requires a specific scope on the API key — see Scopes for the full breakdown. Missing-scope requests return 403. For the complete tool reference — every tool's title, description, full input schema (types, defaults, descriptions) — see TOOLS.md, which is auto-generated from defineTools() and kept in sync by CI. Drop it on an LLM as a one-shot context for what this MCP can do.

Identity

| Name | Backing endpoint | Scope | Returns | |---|---|---|---| | whoami | GET /developer/v1/whoami | none | Workspace identity (store_id, store_name, store_url, store_timezone), the calling key's granted scopes, and the API version. Safe to call as a connection sanity check or for an agent that wants to know what's accessible before chaining other tools. |

Analytics

| Name | Backing endpoint | Scope | Returns | |---|---|---|---| | get_store_metrics | GET /developer/v1/analytics/store_metrics | finance_analytics.read | Top-line MRR, active subscribers, trial counts (current + prior month, with confidence envelope) | | list_top_content | GET /developer/v1/analytics/top_content | content_analytics.read | Content ranked by watch time over a trailing window (days, limit, content_type) | | get_content_performance | GET /developer/v1/analytics/content_performance | content_analytics.read | Per-content daily view + watch-time series. Requires content_id | | get_subscriber_growth | GET /developer/v1/analytics/subscriber_growth | finance_analytics.read | Daily new-signup counts with trial/paid split | | get_revenue_breakdown | GET /developer/v1/analytics/revenue_breakdown | finance_analytics.read | Per-plan MRR + active subscribers, sorted by MRR desc |

Numbers come from the same canonical analytics pipeline the Bullet admin dashboard uses, so MCP MRR matches Bullet MRR by construction.

User detail

All user-detail tools require the crm.read scope.

| Name | Backing endpoint | Returns | |---|---|---| | list_users | GET /developer/v1/users | Cursor-paginated list of users in the store — lightweight {id, name, email, signup_at, last_signed_in_at, current_plan} per row. Optional signup-window filter via days; chain into get_user for full detail. Rate-limited per key and per store; default page size is 25 | | find_user_by_email | POST /developer/v1/users/lookup | Minimal {id, name, email} projection — start here when you only have an email | | get_user | GET /developer/v1/users/{id} | One user's identity, subscription state, plan history, tags, typed custom fields | | list_user_emails | GET /developer/v1/users/{id}/emails | Email history — manual broadcasts vs transactional (automation drips and system messages) — cursor-paginated, trailing window via days, optional kind filter | | list_user_views | GET /developer/v1/users/{id}/views | Content watch history — cursor-paginated, trailing window via days | | list_user_comments | GET /developer/v1/users/{id}/comments | Comments on content + community posts — cursor-paginated, trailing window via days (DMs not included) | | list_user_payments | GET /developer/v1/users/{id}/payments | Payment history (Invoices) — cursor-paginated, trailing window via days. kind discriminator labels each row as subscription / purchase / rental / freebie / gift / donation / booking. Optional status filter (paid / refunded / unpaid / etc.). Drafts and integration ownerships are excluded |

find_user_by_email sends the email in the request body, never in the URL or logs, and is rate-limited per key and per store. The id returned is the canonical internal id — never use email or other PII as a lookup key on subsequent calls.

The projection is intentionally narrow — {id, name, email} only — not a stub. Lookup is rate-limited specifically to discourage enumeration, so the response is kept minimal to avoid amplifying that surface. Token cost matters too: full UserDetail carries plan history, tags, and custom fields that bloat the LLM context on every email probe. When you want full detail, chain into get_user with the returned id.

list_users returns a strictly larger PII surface than the lookup tool (name + email + signup_at + current_plan) and walks the entire CRM when no days window is supplied. The same per-key / per-store throttle applies, but holders of a crm.read key should treat the tool as a bulk-export surface and grant it only to integrations that actually need cohort walks. For one-off lookups, prefer find_user_by_email or get_user.

Reading subscription state

current_plan is Stripe-shaped — it carries the timestamps an LLM needs to compose specific prompts directly, without composing them from indirect signals:

| Question | How to read it | |---|---| | Is the sub active? | current_plan != null && status in ['active', 'trialing'] | | When's the next charge? | current_plan.next_billing_at | | Are they about to churn? | current_plan.cancel_at_period_end == true (they clicked cancel; the sub stays active until next_billing_at) | | When does the trial end? | current_plan.trial_ends_at (null when not trialing) | | Are they paused? | current_plan.paused_at != null; resumes_at is the scheduled resume | | Deep-link to Stripe? | current_plan.provider_subscription_id (Stripe sub_*, PayPal billing agreement id, etc.) |

current_plan: null means no active subscription — combine with plan_history to disambiguate the four customer states:

| State | Signal | |---|---| | Lead — never had a sub | current_plan: null AND plan_history: [] | | Trial-only, never paid | current_plan: null AND every history row has is_trial: true | | Trial → paid → quit | current_plan: null AND any history row has is_trial: false, status: "canceled" | | Active subscriber | current_plan != null |

Trial conversion flips the same Subscription record's trial: true → false, so the is_trial field on a history row reflects what they were when the sub ended (i.e., a converted-then-quit user shows is_trial: false, not the original trial state).

For the absolute "did they pay?" answer including one-time purchases, use list_user_payments and check for any row with status: "paid".

Configuration

| Environment variable | Required? | Default | Purpose | |---|---|---|---| | USCREEN_API_KEY | yes | — | Secret key (usc_sk_live_*). The key gates which store the assistant sees. | | USCREEN_API_BASE_URL | no | https://uscreen.io | Override for local development or staging |

Security

  • API keys are sent as Authorization: Bearer <token> over HTTPS.
  • v1 keys are read-only; rejecting any key with non-read scopes is enforced server-side.
  • Keys are stored on Uscreen as SHA-256 digests, never plaintext — same model Stripe and GitHub use. Lost keys cannot be recovered; revoke and re-create.

Scopes

A key carries one or more scopes; missing-scope requests return 403. The MCP server registers every tool unconditionally — scope enforcement is per-request on the server side.

  • content_analytics.read — gates the content analytics endpoints (top videos, view + watch-time aggregates, content performance).
  • finance_analytics.read — gates the finance analytics endpoints (MRR, churn, ARPU, plan revenue, signup growth). A content recommender has no business reading MRR; a CFO dashboard has no business reading view counts. Issue them independently.
  • crm.read — gates the user-detail endpoints (/developer/v1/users/*). Reads individual user profiles (leads, paid subscribers, one-time buyers), including: contact info, subscription and billing history, all custom field values, email communication history (broadcasts and transactional — system messages, automation drips, password resets), content watch history, and comments. Grant only to trusted integrations.

Multiple scopes may be present on a single key.

Development

pnpm install
pnpm --filter @uscreentv/mcp build
pnpm --filter @uscreentv/mcp test
pnpm --filter @uscreentv/mcp dev    # watch mode

Smoke-test against a live server:

USCREEN_API_KEY=usc_sk_live_... \
USCREEN_API_BASE_URL=http://localhost:3000 \
SMOKE_CONTENT_ID=42 \
[email protected] \
pnpm dlx tsx packages/mcp/test/smoke.ts

User-detail tools require crm.read on the key. Omit SMOKE_USER_EMAIL (and SMOKE_USER_ID) to skip them and exercise only analytics.

The smoke runner prints a truncated JSON slice of each response to stderr — by design, useful when iterating against a local server. Do not run smoke against a usc_sk_live_* key in a shared or recorded terminal (CI logs, pair sessions, screen-share). The slices include user names, primary emails, store name, and plan names. For local-only localhost:3000 runs it's fine.

What's not in v1

  • Catalog reads (videos, collections) — the Rails endpoints are not yet built.
  • Entitlement checks for end-users.
  • Checkout session creation.
  • Sandbox tenants for end-to-end testing.

These are tracked in the Uscreen Headless plan and will land as separate releases.

License

MIT