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

@paigy/mcp

v0.28.0

Published

Paigy MCP server — a voice inbox for your AI agents. Lets an agent notify a user and await their reply.

Readme

@paigy/mcp

Canonical setup: curl -fsSL https://paigy.ai/install | sh — one command, one QR scan; no pairing codes. Everything below is the manual per-client reference for machines that can't run the harness.

A voice inbox for your AI agents. This MCP server lets an agent notify a user and await their reply — so a long-running agent can ask a question, hand off, and resume on the answer. It's a thin MCP-tool wrapper over @paigy/sdk (packages/sdk) — use the SDK directly from any Node process that isn't an MCP client.

Install

As a Claude Code plugin (one step)

/plugin marketplace add paigy-ai/mcp
/plugin install paigy

The Paigy MCP connects automatically. On the first Paigy interaction while unpaired, the agent shows a pairing code; approve it in Paigy. /paigy-onboard remains the terminal-only fallback.

[!NOTE] If you are installing the plugin inside an active Claude Code session, you must type /reload-plugins (or restart the session) afterward so the terminal client starts the MCP server and exposes the new tools to the agent.

Or add the MCP directly

No clone needed. Add it to Claude Code (-s user = available in every project; drop it for just the current one):

claude mcp add paigy -s user -- npx -y @paigy/mcp@latest

Or wire it into any MCP client config:

{
  "mcpServers": {
    "paigy": {
      "command": "npx",
      "args": ["-y", "@paigy/mcp@latest"]
    }
  }
}

First-time pairing (link the server to your Paigy account):

npx -p @paigy/mcp@latest paigy-mcp-onboard

It talks to the hosted backend by default — no config needed. Set PAIGY_BACKEND_URL=http://localhost:3000 only for local development.

Codex CLI (OpenAI)

Recommended: install the Paigy Codex plugin (MCP configuration plus the Paigy workflow skill):

codex plugin marketplace add paigy-ai/mcp --ref main
codex plugin add paigy@paigy-ai

Then pair your phone — under the same agent name the plugin's MCP runs as (the token is saved per agent; a mismatched name leaves Codex "not paired" against an approved pairing):

PAIGY_AGENT=codex npx -y -p @paigy/mcp@latest paigy-mcp-onboard

Or add the MCP server directly (writes ~/.codex/config.toml):

codex mcp add paigy --env PAIGY_AGENT=codex -- npx -y @paigy/mcp@latest

Or add the entry to ~/.codex/config.toml by hand:

[mcp_servers.paigy]
command = "npx"
args = ["-y", "@paigy/mcp@latest"]
env = { PAIGY_AGENT = "codex" }

Then pair: PAIGY_AGENT=codex npx -p @paigy/mcp@latest paigy-mcp-onboard (or have the agent call the pair tool — it pairs under its own name automatically).

Gemini CLI

gemini mcp add -s user -e PAIGY_AGENT=gemini paigy npx -y @paigy/mcp@latest

-s user makes it available across all projects — omit it for just the current one. Or add the entry to ~/.gemini/settings.json:

{
  "mcpServers": {
    "paigy": {
      "command": "npx",
      "args": ["-y", "@paigy/mcp@latest"],
      "env": { "PAIGY_AGENT": "gemini" }
    }
  }
}

Then pair: PAIGY_AGENT=gemini npx -p @paigy/mcp@latest paigy-mcp-onboard.

PAIGY_AGENT names the agent AND keys its token slot (defaults to mcp-agent). Each client reads only its own slot, so pair with the same PAIGY_AGENT the client's config uses — and set it per client so you can tell your connected agents apart.

