Paigy

io.github.paigy-aiPublished by GitHub account paigy-aiv0.40.42Updated Nov 3, 2026

Lets your AI agents call you when they need a decision, and hear your answer.

Overview

AI-generated overview

Paigy is a voice inbox for AI agents: it lets an agent reach you by text, push, banner or real phone call when it needs a decision, and hear your answer back.

What you can do
  • Set up and pair an agent identity, check listening and wake status, and read built-in help
  • Ask the person questions with confirm, single, multi or ranked options, send updates and completions, and withdraw questions
  • Create, assign, defer, complete and organize Goals, and read a Goal's conversation and history
  • Read a Delivery in full, including call state, outcome and optional call transcript
  • Search the person's history across all their agents and see which agents were active in the last 24 hours
  • Send bug reports or ideas about Paigy itself to the Paigy team
When to use it
Use it when long-running or blocking agent sessions would otherwise leave you watching a terminal or returning to a stalled task. It suits people who want to be pulled in on their phone at the moment a decision is needed and to reply by voice or text.
Requirements
Runs as a local stdio process, typically via npx with the @paigy/mcp package, or through Homebrew, a Claude Code plugin, a Claude Desktop bundle or a Codex plugin. Pairing a phone is required, done with the onboard command or a pairing prompt; the native iOS app enables ringing calls. No API keys or environment variables are declared.
Before you install
Pairing links your phone and account to the agent, and the server can place real ringing calls and send push or lock-screen notifications, so urgency levels and account caps matter. Agents can create, change and close Goals and send messages to you and to the Paigy team. Feedback goes to Paigy, not to you. Smaller local models may pick answer shapes less reliably.

Installation

In SourceWeft

  1. Open Paigy in the dashboard and add it to a workspace.
  2. Enable the server for the chats that should use its tools.

Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.

Other MCP clients

Follow the launch instructions in the repository.

README

Paigy — MCP server

A voice inbox for your AI agents. When an agent needs your input — mid-task, blocked, or done with something long-running — it can place an actual phone call and read the question aloud, text, push, or ring your phone with a banner, so you can reply by voice instead of babysitting a terminal.

Without Paigy, a long agent session means one of two bad options: sit and watch the terminal so you don't miss the moment it needs you, or walk away and come back to a task that stalled an hour ago waiting on a question you never saw. Paigy closes that gap — the moment your agent actually needs a decision, your phone gets pulled into the loop with the level of urgency that matches the moment (a silent inbox card, a quiet push, a banner, or a real ringing call), so you find out immediately instead of on your next check-in. Answer by voice or text and the reply lands back with the agent exactly like any other tool response, so it just continues — no copy-pasting, no reopening the terminal. It also pairs with the native Paigy iOS app, so a call rings through like a real phone call (CallKit) even when your phone is locked, and you can glance at or reply to anything from the lock screen.

Works with

A standard MCP server (stdio, TypeScript) — no client-specific code anywhere, verified over the raw protocol against a non-Claude client identity.

  • Claude Code (this repo is also the plugin + marketplace for it)
  • Codex CLI
  • Gemini CLI
  • Any other MCP client via standard config: Cline, Continue.dev, Zed, Cursor, Goose, mcphost — including local-model setups over Ollama, LM Studio, or llama.cpp

(The app + backend live in a separate repo.)

Install

One line, any terminal — detects your agents (Claude Code, Codex, Antigravity), wires Paigy into each, and pairs your phone once. Prints every command before running it; --dry-run shows the plan:

curl -fsSL https://paigy.ai/install | sh

Prefer to do it by hand? Pick your client below.

Homebrew (macOS and Linux):

brew tap paigy-ai/mcp https://github.com/paigy-ai/mcpbrew trust paigy-ai/mcpbrew install paigy

(brew trust is how current Homebrew opts in to a tap outside homebrew-core.) Installs the server and its commands (paigy-mcp, paigy-listen, paigy-mcp-onboard, ...). Point your MCP client at paigy-mcp, then run paigy-mcp-onboard once to pair your phone.

Claude Code (plugin — easiest path on Claude):

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

Connects automatically; the first time an agent uses it while unpaired, it'll prompt you to pair — run /paigy-onboard (opens your browser to approve).

