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

reo-census-mcp

v0.2.0

Published

Product usage HTTP client for Reo (POST JSON to ingest.reo.dev/api/product/usage)

Readme

reo-census-mcp (Node.js)

This README is for teams integrating Reo into customer-facing products: you ship applications or services your customers rely on, and usage data is sent to Reo telemetry from that software.

The SDK uses Node 18+ native fetch, is non-blocking by default, so customer-facing request paths stay responsive while events reach Reo telemetry.

Install

npm install reo-census-mcp

Blocking behavior (important)

  • blocking: false (default): logUsage() returns a boolean immediately. true means the request was queued, not that Reo already responded (not proof of HTTP 2xx).
  • blocking: true: logUsage() returns Promise<boolean>. Use await (or .then()). true means HTTP 2xx after retries.

Early validation failures (opt-out, bad URL, missing API key, payload too large) return false synchronously even if you pass blocking: true.

ReoProductUsageLogger

Public options use camelCase; the JSON body still uses snake_case keys such as activity_type (see payload table below).

Two examples:

  • Version 1required payload fields only; set REO_API_KEY in the environment without passing apiKey.
  • Version 2every option, including apiKey in code for the full example.

Version 1 — required payload fields only

Merged payload must include activity_type, user_id, user_id_type, and product_id. source and environment default to PRODUCT_CLOUD and PRODUCTION when you omit them (override per call, on the constructor, or with REO_PRODUCT_USAGE_SOURCE / REO_PRODUCT_USAGE_ENVIRONMENT).

Set REO_API_KEY before constructing the logger (do not pass apiKey here—it is read from env).

import { ReoProductUsageLogger } from "reo-census-mcp";

const logger = new ReoProductUsageLogger({
  activityType: "LOGIN_ACTIVITY",
  userId: "https://www.linkedin.com/in/userid",
  userIdType: "LINKEDIN",
  productId: "reoWebApp",
});

const ok = logger.logUsage(); // non-blocking by default; boolean

Version 2 — all constructor parameters

Every supported option, including apiKey in code (Version 1 uses REO_API_KEY env only). eventId / eventAt below illustrate the full surface area—omit them in real traffic so each logUsage() auto-fills.

import { ReoProductUsageLogger } from "reo-census-mcp";

const logger = new ReoProductUsageLogger({
  apiKey: "YOUR_API_KEY",
  endpointUrl: "https://ingest.reo.dev/api/product/usage",
  timeout: 3.0,
  blocking: true,
  activityType: "LOGIN_ACTIVITY",
  source: "PRODUCT_CLOUD",
  environment: "PRODUCTION",
  userId: "https://www.linkedin.com/in/userid",
  userIdType: "LINKEDIN",
  ipAddr: "156.59.87.83",
  productId: "reoWebApp",
  userAgent: "Mozilla/5.0 ...",
  meta: { property1: "value1", property2: "value2" },
  eventId: 1231231232,
  eventAt: 639303296,
});

const ok = await logger.logUsage();

Payload fields

The SDK does not reject incomplete payloads locally; ingestion may enforce its own rules. When instrumenting customer-facing products, make sure each merged payload is complete and aligned with your privacy commitments (what you disclose to your customers’ end users, and fields like user_id / meta).

For a valid integration event, supply every required field via the ReoProductUsageLogger constructor, via logUsage, or split across both (constructor merged first — logUsage overrides overlapping keys.)

| Payload key (wire JSON) | Requirement | Notes | | --- | --- | --- | | activity_type | Required | e.g. LOGIN_ACTIVITY | | source | Optional | Defaults to PRODUCT_CLOUD; override with ctor / logUsage / REO_PRODUCT_USAGE_SOURCE | | environment | Optional | Defaults to PRODUCTION; override with ctor / logUsage / REO_PRODUCT_USAGE_ENVIRONMENT | | user_id | Required | e.g. LinkedIn URL or stable id | | user_id_type | Required | e.g. LINKEDIN | | product_id | Required | e.g. reoWebApp | | ip_addr | Optional | Omit on the customer-facing client if unknown; server-side code may fill when available | | meta | Optional | Arbitrary JSON object | | event_id | Auto if omitted everywhere | Omit on constructor and calls for a new id per send; only set once if you intentionally freeze it | | event_at | Auto if omitted everywhere | Same as event_id | | user_agent | Auto if omitted | SDK default or REO_PRODUCT_USAGE_USER_AGENT |

