SparkPay

dev.sparkpay由 sparkpay.dev 發布官方發布者v1.0.0更新於 Oct 24, 2026

Stripe billing for indie apps: plans, coupons, subscriptions, customers and revenue reporting.

已驗證Streamable HTTP可網頁執行金融商業與電商

概覽

AI 產生的概覽

SparkPay 是面向獨立應用的 Stripe 計費遠端 MCP 伺服器,讓助理檢視方案、優惠券、訂閱與營收,並在人工確認後調整計費設定。

可以做什麼
列出已註冊應用及其線上方案目錄,包含方案層級、價格、試用與用量限制,並與已提交的方案檔案比對。檢視訂閱、以電子郵件查詢客戶、近期付款、取消紀錄、推薦與優惠券。彙總整體及各應用的營收與訂閱人數,以美元分為單位,依每位客戶最近一次付款計算流水,而非累計總額。建立、批次建立、刪除、批次刪除、列出或隱藏優惠券,並管理優惠券邀請名單。為新應用規劃並套用方案目錄完成上架,之後調整方案限制、顯示資訊、價格或封存方案層級。透過引導式精靈端到端設定應用的託管定價頁。
適用情境
適合在 SparkPay 上經營多個小型應用時,讓助理回答計費問題、檢視流失與銷售,或不必開啟後台就能準備優惠券與價格調整。寫入操作都需人工確認,因此較適合有人監督而非全自動的流程。
執行需求
需要 sparkpay.dev 上的遠端 streamable HTTP 端點;未宣告任何套件、環境變數或請求標頭。寫入操作需要支援 elicitation 的用戶端(例如 Claude Desktop),不支援 elicitation 的用戶端會被拒絕,但 dry_run 預覽在任何用戶端皆可使用。端點對應的帳戶須擁有所查詢的應用。
安裝前請注意
許多工具會寫入:建立、刪除、隱藏或排程優惠券,新增或撤銷邀請,調整價格、重新命名、封存方案或修改用量限制,以及註冊應用。改價會建立真實的 Stripe 價格,優惠券直接影響客戶實付金額。營收數據是流水口徑而非累計總額,不要當成總收入。確認表單中手動填寫的值會覆蓋參數,請逐項核對。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 SparkPay,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/dev.sparkpay%2Fsparkpay/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "sparkpay": {
      "type": "http",
      "url": "https://sparkpay.dev/api/mcp/mcp"
    }
  }
}

工具

25

list_apps

List the registered apps (app_id + name). Use this first to discover valid app_id values, then pass one to the other tools to scope results to a single product.

無需輸入參數。

list_subscriptions

List subscriptions/registrations, newest first. Optionally filter by app_id, status, or payment_type. Returns metadata (email, status, plan, amounts). Use get_customer for a single user, or revenue_summary for totals.

輸入參數limitapp_idstatuspayment_typeinclude_samples

get_customer

Look up a customer by email. Returns every subscription/registration for that email across apps (or within one app if app_id is given), with full detail: verification, plan, billing period, usage, refunds. Empty when the email is unknown.

輸入參數email必填app_id

list_recent_payments

List recent paid transactions (excludes free-tier rows), newest first, ordered by payment date. Optionally scope by app_id. Use to review recent sales activity. Amounts are in the transaction currency (cents).

輸入參數limitapp_idinclude_samples

revenue_summary

Revenue and subscriber summary in USD cents (normalized from each transaction currency). Returns latest_payments (the MOST RECENT payment summed per customer: a run-rate, NOT lifetime turnover, because amount_paid is overwritten on renewal), refunds, approximate MRR, active/trialing/paid counts, and lifetime_net (the only cumulative total held, accrued per OWNER across all their apps and net of refunds; null when no accrual record exists). lifetime_net counts only charges whose Stripe webhook reached this app, so a missing renewal event under-counts it silently. A 0 or a low figure means "not recorded here", never "no sales". For turnover, accounts or tax, read Stripe directly: it is authoritative, and this database cannot reconstruct lifetime gross. Optionally scope by app_id; omit for platform-wide totals.

輸入參數app_idinclude_samples

revenue_by_app

Per-app rollup in USD cents (latest_payments/refunded/MRR + paid customer count), largest refund-adjusted latest payments first. latest_payments sums the most recent payment per customer, so it is a run-rate and NOT lifetime turnover. No lifetime figure is available per app (accrual is recorded per owner). Use to compare products at a glance; use revenue_summary for one app in depth.

輸入參數include_samples

list_referrals

List referral records (who referred whom, reward coupon code, pending/rewarded status), newest first. Optionally scope by app_id and/or status.

輸入參數limitapp_idstatusinclude_samples

