PushNotif MCP Server
This MCP server lets AI assistants manage PushNotif accounts, apps, push campaigns, subscribers, and billing through 16 schema-exposed tools.
Register new accounts via email OTP or log in existing accounts and retrieve API keys.
List/create/delete apps; update branding, welcome push, and Android FCM/iOS APNs credentials.
Send immediate Web Push (VAPID), Android FCM, and iOS APNs broadcasts with segment targeting.
Create, edit, or cancel scheduled/recurring push campaigns.
Configure on-site in-app popups/banners with triggers, frequency caps, CTA, and styling.
Configure RSS/Atom/Sitemap auto-push polling or dispatch the latest feed item immediately.
Generate payment/order webhook URLs and simulate payment events for toast/push automation.
List subscribers, manage segment tags, or unsubscribe/delete subscriber devices.
View campaign delivery metrics, CTR, and scheduled queue; create QRIS top-up invoices and check payment/credit ledger status.
README additionally advertises social-proof toasts and transactional email automation, but those tools are not present in the supplied schema.
Allows sending real-time push notifications to Android devices via Firebase Cloud Messaging (FCM) and configuring native Android FCM credentials.
Enables configuration of Apple Push Notification service (APNs) credentials and sending push notifications to Apple devices.
Provides tools for configuring Firebase Cloud Messaging (FCM) service account credentials to send push notifications to Android devices.
Allows sending push notifications to iOS devices via Apple Push Notification service (APNs) and configuring APNs .p8 credentials.
Generates ready-to-paste integration code and snippets for integrating PushNotif into Laravel applications.
Generates ready-to-paste integration code and snippets for integrating PushNotif into Next.js applications.
Enables automated background monitoring of RSS/Atom feeds and sitemaps to auto-broadcast new articles as push notifications.
Generates ready-to-paste integration code and snippets for integrating PushNotif into WordPress sites.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@PushNotif MCP ServerSend a push notification to all subscribers about the new feature."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
π PushNotif MCP Server (pushnotif-mcp-server)
Official open-source Model Context Protocol (MCP) Server implementation for PushNotif.biz.id β allowing AI coding assistants (Claude Desktop, Claude Code, Cursor, Windsurf, Cline, and Glama) to register accounts, generate SDK snippets, broadcast Web Push (VAPID) & Mobile Push (Android FCM / iOS APNs), configure In-App Popup Banners, Social Proof Toasts, Transactional Email OTP, and manage QRIS credits.
π¦ Repository Architecture (Open-Source MCP Server Implementation)
This repository contains the complete, runnable MCP Server implementation built on @modelcontextprotocol/sdk:
src/index.jsβ Full Stdio MCP Server implementation (@modelcontextprotocol/sdk) exposing all 19 PushNotif tools (ListToolsRequestSchema&CallToolRequestSchema).Dockerfileβ Containerized build for Glama.ai automated inspection and local Docker execution.package.jsonβ Node.js ES Module package (bin: pushnotif-mcp).glama.json&smithery.yamlβ Registry metadata manifests.
Related MCP server: BotBell MCP Server
π Quick Start (Local Stdio MCP Server)
Option 1: Run via Node.js / npx (Stdio)
Clone and install dependencies:
git clone https://github.com/AarsyDesign/pushnotif-mcp.git
cd pushnotif-mcp
npm installAdd to your claude_desktop_config.json or .cursor/mcp.json:
{
"mcpServers": {
"pushnotif": {
"command": "node",
"args": ["/absolute/path/to/pushnotif-mcp/src/index.js"],
"env": {
"PUSHNOTIF_API_KEY": "pn_live_YOUR_API_KEY_HERE"
}
}
}
}Option 2: Run via Docker (Stdio)
docker build -t pushnotif-mcp .
docker run -i --rm -e PUSHNOTIF_API_KEY=pn_live_YOUR_API_KEY_HERE pushnotif-mcpOption 3: Direct Streamable HTTP Endpoint
You can also connect directly via Streamable HTTP at https://pushnotif.biz.id/mcp with Authorization: Bearer pn_live_YOUR_API_KEY_HERE.
π οΈ Available Tools (19 Full-Lifecycle Tools)
Account Onboarding (No API Key Required)
register_new_accountβ Two-step onboarding to request a 6-digit email OTP or verify the OTP to create a new PushNotif account (+1,000 Free Quota Credits forever), register the first website, and returnapi_key(pn_live_...).login_existing_accountβ Authenticate an existing account with email & password to retrieve itsapi_keyand optionally update workspace profile name or password.
Workspace, Web Push, Mobile Push, In-App & Transactional Email Automation
list_appsβ List all registered websites/apps, active subscriber counts, credit balance, and optional ready-to-paste SDK snippets (html,nextjs,laravel,wordpress,flutter).create_appβ Register a new website or mobile app and generate VAPID keys.update_app_brandingβ Update notification icon URL, automatic Welcome Push message, or upload Firebase FCM Service Account JSON / Apple APNs.p8credentials.delete_appβ Permanently delete a registered application along with its subscribers, campaigns, and logs.send_push_notificationβ Broadcast instant Web Push (VAPID), Android (FCM), and iOS (APNs) notifications.schedule_push_notificationβ Schedule one-time or recurring (daily/weekly) push campaigns.configure_inapp_bannerβ Configure In-App Popup Modals, Top Sticky Bars, or Bottom Slide Cards.configure_social_toastβ Configure standalone on-site Live Activity Social Proof Toast popups.configure_rss_autopushβ Configure automated 24/7 RSS / Sitemap / Atom feed monitoring and auto-push.configure_payment_webhookβ Generate incoming webhook URLs for Midtrans, Xendit, Mayar, Lynk.id, Duitku, Tripay, WooCommerce, and GitHub, or trigger a live test event.configure_email_automationβ Configure per-app switches for Automated Transactional Emails (Order Paid Receipt, Welcome Email, Broadcast Mirror) and custom Reply-To.send_transactional_emailβ Send 1-to-1 transactional emails (otp_code,payment_invoice,order_status,security_alert) via PushNotif's anti-phishing locked templates.list_subscribersβ View active subscriber device distribution and segment tags.update_subscriber_tagsβ Assign, replace, or remove audience segment tags on subscriber devices.get_campaign_analyticsβ Inspect campaign delivery, click-through rate (CTR), and conversion metrics.create_qris_invoiceβ Generate a live QRIS payment invoice (starting from Rp 1,000 / 5,000 Credits).check_billing_and_qris_statusβ Check real-time QRIS payment status (PENDING/PAID), credit ledger history, and downloadable PDF invoices.
π License
MIT License β Copyright (c) 2026 PushNotif.biz.id (AarsyDesign)
Available Tools
16 toolscheck_billing_and_qris_statusARead-onlyIdempotentInspect
Check QRIS top-up order payment status (PENDING or PAID), current workspace credit balance, credit mutation ledger history, and official downloadable PDF invoice URLs. Use this tool to verify whether an order from create_qris_invoice has settled or to audit credit consumption; do not use it to generate a new payment invoice (use create_qris_invoice instead) or view campaign click rates (use get_campaign_analytics instead). Read-only operation requiring PUSHNOTIF_API_KEY with 0 credit cost; pass order_id to inspect a single invoice or omit it to list recent orders and ledger entries. Returns JSON { credits_balance, orders: [{ id, amount_rp, credits_added, status, invoice_pdf_url, created_at }], recent_ledger: [{ id, delta, reason, created_at }] }.
| Name | Required | Description | Default |
|---|---|---|---|
| order_id | No | Optional specific QRIS order ID in format ord_xxxx (from create_qris_invoice) to check; omit to return the latest orders and ledger history |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description adds authentication requirements (PUSHNOTIF_API_KEY), operational cost context (0 credit cost), and the behavioral difference between passing versus omitting order_id. These details materially help an agent invoke the tool correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense but front-loaded: purpose, usage routing, operational constraints, parameter behavior, and return shape are all presented without filler. Every sentence contributes to correct tool selection or invocation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by explicitly documenting the JSON return shape, including credits_balance, orders, and recent_ledger. Annotations cover safety behavior, and the single parameter is fully described, leaving no meaningful gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline would be 3. The description adds practical meaning by explaining that order_id inspects a single invoice, while omitting it lists recent orders and ledger entries.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb and resource: checking QRIS top-up order payment status, credit balance, ledger history, and invoice URLs. It clearly distinguishes this tool from create_qris_invoice and get_campaign_analytics, so an agent can identify its scope without opening sibling schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use the tool: verifying whether an order from create_qris_invoice has settled or auditing credit consumption. It also names two alternatives and when not to use this tool: creating invoices and viewing campaign analytics.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
configure_inapp_bannerAIdempotentInspect
Configure and publish an on-site In-App Popup or Banner (center modal, top sticky bar, or bottom slide-in toast) rendered inside the website by the PushNotif SDK without requiring browser push permission. Use this tool for visual in-page promos and announcements; do not use it for OS lock-screen notifications (use send_push_notification instead). Prerequisite: call list_apps first to obtain app_id. Requires PUSHNOTIF_API_KEY; saving configuration is idempotent and costs 0 credits, while each live visitor display deducts 1 credit (inapp_trigger controls when the banner firesβsuch as 'scroll_50' for 50% page scroll or 'event:add_to_cart' for custom DOM eventsβcombined with inapp_freq to cap repeat impressions per visitor). Returns JSON { ok, app_id, inapp_enabled, inapp_style, inapp_trigger, inapp_freq }.
| Name | Required | Description | Default |
|---|---|---|---|
| app_id | Yes | Target application ID in format app_xxxx (obtain from list_apps) | |
| inapp_body | Yes | Banner supporting message text (1 to 240 characters) | |
| inapp_freq | No | Per-visitor frequency cap: 'once_per_session' (default), 'once_per_day', 'cooldown_3h', 'cooldown_12h', 'once_per_week', or 'always' | |
| inapp_style | No | Visual layout: 'modal' (center dialog), 'top_bar' (sticky top ribbon), or 'bottom_slide' (corner slide-in toast) | |
| inapp_title | Yes | Banner headline text (1 to 100 characters) | |
| inapp_accent | No | Optional 6-digit hex color code for the CTA button and accent border (default: '#0058BE') | |
| inapp_cta_url | No | Optional HTTPS destination URL opened when the CTA button is clicked | |
| inapp_enabled | No | Set true to publish the banner live on the website, or false to pause it (default: true) | |
| inapp_trigger | No | Trigger condition: 'immediate' (default), 'delay_5s', 'delay_10s', 'scroll_50', 'scroll_80', or custom DOM event 'event:<name>' | |
| inapp_cta_text | No | Optional CTA button label (must be paired with inapp_cta_url to render a clickable action button) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover non-destructive, idempotent, closed-world, but the description adds the things annotations cannot: the PUSHNOTIF_API_KEY requirement, that saving is free while each live impression costs 1 credit, and the exact JSON shape returned. That is exactly the value-add behavior layer.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with purpose and the sibling exclusion, and every sentence carries information (prerequisite, auth, cost model, return shape). It is dense and somewhat run-on β the trigger/frequency parenthetical could be split β so not a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 10-parameter mutation tool with no output schema, the description supplies the return shape, auth, cost model, idempotency and prerequisite. Gaps are minor: nothing about error behavior (e.g. invalid app_id) or what happens to an already-published banner when inapp_enabled is omitted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema coverage the schema already documents all ten parameters including the trigger and frequency enums, so the baseline is 3. The description does add a little meaning by explaining that inapp_trigger and inapp_freq work together to cap impressions, but most of its parameter prose restates values already in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (configure/publish) and resource (In-App Popup or Banner) plus the concrete render styles, and explicitly contrasts it with the OS-notification sibling send_push_notification. An agent can distinguish it from every other tool in the sibling list without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives both directions: 'use this tool for visual in-page promos and announcements' and 'do not use it for OS lock-screen notifications (use send_push_notification instead)'. It also names a prerequisite (call list_apps first for app_id), which is a routing instruction, not just context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
configure_payment_webhookAIdempotentInspect
Generate the ready-to-paste Automated Payment & Order Webhook URL (POST /api/v1/apps/{app_id}/incoming-event) for Midtrans, Xendit, Mayar, Lynk.id, Duitku, Tripay, WooCommerce, and GitHub, or trigger a live test payment/order event when simulate_test=true. Use this tool when connecting a payment gateway or e-commerce store to automatically show a Live Activity Toast and/or broadcast a Web Push notification upon payment settlement; do not use it for RSS blog feeds (use configure_rss_autopush instead) or manual push campaigns (use send_push_notification instead). Prerequisite: call list_apps first to obtain app_id. Requires PUSHNOTIF_API_KEY; generating the webhook URL costs 0 credits, while live or simulated push broadcasts deduct 1 credit per delivered device (toast_only mode costs 0 credits on display). Returns JSON { ok, app_id, mode, webhook_url, supported_platforms, setup_guides, simulation_result }.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Action when payment/order event arrives: 'both' (default: show Live Activity Toast on website + send Web Push), 'toast_only' (show Live Activity Toast only, 0 credits), or 'push_only' (send Web Push notification only) | |
| app_id | Yes | Target application ID in format app_xxxx (obtain from list_apps) | |
| platform | No | Platform format to simulate when simulate_test=true: 'midtrans' (default), 'xendit', 'woocommerce', or 'github' | |
| item_name | No | Optional custom product/order name for test simulation (default: 'Paket Premium Rp 149.000') | |
| buyer_name | No | Optional custom buyer name for test simulation (default: 'Budi (Jakarta)') | |
| simulate_test | No | Set true to immediately fire a test payment/order webhook event to verify Live Activity Toast and Web Push delivery |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing auth requirements (PUSHNOTIF_API_KEY), the exact cost model (URL generation 0 credits, 1 credit per delivered device for live/simulated broadcasts, toast_only 0 credits), and the response envelope. This is important because annotations mark the tool non-read-only and idempotent but say nothing about side effects or billing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and endpoint, then usage, exclusions, prerequisites, costs, and return shape in a logical order. It is dense β the opening sentence carries an eight-item platform list and two modes β but nearly every clause adds decision-relevant information, with little redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a six-parameter mutation tool with a simulated-write path, the description covers everything an agent needs: prerequisite resolution of app_id, auth, cost implications per mode, exclusions to sibling tools, and the returned JSON keys (which substitute for the absent output schema). Nothing material is left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real value by tying credit cost to the mode parameter (toast_only costs 0 credits) and by restating app_id's provenance from list_apps. It does not, however, explain how platform and simulate_test interact in the description beyond the schema's own wording.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Generate the ready-to-paste Automated Payment & Order Webhook URL") with the exact endpoint path, and lists both operating modes (URL generation vs. simulate_test=true firing a live event). It also names the eight supported platforms, so the agent knows precisely what it produces and for whom.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit affirmative case ("Use this tool when connecting a payment gateway or e-commerce store...") plus two named exclusions routing to siblings: configure_rss_autopush for feeds and send_push_notification for manual campaigns. It also states the prerequisite, call list_apps first to obtain app_id, which prevents the most likely invocation error.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
configure_rss_autopushAIdempotentInspect
Configure automated 24/7 RSS, Atom, or XML Sitemap polling for an app_id, or trigger an immediate feed check and push broadcast via dispatch_now=true. Use this tool when a blog, news portal, or store wants newly published URLs automatically broadcast as push notifications; do not use it for manual one-off messages (use send_push_notification instead) or fixed-time calendar campaigns (use schedule_push_notification instead). Prerequisite: call list_apps first to obtain app_id. Requires PUSHNOTIF_API_KEY; feed URLs are validated against SSRF rules, deduplicated by item GUID/URL so each post is sent only once, and deduct 1 credit per delivered subscriber when a new item is broadcast (setting dispatch_now=true immediately fetches and broadcasts the newest feed entry even if rss_enabled=false). Returns JSON { ok, app_id, rss_enabled, rss_feed_url, rss_interval, dispatched_now, latest_item_title }.
| Name | Required | Description | Default |
|---|---|---|---|
| app_id | Yes | Target application ID in format app_xxxx (obtain from list_apps) | |
| rss_prefix | No | Optional text prepended to each auto-generated notification title (e.g., 'Artikel Baru: ') | |
| rss_enabled | No | Set true to enable background RSS/Sitemap polling at rss_interval, or false to pause background polling | |
| dispatch_now | No | Set true to immediately fetch the latest feed entry and broadcast it to active subscribers right now | |
| rss_feed_url | No | Public HTTPS URL of the RSS 2.0, Atom, or XML Sitemap feed (required when enabling polling or calling dispatch_now=true) | |
| rss_interval | No | Background polling interval: '5m', '15m', '30m' (default), '1h', '3h', or 'daily_digest' |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=false, idempotent=true, destructive=false, openWorldHint=true, so the description's added context is the differentiator: SSRF URL validation, GUID/URL deduplication so each post is sent once, the PUSHNOTIF_API_KEY requirement, and a per-subscriber credit cost of 1 per broadcast. It falls just short of 5 because it does not state what happens to an existing configuration when parameters are omitted (partial update vs reset).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core action and the immediate-dispatch variant before routing, prerequisites, and cost. The middle sentence is dense with nested parentheticals and stacked clauses, which is efficient but slightly harder to scan than a cleanly split structure.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating multi-mode configuration tool with open-world network behavior, the description covers prerequisites, auth, validation, deduplication, billing impact, mode precedence, and even the return shape ({ ok, app_id, rss_enabled, ... }) despite no output schema. Nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3; the description still adds genuine meaning by clarifying that dispatch_now fetches and broadcasts 'even if rss_enabled=false', a precedence rule absent from the schema's property text. It also reinforces that rss_feed_url is required when enabling polling or dispensing, but adds no interval-duration or prefix-format detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Configure automated 24/7 RSS, Atom, or XML Sitemap polling for an app_id') and adds the alternate mode ('trigger an immediate feed check and push broadcast via dispatch_now=true'). It also names the two siblings it is not (send_push_notification, schedule_push_notification), so an agent can discriminate it without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit positive trigger ('when a blog, news portal, or store wants newly published URLs automatically broadcast') plus two explicit exclusions that name the correct alternative tool for each. It also states a prerequisite sequence ('call list_apps first to obtain app_id'), leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_appAInspect
Register a new website domain or mobile application under the authenticated workspace and generate its unique ECDSA P-256 VAPID keypair and 1-line HTML SDK snippet. Use this tool when adding an additional website or app to an existing account; do not use it to modify an existing app's icon, welcome push, or mobile keys (use update_app_branding instead) or to remove an app (use delete_app instead). Requires PUSHNOTIF_API_KEY, costs 0 credits, and creates a persistent app record where site_url must be a valid HTTPS origin (or http://localhost for local testing). Returns JSON { ok, app: { id, site_name, site_url, vapid_public_key, created_at }, sdk_snippet }.
| Name | Required | Description | Default |
|---|---|---|---|
| site_url | Yes | Canonical HTTPS origin URL of the website (must start with https:// or http://localhost) | |
| site_name | Yes | Display name of the website or mobile application (2 to 80 characters) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (non-read-only, non-destructive, non-idempotent), and the description adds the information that actually matters for calling it: PUSHNOTIF_API_KEY is required, the operation costs 0 credits, and it creates a persistent record. It also discloses the generated artifacts (ECDSA P-256 VAPID keypair, SDK snippet), which cannot be inferred from annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is dense but front-loaded: the purpose sentence comes first, then usage routing, then constraints and return shape, in that order. Every sentence carries distinct information and none repeats the name or annotations.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a non-idempotent mutation tool with no output schema, the description supplies auth requirements, cost, persistence, input validation rules, and the exact return JSON shape. An agent has everything needed to call it correctly and interpret the result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents both parameters, including the HTTPS/localhost constraint and the 2β80 character name limit. The description's restatement of the site_url origin rule adds little beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb and resource ('Register a new website domain or mobile application') plus the concrete side effects (VAPID keypair, HTML SDK snippet). It explicitly names the siblings it is not (update_app_branding, delete_app), so an agent can separate it from every adjacent tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives the positive trigger ('when adding an additional website or app to an existing account') and two explicit exclusions with the correct alternatives for each. Nothing about tool selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_qris_invoiceAInspect
Create a prepaid credit top-up invoice payable via Indonesian QRIS (all banks and e-wallets) at a flat rate of Rp 0.20 per credit (Rp 1,000 = 5,000 non-expiring credits). Use this tool when the user wants to purchase additional credits; do not use it to check whether an existing invoice has been paid (use check_billing_and_qris_status instead). Requires PUSHNOTIF_API_KEY, generates a PENDING order valid for 30 minutes at 0 fee, and automatically credits the workspace upon payment webhook confirmation; if both package_id and custom amount_rp are supplied, amount_rp takes precedence (minimum Rp 1,000). Returns JSON { ok, order: { id, amount_rp, credits_added, status, qris_checkout_url, expires_at } }.
| Name | Required | Description | Default |
|---|---|---|---|
| amount_rp | No | Custom top-up amount in Indonesian Rupiah (minimum 1000, maximum 10000000; 1 IDR = 5 lifetime credits, overrides package_id) | |
| package_id | No | Preset package tier: 'starter' (Rp 20,000 = 100,000 credits), 'growth' (Rp 50,000 = 250,000 credits), or 'pro' (Rp 100,000 = 500,000 credits); ignored if amount_rp is explicitly provided |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the required PUSHNOTIF_API_KEY, that the order is PENDING and expires in 30 minutes at zero fee, that crediting happens automatically on webhook confirmation (i.e. the call does not itself deliver credits), and the amount_rp-vs-package_id precedence. This is the mutation lifecycle detail an agent needs and cannot get from readOnlyHint/destructiveHint alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense but front-loaded: purpose first, then exclusion, then auth/lifecycle, then parameter conflict, then return shape. Every clause carries information, though the inline JSON return shape makes the sentence long and slightly heavy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description usefully spells out the returned JSON fields including qris_checkout_url and expires_at. The remaining hole is behavior with zero arguments, since both parameters are optional and the description never says which one is defaulted to.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% so the baseline is 3, and the description adds the flat Rp 0.20/credit rate, the Rp 1,000 minimum, and the precedence rule in prose. It does not state what happens when neither optional parameter is supplied (required params = 0), which is the one semantic gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a prepaid credit top-up invoice') plus the payment rail (Indonesian QRIS, all banks and e-wallets), which makes it trivially distinguishable from billing/status siblings. An agent knows exactly what is being created without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the trigger ('when the user wants to purchase additional credits') and the anti-trigger with the exact alternative tool ('do not use it to check whether an existing invoice has been paid (use check_billing_and_qris_status instead)'). No inference required.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_appADestructiveIdempotentInspect
Permanently delete a registered application (app_id) along with all of its subscriber device tokens, scheduled campaigns, and delivery history. Use this tool only when a user explicitly asks to remove a duplicate or decommissioned app; do not use it to pause notifications or change app settings (use update_app_branding or configure_inapp_banner instead). Prerequisite: call list_apps first to verify the exact app_id and active subscriber count. Requires PUSHNOTIF_API_KEY, costs 0 credits, and is irreversibly destructive (confirm_delete must be set to true or the call is rejected). Returns JSON { ok, deleted_app_id, deleted_site_name, subscribers_removed }.
| Name | Required | Description | Default |
|---|---|---|---|
| app_id | Yes | Target application ID in format app_xxxx to permanently delete (obtain from list_apps) | |
| confirm_delete | Yes | Safety confirmation flag: must be explicitly set to true to execute permanent deletion |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and confirm_delete is in the schema, but the description adds real context the annotations cannot: the cascade deletion scope, the API key requirement, the zero credit cost, and that the call is rejected without confirm_delete=true. Only missing the return format, which prevents a 5. It does not contradict the idempotentHint=true annotation, since a repeat delete would leave the same end state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, no redundancy: purpose and cascade first, then usage boundary, then prerequisite and cost/auth, then return shape. Each sentence carries distinct, actionable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers authentication, cost, cascade scope, confirmation safety, and return keys, which is thorough for a two-parameter destructive tool with no output schema. The description could not have done much more without becoming verbose.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters are already documented. The description restates confirm_delete behavior and app_id provenance from list_apps but adds no syntax or format detail beyond what the schema provides, meeting the baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (permanently delete) and resource (registered application) plus the exact cascade of what is removed: subscriber device tokens, scheduled campaigns, delivery history. The scope alone distinguishes it from update_app_branding and configure_inapp_banner, which it names explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit when-to-use condition (user asks to remove a duplicate or decommissioned app) and an explicit when-not-to-use condition (pausing notifications or changing app settings), naming the two alternative tools. It also states a prerequisite: call list_apps first to verify app_id and subscriber count.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_campaign_analyticsARead-onlyIdempotentInspect
Retrieve historical push campaign delivery metrics (delivered count, click count, CTR percentage, credits spent) and active scheduled queue items (cmp_sch_xxxx). Use this tool to audit campaign performance or look up scheduled campaign IDs before editing or canceling them with schedule_push_notification; do not use it to inspect QRIS payment invoices (use check_billing_and_qris_status instead) or subscriber device lists (use list_subscribers instead). Read-only operation requiring PUSHNOTIF_API_KEY with 0 credit cost; omitting app_id aggregates metrics across all workspace apps up to limit rows. Returns JSON { summary: { total_sent, total_clicks, avg_ctr_percent }, campaigns: [{ id, app_id, title, delivered_count, click_count, ctr_percent, created_at }], scheduled_queue: [{ id, app_id, title, scheduled_for, recurrence_rule, status }] }.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum number of recent campaigns to return (1 to 50, default: 10) | |
| app_id | No | Optional application ID filter in format app_xxxx (omit to aggregate across all workspace apps) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive, so the safety bar is covered; the description goes well beyond that by disclosing the required PUSHNOTIF_API_KEY credential, the 0-credit cost, and the aggregation semantics when app_id is omitted. These are operationally relevant facts an agent could not derive from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Content is ordered well: purpose, metric scope, usage and exclusions, auth/cost, then return shape, so it is front-loaded with what matters most. The single dense paragraph and the full JSON return sketch could be tightened, but every clause carries useful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description takes on the burden of describing returns and does so fully (summary totals plus campaign and scheduled_queue item shapes). For a two-parameter read-only tool this covers everything an agent needs to call it and interpret results correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the parameters are already documented and baseline is 3. The description adds meaning beyond the schema by explaining the consequence of omitting app_id (aggregation across all workspace apps bounded by limit rows), which clarifies intent rather than repeating format details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (retrieve) and specific resources (push campaign delivery metrics and scheduled queue items), enumerating the exact metric fields and the cmp_sch_xxxx ID format. It also explicitly names the siblings it is not (check_billing_and_qris_status, list_subscribers), so an agent can distinguish it without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives concrete when-to-use cases (audit campaign performance, look up scheduled campaign IDs before editing/canceling) and names the follow-on tool schedule_push_notification. It also states explicit when-not cases with the correct alternatives for QRIS invoices and subscriber device lists, leaving nothing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_appsARead-onlyIdempotentInspect
List all registered websites and mobile apps in the workspace with active subscriber counts, current credit balance, and optional framework SDK installation snippets (when include_sdk_framework is set). Use this tool first as a prerequisite to obtain a valid app_id before calling send_push_notification, schedule_push_notification, update_app_branding, delete_app, configure_inapp_banner, or configure_rss_autopush; do not use it to inspect individual subscriber devices (use list_subscribers instead). Read-only operation requiring PUSHNOTIF_API_KEY with 0 credit cost; when include_sdk_framework is passed ('html', 'nextjs', 'laravel', 'wordpress', 'flutter'), each app entry also includes ready-to-paste SDK setup code. Returns JSON { tenant_name, credits_balance, total_apps, apps: [{ id, site_name, site_url, active_subscribers, sdk_guide }] }.
| Name | Required | Description | Default |
|---|---|---|---|
| app_id | No | Optional specific app_id (format app_xxxx) to filter and inspect in detail | |
| include_sdk_framework | No | Optional target stack ('html', 'nextjs', 'laravel', 'wordpress', or 'flutter') to include copy-paste SDK & service worker installation code |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds material context not in them: the PUSHNOTIF_API_KEY requirement, the zero-credit cost, and the conditional side effect of include_sdk_framework injecting SDK snippets per app. It also states the exact return payload, which matters since no output schema exists.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One dense paragraph, front-loaded with the purpose and then prerequisites, exclusions, and return shape in priority order. No filler sentences, though the inline JSON return signature makes it heavier to read than ideal; a short bullet structure would scan faster.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-param, no-output-schema read tool, everything an agent needs is present: auth requirement, cost, prerequisite ordering, alternative for device-level inspection, optional parameter behavior, and the response shape. Nothing material is left to inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real value by enumerating and explaining the effect of include_sdk_framework values ('html', 'nextjs', 'laravel', 'wordpress', 'flutter') β each app entry gains ready-to-paste setup code. It says nothing about the app_id filter parameter, leaving that entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb+resource+scope: 'List all registered websites and mobile apps in the workspace' including subscriber counts and credit balance. It explicitly distinguishes itself from list_subscribers and names the write tools it feeds, so an agent can place it correctly among 15 siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit prerequisite rule ('use this tool first ... before calling send_push_notification, schedule_push_notification, update_app_branding, delete_app, configure_inapp_banner, configure_rss_autopush') and an explicit exclusion ('do not use it to inspect individual subscriber devices (use list_subscribers instead)'). Both when-to-use and when-not-to-use, with named alternatives, are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_subscribersARead-onlyIdempotentInspect
Retrieve active subscriber device records, assigned segment tags, and platform breakdown counts (Web VAPID, Android FCM, iOS APNs) for the workspace or a specific app_id. Use this tool to inspect audience size, platform distribution, or obtain a subscriber_id before calling update_subscriber_tags; do not use it to view campaign click metrics (use get_campaign_analytics instead) or modify subscriber tags (use update_subscriber_tags instead). Read-only operation requiring PUSHNOTIF_API_KEY with 0 credit cost; filter by app_id and optional tag to narrow results. Returns JSON { total_active, platform_breakdown: { web, android_fcm, ios_apns }, subscribers: [{ id, app_id, platform, tags, created_at }] }.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Optional segment tag filter (returns only subscribers carrying this tag) | |
| limit | No | Maximum number of subscriber records to return (1 to 100, default: 15) | |
| app_id | No | Optional application ID filter in format app_xxxx (omit to aggregate across all apps in the workspace) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the PUSHNOTIF_API_KEY requirement, zero credit cost, and the full JSON return shape β valuable since there is no output schema. It does not discuss pagination/truncation behavior for the limit parameter or how totals relate to the returned page, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose, alternatives, and constraints are front-loaded in the first two sentences, with the return shape last. It is a dense paragraph with some redundancy between the opening enumeration and the trailing return-JSON listing, but every element is functional for an agent without an output schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers auth, cost, filtering, sibling routing, and return structure β everything an agent needs to call a read-only list tool with no output schema. The absence of an output schema is fully compensated by the inline JSON shape description.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters are already documented in the schema at a baseline of 3. The description reinforces app_id and tag as narrowing filters but adds no new semantics (e.g., how tag filtering interacts with platform_breakdown counts) and never mentions limit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Retrieve active subscriber device records... platform breakdown counts') and enumerates exactly what is returned. It explicitly distinguishes itself from get_campaign_analytics and update_subscriber_tags, so an agent can route correctly without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives positive use cases (inspect audience size, platform distribution, obtain a subscriber_id before update_subscriber_tags) and two explicit exclusions with the alternative tool named for each. When-to-use and when-not-to-use are both covered.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
login_existing_accountAIdempotentInspect
Authenticate an existing PushNotif account using email and password to retrieve its live API key and registered apps, with optional inline profile name or password update (when new_name or new_password is provided). Use this tool for existing users connecting from chat or updating account credentials; do not use it for new signups (use register_new_account instead) or app-level branding (use update_app_branding instead). Requires valid email and password (no prior API key needed), costs 0 credits, and is rate-limited against brute-force attempts; read-only unless new_name or new_password is supplied. Returns JSON { ok, tenant: { id, name, email, api_key, credits }, apps: [{ id, site_name, site_url }], profile_updated }.
| Name | Required | Description | Default |
|---|---|---|---|
| Yes | Registered PushNotif account email address | ||
| new_name | No | Optional new workspace display name (2 to 80 characters) to update upon login | |
| password | Yes | Current account login password | |
| new_password | No | Optional new account password (minimum 6 characters) to replace the current password |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnlyHint false, idempotent true, destructive false), it discloses cost (0 credits), a brute-force rate limit, the conditional mutation behavior ('read-only unless new_name or new_password is supplied'), and the exact response envelope. This resolves the ambiguity inherent in a tool whose readOnlyHint is false despite being primarily a login.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with the primary action and scope, then alternatives, then operational facts. Dense but every clause carries information; the response-shape clause is arguably the least essential given no output schema exists, but it is still useful and compact.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 4-parameter login-and-profile-update tool with no output schema, the description covers preconditions, cost, rate limiting, conditional mutation, alternatives, and the return JSON shape. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all four parameters. The description adds value by framing new_name and new_password as optional inline profile updates triggered on login and tying them to the 'profile_updated' return value, which the schema alone does not convey. It does not restate length constraints, which is fine since the schema covers them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb (authenticate), resource (existing PushNotif account), and the concrete outcome (retrieve live API key and registered apps, with optional profile update). It also explicitly contrasts with register_new_account and update_app_branding, so an agent can route between siblings without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It states exactly when to use this tool (existing users connecting from chat, or updating credentials) and when not to, naming the correct alternatives for signups and app-level branding. The prerequisites ('requires valid email and password, no prior API key needed') are also spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_new_accountAInspect
Two-step onboarding tool to request a 6-digit email OTP (step 1: omit otp_code) or verify the OTP to create a new PushNotif account with 1,000 free lifetime credits, register the initial website, and return a live API key (step 2: pass otp_code, password, and name). Use this tool only for brand-new user signups; do not use it for existing accounts (use login_existing_account instead) or to add websites to an existing account (use create_app instead). Public endpoint requiring no API key; step 1 is rate-limited to 5 OTPs per 10 minutes per IP (valid 10 minutes), while step 2 irreversibly creates a tenant and ECDSA P-256 VAPID keypair. Returns JSON { ok, step, tenant: { id, name, email, api_key, credits }, app: { id, site_name, site_url, vapid_public_key } }.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Workspace or company display name (2 to 80 characters; required when verifying otp_code) | |
| Yes | Email address to register (must not already belong to an existing PushNotif account) | ||
| otp_code | No | Optional 6-digit numeric OTP from email: omit on first call to send the OTP email, then provide on second call to complete registration | |
| password | No | Account login password (minimum 6 characters; required when verifying otp_code) | |
| site_url | No | Optional full HTTPS origin URL of the initial website (e.g., https://example.com) | |
| site_name | No | Optional display name for the initial website or app (defaults to workspace name) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations, the description discloses the rate limit (5 OTPs per 10 min per IP), OTP validity window, that step 2 irreversibly creates a tenant plus an ECDSA P-256 VAPID keypair, and that the endpoint is public with no API key. These are behavioral facts the structured fields do not carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The two-step mechanism and sibling exclusions are front-loaded, and every clause carries operational information. It is dense to the point of being a single long sentence, which slightly hurts scannability, but nothing is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
A non-idempotent, open-world mutation tool with no output schema is fully covered: the description supplies the return payload shape (ok, step, tenant, app fields including the API key and VAPID key), the rate limit, and the irreversibility warning. An agent has everything needed to call it correctly and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description earns above that by explaining the conditional coupling of otp_code with password and name and by tying each parameter set to a step. It does not add format constraints beyond what the schema already states (length minimums, HTTPS origin).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a concrete verb and resource (register a new account via OTP) and spells out the two-step protocol explicitly. It names the sibling tools it is not (login_existing_account, create_app), so an agent can distinguish it from all 15 siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('only for brand-new user signups') and when-not-to-use rules with named alternatives for each case. The two-step invocation condition (omit otp_code first, pass it on the second call) is stated as a routing rule, not left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
schedule_push_notificationAInspect
Create a new scheduled or recurring push notification campaign, edit an existing queued campaign (via update_campaign_id), or cancel a queued campaign before execution (via cancel_campaign_id). Use this tool for delayed, recurring, or editable future broadcasts; do not use it for immediate sending (use send_push_notification instead) or automated RSS feed polling (use configure_rss_autopush instead). Prerequisite: call list_apps to obtain app_id, or call get_campaign_analytics to obtain an existing cmp_sch_xxxx ID for editing or cancellation. Requires PUSHNOTIF_API_KEY; scheduling, editing, or canceling costs 0 credits up front, and 1 credit per delivered device is deducted only when the schedule fires (mutually exclusive modes: pass cancel_campaign_id to delete, update_campaign_id to modify fields in-place, or neither to create a new schedule). Returns JSON { ok, action, scheduled_campaign: { id, app_id, title, body, scheduled_for, recurrence_rule, status } }.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Optional HTTPS destination URL opened when the notification is tapped | |
| body | No | Notification body text (1 to 240 characters; required when creating, optional when editing via update_campaign_id) | |
| title | No | Notification headline (1 to 100 characters; required when creating, optional when editing via update_campaign_id) | |
| app_id | No | Target application ID in format app_xxxx (required when creating a new schedule) | |
| scheduled_for | No | ISO-8601 execution timestamp with timezone offset (e.g., '2026-10-21T08:00:00+07:00') | |
| recurrence_rule | No | Recurrence pattern: 'once' (default), 'daily', 'twice_daily', 'weekly', 'monthly', 'every_30m', 'every_3h', 'every_6h', or a 5-field cron expression | |
| cancel_campaign_id | No | Optional existing scheduled campaign ID (format cmp_sch_xxxx from get_campaign_analytics) to cancel and remove from the queue | |
| update_campaign_id | No | Optional existing scheduled campaign ID (format cmp_sch_xxxx from get_campaign_analytics) to edit in-place with new title, body, url, scheduled_for, or recurrence_rule |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the PUSHNOTIF_API_KEY requirement, the credit model (0 up front, 1 credit per delivered device charged when the schedule fires), and the mutual exclusivity of cancel/update/create modes, plus the return shape. Minor gap: annotations declare destructiveHint=false while the description says cancel_campaign_id will 'delete' and 'remove from the queue' β the description could reconcile that asymmetry (irreversible queue removal vs. no data destruction) rather than leave it implicit.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core verb+resource and every sentence carries information (alternatives, prerequisites, auth, cost, mode exclusivity, return shape). Dense single-paragraph packing of mode rules and cost rules makes it slower to scan than a short bulleted breakdown would be.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 8-parameter, zero-required mutation tool with conditional requirements and no output schema, the description supplies the mode logic, prerequisites, credential/cost behavior, and an inline return shape β everything needed to call it correctly in any of its three modes.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so per-parameter meaning is already documented; the description still adds value by explaining that the three mode parameters are mutually exclusive and that passing neither means create. It does not, however, explain interactions such as what happens if title/body are supplied with cancel_campaign_id, or how scheduled_for and recurrence_rule interact.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names specific verbs and a specific resource: creating, editing (via update_campaign_id) and cancelling (via cancel_campaign_id) scheduled/recurring push campaigns, and explicitly excludes two named siblings (send_push_notification for immediate sends, configure_rss_autopush for feed polling). An agent can distinguish this from every sibling without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('delayed, recurring, or editable future broadcasts'), when-not ('do not use it for immediate sending'), and named alternatives for the excluded cases. It also gives the prerequisite chain (call list_apps for app_id; call get_campaign_analytics for cmp_sch_xxxx), which is exactly the guidance an agent needs before invoking.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_push_notificationAInspect
Broadcast an immediate push notification across Web Push (VAPID), Android (FCM), and iOS (APNs) to active subscribers of a specific app_id. Use this tool for instant real-time delivery; do not use it for future or recurring broadcasts (use schedule_push_notification instead) or on-site HTML popups (use configure_inapp_banner instead). Prerequisite: call list_apps first to obtain app_id. Requires PUSHNOTIF_API_KEY, deducts 1 credit (Rp 0.20) per successfully delivered device (0 credits charged for 404/410 dead tokens, which are auto-pruned), and is irreversible once dispatched; when segment is set to a custom tag (from update_subscriber_tags) instead of 'all', only subscribers carrying that tag receive the broadcast, and omitting url defaults the tap action to the app's registered site_url. Returns JSON { ok, campaign_id, total_targeted, total_delivered, total_gone_pruned, credits_deducted, credits_remaining }.
| Name | Required | Description | Default |
|---|---|---|---|
| url | No | Optional HTTPS destination URL opened when the notification is tapped (defaults to app's site_url) | |
| body | Yes | Notification message body text (1 to 240 characters) | |
| title | Yes | Notification headline shown on the lock screen (1 to 100 characters) | |
| app_id | Yes | Target application ID in format app_xxxx (obtain from list_apps) | |
| segment | No | Target audience filter: 'all' (default) or a specific subscriber tag assigned via update_subscriber_tags |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic write/non-idempotent profile; the description adds concrete operational facts: PUSHNOTIF_API_KEY requirement, 1 credit per delivered device with a stated price, zero charge for 404/410 dead tokens that are auto-pruned, and that dispatch is irreversible. It also documents the segment fallback and the url default, which are behavioral, not just schema restatement.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The action and its scope are front-loaded, and every sentence carries non-redundant information (alternatives, prerequisite, cost, irreversibility, segment/url behavior, return shape). It is a single dense block with several clauses chained into one long sentence, which costs a little scannability but wastes no words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite no output schema, the description enumerates the return fields (ok, campaign_id, total_targeted, total_delivered, total_gone_pruned, credits_deducted, credits_remaining). Combined with prerequisites, cost model, sibling routing, and irreversibility for a non-idempotent destructive-adjacent broadcast, an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description adds real semantics: segment as 'all' vs a custom tag sourced from update_subscriber_tags with tag-matching delivery behavior, and url defaulting to the app's registered site_url. It doesn't repeat title/body length limits, but those are already fully specified in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (broadcast), resource (immediate push notification), delivery channels (VAPID/FCM/APNs), and audience scope (active subscribers of a given app_id). It explicitly distinguishes itself from schedule_push_notification and configure_inapp_banner, so an agent can route correctly without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use (instant real-time delivery), explicit when-not-to-use with the two named alternative tools, and a required prerequisite step (call list_apps first to obtain app_id). Nothing about tool selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_app_brandingAIdempotentInspect
Update an existing application's notification icon URL, automated welcome push message, and optional native mobile push credentials (Android FCM HTTP v1 service account JSON and iOS APNs .p8 key). Use this tool to configure app-level branding, onboarding welcome alerts, or native mobile credentials; do not use it to create a new app (use create_app instead) or configure on-site HTML popups (use configure_inapp_banner instead). Prerequisite: call list_apps first to obtain app_id. Requires PUSHNOTIF_API_KEY and idempotently updates only the fields provided at 0 configuration cost (when welcome_enabled=true, each new subscriber welcome push deducts 1 credit; APNs requires apns_key_id, apns_team_id, apns_bundle_id, and apns_p8_key together). Returns JSON { ok, app_id, icon_url, welcome_enabled, android_fcm_configured, ios_apns_configured }.
| Name | Required | Description | Default |
|---|---|---|---|
| app_id | Yes | Target application ID in format app_xxxx (obtain from list_apps) | |
| icon_url | No | Optional direct HTTPS URL to a square PNG/JPG/WebP brand icon (recommended 192x192px) | |
| apns_key_id | No | Optional 10-character Apple Developer APNs Key ID (provide together with apns_team_id, apns_bundle_id, and apns_p8_key) | |
| apns_p8_key | No | Optional full PEM content of Apple's AuthKey_XXXX.p8 private key file | |
| apns_team_id | No | Optional 10-character Apple Developer Team ID | |
| welcome_body | No | Body text of the automated welcome push notification (max 180 characters; used when welcome_enabled=true) | |
| welcome_title | No | Headline of the automated welcome push notification (max 80 characters; used when welcome_enabled=true) | |
| apns_bundle_id | No | Optional iOS application Bundle Identifier (e.g., 'id.company.app') | |
| welcome_enabled | No | Set true to automatically send a welcome push notification immediately after a visitor subscribes | |
| fcm_service_account_json | No | Optional raw JSON string of Google Firebase Service Account key for native Android FCM HTTP v1 delivery |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Well beyond the annotations (readOnlyHint=false, idempotentHint=true, destructiveHint=false), it discloses the auth requirement (PUSHNOTIF_API_KEY), partial-update behavior (only provided fields change), cost implications (1 credit per welcome push when welcome_enabled=true), the all-or-nothing APNs field group, and the return shape. The only gap is absence of any confirmation of irreversibility or rollback for credential overwrites, which keeps it short of a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the action and affected fields, then layers usage exclusions, prerequisites, and return contract in a logical order with zero filler sentences. It is dense and long for a single paragraph, but nearly every clause carries operational information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 10 parameters and no output schema, the description compensates by naming the returned JSON keys and stating the prerequisite and credential grouping rules. An agent has everything needed to invoke it correctly and interpret the response.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so per-parameter meaning is already fully documented; the description mainly restates the field set. It does add cross-field semantics the schema cannot express β the APNs four-field coupling and the credit cost tied to welcome_enabled β but that added value is modest against a fully documented schema, so baseline 3 is fair.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a specific verb+resource (update an existing application's branding) and enumerates exactly which fields it touches: icon URL, welcome push copy, and native mobile credentials. It also explicitly delineates from create_app and configure_inapp_banner, so an agent can distinguish it from siblings without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives positive triggers (configure app-level branding, onboarding welcome alerts, native mobile credentials), explicit exclusions with named alternatives (use create_app instead, use configure_inapp_banner instead), and a prerequisite (call list_apps first to obtain app_id). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_subscriber_tagsAIdempotentInspect
Assign or remove audience segment tags on a subscriber device (subscriber_id), or permanently unsubscribe and delete the device record (when unsubscribe=true). Use this tool to manage subscriber segmentation for targeted send_push_notification broadcasts or to remove a specific subscriber; do not use it to list subscribers (use list_subscribers instead). Prerequisite: call list_subscribers first to obtain a valid subscriber_id. Requires PUSHNOTIF_API_KEY and costs 0 credits; when unsubscribe=true is passed, the subscriber token is irreversibly deleted and tag parameters are ignored, otherwise add_tags and remove_tags idempotently update the subscriber's tag set. Returns JSON { ok, subscriber_id, action, tags, removed }.
| Name | Required | Description | Default |
|---|---|---|---|
| add_tags | No | Optional list of lowercase segment tag strings (e.g., ['vip', 'jakarta']) to attach to the subscriber for targeted broadcasts | |
| remove_tags | No | Optional list of segment tag strings to remove from the subscriber | |
| unsubscribe | No | Set true to permanently unsubscribe and delete this subscriber device record | |
| subscriber_id | Yes | Target subscriber device ID in format sub_xxxx (obtain from list_subscribers) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description contributes a lot beyond the annotations: API key requirement, zero credit cost, idempotent tag updates, tag parameters being ignored when unsubscribe=true, and an irreversible token deletion. However, that last point directly conflicts with the annotation destructiveHint=false β an agent trusting the annotations alone would treat this as a safe non-destructive mutation while the description documents permanent deletion. The mismatch undercuts the annotation contract even though the description is the more accurate side.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and the destructive branch is flagged early, with sibling routing and prerequisites following. It is dense but slightly overstuffed β the redundant '(subscriber_id)' gloss after 'subscriber device' and the trailing return-shape JSON could be tightened without losing information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the full call envelope for a 4-parameter mutation with no output schema: auth requirement, cost, prerequisite, side effects, parameter precedence, and the return shape { ok, subscriber_id, action, tags, removed }. There is no gap an agent would need to guess at.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3; the description exceeds it by adding real semantics the schema lacks β that tag updates are idempotent, that add_tags/remove_tags are silently ignored when unsubscribe=true, and that unsubscribe irreversibly deletes the token. Those interactions between parameters are the useful part an agent cannot get from the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (assign/remove tags, or unsubscribe) against a specific resource (subscriber device identified by subscriber_id), and explicitly names the sibling it is not (list_subscribers). An agent can distinguish this from every other subscriber-related tool without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit when-to-use ('manage subscriber segmentation for targeted send_push_notification broadcasts'), explicit when-not ('do not use it to list subscribers, use list_subscribers instead'), plus a stated prerequisite ('call list_subscribers first to obtain a valid subscriber_id'). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
20 tool updates
v2.2.0- Changed
check_billing_and_qris_status1 field changed- changed
Input schema / properties / order_id / descriptionPrevious value: -"Optional specific QRIS order ID (format ord_xxxx from create_qris_invoice) to inspect; omit to list recent orders"New value: +"Optional specific QRIS order ID in format ord_xxxx (from create_qris_invoice) to check; omit to return the latest orders and ledger history"
- Changed
configure_inapp_banner6 fields changed- changed
Input schema / properties / inapp_accent / descriptionPrevious value: -"Optional hex color code for the CTA button and accent border (default: '#0058BE')"New value: +"Optional 6-digit hex color code for the CTA button and accent border (default: '#0058BE')" - changed
Input schema / properties / inapp_cta_text / descriptionPrevious value: -"Optional call-to-action button label (e.g., 'Klaim Voucher β')"New value: +"Optional CTA button label (must be paired with inapp_cta_url to render a clickable action button)" - changed
Input schema / properties / inapp_cta_url / descriptionPrevious value: -"Optional HTTPS URL opened when the CTA button is clicked"New value: +"Optional HTTPS destination URL opened when the CTA button is clicked" - changed
Input schema / properties / inapp_enabled / descriptionPrevious value: -"Set true to activate the banner on the website, or false to pause it (default: true)"New value: +"Set true to publish the banner live on the website, or false to pause it (default: true)" - changed
Input schema / properties / inapp_style / descriptionPrevious value: -"Visual layout style: 'modal' (center dialog), 'top_bar' (sticky top ribbon), or 'bottom_slide' (corner toast card)"New value: +"Visual layout: 'modal' (center dialog), 'top_bar' (sticky top ribbon), or 'bottom_slide' (corner slide-in toast)" - changed
Input schema / properties / inapp_trigger / descriptionPrevious value: -"Display trigger condition: 'immediate' (default), 'delay_5s', 'delay_10s', 'scroll_50', 'scroll_80', or custom DOM event 'event:<name>'"New value: +"Trigger condition: 'immediate' (default), 'delay_5s', 'delay_10s', 'scroll_50', 'scroll_80', or custom DOM event 'event:<name>'"
- Removed
configure_mobile_credentials - Added
configure_payment_webhook - Changed
configure_rss_autopush4 fields changed- changed
Input schema / properties / rss_enabled / descriptionPrevious value: -"Set true to enable background RSS/Sitemap polling, or false to disable it"New value: +"Set true to enable background RSS/Sitemap polling at rss_interval, or false to pause background polling" - changed
Input schema / properties / rss_feed_url / descriptionPrevious value: -"Public HTTPS URL of the RSS 2.0, Atom, or XML Sitemap feed (e.g., 'https://example.com/feed')"New value: +"Public HTTPS URL of the RSS 2.0, Atom, or XML Sitemap feed (required when enabling polling or calling dispatch_now=true)" - changed
Input schema / properties / rss_interval / descriptionPrevious value: -"Polling frequency: '5m', '15m', '30m' (default), '1h', '3h', or 'daily_digest'"New value: +"Background polling interval: '5m', '15m', '30m' (default), '1h', '3h', or 'daily_digest'" - changed
Input schema / properties / rss_prefix / descriptionPrevious value: -"Optional prefix prepended to each notification title (e.g., 'Artikel Baru: ')"New value: +"Optional text prepended to each auto-generated notification title (e.g., 'Artikel Baru: ')"
- Changed
create_app1 field changed- changed
Input schema / properties / site_url / descriptionPrevious value: -"Canonical HTTPS URL of the website (must start with https:// or http://localhost)"New value: +"Canonical HTTPS origin URL of the website (must start with https:// or http://localhost)"
- Changed
create_qris_invoice2 fields changed- changed
Input schema / properties / amount_rp / descriptionPrevious value: -"Custom top-up amount in Indonesian Rupiah (minimum 1000, maximum 10000000; 1 IDR = 5 credits)"New value: +"Custom top-up amount in Indonesian Rupiah (minimum 1000, maximum 10000000; 1 IDR = 5 lifetime credits, overrides package_id)" - changed
Input schema / properties / package_id / descriptionPrevious value: -"Preset package tier: 'starter' (Rp 20,000 = 100,000 credits), 'growth' (Rp 50,000 = 250,000 credits), or 'pro' (Rp 100,000 = 500,000 credits); overridden if amount_rp is explicitly provided"New value: +"Preset package tier: 'starter' (Rp 20,000 = 100,000 credits), 'growth' (Rp 50,000 = 250,000 credits), or 'pro' (Rp 100,000 = 500,000 credits); ignored if amount_rp is explicitly provided"
- Added
delete_app - Changed
get_campaign_analytics1 field changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"Optional application ID filter (format app_xxxx); omit to aggregate across all apps in the workspace"New value: +"Optional application ID filter in format app_xxxx (omit to aggregate across all workspace apps)"
- Removed
get_integration_guide - Changed
list_apps2 fields changed- added
Input schema / properties / app_idAdded value: +{ + "description": "Optional specific app_id (format app_xxxx) to filter and inspect in detail", + "type": "string" +} - added
Input schema / properties / include_sdk_frameworkAdded value: +{ + "description": "Optional target stack ('html', 'nextjs', 'laravel', 'wordpress', or 'flutter') to include copy-paste SDK & service worker installation code", + "type": "string" +}
- Changed
list_subscribers3 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"Optional application ID filter (format app_xxxx); omit to list subscribers across all workspace apps"New value: +"Optional application ID filter in format app_xxxx (omit to aggregate across all apps in the workspace)" - changed
Input schema / properties / limit / descriptionPrevious value: -"Maximum number of recent subscriber records to return (1 to 100, default: 15)"New value: +"Maximum number of subscriber records to return (1 to 100, default: 15)" - added
Input schema / properties / tagAdded value: +{ + "description": "Optional segment tag filter (returns only subscribers carrying this tag)", + "type": "string" +}
- Changed
login_existing_account3 fields changed- added
Input schema / properties / new_nameAdded value: +{ + "description": "Optional new workspace display name (2 to 80 characters) to update upon login", + "type": "string" +} - added
Input schema / properties / new_passwordAdded value: +{ + "description": "Optional new account password (minimum 6 characters) to replace the current password", + "type": "string" +} - changed
Input schema / properties / password / descriptionPrevious value: -"Account password"New value: +"Current account login password"
- Changed
register_new_account7 fields changed- changed
Input schema / properties / email / descriptionPrevious value: -"Email address that received the OTP from request_registration_otp"New value: +"Email address to register (must not already belong to an existing PushNotif account)" - changed
Input schema / properties / name / descriptionPrevious value: -"User or company workspace name (2 to 80 characters)"New value: +"Workspace or company display name (2 to 80 characters; required when verifying otp_code)" - changed
Input schema / properties / otp_code / descriptionPrevious value: -"Exact 6-digit numeric OTP code sent to the user's email"New value: +"Optional 6-digit numeric OTP from email: omit on first call to send the OTP email, then provide on second call to complete registration" - changed
Input schema / properties / password / descriptionPrevious value: -"Account password (minimum 6 characters)"New value: +"Account login password (minimum 6 characters; required when verifying otp_code)" - changed
Input schema / properties / site_name / descriptionPrevious value: -"Optional display name for the first website or app (defaults to workspace name)"New value: +"Optional display name for the initial website or app (defaults to workspace name)" - changed
Input schema / properties / site_url / descriptionPrevious value: -"Optional full HTTPS origin URL of the first website (e.g., https://example.com)"New value: +"Optional full HTTPS origin URL of the initial website (e.g., https://example.com)" - changed
Input schema / requiredPrevious value: -[ - "name", - "email", - "password", - "otp_code" -]New value: +[ + "email" +]
- Removed
request_registration_otp - Changed
schedule_push_notification7 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"Target application ID in format app_xxxx (required when creating a schedule)"New value: +"Target application ID in format app_xxxx (required when creating a new schedule)" - changed
Input schema / properties / body / descriptionPrevious value: -"Notification body text (required when creating a schedule; 1 to 240 characters)"New value: +"Notification body text (1 to 240 characters; required when creating, optional when editing via update_campaign_id)" - changed
Input schema / properties / cancel_campaign_id / descriptionPrevious value: -"Optional scheduled campaign ID (format cmp_sch_xxxx from get_campaign_analytics) to cancel and delete before execution"New value: +"Optional existing scheduled campaign ID (format cmp_sch_xxxx from get_campaign_analytics) to cancel and remove from the queue" - changed
Input schema / properties / scheduled_for / descriptionPrevious value: -"ISO-8601 execution timestamp (e.g., '2026-10-21T08:00:00+07:00')"New value: +"ISO-8601 execution timestamp with timezone offset (e.g., '2026-10-21T08:00:00+07:00')" - changed
Input schema / properties / title / descriptionPrevious value: -"Notification headline (required when creating a schedule; 1 to 100 characters)"New value: +"Notification headline (1 to 100 characters; required when creating, optional when editing via update_campaign_id)" - added
Input schema / properties / update_campaign_idAdded value: +{ + "description": "Optional existing scheduled campaign ID (format cmp_sch_xxxx from get_campaign_analytics) to edit in-place with new title, body, url, scheduled_for, or recurrence_rule", + "type": "string" +} - changed
Input schema / properties / url / descriptionPrevious value: -"Optional HTTPS destination URL opened on tap"New value: +"Optional HTTPS destination URL opened when the notification is tapped"
- Changed
send_push_notification3 fields changed- changed
Input schema / properties / segment / descriptionPrevious value: -"Subscriber filter: 'all' (default, sends to every active subscriber of app_id) or a specific subscriber tag string (e.g., 'vip', 'jakarta')"New value: +"Target audience filter: 'all' (default) or a specific subscriber tag assigned via update_subscriber_tags" - changed
Input schema / properties / title / descriptionPrevious value: -"Notification headline shown on lock screen (1 to 100 characters)"New value: +"Notification headline shown on the lock screen (1 to 100 characters)" - changed
Input schema / properties / url / descriptionPrevious value: -"Optional HTTPS destination URL opened when the user taps the notification (defaults to the app's site_url)"New value: +"Optional HTTPS destination URL opened when the notification is tapped (defaults to app's site_url)"
- Changed
update_app_branding8 fields changed- added
Input schema / properties / apns_bundle_idAdded value: +{ + "description": "Optional iOS application Bundle Identifier (e.g., 'id.company.app')", + "type": "string" +} - added
Input schema / properties / apns_key_idAdded value: +{ + "description": "Optional 10-character Apple Developer APNs Key ID (provide together with apns_team_id, apns_bundle_id, and apns_p8_key)", + "type": "string" +} - added
Input schema / properties / apns_p8_keyAdded value: +{ + "description": "Optional full PEM content of Apple's AuthKey_XXXX.p8 private key file", + "type": "string" +} - added
Input schema / properties / apns_team_idAdded value: +{ + "description": "Optional 10-character Apple Developer Team ID", + "type": "string" +} - added
Input schema / properties / fcm_service_account_jsonAdded value: +{ + "description": "Optional raw JSON string of Google Firebase Service Account key for native Android FCM HTTP v1 delivery", + "type": "string" +} - changed
Input schema / properties / welcome_body / descriptionPrevious value: -"Body text of the automated welcome push notification (max 180 characters)"New value: +"Body text of the automated welcome push notification (max 180 characters; used when welcome_enabled=true)" - changed
Input schema / properties / welcome_enabled / descriptionPrevious value: -"Set true to automatically send a welcome push notification immediately after a visitor grants permission"New value: +"Set true to automatically send a welcome push notification immediately after a visitor subscribes" - changed
Input schema / properties / welcome_title / descriptionPrevious value: -"Headline of the automated welcome push notification (max 80 characters)"New value: +"Headline of the automated welcome push notification (max 80 characters; used when welcome_enabled=true)"
- Removed
update_profile - Added
update_subscriber_tags
16 tool updates
v2.1.2- Changed
check_billing_and_qris_status1 field changed- changed
Input schema / properties / order_id / descriptionPrevious value: -"Opsional: ID tagihan QRIS tertentu yang ingin dicek (misal: ord_xxxx)"New value: +"Optional specific QRIS order ID (format ord_xxxx from create_qris_invoice) to inspect; omit to list recent orders"
- Changed
configure_inapp_banner10 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"App ID yang ingin diatur"New value: +"Target application ID in format app_xxxx (obtain from list_apps)" - changed
Input schema / properties / inapp_accent / descriptionPrevious value: -"Kode warna HEX tombol (misal: #0058BE, #047857, #E11D48)"New value: +"Optional hex color code for the CTA button and accent border (default: '#0058BE')" - changed
Input schema / properties / inapp_body / descriptionPrevious value: -"Isi pesan singkat"New value: +"Banner supporting message text (1 to 240 characters)" - changed
Input schema / properties / inapp_cta_text / descriptionPrevious value: -"Teks tombol aksi (CTA)"New value: +"Optional call-to-action button label (e.g., 'Klaim Voucher β')" - changed
Input schema / properties / inapp_cta_url / descriptionPrevious value: -"URL tujuan saat tombol diklik"New value: +"Optional HTTPS URL opened when the CTA button is clicked" - changed
Input schema / properties / inapp_enabled / descriptionPrevious value: -"True untuk mengaktifkan banner di website/aplikasi"New value: +"Set true to activate the banner on the website, or false to pause it (default: true)" - changed
Input schema / properties / inapp_freq / descriptionPrevious value: -"Frekuensi tampil: once_per_session, once_per_day, always, cooldown_3h, cooldown_12h, once_per_week"New value: +"Per-visitor frequency cap: 'once_per_session' (default), 'once_per_day', 'cooldown_3h', 'cooldown_12h', 'once_per_week', or 'always'" - changed
Input schema / properties / inapp_style / descriptionPrevious value: -"Gaya tampilan: modal, top_bar, atau bottom_slide"New value: +"Visual layout style: 'modal' (center dialog), 'top_bar' (sticky top ribbon), or 'bottom_slide' (corner toast card)" - changed
Input schema / properties / inapp_title / descriptionPrevious value: -"Judul pengumuman/promo"New value: +"Banner headline text (1 to 100 characters)" - changed
Input schema / properties / inapp_trigger / descriptionPrevious value: -"Pemicu muncul: immediate, delay_5s, delay_10s, scroll_50, scroll_80, atau event:nama_event (misal: event:add_to_cart, event:payment_success)"New value: +"Display trigger condition: 'immediate' (default), 'delay_5s', 'delay_10s', 'scroll_50', 'scroll_80', or custom DOM event 'event:<name>'"
- Changed
configure_mobile_credentials6 fields changed- changed
Input schema / properties / apns_bundle_id / descriptionPrevious value: -"iOS App Bundle ID (misal: id.perusahaan.app)"New value: +"iOS application Bundle Identifier (e.g., 'id.company.app')" - changed
Input schema / properties / apns_key_id / descriptionPrevious value: -"Apple APNs Key ID (10 karakter)"New value: +"10-character Apple Developer APNs Key ID (e.g., 'ABC123DEFG')" - changed
Input schema / properties / apns_p8_key / descriptionPrevious value: -"Isi teks file AuthKey_XXXX.p8 dari Apple Developer"New value: +"Full PEM text content of Apple's AuthKey_XXXX.p8 private key file" - changed
Input schema / properties / apns_team_id / descriptionPrevious value: -"Apple Developer Team ID (10 karakter)"New value: +"10-character Apple Developer Team ID" - changed
Input schema / properties / app_id / descriptionPrevious value: -"App ID yang ingin dikonfigurasi"New value: +"Target application ID in format app_xxxx (obtain from list_apps)" - changed
Input schema / properties / fcm_service_account_json / descriptionPrevious value: -"Isi teks file service-account.json Firebase untuk Android APK"New value: +"Raw JSON string of the Google Firebase Service Account key file for Android FCM HTTP v1"
- Changed
configure_rss_autopush6 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"App ID tujuan"New value: +"Target application ID in format app_xxxx (obtain from list_apps)" - changed
Input schema / properties / dispatch_now / descriptionPrevious value: -"Set true jika ingin langsung menarik item RSS terbaru dan menembak Push Notification detik ini juga"New value: +"Set true to immediately fetch the latest feed entry and broadcast it to active subscribers right now" - changed
Input schema / properties / rss_enabled / descriptionPrevious value: -"True untuk mengaktifkan pemantau RSS otomatis"New value: +"Set true to enable background RSS/Sitemap polling, or false to disable it" - changed
Input schema / properties / rss_feed_url / descriptionPrevious value: -"URL RSS/Atom/Sitemap website (misal: https://domain.com/rss.xml)"New value: +"Public HTTPS URL of the RSS 2.0, Atom, or XML Sitemap feed (e.g., 'https://example.com/feed')" - changed
Input schema / properties / rss_interval / descriptionPrevious value: -"Interval cek: 5m, 15m, 30m, 1h, 3h, atau daily_digest"New value: +"Polling frequency: '5m', '15m', '30m' (default), '1h', '3h', or 'daily_digest'" - changed
Input schema / properties / rss_prefix / descriptionPrevious value: -"Awalan judul notifikasi (misal: Artikel Baru:)"New value: +"Optional prefix prepended to each notification title (e.g., 'Artikel Baru: ')"
- Changed
create_app2 fields changed- changed
Input schema / properties / site_name / descriptionPrevious value: -"Nama website atau aplikasi"New value: +"Display name of the website or mobile application (2 to 80 characters)" - changed
Input schema / properties / site_url / descriptionPrevious value: -"URL domain lengkap dengan https://"New value: +"Canonical HTTPS URL of the website (must start with https:// or http://localhost)"
- Changed
create_qris_invoice2 fields changed- changed
Input schema / properties / amount_rp / descriptionPrevious value: -"Nominal Rupiah top-up (default: 20000)"New value: +"Custom top-up amount in Indonesian Rupiah (minimum 1000, maximum 10000000; 1 IDR = 5 credits)" - changed
Input schema / properties / package_id / descriptionPrevious value: -"Pilih paket: starter, growth, atau pro (opsional jika mengisi amount_rp)"New value: +"Preset package tier: 'starter' (Rp 20,000 = 100,000 credits), 'growth' (Rp 50,000 = 250,000 credits), or 'pro' (Rp 100,000 = 500,000 credits); overridden if amount_rp is explicitly provided"
- Changed
get_campaign_analytics2 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"Opsional: filter untuk App ID tertentu"New value: +"Optional application ID filter (format app_xxxx); omit to aggregate across all apps in the workspace" - changed
Input schema / properties / limit / descriptionPrevious value: -"Jumlah riwayat kampanye terakhir yang ditampilkan (default: 10)"New value: +"Maximum number of recent campaigns to return (1 to 50, default: 10)"
- Changed
get_integration_guide2 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"App ID yang ingin diambil panduannya"New value: +"Target application ID in format app_xxxx (obtain from list_apps)" - changed
Input schema / properties / framework / descriptionPrevious value: -"Nama framework (misal: Next.js / React, Flutter, Laravel)"New value: +"Target stack: 'html' (default 1-line script), 'nextjs', 'laravel', 'wordpress', or 'flutter'"
- Changed
list_subscribers2 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"Opsional: filter untuk App ID tertentu"New value: +"Optional application ID filter (format app_xxxx); omit to list subscribers across all workspace apps" - changed
Input schema / properties / limit / descriptionPrevious value: -"Jumlah baris pelanggan terbaru yang ditampilkan (default: 15)"New value: +"Maximum number of recent subscriber records to return (1 to 100, default: 15)"
- Changed
login_existing_account2 fields changed- changed
Input schema / properties / email / descriptionPrevious value: -"Alamat email akun PushNotif"New value: +"Registered PushNotif account email address" - changed
Input schema / properties / password / descriptionPrevious value: -"Password akun PushNotif"New value: +"Account password"
- Changed
register_new_account6 fields changed- changed
Input schema / properties / email / descriptionPrevious value: -"Alamat email pengguna (sama dengan saat request_registration_otp)"New value: +"Email address that received the OTP from request_registration_otp" - changed
Input schema / properties / name / descriptionPrevious value: -"Nama pengguna atau workspace"New value: +"User or company workspace name (2 to 80 characters)" - changed
Input schema / properties / otp_code / descriptionPrevious value: -"Kode OTP 6 angka yang diterima pengguna di inbox email"New value: +"Exact 6-digit numeric OTP code sent to the user's email" - changed
Input schema / properties / password / descriptionPrevious value: -"Password akun baru (minimal 6 karakter)"New value: +"Account password (minimum 6 characters)" - changed
Input schema / properties / site_name / descriptionPrevious value: -"Nama website atau aplikasi pertama"New value: +"Optional display name for the first website or app (defaults to workspace name)" - changed
Input schema / properties / site_url / descriptionPrevious value: -"URL lengkap website pertama (diawali https://)"New value: +"Optional full HTTPS origin URL of the first website (e.g., https://example.com)"
- Changed
request_registration_otp2 fields changed- changed
Input schema / properties / email / descriptionPrevious value: -"Alamat email pengguna yang akan didaftarkan"New value: +"Valid email address to register (e.g., user@domain.com); must not already be registered" - changed
Input schema / properties / name / descriptionPrevious value: -"Nama pengguna atau nama perusahaan/workspace"New value: +"Optional user or workspace display name (2 to 80 characters)"
- Changed
schedule_push_notification7 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"App ID tujuan (misal: app_xxxx)"New value: +"Target application ID in format app_xxxx (required when creating a schedule)" - changed
Input schema / properties / body / descriptionPrevious value: -"Isi pesan notifikasi"New value: +"Notification body text (required when creating a schedule; 1 to 240 characters)" - changed
Input schema / properties / cancel_campaign_id / descriptionPrevious value: -"Isi jika ingin membatalkan/menghapus jadwal kampanye (cmp_sch_xxxx)"New value: +"Optional scheduled campaign ID (format cmp_sch_xxxx from get_campaign_analytics) to cancel and delete before execution" - changed
Input schema / properties / recurrence_rule / descriptionPrevious value: -"Aturan perulangan: once, daily, twice_daily, weekly, monthly, every_30m, every_3h, every_6h, atau ekspresi cron kustom (misal: 0 5,12,15,18,19 * * *)"New value: +"Recurrence pattern: 'once' (default), 'daily', 'twice_daily', 'weekly', 'monthly', 'every_30m', 'every_3h', 'every_6h', or a 5-field cron expression" - changed
Input schema / properties / scheduled_for / descriptionPrevious value: -"Waktu kirim format ISO-8601 (misal: 2026-10-17T06:00:00Z)"New value: +"ISO-8601 execution timestamp (e.g., '2026-10-21T08:00:00+07:00')" - changed
Input schema / properties / title / descriptionPrevious value: -"Judul pesan notifikasi"New value: +"Notification headline (required when creating a schedule; 1 to 100 characters)" - changed
Input schema / properties / url / descriptionPrevious value: -"URL tujuan saat notifikasi diketuk"New value: +"Optional HTTPS destination URL opened on tap"
- Changed
send_push_notification5 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"App ID tujuan (misal: app_xxxx)"New value: +"Target application ID in format app_xxxx (obtain from list_apps)" - changed
Input schema / properties / body / descriptionPrevious value: -"Isi pesan notifikasi"New value: +"Notification message body text (1 to 240 characters)" - changed
Input schema / properties / segment / descriptionPrevious value: -"Filter segmen pelanggan (default: all)"New value: +"Subscriber filter: 'all' (default, sends to every active subscriber of app_id) or a specific subscriber tag string (e.g., 'vip', 'jakarta')" - changed
Input schema / properties / title / descriptionPrevious value: -"Judul pesan notifikasi"New value: +"Notification headline shown on lock screen (1 to 100 characters)" - changed
Input schema / properties / url / descriptionPrevious value: -"URL tujuan saat notifikasi diketuk"New value: +"Optional HTTPS destination URL opened when the user taps the notification (defaults to the app's site_url)"
- Changed
update_app_branding5 fields changed- changed
Input schema / properties / app_id / descriptionPrevious value: -"App ID yang ingin diubah (misal: app_xxxx)"New value: +"Target application ID in format app_xxxx (obtain from list_apps)" - changed
Input schema / properties / icon_url / descriptionPrevious value: -"URL gambar logo PNG/JPG aplikasi"New value: +"Optional direct HTTPS URL to a square PNG/JPG/WebP brand icon (recommended 192x192px)" - changed
Input schema / properties / welcome_body / descriptionPrevious value: -"Isi pesan notifikasi sambutan"New value: +"Body text of the automated welcome push notification (max 180 characters)" - changed
Input schema / properties / welcome_enabled / descriptionPrevious value: -"Aktifkan/matikan pesan sambutan otomatis"New value: +"Set true to automatically send a welcome push notification immediately after a visitor grants permission" - changed
Input schema / properties / welcome_title / descriptionPrevious value: -"Judul notifikasi sambutan saat user baru klik Izinkan"New value: +"Headline of the automated welcome push notification (max 80 characters)"
- Changed
update_profile2 fields changed- changed
Input schema / properties / name / descriptionPrevious value: -"Nama perusahaan atau pemilik workspace baru"New value: +"New workspace or company display name (2 to 80 characters)" - changed
Input schema / properties / new_password / descriptionPrevious value: -"Opsional: password baru (minimal 6 karakter)"New value: +"Optional new account login password (minimum 6 characters; omit to keep current password unchanged)"
17 tool updates
v2.1.0- First observed
check_billing_and_qris_status - First observed
configure_inapp_banner - First observed
configure_mobile_credentials - First observed
configure_rss_autopush - First observed
create_app - First observed
create_qris_invoice - First observed
get_campaign_analytics - First observed
get_integration_guide - First observed
list_apps - First observed
list_subscribers - First observed
login_existing_account - First observed
register_new_account - First observed
request_registration_otp - First observed
schedule_push_notification - First observed
send_push_notification - First observed
update_app_branding - First observed
update_profile
TDQS
Scored across 16 tools
Each tool targets a distinct resource+action and the descriptions include explicit 'do not use X, use Y instead' cross-references, making boundaries unusually clear. The only friction is that a few tools are multi-modal (schedule_push_notification creates, edits, and cancels campaigns; configure_rss_autopush and configure_payment_webhook take dispatch_now/simulate_test flags), so an agent must parse parameters to know which operation it is invoking.
All 16 tools are snake_case and begin with a clear action verb followed by the resource (list_apps, create_app, update_app_branding, send_push_notification, check_billing_and_qris_status). The get_/list_ split reflects genuine read-shape differences rather than convention drift, and nothing mixes casing or verb style.
16 tools is at the upper-but-reasonable end for a server spanning auth, app CRUD, push delivery, scheduling, in-app banners, RSS, payment webhooks, subscribers, analytics, and billing. Each tool maps to a real workflow step, though compressing the three schedule modes (create/edit/cancel) into one tool hints the surface could be tightened further.
Coverage is strong: full app lifecycle (list/create/update branding/delete), subscriber read+tag+unsubscribe, push send/schedule/analytics, and billing invoice+status. Minor gaps remainβthere is no way to rename an app or change its site_url outside branding, no per-campaign detail fetch, and no API-key rotation or logout operation.
Maintenance
Related MCP Connectors
Create, test, publish, and manage Dreamlit notification workflows from AI clients.
Webhooks for AI agents: send events, manage endpoints, inspect and retry deliveries.
Build and send email, SMS, and push straight from your AI agent.
Email, WhatsApp and Telegram for AI agents: send, campaigns, automations, contacts, agent inboxes.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage OneSignal push notifications, email, SMS, and user management through natural language. Supports multi-channel messaging, segmentation, templates, analytics, and iOS Live Activities with 50+ tools for complete OneSignal API coverage.1-
- AlicenseAqualityCmaintenanceEnables AI assistants to send push notifications and interactive alerts to iPhone and Mac devices via the BotBell app. It allows AI to receive user replies and manage notification bots for tasks like alerts, reminders, and remote approvals.210 npm1MIT
- FlicenseNot gradedqualityCmaintenanceLets AI assistants manage subscribers, trigger workflows, inspect notification events, and tune preferences across any MCP-compatible client.-
- AlicenseAqualityBmaintenanceLets AI agents send notifications, manage templates and read delivery status.112 npmMIT