New:Microsoft Teams Notifications Are Now Available in Socket.Learn more →
Get Started

@paigy/mcp

Package Overview
Dependencies
Maintainers
1
Versions
66
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@paigy/mcp

Paigy MCP server — the AI agent harness that calls you. Lets an agent notify a user and await their reply.

latest
Source
npmnpm
Version
0.40.17
Version published
Weekly downloads
0
Maintainers
1
Weekly downloads
 
Created
Source

@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.

The AI agent harness that calls you. 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

One catalog, on every transport (2026-09-11): the agent tools are AGENT_TOOLS in packages/schema/src/tools.ts — contact, check_replies, create_goal, claim_goal, get_goal, update_goal — and both this server and the hosted MCP (apps/api/src/mcp) publish that list and dispatch it through the SDK's one runTool. This server adds only onboard, pair and unpair, the tools that mint and delete the token file this machine holds. See the SDK contract for the single-Goal start shape. Notification returns immediately. Call holds one cancellable ~45-second window here (the hosted transport returns after one read); continue with contact({deliveryId}) without sending another ask. Durable Entries and accepted answers can repeat on reads; check_replies lists every open Delivery addressed to you (a request the user started toward you, an answer relayed to something you asked, a handoff) without consuming any of it, and claim_goal is the catch-up for your own Goals. Bookkeeping ids (operationId, idempotencyKey) are minted here, never asked of the model. Retired reply-lease/ACK/work/callback tools and hidden notification aliases are rejected.

The standalone listener below is still a legacy host and target-release blocker. Its old reply intake must migrate before enabling it against the target runtime; it is not a compatibility fallback for target MCP tools.

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 reads do.

Wake any harness (paigy-listen)

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

The read is check_replies — the open Deliveries addressed to this agent — and it consumes nothing: no lease, no acknowledgement, and the same read twice returns the same list. So the daemon hands the launcher what it found and stops there; claiming is the agent's own first act (claim_goal), because the daemon shares this machine's token with the agent it launches and a second claimer on one identity eats the first one's claim.

To launch an agent — any agent, not just Claude — when work arrives, set PAIGY_ON_WAKE to a command before --install:

VariableWhat it holds
PAIGY_WORKeverything the wake found, as JSON (deliveries, goal)
PAIGY_EVENTthe wake that caused this run — boot, wake:reply, wake:request…
PAIGY_PARENT_IDthe thread to continue on (PAIGY_THREAD_ID is the same value, for existing scripts)
PAIGY_DELIVERY_IDthe Delivery being acted on — contact({deliveryId}) rereads it
PAIGY_GOAL_IDthe Goal it belongs to — claim_goal it first
PAIGY_TEXTwhat the person said, 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 open Delivery — because the contract is one thread at a time. An absent fact is unset rather than empty, so ${PAIGY_GOAL_ID:-} distinguishes "no Goal" from "an empty id".

# Claude Code — hand it everything and let it plan:
PAIGY_ON_WAKE='claude -p "Handle the Paigy work in $PAIGY_WORK — claim_goal first, and read a Goal you do not recognize with get_goal."' \
  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 "Claim Paigy goal $PAIGY_GOAL_ID and continue thread $PAIGY_THREAD_ID. The user said: $PAIGY_TEXT. Reply with contact."' \
  npx -y -p @paigy/mcp paigy-listen --install

A session that starts listening (listen, #2265)

Nothing pushes an answer into a session started in a terminal — it waits for that session's next check_replies. What can reach a running session mid-turn is a watched background task, so a terminal session runs paigy-listen --brief as its own watched task (one human line per event: Paigy · wake:reply · 2 waiting · lead <deliveryId> on Goal <goalId>: "…"). The listen tool is how a session asked to "start listening" gets there in one call: it decides and hands over — listening (nothing to do), unpaired (call onboard), or start with the exact command (this server's own node and listen.js, PAIGY_AGENT and PAIGY_SESSION_ID set to this session's slot and id — a session-bound identity is refused from any other) for the agent to run as its background task in the same turn. It never subscribes, spawns or writes settings. "Already running" is a fact: the daemon marks its pid under ~/.paigy/listen/<slot>.pid while it runs. A session started by the Paigy harness (paigy-harness host / run) needs none of this — its pump types each answer in as it lands, and listen says so.

$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
codex exec "Paigy goal $PAIGY_GOAL_ID. claim_goal it first. The user said: $PAIGY_TEXT. Reply with contact when done."

Stalled work (Claude Code stop hook)

An agent that goes quiet leaves its Goals behind. Three things hand it that work back, all reading one rule (no progress for 3 days, COLD_AFTER_MS): check_replies lists it under stalled, paigy-listen carries it in PAIGY_WORK (and launches for it on boot), and this hook holds a Claude Code session's stop once a day to list it:

{ "hooks": { "Stop": [{ "hooks": [{ "type": "command", "command": "npx -y -p @paigy/mcp paigy-stalled" }] }] } }

It is silent when nothing is stalled, when the stop is already being continued by a hook, and after it has reminded that session once today.

Statusline (Claude Code)

paigy-statusline prints which Paigy identity this Claude Code session is, for the status bar:

paigy: Marlow

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

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

It reads only ~/.paigy — no network. paigy: paired · session hatches on first use means the machine is paired and this session's identity is minted by its first tool call; paigy: unpaired means there's no token — run /paigy-onboard to pair.

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

FAQs

Package last updated on 25 Sep 2026

Related posts