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

@xmcp-dev/billing

v0.1.0

Published

Billing integration for xmcp

Readme

@xmcp-dev/billing

Meter tool admissions with @xmcp-dev/billing, then deliver durable usage events to Metronome or Stripe Billing Meters. One middleware covers filesystem tools. The application owns customer authentication, persistence, pricing, and credit policy.

pnpm add @xmcp-dev/billing

Record before executing

import { usageBilling } from "@xmcp-dev/billing";

export const mcp = usageBilling({
  customer: (context) => context.get<string>("billingCustomerId"),
  units: (context) => (context.params.name === "report" ? 3 : 1),
  admit: async (event) => {
    // In one database transaction: check/debit credits and INSERT this event
    // into a durable outbox. Resolve true only after COMMIT; false denies.
    return yourBillingStore.admit(event);
  },
});

yourBillingStore represents your application's transactional persistence, not an exported xmcp API. The runnable example supplies a concrete SQLite implementation and delivery worker. An earlier authenticated middleware must set the billing customer ID, or verify the current request inside customer. Never accept a billing customer ID or price directly from untrusted tool arguments.

admit receives an immutable event containing id, customerId, tool, positive integer units, and an ISO timestamp. The ID identifies one execution round. Returning false denies execution; throwing returns a generic tool error and does not run the handler. Listings, prompts, and resources bypass billing.

This meters admitted attempts. Once admission commits, subsequent failure, cancellation, or a crash does not refund credits. Each input-required execution round is another admission. If your product bills only completed work, its business transaction must record that completion and usage together; this admission middleware is not that billing model. Tool retries are new attempts; delivery retries reuse the stored event ID.

Deliver from a worker

import { metronomeEvents, stripeMeterEvents } from "@xmcp-dev/billing";

const deliver = metronomeEvents({
  secretKey: process.env.METRONOME_API_KEY!,
  eventName: "xmcp_tool_attempt",
});
// Existing Stripe Billing Meters users can choose:
const deliverToStripe = stripeMeterEvents({
  secretKey: process.env.STRIPE_SECRET_KEY!,
  eventName: "xmcp_tool_attempt",
});

Read pending events from your outbox, await deliver(event), then mark the row delivered. Retain failures for retry and alert on persistent errors. A crash after provider acceptance may cause redelivery: Stripe receives the same event identifier and idempotency key; Metronome receives the same transaction_id. Providers' deduplication windows are finite. The example stops automatic delivery for events older than 23 hours so an operator can reconcile ambiguous records before replaying them. API acceptance does not prove successful invoicing; monitor provider ingestion errors and reconcile your outbox.

Stripe recommends Metronome for new usage-based integrations. Configure a Metronome billable metric for xmcp_tool_attempt that sums properties.units, plus the customer's product/contract. For existing Stripe Billing Meters, configure the matching meter event name, stripe_customer_id customer field, value sum field, and a subscribed metered price. These adapters do not create subscriptions, contracts, invoices, or checkout sessions.

Prepaid credits

The example atomically debits local integer usage credits and inserts an outbox event before allowing a tool call. It never checks an eventually consistent invoice total as a real-time spending gate. Grants are explicit demo administrative commands. A production grant must come from a verified, idempotently handled purchase or entitlement event. Do not add credits from an unsigned webhook or a client assertion.

SQLite demonstrates durability on one host. Deployments across hosts need a shared transactional store with equivalent atomic behavior. Keep each outbox bound to one provider configuration; changing providers requires reconciling outstanding records. No Redis, payment SDK, or job-queue service is required by the plugin itself.