list_recent_cancellations

Recently canceled paid subscriptions (excludes free rows), most recent cancellation first, with what each customer was paying. Use for churn review; list_subscriptions orders by signup date instead.

輸入參數limitapp_idinclude_samples

list_coupons

List discount coupons (code, percent off, expiry, max uses, use count, which paid tiers they apply to). Optionally scope by app_id and/or restrict to currently-active ones (not expired, not maxed out). Read-only: cannot create, edit, or delete coupons.

輸入參數limitapp_idactive_only

create_coupon

Create a percentage discount coupon for an app. WRITE, human-gated: a real create requires an elicitation-capable client (e.g. Claude Desktop). The human enters the final code, percent, expiry, visibility, and tier scope in a form; those values OVERRIDE the arguments here, which only pre-fill the form message as a proposal. Clients without elicitation are refused (dry_run still works anywhere). Inserts a `coupons` row and best-effort-mints the matching Stripe coupon (checkout backfills it on first use if Stripe is unreachable). The code is uppercased and must be unique per app. By default the coupon applies to every paid tier. Set dry_run:true first to preview the exact row without writing. Cannot discount a free-only app. Three house rules are enforced and cannot be argued out of: every coupon expires within 6 months (omitting expires_at means the 6-month term, not a code that never expires); a coupon at 90%+ is created invite_only, so it is redeemable only by addresses added with invite_to_coupon; and a 90%+ coupon is pinned to the second-highest paid recurring tier and may never cover the top tier or a one-time (lifetime) plan. Use list_coupons afterwards to confirm, and list_plans to see an app's tier slugs.

輸入參數code必填app_id必填listeddry_runmax_usesexpires_atdescriptionapplies_to_tiersdiscount_percent必填confirm_high_discount

bulk_create_coupon

Create the SAME discount code across many apps in one call: the portfolio-promo shortcut (e.g. a summer sale on every owned app). WRITE, human-gated: a real create requires an elicitation-capable client; the human enters the coupon terms ONCE in a form (overriding the arguments here) and that one approval covers the whole batch. Clients without elicitation are refused (dry_run still works anywhere). Runs each app through the same fully-guarded create as create_coupon. Unlike a single call it does NOT fail the batch when an app already has the code: that app is reported `skipped` and the rest are still created. Returns a per-app outcome matrix plus created/skipped/failed counts. Use dry_run:true first to see which apps would create vs skip. Pass explicit app_ids (from list_apps). There is deliberately no 'all apps' shortcut, so a discount can't hit an app you didn't name.

輸入參數code必填listedapp_ids必填dry_runmax_usesexpires_atdescriptionapplies_to_tiersdiscount_percent必填confirm_high_discount

delete_coupon

Delete one coupon from an app. WRITE, human-gated: a real delete requires an elicitation-capable client; the human sees the exact coupon (code, percent, redemption count) and must click approve. The model cannot confirm on its own, and confirm_used is only consulted for dry_run previews. Clients without elicitation are refused (dry_run still works anywhere). Removes the Stripe coupon object and then the `coupons` row, exactly like the dashboard's delete, so no orphaned Stripe object is left behind. Deleting is permanent and the code becomes reusable afterwards. Set dry_run:true to see exactly which coupon would go (and its redemption count) without touching anything. Use list_coupons first to confirm the code.

輸入參數code必填app_id必填dry_runconfirm_used

bulk_delete_coupon

Delete the SAME coupon code across many apps in one call: the inverse of bulk_create_coupon, for retiring a portfolio-wide promo. WRITE, human-gated: a real delete requires an elicitation-capable client; the human sees every app the code would be removed from (with per-app redemption counts) and must click approve, and confirm_used is only consulted for dry_run previews. Clients without elicitation are refused (dry_run still works anywhere). An app that never had the code is reported `skipped` rather than failing the batch, since the desired end state already holds there. Returns a per-app outcome matrix plus deleted/skipped/failed counts. Use dry_run:true first to see exactly which apps would lose the code. Pass explicit app_ids (from list_apps) so a delete can't hit an app you didn't name.

輸入參數code必填app_ids必填dry_runconfirm_used

set_coupon_listed

