Billing ToolsCAUTION
The get-paid engine for Stripe + WorkOS apps, for humans and AI agents.
Overview
From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.
Drop-in auth + billing for any Stripe + WorkOS app, usable by humans and AI agents, exposed as MCP tools, a REST API, and a CLI, over one storage-agnostic engine.
Billing Tools packages the "get money in" plumbing you'd otherwise rebuild in every SaaS: API-key auth on top of WorkOS, credit + subscription billing on top of Stripe, and (because the next wave of customers is autonomous) first-class agent rails: `auth.md` self-registration and `MPP` machine paymen
6377a9ae5fa8OBSERVED · 2026-10-12Connect
Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.
claude mcp add billing-tools --env BILLING_OPERATOR_TOKEN=${BILLING_OPERATOR_TOKEN} --env REFRESH_TOKEN_SECRET=${REFRESH_TOKEN_SECRET} --env STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY} --env STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET} -- npx -y @arnaudjnn/[email protected]{
"mcpServers": {
"billing-tools": {
"command": "npx",
"args": [
"-y",
"@arnaudjnn/[email protected]"
],
"env": {
"BILLING_OPERATOR_TOKEN": "${BILLING_OPERATOR_TOKEN}",
"REFRESH_TOKEN_SECRET": "${REFRESH_TOKEN_SECRET}",
"STRIPE_SECRET_KEY": "${STRIPE_SECRET_KEY}",
"STRIPE_WEBHOOK_SECRET": "${STRIPE_WEBHOOK_SECRET}"
}
}
}
}Exposed tools (51)
36 read · 11 write · 4 destructive. Blast radius: 4 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.
| Tool | Risk | Description |
|---|---|---|
accept_plan_quote | read | Accept the price an operator quoted for a plan change (workspace admins). Charges the card on file if there is one, otherwise emails a payable invoice — either way the credits land when the invoice is PAID. Nothing is charged until this is called. |
approve_top_up | read | Approve a pending top-up request → grants the requested extra credits to that member for the cycle (added on top of their seat pack by the meter). |
assign_seat_type | read | Assign a workspace member to a seat type (e.g. standard, premium). The member |
broke_tool | read | refuses for money |
buy_credits | read | Purchase credits. 1 unit of currency = 100 credits. HOW it is paid for is \ |
cancel_plan | read | Cancel the subscription at the end of the period already paid for. Nothing is refunded and nothing is lost today — the workspace drops to the free plan when the period ends. Reverse it before then with change_plan back to the current plan. |
change_member_role | write | Move a member between roles (${roles.join( |
change_plan | read | |
close_workspace | write | Stop a workspace: cancel its billing, KEEP its invoices, and return each member |
create_api_key | write | |
deny_top_up | read | Deny a pending top-up request. |
download_invoice | read | Returns a direct PDF link for one invoice. Drafts and auto-reload receipts have no PDF; use view_invoice for those. |
echo | read | Echo the arguments |
get_api_key | read | Provisions or retrieves an API key for accessing protected tools. Call with just an email to start authentication (sends a 6-digit code via email). Then call again with the email and the code to complete authentication and receive your API key. Add the key to your config as: |
get_billing_portal | read | Get a Stripe billing-portal URL to manage your subscription (upgrade, downgrade, cancel), update your payment method, and view invoices. Returns a short-lived link. Pass \ |
get_billing_profile | read | The workspace |
get_credit_balance | read | Returns your current credit balance, per-tool costs, and auto-reload settings. |
get_org_usage | read | Every member of the workspace measured against whatever caps them — their seat pack, else the shared pool — plus who is at or over it, and the team |
get_plan | read | The workspace |
get_spend_controls | read | Your workspace |
get_usage | read | Get your workspace |
get_usage_limits | read | Get every usage limit that applies to you right now (per hour/day/week/month and per billing cycle), how much of each is used, and when each resets. |
grant_top_up | read | Grant a member extra allowance for the current cycle WITHOUT waiting for them to request it, as a percentage of their own seat pack (default 25%). Admin action. |
invite_member | read | Invite somebody to the workspace by email. Roles: ${roles.join( |
list_api_keys | read | Lists the API keys for your workspace (obfuscated values, never the full key). Useful for finding stale keys to revoke. Free. |
list_invitations | read | Invitations for this workspace and their state (pending, accepted, expired, revoked). |
list_invoices | read | Returns your recent invoices with amounts, dates, status (paid/open), and links to view/download PDFs. |
list_members | read | List everyone in the workspace: user id, email, role, and status. Also reports how many |
list_payment_methods | read | The cards saved for this workspace, and which one is the default that subscription and usage charges are billed to. |
list_plans | read | List the available subscription plans (seats, included credits, and monthly/yearly prices). Prices are provisioned in Stripe automatically. |
list_seats | read | List the workspace |
list_top_up_requests | read | List the workspace |
preview_credit_purchase | read | What a credit purchase will cost, before buying: credits, tax and total. Quoted from the same Stripe tax rates buy_credits will charge, so the two agree. |
preview_plan_change | read | What moving to a plan would cost, WITHOUT making the change. Returns four numbers, and they mean different things: \ |
quote_plan_change | read | Price an open plan-change request (platform operators only). Give a credit quantity and a price PER CREDIT — the total is computed here, so the figure a customer accepts and the figure they are charged cannot drift. Charges nothing: they accept with accept_plan_quote. |
remove_member | destructive | Remove somebody from the workspace. Their seat assignment and any granted allowance |
remove_payment_method | destructive | Remove a saved card. Removing the default is refused while another card exists — Stripe does not promote a replacement, so the next invoice would simply fail. |
rename_workspace | write | Rename the workspace. The name appears on invoices, in the members list, and wherever |
request_plan_change | write | Ask an owner to move the workspace up a plan. Use when usage is exhausted and the plan has no per-seat allowance to top up. Does NOT change the plan or take a payment — it queues the ask for whoever can. The plan defaults to the next one up. |
request_seat_change | write | Ask an owner to move you to a bigger seat. Use when a seat |
request_top_up | read | Ask for extra credits on a member |
resolve_plan_request | read | Mark a plan-change or seat-change request handled or refused (admin). Recording it handled does NOT move anything — use change_plan or assign_seat_type for that, and change_plan takes a payment. |
revoke_api_key | destructive | Revokes (deletes) an API key by id. Use list_api_keys to find the id. The revoked key stops working immediately. Free. |
revoke_invitation | destructive | Cancel a pending invitation, freeing the seat it was holding. |
sell_credits | read | |
set_auto_reload | write | Configure automatic credit reload. When your balance drops to or below the threshold after a tool call, your saved card is charged to bring the balance back to reload_to. Requires a saved card (use buy_credits first). |
set_billing_profile | write | Update the billing details. Only the fields you pass are changed; pass an empty string to clear one. The address determines the tax charged on future invoices — Stripe does not reissue invoices already sent. |
set_default_payment_method | write | Choose which saved card future charges are billed to. Use get_billing_portal to ADD a card — that needs a browser to confirm it with Stripe. |
set_spend_controls | write | Set your workspace |
set_tax_id | write | Set the workspace |
view_invoice | read | Returns one invoice by id: amount, status, date, and a hosted link to view it in the browser. |
Trust audit
CAUTIONgrade B · trust 86/100 Install with care. The audit found things worth knowing before you trust its output.
| Layer | What it checks | Result |
|---|---|---|
| L0 | Provenance & inventory | PASS |
| L1 | Static analysis of the code | WARN |
| L2 | Instruction surface (what it tells the agent) | PASS |
| L3 | Class-specific surface | WARN |
| L4 | Behavioural (sandbox) | SKIPPED |
What the source does
- Filesystem
- declared (6 observation(s))
- Network
- declared (7 observation(s))
- Shell
- none-observed
- Dependencies
- not all pinned
- Secrets in source
- none-found
Findings (15)
const endpoint = `http://127.0.0.1:${server.address().port}/api/notify`;webhookNotifier({ endpoint: `http://127.0.0.1:${deadPort}/gone`, secret, retries: 1, timeoutMs: 4000 }),remove_member, remove_payment_method, revoke_api_key, revoke_invitation
.releaserc.json
import { runWithAuth, runWithPrincipal } from "../../dist/auth.js";import { lookupKeyFor } from "../../dist/plans.js";import { __setPlanPricesForTests } from "../../dist/plans.js";import { getWorkOS } from "../../dist/workos.js";import { ADMIN_ROLE_SLUG, listWorkOSRoleSlugs } from "../../dist/workos-setup.js";@stripe/react-stripe-js, @stripe/stripe-js, @workos-inc/node, eu-vat-rates-data, stripe, @semantic-release/changelog, @semantic-release/exec, @semantic-release/git
- **Event polling instead of webhooks** (`events.ts`): a product choice — zero webhook secret, zero dashboard. **ONE EVENT MUST NOT WEDGE THE SWEEP**, and it did: a handler throw left the stored curso
`createAgentAuth({ adapter, config, branding, paths?, identityTypes?, baseUrl?, claimStore?, policy? })` returns framework-agnostic `(Request)=>Response` handlers implementing the [WorkOS auth.md](htt**Opening a Checkout Session was always the library's; FINISHING one was every consumer's.** `completeCheckout(adapter, sessionId, opts)` / `api.checkout.complete` is the composite, because it is not
* **webhook:** forward subscription checkouts; expose session metadata ([1815d0b](https://github.com/arnaudjnn/billing-tools/commit/1815d0bbacbcb9421f3ec7dd177355173fa6cd9c))
// app/api/stripe/webhook/route.ts → export const POST = webhook // raw body: keep it out of session middleware
Gates applied: no_behavioural_pass.
6377a9ae5fa8full audit observations/trust-audit/mcp-server/arnaudjnn__billing-tools.json · Report an issue / request a re-scanAudit history
Every audit this server has had. A grade with a past is a grade somebody is still checking.
| Date | Source | Verdict | Grade | Score | Change |
|---|---|---|---|---|---|
| 2026-10-12 | 6377a9ae5fa8 | CAUTION | B | 86 | first audit |
Questions
What is the @arnaudjnn/billing-tools MCP server?
The get-paid engine for Stripe + WorkOS apps, for humans and AI agents.
What tools does @arnaudjnn/billing-tools expose?
51 in total: 36 read-only, 11 that write, and 4 that can delete or overwrite (remove_member, remove_payment_method, revoke_api_key, revoke_invitation). Every one is listed on this page with its risk.
Is @arnaudjnn/billing-tools safe to connect to an agent?
With care. The audit graded it B (86/100) and found 15 things worth knowing before you trust this server, listed below with the exact line each was found on. Separately from the audit: 4 of its tools can destroy data, so scope the token you give it to what you actually need.
What credentials does @arnaudjnn/billing-tools need?
It reads BILLING_OPERATOR_TOKEN, REFRESH_TOKEN_SECRET, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET and WORKOS_API_KEY from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.
How current is this page?
The grade is for one exact copy of the source (6377a9ae5fa8), read on 2026-10-12. The repository is watched and re-audited when it changes.