How it works
How Pushary works for AI agents. A hosted MCP server your agent calls, hooks that hold risky actions until you approve, API key auth, limits and tools.
Pushary runs a hosted Model Context Protocol (MCP) server. MCP is the standard way an AI agent calls outside tools. Your agent connects over HTTPS and gets tools such as send_notification and ask_user. Pushary delivers each call to your phone app, browser or Mac. For agents with hooks, Pushary also holds a risky action until you approve it.
Set it up with one command. It connects your agents, saves your API key and pairs your phone:
npx pushary@latest setupArchitecture
AI agent (Claude Code, Codex, Cursor, ChatGPT, ...)
|
| MCP over HTTPS (Streamable HTTP)
v
https://pushary.com/api/mcp/mcp
|
+--> Pushary phone app (iOS and Android)
+--> Push notifications in your browser
+--> Mac app (Pushary Isle)
+--> Slack approvals, if you connected SlackYour answer travels back the same way. Answer on your phone and the agent's waiting ask_user call returns it, for example "value": "yes".
The agent tools (ask_user, send_notification and the rest) run on the Pushary server and share one question store with the REST endpoint POST /api/v1/server/ask. The push platform tools (subscribers, campaigns, templates, flows) call the REST API at https://pushary.com/api/v1/server.
Agents reach Pushary in two ways.
MCP tools: the agent decides to ask
The agent calls ask_user when it needs a decision, and send_notification when work finishes or fails. Every MCP client can do this, but the agent chooses when. This is the cooperative path.
Hooks: Pushary steps in before an action
For agents with hooks, such as Claude Code, Codex, Gemini CLI and Cursor, the setup command installs Pushary's hook. A hook is a small program the agent runs before each tool call:
Agent is about to run a tool (for example Bash: git push --force)
-> the Pushary hook reads the tool call on stdin
-> fetches your permission policy from /api/mcp/policy
-> if the policy needs you, asks your phone and waits
-> returns allow or deny, or hands the call to the agent's own promptIf Pushary cannot be reached, the hook gives no opinion and the agent's own prompt decides. What happens when you do not answer depends on your policy. By default the agent's own prompt takes over, as described in When you don't answer. The supported agents table lists which agents have hooks.
Connect an MCP client
Streamable HTTP (recommended)
Most MCP clients accept a URL and a header:
{
"pushary": {
"url": "https://pushary.com/api/mcp/mcp",
"headers": {
"Authorization": "Bearer pk_xxx.xxx"
}
}
}stdio via mcp-remote
For a client that only supports stdio, use the mcp-remote bridge:
{
"pushary": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://pushary.com/api/mcp/mcp",
"--header",
"Authorization:Bearer pk_xxx.xxx"
]
}
}Claude and ChatGPT
Claude.ai, Claude Desktop and ChatGPT cannot send a header. You add Pushary there as a custom connector and sign in to your Pushary account instead. Follow the Claude setup guide or the ChatGPT setup guide.
Add the Pushary skill
The skill teaches your agent when to notify you and when to ask:
npx skills add pushary/pushary-skillIt works with Claude Code, Codex, Cursor, Windsurf and the other agents listed on skills.sh. It includes the tool documentation and guidance on when a notification is worth sending.
Authentication
Every request sends your API key as a Bearer token:
Authorization: Bearer pk_xxx.xxxA key is pk_ plus 24 hex characters, a dot, then a 48 hex character secret. It belongs to one workspace's agent site, and Pushary shows it only once, when it is created. See Get your API key.
- A missing, wrong or revoked key gets HTTP 401, and every tool call fails.
- A workspace with no active plan or trial gets HTTP 403 with
"code": "subscription_required".ask_user,send_notificationandpropose_scopestop working.wait_for_answerandcancel_questionstill work, so an agent can close out a question it already asked.
How Pushary tells sessions apart
When you run several agents at once, Pushary keeps them apart. The hook sends two fields with every call:
sessionId: one per agent window, taken from the agent.machineId: a random ID the CLI creates once and stores in~/.pushary/machine-id.
The pair identifies each session. Two Claude Code windows in the same repo show up as two sessions, and a blocked approval points at the exact one that raised it. See the Multi-Agent Control Panel.
Task titles and privacy
For Claude Code, setup also registers a UserPromptSubmit hook. When you submit a prompt, the hook sends its first 120 characters to Pushary as the session's task title. The dashboard then shows what each session is working on instead of a bare session ID. Each new prompt replaces the title.
The CLI hook sends no other prompt text unencrypted. Approval requests do carry the command or diff you are asked to approve, with secrets redacted.
Sessions that Pushary launches, such as one you start from your phone, sync a transcript by default. It is redacted on your machine and encrypted there, for your phone and for Pushary's documented compliance recovery, before upload.
Turn off task titles
Set this where your agent runs:
export PUSHARY_TASK_TITLES=offWith titles off, the hook still reports that a prompt was submitted, so the session shows as active. It sends no prompt text at all.
Turn off transcript sync
Run this on the agent machine:
npx pushary@latest setup --transcripts offSetting PUSHARY_TRANSCRIPTS=off in the agent's environment does the same.
Rate limits
Questions and notifications from the agent tools have their own limits. A burst of parallel agents still gets through, and one runaway agent is still capped:
- 3 pending questions per agent session
- 25 pending questions per site
- 10 notifications per 5 minutes per site
A question frees its slot when it is answered, cancelled or expires. Ordinary full-access MCP questions without a host deadline stay answerable and keep their slots until answered or cancelled. Restricted connectors, REST asks and native permission hooks retain their existing deadlines.
Connector keys get their own counters, so a leaked connector link cannot use up the limit your CLI agents rely on. REST calls to /api/v1/server also have a per-plan request limit, for example 120 requests a minute on the Agent plan. See Pricing and limits.
Which tools your key gets
A connector key gets the five agent tools. A key from setup or phone pairing adds list_sessions. A key you create in Settings > API keys also gets the push platform tools. The Partner and Enterprise plans add durable decisions for your own end users.
| Category | Tools | What they do |
|---|---|---|
| Notifications | send_notification | Send a push notification, with optional rich context |
| Human in the loop | ask_user, propose_scope, wait_for_answer, cancel_question | Ask a question, agree a run's scope, wait for the answer, retract a question |
| Sessions | list_sessions | Read the live list of agent sessions (not connector keys) |
| Subscribers | list_subscribers, get_subscriber, count_subscribers | Look up browser subscribers |
| Campaigns | list_campaigns, create_campaign, get_campaign, send_campaign, pause_campaign, get_campaign_stats | Create and manage campaigns |
| Templates | list_templates, create_template | Reusable notification templates |
| Flows | list_flows, create_flow, activate_flow, pause_flow | Automation flows, such as a welcome series |
| Partner decisions | enroll_end_user, create_decision, get_decision, cancel_decision | Connect an end user and collect a durable decision |
Next steps
Run the quickstart
Connect your agent and get your first approval on your phone.
Ask for approval from your agent
Use ask_user, read the answer, and handle a question nobody answered.
Read the tools reference
Every MCP tool, argument and return field.