Show, hide or SCHEDULE an EXISTING coupon on the public pricing pages by setting its `listed` flag and optional `listed_from` start date. WRITE, human-gated: a real write requires an elicitation-capable client and the human sees the code, the discount, which way it is moving and any start date; clients without elicitation are refused (dry_run works anywhere). These are deliberately the ONLY fields an agent can change on a live coupon: the percent, expiry and tier scope are terms somebody may already have been quoted, while `listed`/`listed_from` are purely a display decision. Together they decide whether the public coupons API returns the code today, which is what every app's promo bar draws from; the discount itself does not move and no Stripe object is touched. `listed_from` in the future STAGES a seasonal coupon so it appears on its own date with no cron: it never blocks anyone holding the code from redeeming it, it only holds the code back from the promo bar. Listing with no `listed_from` clears any existing schedule (lists now). Listing an INVITE-ONLY coupon is refused outright, since that would advertise a near-free code to people who cannot redeem it. A `listed_from` with listed:false is refused as a contradiction. Listing an expired/maxed coupon, or scheduling a start at or after expiry, is allowed but warns. A coupon already in the requested state reports `noop`. Use list_coupons first to see codes and their current visibility.

輸入參數code必填app_id必填listed必填dry_runlisted_from

list_coupon_invites

List who a coupon was offered to and what they did with it: per-address status (invited / redeemed / revoked), where the invite came from, and the timestamps. Also returns the coupon's own `invite_only` flag -- read that FIRST: when it is false the invite rows are recorded but NOT enforced, and anyone holding the code can still redeem it. Read-only. Use list_coupons for the coupon's terms, invite_to_coupon to add addresses, revoke_coupon_invite to withdraw one.

輸入參數code必填app_id必填

invite_to_coupon

Add email addresses to a coupon's invite list and, by default, switch the coupon to invite-only so the list is actually enforced. WRITE, human-gated: a real write requires an elicitation-capable client and the human sees every address plus whether the coupon is about to be closed to everyone else; clients without elicitation are refused (dry_run works anywhere). Addresses are lowercased and de-duplicated, malformed ones are reported rather than dropped, and an address already on the list is left exactly as it is -- so re-inviting someone who already redeemed does NOT hand them a second free account, and re-inviting someone who was revoked does NOT un-block them. Set enforce_invite_only:false only to stage a list before gating the code; the result then carries a warning that the coupon is still open. Use dry_run:true first to see exactly who would be added.

輸入參數code必填app_id必填emails必填sourcedry_runenforce_invite_only

revoke_coupon_invite

Withdraw one address's right to spend a coupon: the targeted block. WRITE, human-gated: a real write requires an elicitation-capable client and the human sees the address and its current status; clients without elicitation are refused (dry_run works anywhere). Works on an address that was never invited too, writing a revoked tombstone, so blocking someone does not depend on whether they were on the list and survives a later bulk re-invite. This only blocks FUTURE redemptions: if the status was already `redeemed` the discount has been granted, and undoing that means cancelling or refunding the subscription in the dashboard. Prefer this over delete_coupon when one recipient misbehaves -- deleting the code punishes every other invitee. Use list_coupon_invites first to see the current status.

輸入參數code必填email必填app_id必填reasondry_run

plan_app_kit

Step 1 of onboarding a new app onto SparkPay. Recons app_name against existing apps and the rest of the portfolio's plan catalogs, then returns automated findings plus the minimum set of questions that genuinely need a human answer (plan prices, billing model, redirect URLs, trial length, push-webhook opt-in). Pass the answers to create_app_kit next.

輸入參數app_name必填

create_app_kit

Step 2 of onboarding a new app onto SparkPay. Applies answers.plan_catalog by minting real Stripe prices (same helper /api/apps/sync-plans uses) and registers/updates the app, then returns a downloadable integration kit (lib/spark-pay client + plans.json + sync script + INTEGRATION.md, modeled on still-applying's golden pattern) plus exact post_steps for env vars and secrets. Refuses to overwrite an existing app's plans unless answers.confirm_overwrite is true. Real secrets (a push-mode webhook secret) are only ever returned in post_steps, never written into a kit file.

輸入參數answers必填app_name必填

list_plans

Download an app's live plan catalog: tiers, names, prices, trial, and the machine-readable `limits` that gate features inside the app. This is the source of truth each app repo's `bun run plans:sync` regenerates lib/spark-pay/plans.json from, so diff against this rather than trusting the committed file. Stripe price/product IDs are omitted unless include_stripe_ids is set.

輸入參數app_id必填include_stripe_ids

update_plan_limits

Change the usage limits on an app's existing tiers (e.g. set ai_generations_daily to 200 on pro). WRITE, human-gated: a real write requires an elicitation-capable client; the human sees the per-tier before -> after diff and must click approve. Clients without elicitation are refused (dry_run still works anywhere). Tier-keyed, so one call can set a new limit key across every tier in a single atomic write. Use -1 for unlimited, matching the catalog convention. This writes ONLY the limits object: it never touches Stripe, prices, or plan names, so it cannot mint a price by accident. Changing prices or adding a tier is a different job: use create_app_kit or the dashboard. Set dry_run to preview the before/after without writing. After this succeeds, run `bun run plans:sync` in the app repo and commit the regenerated plans.json so the code and the catalog agree.

輸入參數modeapp_id必填dry_runupdates必填

update_plan_meta

Set an existing tier's display metadata: its name and the two badge flags the public pricing page styles cards from: is_elite (gold/carbon BEST VALUE card with the rainbow title and app icon) and recommended (MOST POPULAR). A tier called "Elite" is NOT styled as elite unless is_elite is actually true on the stored plan; the page reads the flag, never the tier slug, so a catalog whose top tier lacks the flag renders as a plain grey card. Use this to repair that. WRITE, human-gated: the human sees the before -> after diff and approves (clients without elicitation pass through, since this touches no money: it never reaches Stripe, never changes an amount, limits or billing model, and is reversible by calling it again). Setting a flag false REMOVES the key rather than storing false, keeping exported plans.json minimal. Convention is at most ONE is_elite and ONE recommended tier per app: this tool does not clear the flag from its siblings, so unset the old holder in a second call. Use list_plans first for tier slugs and current flags, and run `bun run plans:sync` in the app repo afterwards to regenerate plans.json.

輸入參數nametier必填app_id必填dry_runis_eliterecommended

update_plan_pricing

Change what an app's EXISTING tiers charge: the amount, the billing model (one_time vs subscription), or both. WRITE, human-gated at the highest tier: a real write requires an elicitation-capable client, and the human types the tier, billing model and price into a form. Those typed values OVERRIDE the arguments here, which only pre-fill the proposal, so the model cannot move a price on its own. Clients without elicitation are refused (dry_run still works anywhere). Stripe prices are immutable, so this mints a NEW price and repoints the plan; the old price object is left intact and existing subscribers keep the price they signed up on, so this changes what NEW buyers pay. Switching a tier to one_time also clears its monthly/yearly price ids, so checkout cannot fall back to a recurring price the pricing page no longer advertises. Free, contact and payg tiers are refused: converting those is a catalog change, not a reprice. Use list_plans first for tier slugs and current amounts, and run `bun run plans:sync` in the app repo afterwards to regenerate plans.json.

輸入參數app_id必填dry_runupdates必填

archive_plan

Remove a tier from an app's plan catalog. WRITE, human-gated: a real write needs an elicitation-capable client and the human must approve; dry_run previews anywhere. Every other plan tool edits tiers that already exist, so a catalog could grow but never shrink, and collapsing a multi-tier page down to a single offer was a dashboard-only job. Stripe products and prices are deliberately left intact, exactly as update_plan_pricing leaves the old price behind: removing the row stops the plan being offered and never reaches into anyone's existing subscription. Refuses while the tier still has non-cancelled subscribers (matched on its Stripe price ids, since subscriptions carry a price rather than a tier slug), and refuses to remove an app's last remaining tier. Run `bun run plans:sync` in the app repo afterwards to regenerate plans.json.

輸入參數tier必填app_id必填dry_run

setup_pricing_page

Guided, stage-chained wizard that configures an app's hosted pricing page end to end: plan billing model + price (with clickable recommendations), plan name and badge (elite/recommended), optional free tier, a seasonal coupon (SUMMER26-style code suggested from the current season), favicon-derived theme color + card style, and FAQ content. WRITE, human-gated per stage: each call runs AT MOST ONE elicitation form and commits only that stage, then returns next_call for the model to continue (stages: overview -> plans -> coupon -> branding -> content -> finish). The values the HUMAN types in each form OVERRIDE the arguments here - args only pre-fill form defaults (pass price_suggestions from market research and faq_drafts to seed them). Testimonials are NOT configurable here: they are collected from real customers on Sellular and rendered from there. Form stages are refused on clients without elicitation; overview/finish are read-only recon and work anywhere, as does dry_run (echoes the form + would-be writes, writes nothing). A declined stage leaves earlier committed stages applied - each stage is individually approved, and each effect is reversible via the standalone tools. Stripe prices are minted only by the plans stage with human-typed amounts (existing paid tiers only; free tiers never touch Stripe). After plan changes, run `bun run plans:sync` in consumer app repos. Use list_apps first for app_id.

輸入參數tierstageapp_id必填domaindry_runfaq_draftscoupon_codediscount_percentprice_suggestions

版本歷史

1
  1. v1.0.0最新Sep 16, 2026

評分

已滿足適用檢查項的 83%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分

    請宣告包含 README 的 GitHub 儲存庫,或在 OAuth 受保護資源後設資料中提供 resource_documentation。

  • 授權條款不適用

    託管服務按其提供方的條款使用,因此這裡不要求授權條款。此檢查項不計入百分比。