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

freeport-nostr-mcp

v0.5.0

Published

MCP server for searching Freeport Nostr events (ride requests, driver/provider offers, service & product posts, reputation) by kind, tag, and geohash radius.

Readme

freeport-nostr-mcp

An MCP server that lets AI agents search Freeport's decentralized Nostr marketplace — ride requests, driver/provider offers, service & product posts, and reputation — by kind, tag, and geohash radius. Read-only; never signs or publishes; never touches encrypted DMs.

Tools

| Tool | What it does | |------|--------------| | nostr_search_intents | Offers/requests by side + topic tags + distance radius. Decoded, expiry-filtered, sorted nearest-first. | | nostr_search_reputation | Karma ratings (kind 32103) + proven deal count (kind 32104 receipt pairs) for a pubkey. | | nostr_profile | NIP-01 profile metadata (kind 0) for any pubkey(s), optionally with recent notes. General-purpose. | | nostr_get_event | Fetch events by id. | | nostr_query_raw | Arbitrary NIP-01 filter escape hatch. |

Every query tool accepts an optional relays array to override the relay set for that call (ws/wss only, max 10, private/loopback hosts blocked).

On connect, the server sends an instructions string and exposes two resources so an agent self-onboards: freeport://relays (active relay set) and freeport://protocol (event kinds, intent schema, discovery tags, tool usage).

Example agent prompts

  • "Find ride requests within 10 km of {lat},{lon} in Hanoi." → nostr_search_intents { side:"request", near:{lat,lon,radiusKm:10}, topics:["vn_hanoi_ridesharing"] }
  • "Any plumbers offering service near me right now?" → nostr_search_intents { side:"offer", near:{...}, topics:["<area>_homeservices_plumbing"] }
  • "Is this seller trustworthy before I deal with them?" → nostr_search_reputation { pubkey }
  • "Who is npub… and what have they posted?" → nostr_profile { pubkeys:["<hex>"], recentNotes:5 }
  • "Show me everything new in my city in the last hour." → nostr_search_intents { topics:["<area>"], since:<unix-1h> }

Run

# stdio (Claude Desktop / registry self-host)
npx freeport-nostr-mcp

# hosted HTTP endpoint
PORT=8788 npm run start:http   # POST /mcp, GET /health

FREEPORT_RELAYS (comma-separated wss URLs) overrides the default relay set.

Scalability

  • One shared SimplePool — a single websocket per relay, multiplexed across all requests.
  • Short-TTL query cache + in-flight dedup — repeated/identical agent queries collapse to one relay round-trip.
  • Stateless HTTP — no per-session state; scale horizontally behind a load balancer (add a shared cache like Redis if you run multiple nodes).
  • Rate limiting (hosted endpoint) — per-IP + global token buckets return 429 with Retry-After. Tunables: RATE_LIMIT_PER_MIN (default 60), RATE_LIMIT_GLOBAL_PER_MIN (1200), RATE_LIMIT_BURST (20). Behind Cloudflare it keys on CF-Connecting-IP. /health is exempt.

Web Push notifier (same hostname)

The HTTP server also runs a self-hostable, content-blind Web Push notifier on the same host — so anyone running this becomes a push host for Freeport web/PWA users (incl. iOS 16.4+ Home-Screen installs). It does not push to the native App Store iOS app (that needs Apple's APNs key, runnable only by the app owner). Set ENABLE_NOTIFY=0 for MCP-only.

| Route | Purpose | |-------|---------| | GET /vapidPublicKey | Public key — clients create a push subscription bound to this host. | | POST /subscribe | { subscription, filters }; filters: { kinds?, topics?, near?{lat,lon,radiusKm} }. | | POST /unsubscribe | { id }. |

It watches relays for new intents matching each subscriber's filters and sends a short generic notification. Config: DATA_DIR (subscription store + VAPID keys), VAPID_SUBJECT, optional VAPID_PUBLIC_KEY/VAPID_PRIVATE_KEY to pin keys across redeploys. Stores only opaque push keys + coarse filters — no identity or message content.

Geohash radius note

Nostr relay filters match tag values exactly — no prefix/radius operator. nostr_search_intents filters by topic (#t) at the relay and refines distance client-side via haversine on each post's g tag. To push radius filtering to the relay (relaySideGeohash: true), posts must carry multi-precision geohash prefix tags; today they carry a single precision-6 g, so relay-side geohash is opt-in and a no-op until publishers add prefix tags.