Claude Desktop (MCPB bundle — no terminal needed): download paigy.mcpb, then in Claude Desktop open Settings → Extensions and drag the file in (or double-click it). Ask Claude to "pair with Paigy" — it runs pairing itself and shows a code to approve on your phone. Also on Smithery.

Codex CLI:

codex plugin marketplace add paigy-ai/mcp --ref maincodex plugin add paigy@paigy-ainpx -y -p @paigy/mcp@latest paigy-mcp-onboard

The plugin configures the Paigy MCP server and includes guidance for calls, replies, and callbacks. Start a new Codex session after installation.

Codex CLI — direct MCP fallback:

codex mcp add paigy -- npx -y @paigy/mcp@latest

Then forward Codex's thread id into the server, so each Codex conversation gets its own Paigy identity — Codex builds the MCP server's environment from a fixed allow-list, so a variable it isn't told to pass never reaches us. Add this line under [mcp_servers.paigy] in ~/.codex/config.toml (paigy-harness setup does it for you):

toml
env_vars = ["CODEX_THREAD_ID", "CODEX_SESSION_ID"]

(Don't pass it as a -c override on mcp add — that lands before the block is written and Codex rejects the half-table with "invalid transport", writing nothing.)

Gemini CLI:

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

Any other MCP client (Cline, Continue.dev, Zed, Cursor, or a CLI that takes the standard MCP JSON config directly) — most GUI clients take this in their MCP settings (Cline: cline_mcp_settings.json; Continue: ~/.continue/config.json):

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

Then pair your phone:

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

Each session hatches its own identity automatically the first time it reaches Paigy — no agent name to set or match. (Set PAIGY_AGENT=<name> only if you deliberately want a client to always speak as one fixed named identity; then run onboard with the same name.) Approve on your phone, then sign in at paigy.ai to start receiving messages.

Heads-up for smaller/local models: the tool descriptions ask the agent to pick between a few answer shapes (confirm, options, free text) based on context — Claude follows this reliably; smaller local models may be less consistent about it. Free text always works as a fallback.

Choosing how the user answers

notify_user should ask in the shape that's fastest to answer — don't leave a decision as free text. Pick with select (and options):

You need…UseAnswer comes back as
Yes/No or Approve/Denyselect:"confirm" (confirmStyle:"approve" for Approve/Deny){kind:"confirm", approved}
Pick one of severaloptions + select:"one"{kind:"option", optionId}
Pick severaloptions + select:"many"{kind:"multi", optionIds}
Rank / order a subsetoptions + select:"rank"{kind:"ranked", optionIds}
A visual choiceoptions with an html or image previewone of the above
An open-ended replyno options{kind:"text", text}

confirm is answerable straight from the banner (Yes/No or Approve/Deny buttons). Other paiges get banner actions See Options · Hear them · Remind me later.

urgency is a request, not a guarantee — the user's account settings can cap it lower. Four levels, low to high: "inbox" (silent, sits in the inbox), "push" (a quiet passive notification, no sound), "banner" (a time-sensitive lock-screen banner with sound), "call" (rings the phone — use only when you genuinely need the user in the moment).

If you're about to start something long-running or blocking — the kind of thing where the user would otherwise sit and wait on you — mention once, in passing, that you can text or call them when it's done or if you hit a blocker. Don't offer it for quick tasks, and don't repeat the offer once they've answered.

Stalled work (automatic, no setup)

When a session stops and its agent owns Paigy Goals with no progress for three days, a Stop hook holds the stop once a day and lists them, so the agent updates, finishes or cancels each before it goes quiet. It runs paigy-stalled from @paigy/mcp (0.40.15 or later) and is silent otherwise: nothing stalled, a stop already being continued by a hook, a reminder already given that day, or any error. One script, the same hook in each harness's plugin:

  • Claude Code — hooks/hooks.json, wired by the plugin; nothing to set up.
  • Codex CLI — plugins/paigy/hooks/hooks.json, wired by the Codex plugin. Codex runs a plugin's hooks only after you trust them: review and trust the Paigy hook when Codex asks.
  • Any other harness with a Claude-style Stop hook — register npx -y -p @paigy/mcp@latest paigy-stalled as the Stop command. It reads the hook's JSON (session_id, stop_hook_active) on stdin and prints {"decision":"block","reason":…}.

Hosts with no hooks still get the list: check_replies (which the server's instructions tell every agent to call on startup and after a wake) returns it under stalled, and paigy-listen carries it in the work it hands a session it wakes.

License

MIT

Source: README.md at commit b0c96fb

Tools

10

configure

Set this agent up with Paigy — call it FIRST, before contact, and any time you're unsure who you are. One call does whatever the situation needs: NOT SET UP → if this machine holds a device credential (the user ran the Paigy desktop app or harness) it hatches an identity INSTANTLY, no code and no approval; otherwise it starts the code ceremony. ALREADY SET UP → returns your current identity and the two things left to decide, renaming it or logging out. TOKEN NO LONGER VALID → says so, then re-pairs. Pass { name, voice } to choose who you are when hatching, or to RENAME yourself when already set up (pick your own; voices: rachel, george, jessica, brian, lily). Safe to call any time: idempotent, and it never writes settings. THE CODE CEREMONY does not open a browser; the user enters the code in the Paigy app (or scans `qr`). A result with { user_code, device_code, qr, user_message } has already started polling for approval in the background: you MUST immediately print the `user_message` (the bare code) to the user, AND in that same turn call configure again with that `device_code` to collect the result. It returns the moment the user approves; on { status:'pending' } call again to keep waiting; on { status:'awaiting_confirmation' } (E2EE) show the bare `user_message` verify code and call again to finish. Every result's first text block states the code plainly. On { status:'paired' }, or whenever it returns `enable_command`, ALWAYS follow the `enable_prompt`: PRINT that command for the user to run, so Paigy's tools stop prompting each time. You cannot apply it yourself (it writes your own permission allowlist, which hosts block as privilege escalation), so print it, don't wait for it, and carry on. LOG OUT with { logOut: true }: it logs out THIS agent only — its token is revoked server-side and its local entry removed. Other agents and this device's credential are untouched, and a later configure re-hatches instantly while the device credential exists. Disconnecting

ParametersnamescopevoicelogOutdevice_code

contact

Send to and receive from the person: completions, updates, questions, answers to questions addressed to you, withdrawals, and what a question holds up. Every Goal named must exist: an unknown one refuses the whole contact. Each item applies on its own: read `results`, where a failed one names why. HOW TO ASK: 1. One question per object in `questions`, so each is answered on its own. 2. `goalId` names the existing Goal it is about (create one with manage_goals first); the answer comes back there. 3. `workItBlocks` only when you are truly blocked: it asks for a call. 4. No while-loops. While any Call is open, even one your question joined from their items, keep receiving through empty windows; otherwise stop at one: the answer reaches you on the Goal. Yield only with a listener or wakeup. 5. One question, one row: never re-send one still waiting; take back one that no longer matters with `withdrawQuestionIds`. 6. Read the Goal before asking; never re-ask what was answered or shipped. `replied` means they chose no option: it is still yours to settle. 7. Give options when you have them. Each label names its choice in full (never "Option 2"); never add "Other". `pickMode`: one (default), many, rank. 8. A diagnosis says when, why and how it happens, then proposes one fix. 9. Give a report its `reply`: one line in THEIR voice for THAT report, so you learn whether they verified it or only received it. Required when it is delivered or its Goal is done. LENGTH: the question, message or answer is the one point, at most 80 characters; the rest goes in `units`, one idea each. Over a cap is refused by name and nothing is sent. Several results are several updates. UPDATES ask nothing. One reaches the person only when they asked for it, it answers something they said, or its Goal is done; else it is kept as progress. One that reaches them joins an open report card or a live call. RECEIVING: contact({}) waits ~45 s; contact({wait:false}) returns `events` at once. Confirm the one

ParameterswaitanswersupdatesquestionsackEventIdscompletionsbumpQuestionIdswithdrawQuestionIdsquestionDependencies

manage_goals

Create, edit, assign, organize or close work. Every change here changes Goals; answering, withdrawing or asking Questions stays in contact. Each change applies independently: a refused one names why (`results[i].error`, e.g. goal_revision_conflict, goal_children_open, goal_not_found) and the rest still apply, so read every result: a partial result is never a complete success. Kinds: complete (goalId, message capped at 50 characters, units, reply, optional next-step options {label, hint}) closes and reports atomically, exactly as contact.completions; create (title, outcome, ownerId, parentGoalId, sourceEntryIds) returns the new Goal's id in `results[i].goalId`, in the order requested, to use in later calls (an outcome is one paragraph, at most 500 characters: split more into child Goals with parentGoalId); edit (title and/or outcome); state (open, completed, canceled); assign (ownerId); defer (until: the Goal waits until then and its owner is woken when it passes; null takes it back); move (parentGoalId, or null for a root: only this Goal moves); dependency (add or remove: goalId waits on dependsOnGoalId to start or to complete). A Goal cannot be completed while its required children or dependencies remain open: finish or move them first. Finishing the children does not prove the parent's own work is done. An edit applies at the version you last read: if someone changed the Goal since, it is refused as goal_revision_conflict, so read it again (get_goals) and reconsider. You may change any Goal of your person; a change puts you on it. Returns `ok` (every change applied), `results` per change (applied or failed), and `goals`, each changed Goal's id, state, title, outcome and revision.

Parameterschangesrequired

get_delivery

Read a Delivery in full: its whole ask, units, options and answers, plus current callState and callOutcome for a Call. For a Call, transcript: true adds what was said: each spoken line in order, who said it, and when from pickup, a page at a time. A line from the room, not the person, is marked room. Any agent of the same account may read it; another account is not disclosed. Reading never acknowledges or resends anything. Use this after a call or when receive names a Call you are waiting on.

ParametersafterdeliveryIdrequiredtranscript

get_goals

Read one to ten Goals by goalIds, returned in the same order under goals (a read never puts you on them). history applies to every requested Goal. A refused read fails the call with its original refusal; no partial result is presented as complete. Each Goal includes its ten most recent other contributors (names, latest entry headlines and times), outcome, state, revision, progress, blockers, the conversation on it (each question with its options and what was decided), `next`, the one step to take, and `more`, where to read further. A question in that conversation reads `open` (nothing yet), `answered` (a choice was made, and `answer` carries it), `replied` (they said something and the read settled the question on their words — NO option of yours was chosen, and the words are the reply line beside it, so read that before you act), or `closed`. The conversation carries everything the person said, every open question and your newest entry; your older entries are left out and counted — history: true reads every entry in full. Every Goal of your person is readable, whichever of their agents owns it; another account's Goals are not disclosed.

ParametersgoalIdsrequiredhistory

check_activity

Read your person's agents that contributed in the last 24 hours, newest first: at most 30 agents and their five most recently touched Goals, with their latest entry headline and time. Use get_goals to read a Goal and its other contributors before starting overlapping work. Read-only; no arguments.

Takes no parameters.

send_feedback

Send feedback about Paigy itself (a bug report, an idea) straight to the Paigy team. Send it only when the person asked you to, or agreed when you offered: it goes to Paigy, never to the person, and nobody answers it here. Not for your work or a question for the person: use contact for those. Returns whether it was stored.

Parameterskindtextrequiredtitle

help

Start here: how to use Paigy, in full — pairing, listening, receiving, asking, updates and completions, Goals and calls. Pass a topic for one section. Read-only; needs no setup.

Parameterstopic

listen

Am I listening for answers, and can Paigy resume this session? Takes no arguments. Returns status `listening` for harness delivery or a running listener with a ready wake adapter; `receiving` means a process is running but automatic resume is not confirmed (read its wake error or watch its output); `unpaired` means call configure; `start` gives the exact command to run NOW with your harness's Monitor tool (not a background command, which speaks only when it exits). Start it once. Codex queues into CODEX_THREAD_ID automatically when its CLI supports queue; PAIGY_ON_WAKE overrides it. A successful queue is not evidence the agent handled the answer: receive with contact({ wait: false }) and read the relevant Goal, then respond with contact. This tool never subscribes or starts anything itself.

Takes no parameters.

Version history

1
  1. v0.40.42LatestOct 29, 2026

Score

90% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 days25 pts
  • Auth declared10 pts

    Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.

  • Tools listedRequired15 pts
  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts