Skip to main content
Glama
split-bill-mcp

split-bill-mcp

by elyor-sh

split-bill-mcp

MCP server (stdio) for SplitBill (a Next.js app for splitting bills between friends). It lets an AI agent create bills from split receipts, list and filter bills, update payment statuses, and look up users — all through the SplitBill REST API.

How it works

  • The server logs in to SplitBill as a service user (email + password from env) via the NextAuth credentials flow, caches the session cookie, and re-logs in once on 401.

  • Money math is cent-exact: receipt positions are split per consumer, remainder cents go to the first consumers, and Σ per-person == total is verified before every create_bill.

  • Responses are language-neutral JSON (data) plus a short human summary (English by default, Russian with lang: "ru"). Item names and titles are never translated — they pass through byte-for-byte.

Related MCP server: Splitwise MCP Server

Prereqs

  • Node 20+

  • A running SplitBill instance, e.g. http://localhost:3000

  • A service user registered in SplitBill via /auth/register and confirmed (registration sends a confirmation link; the account must be confirmed before the MCP server can log in as it)

Setup

git clone <this-repo> split-bill-mcp
cd split-bill-mcp
npm install
cp .env.example .env  # then fill in the values below
npm run build

Environment

Variable

Required

Default

Description

SPLITBILL_BASE_URL

yes

—

SplitBill origin, e.g. http://localhost:3000

SPLITBILL_EMAIL

yes

—

Service-user email

SPLITBILL_PASSWORD

yes

—

Service-user password

SPLITBILL_TIMEOUT_MS

no

15000

HTTP timeout per request (ms)

LOG_LEVEL

no

info

debug | info | warn | error (reserved)

Missing/invalid vars fail fast at startup with Invalid MCP configuration: VAR: reason.

Connect a client

Build first (npm run build), then pick your client. Replace <path-to-split-bill-mcp> with the directory where you cloned this repo. Secrets can live in the client config or in a .env file next to dist/.

Claude Code — one command (writes to ~/.claude.json):

claude mcp add \
  --env SPLITBILL_BASE_URL=http://localhost:3000 \
  --env SPLITBILL_EMAIL=agent@example.com \
  --env SPLITBILL_PASSWORD=change-me \
  --transport stdio split-bill --scope user \
  -- node <path-to-split-bill-mcp>/dist/index.js

Check with claude mcp list. Or share with the team via .mcp.json (--scope project instead of --scope user).

Codex — one command (writes to ~/.codex/config.toml):

codex mcp add split-bill \
  --env SPLITBILL_BASE_URL=http://localhost:3000 \
  --env SPLITBILL_EMAIL=agent@example.com \
  --env SPLITBILL_PASSWORD=change-me \
  -- node <path-to-split-bill-mcp>/dist/index.js

Check with codex mcp list. Or edit ~/.codex/config.toml by hand:

[mcp_servers.split-bill]
command = "node"
args = ["<path-to-split-bill-mcp>/dist/index.js"]

[mcp_servers.split-bill.env]
SPLITBILL_BASE_URL = "http://localhost:3000"
SPLITBILL_EMAIL = "agent@example.com"
SPLITBILL_PASSWORD = "change-me"

OpenCode — no install command exists, copy this into opencode.json / opencode.jsonc (global ~/.config/opencode/ or project root):

{ "$schema": "https://opencode.ai/config.json",
  "mcp": { "split-bill": {
    "type": "local",
    "command": ["node", "<path-to-split-bill-mcp>/dist/index.js"],
    "environment": {
      "SPLITBILL_BASE_URL": "http://localhost:3000",
      "SPLITBILL_EMAIL": "agent@example.com",
      "SPLITBILL_PASSWORD": "change-me"
    }
  } } }

Pi — pi install only installs Pi extensions, not MCP servers, so a one-liner for our server alone is impossible. Two steps instead: install an MCP client extension, then add the server to its config:

pi install npm:pi-mcp-extension

~/.pi/agent/mcp.json (global) or .pi/mcp.json (project):

{ "mcpServers": { "split-bill": {
  "command": "node",
  "args": ["<path-to-split-bill-mcp>/dist/index.js"],
  "transport": "stdio",
  "lifecycle": "eager",
  "env": {
    "SPLITBILL_BASE_URL": "http://localhost:3000",
    "SPLITBILL_EMAIL": "agent@example.com",
    "SPLITBILL_PASSWORD": "change-me"
  }
} } }

Check with /mcp inside Pi.

Tools

All tools accept an optional lang ("en" default, "ru" for Russian summaries) and return { data, summary, lang }. Users are referenced by email or userId everywhere and resolved automatically (ObjectId passthrough → own email → user search → friends).

create_bill

Create a bill. Two modes:

  • mode: "ready_split" — agent already split the receipt: participants: [{ user, items: [{ name, price, priceWithVat?, vat? }], totalSum }], payerId, optional title/description. Item sums are verified per participant (mismatch > 1 cent → VALIDATION_ERROR).

  • mode: "raw_receipt" — agent sends receipt positions and who shared what: receipt_items: [{ name, price, priceWithVat?, vat?, consumers: [email|userId], portions? }], payer, optional title/description. The server splits each position across consumers (equally or by portions) and builds the participants itself.

