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

@practicemakes/mcp

v26.824.1

Published

MCP server exposing PracticeMakes prod data (read-only) to Claude, authenticated as the calling user's own Firebase identity.

Readme

@practicemakes/mcp

A small MCP server that exposes PracticeMakes production data (read-only) to Claude for admin and development work — and surfaces your Planner backlog so your own task list can drive development.

It authenticates as your own platform identity (your Firebase user), so every result is scoped to your real role and organization by the backend. A SYSADMIN sees the whole platform; a regular user sees only their org. That's what lets the same server be handed to other users on the platform.

How it works

Claude  ──stdio──▶  @practicemakes/mcp  ──HTTPS Bearer──▶  https://api.practicemakes.io/api/...
                    (refreshes your Firebase ID token)      (existing authz + business logic)

No backend changes and no secret credentials — the Firebase Web API key it uses is a public client value (baked in as a default), so each user supplies only a credential for their own account. Read-only.

Use it (published package)

Once published to npm, any platform user connects with one line — nothing to clone or build:

claude mcp add practicemakes \
  --env FIREBASE_REFRESH_TOKEN=<your-refresh-token> \
  -- npx -y @practicemakes/mcp

Point at a local backend during development with --env PM_API_BASE_URL=http://localhost:9090.

Getting a refresh token

  • Password account: create .env (see .env.example) with PM_EMAIL / PM_PASSWORD, run yarn workspace @practicemakes/mcp login — it prints a FIREBASE_REFRESH_TOKEN=... line to use.
  • Google/Apple sign-in: log into the web app, open DevTools → Application → IndexedDB → firebaseLocalStorage → the auth user record, and copy stsTokenManager.refreshToken.

Develop (from the monorepo)

yarn install                                   # at repo root, links the workspace
yarn workspace @practicemakes/mcp build
cp packages/mcp/.env.example packages/mcp/.env # then fill in a credential
yarn workspace @practicemakes/mcp smoke        # end-to-end check against prod

smoke prints who you're authenticated as, how many orgs are visible, and your Planner backlog. To run the local build directly in Claude instead of the published package:

claude mcp add practicemakes \
  --env FIREBASE_REFRESH_TOKEN=... \
  -- node "$(pwd)/packages/mcp/dist/index.js"

Publish

Versioned on the monorepo's calendar scheme (26.MMDD.patch). Scoped public package:

yarn workspace @practicemakes/mcp publish   # runs prepublishOnly (clean + build) first

Tools (read)

| Tool | What it returns | |---|---| | list_organizations | Orgs visible to you (SYSADMIN → all) | | get_organization | One org by UUID | | get_my_profile | Your profile + entitlements/roles/org context | | list_profiles | Profiles (SYSADMIN → all, ADMIN → your org) | | get_profile | One profile by UUID | | get_my_planner_tasks | Your Planner backlog (drives development) | | search_tasks | Search tasks; reveal completed/deleted/snoozed via showFields | | get_task | One task by UUID | | list_workflows | Your Planner workflows | | get_workflow | One workflow, hydrated with run state | | get_billing_config | Billing/entitlement config for your org (takes a required platform) | | list_servers | Monitored servers + both identifiers the tools below need | | get_server | One server's config, including its maintenance windows | | list_server_statuses | Live status of all your servers (is anything down now) | | get_server_uptime | Uptime % over the last 1–168 hours, from raw heartbeats | | get_server_uptime_daily | Per-day uptime history beyond heartbeat retention | | list_server_incidents | Outage history for one server, planned vs unplanned |

Server identifiers

The monitoring tools take two different, non-interchangeable identifiers, and passing the wrong one returns a 404 that reads like a missing server. list_servers returns both:

| Identifier | Used by | Route family | |---|---|---| | serverShortLink | get_server_uptime, get_server_uptime_daily | /api/public/... (unauthenticated) | | serverId | get_server, list_server_incidents | /api/server/... (authenticated, org-scoped) |

Neither is a UUID — serverId is the operator-assigned id (e.g. web-01).

Tools (write)

Every write tool asks you to confirm the exact request before it sends anything.

| Tool | What it does | |---|---| | create_task | Creates a Planner task in your current org context (needs ADMIN there) | | complete_task | Sets completedAt on a task — the tool that closes the Planner-driven-dev loop | | switch_org_context | Switches your active org context (SYSADMIN → any org, otherwise invite-only) |

Read this before enabling write tools

These tools run as you, with all of your permissions. Authentication is a per-user Firebase ID token, not a service account — there is no read-only role, no separate service identity, and no server-side allow-list behind them. If your account is SYSADMIN, a write tool can write across every tenant on the platform. The tool list and the confirmation prompt are the entire safety boundary.

Confirmation needs client support. The gate uses MCP elicitation. If your client did not advertise elicitation support during the handshake, there is no channel to ask you on, and every write tool refuses and sends nothing — it will not fall back to writing unconfirmed. The error names the mutation it declined to perform. This is deliberate: silently proceeding would disable the guardrail for exactly the clients that never agreed to be asked.

switch_org_context is session-global. It mutates your profile, so it changes what every later read tool returns for the rest of the session — not just the next call.

complete_task is a read-modify-write. There is no dedicated completion endpoint; the tool reads the task, sets completedAt, and re-posts it, carrying the read's ETag back as If-Match so a concurrent edit is not silently clobbered.

yarn smoke is unaffected — it issues three fixed read-only requests and never touches the tool registry, so no write can reach production through it.

Roadmap

  • Admin actions (e.g. the ARCH-153 org/user purge) — blocked: no executable endpoint exists yet, only a GET .../data-inventory that reports what a purge would do and deletes nothing.
  • OpenAPI-driven tool generation from the backend's grouped specs (the monorepo already uses openapi-typescript in packages/core).
  • Hosted remote server (streamable-HTTP + per-user OAuth) so users connect to a URL with nothing to install.