# Xupersplit [Health: Active]

**Category:** 💻 Developer Tools  
**Repository:** https://github.com/kanylbullen/xupersplit  
**GitHub Stars:** 4  
**Views:** 0  
**Installs:** 0  
**Upvotes:** 0  
**Directory Page:** https://allmcps.com/mcp/xupersplit

## Description
Split shared expenses in a group — no account needed. See who owes whom and settle up.

## Claude Desktop Quick Installation
Install path detected from listing signals. Uses `npx` (confidence: high):

```json
"mcpServers": {
  "xupersplit": {
    "command": "npx",
    "args": ["-y","mcp-remote"]
  }
}
```

## Documentation & README

<div align="center">

<img src="https://raw.githubusercontent.com/kanylbullen/xupersplit/HEAD/docs/cover.png" alt="xupersplit — split expenses, skip the fuss" width="640" />

# xupersplit

**Split shared expenses without the fuss.** Create a split, share the link, and
let everyone add what they paid — balances and who-owes-whom are worked out
automatically, with one-tap payments straight from the balance view.

[**split.xuper.fun**](https://split.xuper.fun) · English · [Svenska](https://github.com/kanylbullen/xupersplit/blob/HEAD/README.sv.md)

[![CI](https://github.com/kanylbullen/xupersplit/actions/workflows/ci.yml/badge.svg)](https://github.com/kanylbullen/xupersplit/actions/workflows/ci.yml)
&nbsp;[![License: MIT](https://img.shields.io/badge/License-MIT-0d9488.svg)](LICENSE)
&nbsp;[![MCP registry](https://img.shields.io/badge/MCP-registry-f59e0b.svg)](https://registry.modelcontextprotocol.io/v0/servers?search=xupersplit)
&nbsp;[![Live app](https://img.shields.io/badge/live-split.xuper.fun-0d9488.svg)](https://split.xuper.fun)

Next.js 16 · Supabase · Tailwind v4 · wagmi/viem

<br />

<img src="https://raw.githubusercontent.com/kanylbullen/xupersplit/HEAD/docs/demo.gif" alt="xupersplit demo — create a split, add an expense, then settle up onchain in USDC" width="240" />
&nbsp;
<img src="https://raw.githubusercontent.com/kanylbullen/xupersplit/HEAD/docs/screenshot-pay.png" alt="Pay dialog: a Swish QR with the exact amount already filled in" width="240" />
&nbsp;
<img src="https://raw.githubusercontent.com/kanylbullen/xupersplit/HEAD/docs/screenshot-shares.png" alt="New expense: splitting by shares, a couple counting double" width="240" />

<sub>Create a split and see who owes whom · a Swish QR with the amount already in it · splitting by shares</sub>

</div>

---

> **Works with AI agents.** xupersplit is an [MCP server](#mcp-server) too —
> point your assistant at one URL and it can create the split, add what everyone
> paid and tell you who owes whom. No account, no API key, nothing to install.
>
> ```
> claude mcp add --transport http xupersplit https://split.xuper.fun/api/mcp
> ```

## What it is

A clean, accountless expense splitter. The **secret link is the key** — anyone
with it can add expenses and settle up; no login required. Optional email
sign-in just makes your splits follow you across devices. Built as a one-prompt
project and grown from there.

## Features

- **No account needed.** The unguessable split link (122 bits of entropy) *is*
  the capability. Sign-in is optional.
- **Flexible splitting** — equal, weighted shares, or exact amounts, with cent
  rounding via the largest-remainder method.
- **Smart settlements** — the minimum set of "A pays B" transfers, with
  **partial payments** ("pay all or part") and strike-through once settled.
- **Don't settle too early** — see who has opened the split and who's marked
  themselves done; the pay dialog warns if someone hasn't weighed in yet.
- **Secure splits** *(optional, when signed in)* — bind participants to their
  accounts: you can only edit your own payment details and enter your own
  expenses. The creator picks who must log in, who can view, and how people join.
- **Multi-currency** — enter expenses in any currency with the rate **locked at
  save** (Kittysplit-style); set a main currency per split. Includes **sats** —
  run a whole split in bitcoin if you like.
- **Eight payment methods**, several with genuine one-tap prefill — [see below](#payments).
- **MCP server** — AI agents can run a whole split over
  [Model Context Protocol](#mcp-server), with no account and no API key.
- **Six languages** — English, Svenska, Norsk, Dansk, Suomi, Íslenska
  (auto-detected, switchable).
- **Privacy by design** — payment details can be wiped once everyone is square,
  inactive splits are purged after 6 months, IP hashes deleted within a day,
  CSV/JSON export, full GDPR policy.
- **Dark / light / system** theme, cookie-less analytics, discreet cookie notice.

## Payments

xupersplit stores each recipient's payment handle(s) and, wherever a payment
network exposes an **open, agreement-free** interface, turns the balance row
into a real one-tap payment — **prefilled with the exact amount**. No money ever
passes through xupersplit; it only builds the link/invoice/transaction the payer
approves in their own app.

| Method | Experience | How |
| --- | --- | --- |
| **Swish** 🇸🇪 | QR + app deep link, amount prefilled | Public `app.swish.nu` link + QR endpoint — no merchant contract |
| **Lightning** ⚡ | QR + `lightning:` link, **exact amount baked in** | LNURL-pay (LUD-16): a lightning address → BOLT11 invoice |
| **Ethereum / USDC** Ξ | **One-tap prefilled USDC** transfer | WalletConnect (Reown AppKit) — connect, pick chain, approve |
| **Solana / USDC** ◎ | **One-tap prefilled USDC** SPL transfer | WalletConnect (Reown AppKit) — Phantom/Solflare, recipient ATA auto-created |
| **Ethereum / Solana address** | Address QR + copy, ENS resolved | `0x…` / `name.eth` / base58 — for any wallet |
| **Revolut** | Clickable `revolut.me` profile link | Opens the recipient's profile to pay |
| **Vipps · MobilePay · IBAN** | Stored handle + copy button | No open P2P API — the payer finishes in their own app |

**Why the difference?** Swish exposes a genuinely open prefilled deep link and
QR endpoint; Lightning's LNURL and EVM/Solana over WalletConnect are open
protocols. Vipps
and MobilePay (now Vipps MobilePay) only offer amount-prefilled flows through
their **merchant** APIs — a business agreement that routes money to a company,
not person-to-person — so for those xupersplit does the honest thing and shows
the handle with a copy button. If they ever ship an open P2P deep link, wiring
it in is a small change. PRs welcome. 🤞

> **Crypto is irreversible.** Crypto methods show extra warnings, and **any**
> method warns (with a date) if the recipient's details were ever changed from
> what was first entered — anyone with the link can edit them.

## MCP server

xupersplit speaks [Model Context Protocol](https://modelcontextprotocol.io), so
an AI assistant can create a split, add what everyone paid and report who owes
whom — then hand you the link to share. Accountless like the rest of the app:
no sign-up, no API key.

```bash
claude mcp add --transport http xupersplit https://split.xuper.fun/api/mcp
```

Or point any MCP client at `https://split.xuper.fun/api/mcp` (Streamable HTTP;
stdio-only clients can bridge via `npx mcp-remote`). Self-hosted instances get
the same endpoint at their own `/api/mcp`.

It also works as a custom connector in **Claude** and **ChatGPT** on the web —
paste the endpoint, no authentication. ChatGPT needs developer mode switched on
first, or the option to add one isn't there at all. Step-by-step at
[/mcp](https://split.xuper.fun/mcp).

Eleven tools cover the whole lifecycle — `create_split`, `get_split`,
`add_expense`, `record_payment`, `update_entry`, `delete_entry`,
`add_participant`, `rename_participant`, `remove_participant`,
`set_payment_methods`, `update_split`. People are referred to by name and
amounts are plain decimals, so an agent never handles uuids or cents.

The server is a thin layer over the same RPCs and `money.ts` helpers the web app
uses, and it only ever holds the anonymous role — which is what keeps *secure*
splits (they need a signed-in `auth.uid()`) unreachable over MCP. Full details
at [/mcp](https://split.xuper.fun/mcp).

## Architecture

- **No service-role key in the app.** All data access goes through
  `security definer` Postgres RPCs (`split_data`, `save_entry`,
  `set_payment_methods`, …) where the secret split key in the URL is the
  capability. RLS is deny-all on every table and direct grants are revoked — the
  client only ever holds the public publishable key. Schema and every change
  live in [`supabase/migrations/`](https://github.com/kanylbullen/xupersplit/blob/HEAD/supabase/migrations).
- **Next.js App Router** + server actions; the client is plain React, no state
  library. Tailwind v4 with CSS-variable theming.
- **Thin, keyless API routes** proxy the open payment networks, all
  same-origin-locked: `/api/swish-qr`, `/api/ln-invoice` (LNURL-pay),
  `/api/ens` (viem), `/api/fx` (fiat + BTC, with provider fallback).
- **WalletConnect** is fully gated on a project id — absent, the EVM dialog
  cleanly falls back to QR + copy.
- **Privacy & abuse controls** — settle-time payment wipe (opt-out), 6-month
  purge of inactive splits, per-IP-hash + global create rate limits, and a
  daily job that flags split-key enumeration attempts.

## Tech stack

Next.js 16 · React 19 · TypeScript · Tailwind CSS v4 · Supabase (Postgres,
Auth) · wagmi + viem + @solana/web3.js + Reown AppKit · Playwright · Vercel

## Run it locally

```bash
npm install
cp .env.example .env.local   # add your own Supabase URL + anon key
npm run dev
```

`.env.local`:

```
NEXT_PUBLIC_SUPABASE_URL=https://<your-project>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<your publishable key>
# Optional — enables the WalletConnect USDC flow (free id from cloud.reown.com)
NEXT_PUBLIC_REOWN_PROJECT_ID=<your reown project id>
```

## Deploy your own

Self-hostable on the free tiers of **Supabase + Vercel**.

1. **Supabase** — create a project (EU regions keep data in Europe), then apply
   the schema with `supabase link --project-ref <ref> && supabase db push`
   (runs every migration in [`supabase/migrations/`](https://github.com/kanylbullen/xupersplit/blob/HEAD/supabase/migrations)).
   Grab the **Project URL** and **publishable (anon) key**. For optional email
   sign-in, configure SMTP and the `…/auth/confirm` redirect.
2. **Vercel** — import the repo, add `NEXT_PUBLIC_SUPABASE_URL` and
   `NEXT_PUBLIC_SUPABASE_ANON_KEY` (both safe to expose; security relies on RLS
   + RPCs). Add `NEXT_PUBLIC_REOWN_PROJECT_ID` too if you want WalletConnect.
   Deploy.
3. **Custom domain (optional)** — add it in Vercel, point a **DNS-only** CNAME
   to `cname.vercel-dns.com`, and add the domain's `…/auth/confirm` to the
   Supabase redirect allowlist if using email sign-in.

## Full self-host with Docker

Prefer to own the whole stack? [`selfhost/`](https://github.com/kanylbullen/xupersplit/blob/HEAD/selfhost) brings up the app **and
its own backend** — Postgres, auth (GoTrue), the REST/RPC layer (PostgREST) and
a local mailbox — with no external services. The app itself acts as the gateway,
so the browser only ever talks to one origin.

```bash
cd selfhost
cp .env.example .env       # ⚠️ change the secrets — see the notes in the file
docker compose up -d --build
```

- App: **http://localhost:3000**. Sign in with **email + password** (works
  instantly, no SMTP needed) — or use the magic code, which lands in **Mailpit**
  at **http://localhost:8025**.
- **HTTPS** is one flag away: point a domain at the host, set `DOMAIN` +
  `ACME_EMAIL` and `SITE_URL=https://…` in `.env`, then
  `docker compose --profile tls up -d --build` — Caddy fetches and renews a
  Let's Encrypt certificate automatically. Behind NAT or want a wildcard cert?
  Set `CF_API_TOKEN` (a scoped Cloudflare token) and Caddy uses the DNS-01
  challenge instead — no port 80 exposure needed.
- The migrations in [`supabase/migrations/`](https://github.com/kanylbullen/xupersplit/blob/HEAD/supabase/migrations) are applied
  automatically on first start.
- `.env.example` ships with **public demo** JWT keys so it runs out of the box.
  For anything internet-facing, change `JWT_SECRET` + the passwords and
  regenerate `ANON_KEY`/`SERVICE_ROLE_KEY` (any JWT tool works — sign
  `{"role":"anon",...}` / `{"role":"service_role",...}` with the new secret).
- Set `APP_PORT` / `MAILPIT_PORT` in `.env` to change host ports;
  `REOWN_PROJECT_ID` enables the WalletConnect pay buttons.

See **[`selfhost/README.md`](https://github.com/kanylbullen/xupersplit/blob/HEAD/selfhost/README.md)** for the full guide —
secret regeneration, the gateway architecture, Cloudflare DNS-01, a config
reference and troubleshooting.

## Tests & CI

Playwright smoke tests (`npm run test:e2e`) run on every PR against a local
production build, gating merges to `main`; the pure split/balance/settlement
logic lives in `src/lib/money.ts`.

## Contributing

Issues and PRs are welcome, and so is a bug report from someone who just used
the site. Start with [CONTRIBUTING.md](https://github.com/kanylbullen/xupersplit/blob/HEAD/CONTRIBUTING.md).

> **Never post a split link.** A split's URL is its password — anyone who sees
> it can read and edit that split, and issues are public and indexed. Describe
> the problem, or make a throwaway split with fake names.

- 🐛 [**Report a bug**](https://github.com/kanylbullen/xupersplit/issues/new?template=bug_report.yml) — or just email **split@xuper.fun** if a GitHub account is a hassle
- 💡 [**Suggest a feature**](https://github.com/kanylbullen/xupersplit/issues/new?template=feature_request.yml)
- 🔒 [**Report a vulnerability privately**](https://github.com/kanylbullen/xupersplit/security/advisories/new) — never as a public issue; see [SECURITY.md](https://github.com/kanylbullen/xupersplit/blob/HEAD/SECURITY.md)
- 🌱 [**good first issue**](https://github.com/kanylbullen/xupersplit/labels/good%20first%20issue) — small, self-contained tasks

Most wanted right now: a real open P2P deep link for **Vipps** or **MobilePay**
so the amount can be prefilled the way Swish and Lightning already do, plus
additional payment rails and translation fixes across the six locales. The
codebase is small and fully typed.

## License

MIT — see [LICENSE](https://github.com/kanylbullen/xupersplit/blob/HEAD/LICENSE).

---

<div align="center">

If xupersplit saved your group some bickering, you can

[![Buy me a beer](https://img.shields.io/badge/Buy%20me%20a%20beer-%F0%9F%8D%BA-9A7BFF?style=for-the-badge)](https://beer.xuper.fun/?from=github)

*built with love, coffee and beer*

</div>