Missing priceWithVat defaults to price, missing vat to false (upstream requires priceWithVat).

Example (raw receipt, agent already figured out who ate what):

{ "mode": "raw_receipt",
  "receipt_items": [
    { "name": "Pizza", "price": 1200, "consumers": ["ann@x.ru", "bob@x.ru"] },
    { "name": "Tea", "price": 300, "consumers": ["ann@x.ru"] }
  ],
  "payer": "ann@x.ru", "title": "Dinner", "lang": "ru" }

→ data: { billId, title, total, per-person amounts/statuses }.

list_bills

List my bills with local filters (upstream has none): status (all|paid|unpaid|pending_confirmation|partial), role (all|creator|payer|debtor), search (title substring), date_from/date_to (must be parseable dates), page/limit. Returns the page plus grouped_by_status counts and a totals summary.

get_bill

billId → full bill with participants, amounts, and payment statuses.

update_payment

billId, participant (email or userId, case-insensitive), status (paid|unpaid|pending_confirmation). Marks one participant's share; returns the refreshed bill.

search_users

query (min 2 chars) → [{ id, name, email }]. Note: upstream search excludes you and your friends — use it to find strangers to add, list_friends for existing friends.

list_friends

Your friends as [{ id, name, email }]. include_requests: true also returns { sent, received } request queues.

get_dashboard_stats

{ totalBills, totalOwed, totalOwing, pendingBills, completedBills }.

Error codes

code

Meaning / what to do

AUTH_FAILED

Service-user login failed — check email/password, confirm the account, check SPLITBILL_BASE_URL. Single re-login only, no retry loops.

VALIDATION_ERROR

Input invalid (bad sums, bad dates, short query) — the message says exactly what mismatched. Fix the input, don't retry blindly.

RESOLVE_FAILED

Email/user not found — clarify the email or add them as a friend; close name matches are included when available.

BILL_API_ERROR

Upstream SplitBill error — status + verbatim upstream body included. POST calls are never auto-retried (not idempotent): on network/5xx failure during create, check list_bills before retrying to avoid duplicates.

Dev

npm test        # vitest, 30 tests
npm run dev     # stdio with tsx (needs env set)
npm run typecheck  # covers src + tests
npm run build   # tsc → dist/ (src only)

Available Tools

7 tools
create_billA

Create a SplitBill bill. mode=ready_split takes pre-split participants with totals; mode=raw_receipt takes receipt positions with consumers and splits them.

get_billA

Get one SplitBill bill by ID with participants and payment statuses.

Inputs: billId (required), lang.

get_dashboard_statsB

Get SplitBill dashboard totals: bill count, amounts owed and owing.

Inputs: lang.

list_billsA

List my SplitBill bills with filters by payment status, my role, title search, date range, and pagination.

Inputs: lang, page, role, limit, +4 more.

list_friendsB

List my SplitBill friends (for picking bill participants).

Inputs: lang, include_requests.

search_usersB

Search SplitBill users by name or email (to resolve participant IDs).

Inputs: query (required), lang.

update_paymentC

Update a participant payment status (paid, unpaid, pending_confirmation) on a bill.

Inputs: billId (required), status (required), participant (required), lang.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 7 tools

    Disambiguation4/5

    Most tools target distinct resources: bills, payments, users, friends, and stats. The only slight overlap is search_users versus list_friends, but their descriptions clarify that one resolves arbitrary users while the other picks from existing friends.

    Naming Consistency5/5

    All tool names follow a consistent verb_noun pattern in snake_case: create_bill, list_bills, get_bill, update_payment, search_users, list_friends, get_dashboard_stats. Pluralization is handled idiomatically per resource without mixing conventions.

    Tool Count5/5

    Seven tools is well-scoped for a split-bill domain. Each tool covers a distinct, necessary operation without redundancy or bloat.

    Completeness3/5

    The core bill workflow is covered: create, list, get, and update payment status. However, there is no update_bill or delete_bill operation, so editing or canceling a bill would be impossible through this server.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables AI assistants to manage Splitwise expenses with atomic duplicate prevention, smart fuzzy matching, and support for flexible split ratios between two people.
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables conversational control of Splitwise accounts through Claude AI, allowing users to add expenses, check group balances, record settlements, and manage payment splits using natural language commands. Supports multiple currencies and flexible splitting methods including equal, exact, and percentage-based divisions.
      1
      MIT
    • A
      license
      A
      quality
      C
      maintenance
      Enables managing Splitwise expenses and generating premium spending analytics with category breakdowns, trends, and settlement optimization through natural language.
      42
      MIT
    • A
      license
      A
      quality
      B
      maintenance
      Enables AI agents to manage Splitwise expenses through natural language, including reading balances, splitting costs, and handling authentication and rate limits automatically.
      7
      MIT