Atlas / MCP servers / arnaudjnn / Billing Tools

Billing ToolsCAUTION

mcp/arnaudjnn/billing-tools

The get-paid engine for Stripe + WorkOS apps, for humans and AI agents.

Verdict
CAUTION
Grade
B
Trust score
86 /100
Exposed tools
51 36r · 11w · 4d
Transport
—
License
MIT
Stars
0
01

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

Read from source at commit 6377a9ae5fa8OBSERVED · 2026-10-12
02

Connect

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-code
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]
claude-desktop
{
  "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}"
      }
    }
  }
}
03

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.

ToolRiskDescription
accept_plan_quotereadAccept 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_upreadApprove 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_typereadAssign a workspace member to a seat type (e.g. standard, premium). The member
broke_toolreadrefuses for money
buy_creditsreadPurchase credits. 1 unit of currency = 100 credits. HOW it is paid for is \
cancel_planreadCancel 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_rolewriteMove a member between roles (${roles.join(
change_planread
close_workspacewriteStop a workspace: cancel its billing, KEEP its invoices, and return each member
create_api_keywrite
deny_top_upreadDeny a pending top-up request.
download_invoicereadReturns a direct PDF link for one invoice. Drafts and auto-reload receipts have no PDF; use view_invoice for those.
echoreadEcho the arguments
get_api_keyreadProvisions 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_portalreadGet 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_profilereadThe workspace
get_credit_balancereadReturns your current credit balance, per-tool costs, and auto-reload settings.
get_org_usagereadEvery 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_planreadThe workspace
get_spend_controlsreadYour workspace
get_usagereadGet your workspace
get_usage_limitsreadGet 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_upreadGrant 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_memberreadInvite somebody to the workspace by email. Roles: ${roles.join(
list_api_keysreadLists the API keys for your workspace (obfuscated values, never the full key). Useful for finding stale keys to revoke. Free.
list_invitationsreadInvitations for this workspace and their state (pending, accepted, expired, revoked).
list_invoicesreadReturns your recent invoices with amounts, dates, status (paid/open), and links to view/download PDFs.
list_membersreadList everyone in the workspace: user id, email, role, and status. Also reports how many
list_payment_methodsreadThe cards saved for this workspace, and which one is the default that subscription and usage charges are billed to.
list_plansreadList the available subscription plans (seats, included credits, and monthly/yearly prices). Prices are provisioned in Stripe automatically.
list_seatsreadList the workspace
list_top_up_requestsreadList the workspace
preview_credit_purchasereadWhat 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_changereadWhat moving to a plan would cost, WITHOUT making the change. Returns four numbers, and they mean different things: \
quote_plan_changereadPrice 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_memberdestructiveRemove somebody from the workspace. Their seat assignment and any granted allowance
remove_payment_methoddestructiveRemove 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_workspacewriteRename the workspace. The name appears on invoices, in the members list, and wherever
request_plan_changewriteAsk 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_changewriteAsk an owner to move you to a bigger seat. Use when a seat
request_top_upreadAsk for extra credits on a member
resolve_plan_requestreadMark 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_keydestructiveRevokes (deletes) an API key by id. Use list_api_keys to find the id. The revoked key stops working immediately. Free.
revoke_invitationdestructiveCancel a pending invitation, freeing the seat it was holding.
sell_creditsread
set_auto_reloadwriteConfigure 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_profilewriteUpdate 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_methodwriteChoose 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_controlswriteSet your workspace
set_tax_idwriteSet the workspace
view_invoicereadReturns one invoice by id: amount, status, date, and a hosted link to view it in the browser.
04

Trust audit

CAUTIONgrade B · trust 86/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (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)

MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
scripts/live/13-notifications-quotes-alerts.mjs:68
const endpoint = `http://127.0.0.1:${server.address().port}/api/notify`;
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
scripts/live/13-notifications-quotes-alerts.mjs:470
webhookNotifier({ endpoint: `http://127.0.0.1:${deadPort}/gone`, secret, retries: 1, timeoutMs: 4000 }),
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
remove_member, remove_payment_method, revoke_api_key, revoke_invitation
Why it matters. 4 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.hidden_file · CWE-1104
.releaserc.json
.releaserc.json
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/lib/callers.mjs:7
import { runWithAuth, runWithPrincipal } from "../../dist/auth.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/lib/scratch-stripe.mjs:26
import { lookupKeyFor } from "../../dist/plans.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/lib/scratch-stripe.mjs:27
import { __setPlanPricesForTests } from "../../dist/plans.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/lib/scratch-workos.mjs:10
import { getWorkOS } from "../../dist/workos.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
scripts/lib/scratch-workos.mjs:11
import { ADMIN_ROLE_SLUG, listWorkOSRoleSlugs } from "../../dist/workos-setup.js";
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@stripe/react-stripe-js, @stripe/stripe-js, @workos-inc/node, eu-vat-rates-data, stripe, @semantic-release/changelog, @semantic-release/exec, @semantic-release/git
Why it matters. 18 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
AGENTS.md:69
- **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
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
AGENTS.md:493
`createAgentAuth({ adapter, config, branding, paths?, identityTypes?, baseUrl?, claimStore?, policy? })` returns framework-agnostic `(Request)=>Response` handlers implementing the [WorkOS auth.md](htt
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
AGENTS.md:749
**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
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
CHANGELOG.md:1927
* **webhook:** forward subscription checkouts; expose session metadata ([1815d0b](https://github.com/arnaudjnn/billing-tools/commit/1815d0bbacbcb9421f3ec7dd177355173fa6cd9c))
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
README.md:262
// app/api/stripe/webhook/route.ts →  export const POST = webhook      // raw body: keep it out of session middleware
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 6377a9ae5fa8full audit observations/trust-audit/mcp-server/arnaudjnn__billing-tools.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-126377a9ae5fa8CAUTIONB86first audit
06

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.

Advertisement