Tools

  • pair — pair this agent with the user's Paigy account (one-time). No args to start: returns the code to show the user and begins polling for approval in the background; pass the returned device_code to collect the result (it returns the moment the user approves). On success it prompts you to allowlist Paigy's notify/await tools so they run without an approval prompt each time.
  • unpair — log this agent out of the user's Paigy account; revokes the token server-side and deletes the local one.
  • enable_tools — after pairing (and only with the user's consent), allowlist Paigy's notify/await tools so they run without an approval prompt each time. Writes Claude Code's permissions.allowscope:'user' (default, every project) or scope:'project' (this repo). Merges, never clobbers; leaves pair/unpair human-approved.
  • contact — THE way to reach the user: tell them something, or ask and get their answer. Core form is two fields — ask (plain prose: what you need to tell them or find out) and waiting (what happens to your work meanwhile: none = just informing, soft = want an answer but can keep working, hard = stopped until answered — reaches them urgently and escalates to a real phone call). Paigy's broker picks the channel, phrasing, and answer format. When the choices themselves must be seen, attach options (each may carry a sandboxed html or image preview); attach visuals for context screenshots. Returns { notificationId, threadId }; a threaded follow-up supersedes that thread's pending items, and an identical threaded re-send escalates in place. If a reply comes back as {kind:'clarify', chunks:[...]}, contact again on the SAME threadId with an expanded ask. (The former notify_user/notify names remain accepted as hidden aliases for older setups, and the fully-shaped wire form — context/select/urgency — is still accepted from code; neither is part of the model surface anymore.)
  • await_reply — wait for the user's reply to a specific notification (pass its notificationId). Scoped: will not return replies meant for other notifications. Returns reply / remind / idle.
  • check_replies — catch-up sweep: returns replies you haven't consumed yet (now marked seen) plus still-pending notifications, new user-initiated requests, and owed callbacks.
  • set_task_state — report progress on a request: in_progress / completed / needs_input.
  • schedule_callback — promise the user a follow-up (on_done / on_blocked / scheduled) so it's not dropped if you go idle.

Configuration

  • PAIGY_BACKEND_URL — the Paigy API base (defaults to the hosted backend).
  • HTTPS_PROXY / HTTP_PROXY / NO_PROXY — honored for every REST call, with curl's semantics. Node's fetch ignores these (unlike curl), so the server wires them up itself; in environments where egress only flows through a proxy (Claude Code on the web, corporate CI), calls route through it automatically — no extra setup. Two edges: with HTTP_PROXY set, an http://localhost backend proxies too unless NO_PROXY=localhost (hostname entries work; CIDR ranges are ignored), and paigy-listen's realtime wake channel is a websocket that doesn't proxy — its REST sweeps do.

Wake any harness (paigy-listen)

paigy-listen is the self-hosted push daemon: it subscribes to this connection's wake channel and sweeps on every nudge. Keep it alive past the terminal with paigy-listen --install (launchd on macOS, systemd user unit on Linux; --uninstall removes it).

To launch an agent — any agent, not just Claude — when work arrives, set PAIGY_ON_WAKE to a command before --install. The sweep has already claimed the work, so the launcher reads it from the environment rather than calling check_replies again:

| Variable | What it holds | | --- | --- | | PAIGY_WORK | the whole swept payload as JSON (replies, requests, owedCallbacks, stalled, threads) | | PAIGY_EVENT | the wake that caused this run — boot, wake:reply, cron:callback… | | PAIGY_THREAD_ID | the thread to continue on | | PAIGY_NOTIFICATION_ID | the notification being answered or acted on (unset for an owed callback) | | PAIGY_CONTEXT_THREAD_ID | a past conversation the user seeded this with — get_thread it first | | PAIGY_TEXT | what the user said (or the callback note you owe them), in prose |

Hand $PAIGY_WORK to a harness that can read JSON and decide for itself; use the scalars for a plain shell launcher that shouldn't need jq. They describe one item — the oldest thread without a turn already in flight — because the queue rail's contract is one thread at a time. An absent fact is unset rather than empty, so ${PAIGY_CONTEXT_THREAD_ID:-} distinguishes "no seed" from "seeded with nothing".

# Claude Code — hand it everything and let it plan:
PAIGY_ON_WAKE='claude -p "Handle the Paigy work in $PAIGY_WORK — rehydrate threads you do not recognize via get_thread first."' \
  npx -y -p @paigy/mcp paigy-listen --install

# Codex (or any CLI harness) — the scalars are enough for a one-liner:
PAIGY_ON_WAKE='codex exec "Continue Paigy thread $PAIGY_THREAD_ID. The user said: $PAIGY_TEXT. Call get_thread on it first if you do not recognize it, then reply with contact."' \
  npx -y -p @paigy/mcp paigy-listen --install

$PAIGY_TEXT is whatever the user said, expanded inside a shell command — keep it quoted, as above. For anything longer than a one-liner, point PAIGY_ON_WAKE at a script and branch on $PAIGY_EVENT there:

#!/bin/sh
# ~/.paigy/on-wake.sh — chmod +x, then PAIGY_ON_WAKE=~/.paigy/on-wake.sh
seed=""
[ -n "${PAIGY_CONTEXT_THREAD_ID:-}" ] && seed="It continues thread $PAIGY_CONTEXT_THREAD_ID — get_thread that first."

case "$PAIGY_EVENT" in
  cron:callback*) codex exec "You owe the user a callback on thread $PAIGY_THREAD_ID: $PAIGY_TEXT. Deliver it with contact." ;;
  *)              codex exec "Paigy thread $PAIGY_THREAD_ID. The user said: $PAIGY_TEXT. $seed Reply with contact when done." ;;
esac

Statusline (Claude Code)

paigy-statusline prints a one-line connection status — the account's session mode and whether a phone is paired — for Claude Code's status bar:

paigy: all calls · phone ✓

Enable it in ~/.claude/settings.json:

"statusLine": { "type": "command", "command": "npx -y -p @paigy/mcp@latest paigy-statusline" }

It reads GET /api/status with the pairing token and caches the result in ~/.paigy/status.json for 60 seconds, so the bar's constant refreshes never hammer the API; when offline it shows the last known state. paigy: unpaired means there's no token (or the pairing was revoked) — run /paigy-onboard to pair; paigy: … means the status isn't known yet (first run while offline).

Publishing (maintainers)

Tool input schemas are generated from zod in src/schema.ts as draft-2020-12 JSON Schema, and src/schema.test.ts guards that every tool stays valid (strict clients like the Anthropic API reject anything else). A schema fix only reaches agents once a new version is published to npm — 0.8.0 once shipped without a committed fix and 400'd strict clients for weeks. So after any change under src/schema* or the tool definitions: bump the version and pnpm publish (don't rely on the commit alone). Install recipes pin @paigy/mcp@latest so a fresh npx picks up the new version; if a stale one sticks, rm -rf ~/.npm/_npx and restart the client.

License

MIT