# Pushary (remote · pushary.com)

Notify me when my agent needs me: approve from my phone, answer questions away from the terminal.

- Trust score: 76/100 (medium)
- Change this week: +54
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- remote · `pushary.com`: 76/100 (this document), [markdown](https://verifymcp.io/servers/pushary-pushary/api-mcp-mcp.md), [page](https://verifymcp.io/servers/pushary-pushary/api-mcp-mcp)
- remote · `pushary.com`: 22/100, [markdown](https://verifymcp.io/servers/pushary-pushary/api-mcp-sse.md), [page](https://verifymcp.io/servers/pushary-pushary/api-mcp-sse)

## Channel facts

- Endpoint: `https://pushary.com/api/mcp/mcp`
- Transports: `streamable-http`
- Auth: `required`
- Version: `1.1.0`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Endpoint Security**: 89/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - Authorisation is enforced on tool calls, but the challenge carries no valid RFC 9728 metadata, so a client cannot discover where to get a token.
  - HTTPS is enforced; there's no plaintext access path.
  - The HSTS (Strict-Transport-Security) header is present.
  - DNSSEC check failed: this domain isn't protected by DNSSEC.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 64/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 4183 tokens (~199/item across 21 items; 21 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 17/100
  - Stability observed for 5 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add --transport http pushary-pushary https://pushary.com/api/mcp/mcp
```

### Codex

```toml
[mcp_servers.pushary-pushary]
url = "https://pushary.com/api/mcp/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "pushary-pushary": {
      "type": "remote",
      "url": "https://pushary.com/api/mcp/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add pushary-pushary --url https://pushary.com/api/mcp/mcp --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  pushary-pushary:
    url: "https://pushary.com/api/mcp/mcp"
```

### Other

```json
{
  "mcpServers": {
    "pushary-pushary": {
      "type": "http",
      "url": "https://pushary.com/api/mcp/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 76, +1)

No change was recorded against any check on this day. Stability & Change Management went from 13 to 17. That category is still filling its 30-day observation window: 4 days of observed history at the previous scan, 5 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-08-02 (score 75, 0)

- [security] Tool “ask_user” rewrote its description, which is the text the model reads

### 2026-08-01 (score 75, +1)

No change was recorded against any check on this day. Stability & Change Management went from 7 to 10. That category is still filling its 30-day observation window: 2 days of observed history at the previous scan, 3 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-07-31 (score 74, +5)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 69, +1)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-29 (score 68, +46)

- [security improvement] Transport: unverified → pass
- [security] Authorization: Authorisation is enforced on tool calls, but the challenge carries no valid RFC 9728 metadata, so a client cannot discover where to get a token.
- [functional improvement] MCP protocol: unverified → pass
- [functional improvement] Tool coverage: unverified → 100
- [functional] First check of Tool coverage: 100
- [functional] First check of Schema quality: excellent
- [functional] First check of Schema quality: fail
- [functional] First check of Schema quality: fail

### 2026-07-27 (score 22, 0)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-26 (score 22)

First indexed and scored.

## MCP tools (21)

### `send_notification` (~552 tokens)

Send Push Notification

Send a one-way push notification to the user's phone and browser. Nothing is awaited; use ask_user instead when you need an answer back. Reach for this when a long-running task finishes and the user asked to be told, when the agent hits an error it cannot resolve on its own, or for any "notify me when my agent needs me" moment while the user is away from the terminal. By default the notification reaches every device connected to the site; narrow delivery with subscriberIds, externalIds, or tags. The optional context object turns the tap-through into a rich detail page (summary, bullet details, changed files, error info, next steps), and context.askQuestion embeds a decision prompt on that page, returning a linkedCorrelationId you can poll with wait_for_answer. Returns per-channel delivery counts for web and mobile, plus a warning when zero devices are connected. Works from Claude Code, Codex, Cursor, Hermes, or any MCP client; no Claude subscription is required. SIDE EFFECT: delivers real notifications to real devices immediately.

Input parameters:

- `agentName` (string): Name of the agent sending this notification, format "{Agent} - {project}" (e.g. "Claude Code - myproject"). Shown in the notification so the user knows which session is talking. Falls back to the MCP…
- `body` (string, required): Notification body text (max 500 chars). One or two sentences the user can act on without opening anything.
- `context` (object): Structured context rendered as a rich detail page when the user taps the notification. Strongly recommended for task_complete and error notifications so the user can act from their phone.
- `externalIds` (array): Deliver only to subscribers matching these external IDs.
- `iconUrl` (string): URL of the notification icon image
- `imageUrl` (string): URL of a large image shown in the notification
- `machineId` (string): Stable machine id of the sending agent, so two machines never collapse into one session.
- `sessionId` (string): Opaque per-session id of the sending agent, so parallel sessions are attributed separately in the activity feed.
- `subscriberIds` (array): Deliver only to these subscriber IDs. Omit all targeting fields to reach every connected device.
- `tags` (array): Deliver only to subscribers that have any of these tags.
- `title` (string, required): Notification title shown on the lock screen (max 100 chars). Lead with the outcome, e.g. "Build finished" or "Migration failed".
- `url` (string): URL opened when the user taps the notification. Ignored if context is provided, because a context detail page URL is generated automatically.

### `list_subscribers` (~154 tokens)

List Subscribers

List push notification subscribers for the site, with optional filters. Use it to find who can receive notifications, look up a subscriber ID for targeted delivery, or audit subscription health by status. Returns a paginated list; pass the cursor from the response to fetch the next page.

Input parameters:

- `cursor` (string): Pagination cursor from a previous response
- `externalId` (string): Look up the subscriber mapped to this external ID from your own system
- `limit` (integer): Number of results per page (default 20, max 100)
- `status` (string): Filter by subscription status. Only "active" subscribers can receive notifications.
- `tags` (array): Only return subscribers that have any of these tags

### `get_subscriber` (~71 tokens)

Get Subscriber

Get full details of a single subscriber by ID: browser, OS, location, tags, subscription status, and activity. Use it to inspect one recipient before targeting them or to debug why a device did not receive a notification.

Input parameters:

- `id` (string, required): The subscriber ID, as returned by list_subscribers

### `count_subscribers` (~53 tokens)

Count Subscribers

Get subscriber counts for the site broken down by status: total, active, and unsubscribed. A quick way to check audience size before sending, or to verify that at least one device is subscribed. Takes no parameters.

### `list_campaigns` (~94 tokens)

List Campaigns

List push notification campaigns in reverse chronological order, including each campaign's status (draft, scheduled, sending, sent, paused). Use it to find a campaign ID before calling get_campaign, send_campaign, or get_campaign_stats. Paginated; pass the cursor from the response to fetch the next page.

Input parameters:

- `cursor` (string): Pagination cursor from a previous response
- `limit` (integer): Number of results per page

### `create_campaign` (~245 tokens)

Create Campaign

Create a push notification campaign in draft status. Nothing is delivered yet: send it with send_campaign, or set scheduledAt to queue it for a future time. Use campaigns instead of send_notification when the message targets an audience segment and you want delivery stats afterwards. SIDE EFFECT: creates a new campaign resource.

Input parameters:

- `actionUrl` (string): URL opened when the notification is clicked
- `body` (string, required): Notification body text (max 500 chars)
- `iconUrl` (string): Notification icon URL
- `imageUrl` (string): Large image URL shown in the notification
- `name` (string, required): Internal campaign name for identification. Not shown to subscribers.
- `scheduledAt` (string): ISO 8601 datetime to schedule delivery (e.g. 2026-03-01T10:00:00Z). Omit to keep the campaign as a draft you send manually.
- `segmentId` (string): Target a specific subscriber segment by ID
- `tags` (array): Target subscribers with any of these tags. Omit all targeting to reach every active subscriber.
- `title` (string, required): Notification title shown to subscribers (max 100 chars)

### `get_campaign` (~70 tokens)

Get Campaign

Get full details of a campaign by ID: content, status, targeting, schedule, and delivery counts. Use it to verify a draft before send_campaign or to check the state of a campaign you sent earlier.

Input parameters:

- `id` (string, required): The campaign ID, as returned by list_campaigns or create_campaign

### `send_campaign` (~74 tokens)

Send Campaign

Send a draft or scheduled campaign immediately, skipping any schedule. Confirm the campaign content and targeting with get_campaign first. SIDE EFFECT: triggers push notification delivery to all targeted subscribers. This action cannot be undone; consider asking the user with ask_user before sending on their behalf.

Input parameters:

- `id` (string, required): The campaign ID to send

### `pause_campaign` (~64 tokens)

Pause Campaign

Pause an active or currently sending campaign. Use it to stop a campaign that was sent by mistake or needs a content fix. SIDE EFFECT: halts further notification delivery for this campaign; notifications already delivered cannot be recalled.

Input parameters:

- `id` (string, required): The campaign ID to pause

### `get_campaign_stats` (~51 tokens)

Get Campaign Statistics

Get delivery statistics for a campaign: sent, delivered, clicked, and failed counts plus their rates. Use it after send_campaign to report how a campaign performed.

Input parameters:

- `id` (string, required): The campaign ID

### `list_templates` (~71 tokens)

List Templates

List reusable notification templates for the site. Use it to find an existing template before creating a duplicate with create_template. Paginated; pass the cursor from the response to fetch the next page.

Input parameters:

- `cursor` (string): Pagination cursor from a previous response
- `limit` (integer): Number of results per page

### `create_template` (~134 tokens)

Create Template

Create a reusable notification template so the same title, body, and imagery can be reused across campaigns without retyping. Nothing is sent by this call. SIDE EFFECT: creates a new template resource.

Input parameters:

- `actionUrl` (string): URL opened when the notification is clicked
- `body` (string, required): Notification body text (max 500 chars)
- `iconUrl` (string): Notification icon URL
- `imageUrl` (string): Large image URL shown in the notification
- `name` (string, required): Internal template name for identification. Not shown to subscribers.
- `title` (string, required): Notification title (max 100 chars)

### `list_flows` (~106 tokens)

List Flows

List automation flows for the site, optionally filtered by status. Use it to find a flow ID before calling activate_flow or pause_flow, or to check what automations are currently running. Paginated; pass the cursor from the response to fetch the next page.

Input parameters:

- `cursor` (string): Pagination cursor from a previous response
- `limit` (integer): Number of results per page
- `status` (string): Filter by flow status. Only "active" flows process subscriber events.

### `create_flow` (~145 tokens)

Create Flow

Create an automation flow that sends notification sequences in response to subscriber events, such as a welcome series after subscription or a follow-up after a notification click. The flow is created in draft status and does nothing until activate_flow is called. SIDE EFFECT: creates a new flow resource.

Input parameters:

- `description` (string): What this flow does, for humans reading the dashboard
- `name` (string, required): Flow name for identification
- `steps` (array): Ordered list of flow steps
- `triggerCampaignId` (string): Scope notification-based triggers (click, impression, dismiss) to a specific campaign ID
- `triggerType` (string, required): Subscriber event that starts the flow for that subscriber

### `activate_flow` (~61 tokens)

Activate Flow

Activate a draft or paused flow so it starts running. Review the flow steps first with list_flows or the dashboard. SIDE EFFECT: the flow begins processing subscriber events and sending its notifications automatically until paused.

Input parameters:

- `id` (string, required): The flow ID to activate

### `pause_flow` (~73 tokens)

Pause Flow

Pause an active flow so it stops reacting to subscriber events. Use it to halt an automation that is misfiring or no longer wanted; reactivate later with activate_flow. SIDE EFFECT: stops the flow from processing new events. In-progress executions may still complete.

Input parameters:

- `id` (string, required): The flow ID to pause

### `ask_user` (~1065 tokens)

Ask User a Question

Ask the user a question as a push notification on their phone and block until they answer. Reach for this whenever you need the user's decision and they may be away from the terminal: approving a risky or irreversible step (deleting files, force pushing, spending money, sending external messages), picking between implementation options, or supplying missing input. The user answers from the lock screen or a decision page; you do not need a separate wait_for_answer call because this tool waits by default. Three question types: "confirm" (yes/no), "select" (2 to 6 fixed choices), "input" (free text). Timing: a single call blocks for at most 55 seconds, but the question itself stays answerable for 10 minutes. On { answered: true } the response carries value with the user's choice or text. On { answered: false, timedOut: true } keep the returned correlationId and call wait_for_answer with it, retrying up to 3 times with timeoutMs 55000, before falling back to asking in the terminal. Every response carries answerUrl, the signed-in dashboard page where this question is waiting. When you report that you are waiting, print that URL to the user so they can answer from a browser instead of hunting for it. Works from Claude Code, Codex, Cursor, Hermes, or any MCP client; no Claude subscription is required. SIDE EFFECT: sends a real push notification.

Input parameters:

- `action` (string): The concrete operation about to happen, one line. Shown as the Action line.
- `actionBody` (string): The diff (Edit/Write) or full command (Bash/apply_patch), secret-redacted and size-capped. Rendered as a collapsible detail block; never used as the push body.
- `agentName` (string): Name of the agent asking, format "{Agent} - {project}" (e.g. "Claude Code - myproject"). Shown in the notification title so the user knows which session needs them. Falls back to the MCP client name…
- `blocker` (string): The single gating reason the agent stopped, one line. Shown as the Blocker line.
- `callbackUrl` (string): Webhook URL that receives a POST with the answer when the user responds, signed with the X-Pushary-Signature header. Useful when the agent process may exit before the answer arrives.
- `context` (string): One or two sentences about what the agent is working on, shown above the question so the user can decide without opening the terminal.
- `externalIds` (array): Deliver only to subscribers matching these external IDs.
- `intent` (string): The user's stated task (from their last prompt), one line. Shown as the Intent line so the user can see why the agent stopped.
- `machineId` (string): Stable machine id of the asking agent, so two machines never collapse into one session.
- `options` (array): The 2 to 6 choices for a select question. Required when type is "select", ignored otherwise. The answered value is the chosen option string.
- `placeholder` (string): Hint text shown inside the free-text field for input questions
- `question` (string, required): The question shown on the user's lock screen (max 500 chars). Phrase it so it is answerable at a glance; put background in context instead.
- `repoKey` (string): Stable repository identity for the working directory, e.g. "github.com/acme/api". Lets an approval routing rule scoped to one repository avoid governing another. Optional; omit it and only workspace-…
- `scopePath` (string): Set ONLY when this approval exists because the path falls outside the scope the user ratified via propose_scope. Approving then widens the run scope to include this exact path, so the user is not ask…
- `sessionId` (string): Opaque per-session id of the asking agent, so parallel sessions are attributed separately.
- `subscriberIds` (array): Deliver only to these subscriber IDs. Omit all targeting fields to reach every connected device.
- `tags` (array): Deliver only to subscribers that have any of these tags.
- `timeoutMs` (integer): How long this call blocks, in milliseconds (max 55000). Defaults to the site policy timeout. The question stays open for 10 minutes regardless, so a timeout here is not a refusal; follow up with wait…
- `toolName` (string): The tool this approval is for (e.g. "Bash"), so the user can choose to always-allow it.
- `toolTarget` (string): Compact target of the tool call (e.g. the command head "git push" for Bash, or a file extension like ".ts" for Edit/Write). Used to mine policy suggestions.
- `type` (string): Question type: confirm renders yes/no buttons, select renders the options list, input renders a free-text field.
- `wait` (boolean): true (default) blocks until the user answers or the timeout fires. Set false to return immediately with a pending correlationId and poll it yourself via wait_for_answer.

### `propose_scope` (~421 tokens)

Propose Run Scope

Propose what this run will touch and block until the user ratifies it. Call ONCE at the start of a multi-step run, before doing work. The user sees the paths you intend to change, the areas you promise to leave alone, and your definition of done, and approves the whole thing in one tap. After that, editing a file outside the agreed scope stops being auto-approvable: it becomes a separate "wants to widen scope" question instead of a silent approval, so you are asked once about the boundary rather than repeatedly about each file. Use glob syntax ("src/**", "**/*.test.ts"). Shell commands are NOT scoped here, they stay governed by the permission policy. Scope lives for this session only and is never inherited by another run. Returns { ratified, answered, value }; ratified:true means the contract is live. If the user declines, do not proceed as if they had agreed, ask them what scope they want. SIDE EFFECT: sends a real push notification.

Input parameters:

- `agentName` (string): Name of the agent asking, format "{Agent} - {project}".
- `allowedPaths` (array): Globs you intend to change, e.g. ["src/**", "docs/*.md"]. Omit or leave empty to propose no path restriction, which the user is told plainly.
- `doneWhen` (string, required): What "finished" means for this run, one or two lines. Carried for the human to judge against; never enforced automatically.
- `machineId` (string): Stable machine id, so two machines never collapse into one session.
- `offLimitsPaths` (array): Globs you promise not to touch, e.g. ["**/.env*", "infra/**"]. These win wherever they overlap allowedPaths.
- `sessionId` (string, required): Your per-session id. Required: a scope with no session cannot be enforced, and must never leak into another run.
- `timeoutMs` (integer): How long this call blocks, in milliseconds (max 55000).

### `wait_for_answer` (~262 tokens)

Wait for User Answer

Poll for the user's answer to a previously created question. Use it in three cases: after ask_user with wait set to false, after an ask_user call that returned timedOut, or with the linkedCorrelationId from a send_notification that embedded an askQuestion. Each call blocks until the answer arrives or timeoutMs expires (default 30 seconds, max 55). Questions live for 10 minutes in Redis, so when a call comes back { answered: false }, retry with the same correlationId up to 3 times with timeoutMs 55000 to give the user time to reach their phone; only then treat the question as unanswered and fall back to asking in the terminal. Returns { answered: true, value } once the user responds, where value is "yes"/"no" for confirm, the chosen option for select, or the typed text for input.

Input parameters:

- `correlationId` (string, required): The correlationId from an earlier ask_user response, or the linkedCorrelationId from a send_notification with an embedded askQuestion
- `timeoutMs` (integer): How long this call blocks, in milliseconds (default 30000, max 55000). Retry with the same correlationId to keep waiting; the question expires 10 minutes after it was asked.

### `cancel_question` (~145 tokens)

Cancel Pending Question

Retract a pending question so it can no longer be answered. Use this when a question became irrelevant before the user replied: the agent found the answer itself, the task was aborted, or a newer question supersedes it. Cancelling prevents a stale approval from arriving later and acting on work that has moved on. Only affects questions that are still pending; questions expire on their own 10 minutes after creation. Returns { cancelled: true } when a pending question was removed, { cancelled: false } when it was already answered, expired, or unknown.

Input parameters:

- `correlationId` (string, required): The correlationId of the pending question to cancel, as returned by ask_user or send_notification

### `list_sessions` (~145 tokens)

Agent Status

Read-only fleet view. Returns the live agent sessions for your site, keyed by machine and session, with each session's computed status (active, idle, waiting, errored) and any pending approval questions. Use it to check what your parallel agents are doing, spot which one is blocked waiting on a human answer, or confirm a session is still alive before assigning follow-up work. Does NOT start, stop, or steer agents, and sends no notification.

Input parameters:

- `limit` (integer): Maximum number of sessions to return, most recently seen first
- `status` (string): Only return sessions with this computed status. "waiting" means the session is blocked on a pending question.

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/pushary-pushary/api-mcp-mcp#diagnostics

## Score history

- 2026-08-03: 76
- 2026-08-02: 75
- 2026-08-01: 75
- 2026-07-31: 74
- 2026-07-30: 69
- 2026-07-29: 68
- 2026-07-28: 22
- 2026-07-27: 22
- 2026-07-26: 22

## Links

- Remote endpoint: https://pushary.com/api/mcp/mcp
- Authorisation metadata: https://pushary.com/.well-known/oauth-protected-resource/api/mcp/mcp
- Repository: https://github.com/Pushary/pushary-skill
- Changelog RSS feed: https://verifymcp.io/servers/pushary-pushary/api-mcp-mcp/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/pushary-pushary/api-mcp-mcp/changelog.json
- HTML version of this page: https://verifymcp.io/servers/pushary-pushary/api-mcp-mcp