Constructor / logUsage option names: activityTypeactivity_type, userIduser_id, userIdTypeuser_id_type, productIdproduct_id, ipAddrip_addr, eventIdevent_id, eventAtevent_at, userAgentuser_agent.

Usage

Your customer-facing Node service (web app, worker, agent, etc.) can mirror this contract. Equivalent curl:

curl --location 'https://ingest.reo.dev/api/product/usage' \
  --header 'X-API-KEY: <API_KEY>' \
  --header 'Content-Type: application/json' \
  --data '{"payload":{...}}'

Node: minimal (required fields only)

import { ReoProductUsageLogger } from "reo-census-mcp";

// REO_API_KEY in environment — omit apiKey
const logger = new ReoProductUsageLogger({
  timeout: 3.0,
  activityType: "LOGIN_ACTIVITY",
  source: "PRODUCT_CLOUD",
  environment: "PRODUCTION",
  productId: "reoWebApp",
});

const ok = logger.logUsage({
  userId: "https://www.linkedin.com/in/userid",
  userIdType: "LINKEDIN",
});
// Omit blocking → false (non-blocking): default for customer-facing products and long-running apps.

Node: full payload entirely on constructor (optional)

Use when the merged payload is fixed for this logger (REO_API_KEY env; no apiKey):

const logger = new ReoProductUsageLogger({
  timeout: 3.0,
  activityType: "LOGIN_ACTIVITY",
  source: "PRODUCT_CLOUD",
  environment: "PRODUCTION",
  userId: "https://www.linkedin.com/in/userid",
  userIdType: "LINKEDIN",
  ipAddr: "156.59.87.83",
  productId: "reoWebApp",
  userAgent: "Mozilla/5.0 ...",
  meta: { property1: "value1" },
});

await logger.logUsage({ blocking: true }); // or non-blocking logger.logUsage(); eventId / eventAt unset → auto-filled each send

Node: full payload (mix constructor + overrides on logUsage)

Assume you already constructed new ReoProductUsageLogger({...}) with steady product defaults:

Recommended for customer-facing products: blocking: false (omit it — that is the default). The POST runs asynchronously so you do not add latency on user-facing paths.

logger.logUsage({
  activityType: "LOGIN_ACTIVITY",
  source: "PRODUCT_CLOUD",
  environment: "PRODUCTION",
  userId: "https://www.linkedin.com/in/userid",
  userIdType: "LINKEDIN",
  ipAddr: "156.59.87.83",
  eventId: 1231231232,
  eventAt: 639303296,
  productId: "reoWebApp",
  userAgent: "Mozilla/5.0 ...",
  meta: { property1: "value1", property2: "value2" },
});

Awaited sends (blocking: true)

Only when you need the round-trip before the process exits (CLI, Cron, Lambda-style short workers, tests) — otherwise the event loop may unwind before a fire-and-forget request completes.

const logger = new ReoProductUsageLogger({ /* ... */, blocking: true });
await logger.logUsage();
// optional: synchronous one-shot on otherwise non-blocking instances
await logger.logUsage({ blocking: true });
  • blocking on logger: Constructor sets the instance default (blocking: false for customer-facing throughput). Omit blocking on logUsage to use it; pass blocking: true on logUsage only for one-off awaited sends.

  • blocking: false: true if queued, false if opted out, invalid URL, missing API key, or body too large (not proof of HTTP 2xx).

  • blocking: true: resolved true only after HTTP 2xx (with retries).

If you omit eventId / eventAt, they are filled automatically (event_id from a time-based integer, event_at as Unix seconds). If you omit userAgent on the call, the SDK sets a default (reo-census-mcp/<version> or REO_PRODUCT_USAGE_USER_AGENT).

API key

REO_API_KEY must be set in your deployment environment or secret manager, or you must pass a non-empty apiKey when constructing ReoProductUsageLogger. Empty or whitespace-only values are treated as missing.

Opt-out

Uses the same variables as reo-census so your customers (or admins running your customer-facing software) can turn off sending — document these in your privacy or deployment guide:

  • PACKAGE_TRACKER_ANALYTICS=false
  • DO_NOT_TRACK set to 1, true, or yes (case-insensitive)

Endpoint override

export REO_CENSUS_MCP_ENDPOINT="https://your-host/api/product/usage"

Only http:// and https:// URLs with a host are accepted.

Verbose logging

export PACKAGE_TRACKER_VERBOSE=true

Prints send details to stderr.