Skip to main content
Glama
nnishad

open-splitwise

by nnishad

open-splitwise

Turn Splitwise into an agent-native expense tracker.

An open Model Context Protocol (MCP) server that lets any AI agent — Hermes, Claude Desktop, Claude Code, Cursor, or anything that speaks MCP — read balances, split expenses from messy natural language, diagnose its own auth problems, and never think about rate limits.

Python 3.11+ · MCP spec 2026-07-28 · stdio transport · 33 tools · lazy-loaded


Why

Existing Splitwise integrations hand the model a raw API mirror and hope for the best. That fails in predictable ways: the model invents category IDs, mis-splits ₹300 three ways, believes Splitwise's 200 OK when the request actually failed, or treats a rate-limit response as a bug to retry aggressively.

open-splitwise fixes this at the server layer:

Problem for agents

What open-splitwise does

"Split dinner with Alice" requires 3–4 API calls + arithmetic

quick_add_expense resolves names → IDs, computes cent-exact shares, picks the category, posts once

Two Alices in your friends list

resolve_users returns candidate lists so the agent asks you which one

"What do I owe?" needs multi-endpoint aggregation

money_summary returns per-currency totals in one call

Splitwise returns 200 OK with an errors object

Server checks it; failures surface as tool errors with actionable text — never false success

HTTP 429 rate limits

Retried invisibly (Retry-After honored, exponential backoff fallback)

Key revoked / logged out mid-session

Errors tell the agent the cause and to run setup_auth; new keys apply instantly, no restart

33 tool schemas burn ~4k tokens in every prompt

Lazy tool discovery: only 7 essential tools are exposed by default; search_tools("expenses") loads the rest on demand with full schemas

Features

  • Complete API coverage — all 27 endpoints of the official Splitwise OpenAPI 3.0 spec, one tool each, faithful names.

  • Workflow layer — high-level tools so a single utterance maps to a single call.

  • Self-service auth lifecyclesetup_auth validates a key live against Splitwise before storing it (wrong keys are never persisted), get_auth_status explains what's configured, logout clears credentials. Re-auth works mid-session.

  • Honest errors — every failure mode (unresolved person, share-sum mismatch, unknown category, revoked key, exhausted retries) returns text telling the agent exactly what happened and what to do next.

  • Safe-by-default annotations — reads carry readOnlyHint, destructive deletes carry destructiveHint, per MCP 2026-07-28 semantics. Tools register in deterministic order for cache-friendly discovery.

  • Local-first secrets — API key stored at ~/.config/splitwise-mcp/credentials.json, mode 0600, atomic writes, never echoed back (masked previews only).

Quick start

git clone https://github.com/<you>/open-splitwise.git
cd open-splitwise
uv sync

Run it standalone (stdio):

uv run open-splitwise          # starts with no key configured — see auth below

Get an API key at https://secure.splitwise.com/apps (Account Settings → API keys).

Connect any MCP client

Generic stdio block (Claude Desktop claude_desktop_config.json, Claude Code .mcp.json, Cursor, …):

{
  "mcpServers": {
    "splitwise": {
      "command": "uv",
      "args": ["--directory", "/absolute/path/to/open-splitwise", "run", "open-splitwise"],
      "env": { "SPLITWISE_API_KEY": "<optional: preconfigure>" }
    }
  }
}

Connect Hermes Agent

Add to ~/.hermes/config.yaml:

mcp_servers:
  splitwise:
    command: "uv"
    args: ["--directory", "/absolute/path/to/open-splitwise", "run", "open-splitwise"]
    env:
      SPLITWISE_API_KEY: "<optional>"
    tools:
      include: [quick_add_expense, resolve_users, money_summary, get_auth_status]
    prompts: false
    resources: false

Then /reload-mcp. Start with the four workflow/auth tools above; add raw API tools only when needed — Hermes' per-server filtering keeps the tool surface small.

Authentication lifecycle

The server is designed so agents diagnose and fix auth themselves, asking you only for the secret:

Situation

Agent-visible behavior

No key anywhere

Every tool fails with: "No Splitwise API key is configured. Ask the user to generate one at secure.splitwise.com/apps, then call setup_auth."

User provides a key

setup_auth(api_key) probes /get_current_user first — invalid keys are rejected, not stored; valid keys are saved and who they belong to is reported

Key revoked / account logged out (HTTP 401/403)

Tools fail with "key may have been revoked, expired, or the account was logged out… ask the user for a fresh key and call setup_auth"

Diagnosis

get_auth_status(){configured, source: stored|environment, masked_key}

Switching accounts

logout() deletes the stored credential

Key resolution happens per request: stored credential → SPLITWISE_API_KEY env var → none. A freshly saved key takes effect immediately in the running process — zero restarts.

Credentials live at ~/.config/splitwise-mcp/credentials.json (mode 0600). Override the directory with SPLITWISE_MCP_CONFIG_DIR (handy for tests or multi-profile setups).

Agent ergonomics

You:      "add dinner 900 split with alice and bob@x.com, groceries"
Agent:    quick_add_expense(description="Dinner", cost="900.00",
                            participants=["alice", "bob@x.com"],
                            category_name="groceries")
Server:   resolves alice→12? two matches! → error listing Alice A (id 10), Alice Wood (id 12)
Agent:    "Which Alice?"  → you answer → re-call succeeds
Server:   { status: created, expense_id: 99123,
            splits: [ "Nikhil paid 900.00 INR",
                      "Alice A owes 300.00 INR",
                      "Bob B owes 300.00 INR" ] }
  • quick_add_expense — names/partial-names/emails/IDs accepted; equal shares computed with remainder cents distributed deterministically; custom owed_shares validated to sum exactly; payer included by default (include_payer_in_split=false when they didn't consume); currency defaults from your profile.

  • resolve_users — email exact-match, full-name match, unique first-name, substring fallback; ambiguity returns candidates instead of guessing.

  • money_summary — per-currency owed_to_you / you_owe / net, friend-level balances, and group simplified debts involving you.

Tool reference (33)

Group

Tools

Workflows

quick_add_expense · resolve_users · money_summary

Users

get_current_user · get_user · update_user

Groups

get_groups · get_group · create_group · delete_group* · undelete_group · add_user_to_group · remove_user_from_group

Friends

get_friends · get_friend · create_friend · create_friends · delete_friend*

Expenses

get_expenses · get_expense · create_expense · update_expense · delete_expense* · undelete_expense

Comments

get_comments · create_comment · delete_comment*

Notifications

get_notifications

Other

get_currencies · get_categories

Auth

setup_auth · get_auth_status · logout*

* annotated destructiveHint=true; all get_* tools annotated readOnlyHint=true. Prefer workflow tools over their raw counterparts whenever both exist.

Rate limiting

Splitwise answers HTTP 429 when throttled. open-splitwise retries automatically: Retry-After header honored verbatim; otherwise exponential backoff (0.5 s doubling, capped at 30 s), up to 3 attempts by default. Agents see an error only if every attempt is exhausted — and that error says to slow down, not retry blindly.

Configuration

Env var

Default

Purpose

SPLITWISE_API_KEY

Bootstrap key (stored credentials take precedence)

SPLITWISE_MCP_CONFIG_DIR

~/.config/splitwise-mcp

Where credentials.json lives

SPLITWISE_MCP_MAX_RETRIES

3

429 retry attempts before surfacing

SPLITWISE_MCP_LAZY

on

off registers all 33 tools upfront

Splitwise quirks handled for you

  • Array params flattened to Splitwise's odd users__{index}__{property} encoding

  • 200 OK ≠ success: errors{} / success:false checked on every mutation

  • Money as decimal strings with 2 dp; remainder cents distributed, sums always exact

  • category_id must be a subcategory — enforced via fuzzy name resolution

  • Balances/debts read from pre-computed balance[] / simplified_debts (never recomputed)

  • "Settle up" is just an expense with payment:true (no dedicated endpoint exists)

  • OAuth2 exists but is deliberately out of scope: personal API keys fit the agent-asks-user flow; OAuth needs a redirect URI + browser (hosted deployments only)

Architecture

┌─────────────── any MCP client ───────────────┐
│  Hermes / Claude Desktop / Cursor / …        │
└──────────────────┬───────────────────────────┘
                   │ JSON-RPC over stdio
┌──────────────────▼───────────────────────────┐
│ server.py — FastMCP app, 33 tools            │
│   workflows · raw endpoints · auth lifecycle │
├──────────────────────────────────────────────┤
│ client.py — async REST client                │
│   bearer auth (per-request key resolution)   │
│   param flattening · success verification    │
│   transparent 429 retry/backoff              │
├──────────────────────────────────────────────┤
│ auth.py — credentials.json (0600, atomic)    │
└──────────────────┬───────────────────────────┘
                   │ HTTPS
          secure.splitwise.com/api/v3.0

Development

uv run pytest                        # 54 tests: client, rate limits, auth, workflows, lazy loading, MCP semantics
uv run python scripts/smoke_stdio.py # real subprocess: handshake, discovery, live auth-failure paths

Built test-first (strict TDD): every behavior above has a failing-test-first provenance. Layout:

src/open_splitwise/
  client.py    # REST client: auth provider, flattening, retry, error mapping
  auth.py      # credential storage
  server.py    # FastMCP definitions: workflows + raw + auth tools
tests/
scripts/smoke_stdio.py

Terms of use

Splitwise's self-serve API is non-commercial per their API terms. Your API key grants full access to your account — treat it like a password. This project is an independent integration and is not affiliated with or endorsed by Splitwise Inc.

Roadmap

  • Receipt upload on expense creation

  • Multi-currency expense helper with conversion awareness

  • Recurring-expense summaries as an MCP prompt

  • Optional Streamable HTTP transport for hosted/multi-user deployments (+OAuth2)

  • Publish to PyPI (uvx open-splitwise)

Contributing

PRs welcome — please keep the TDD discipline (tests fail first, then pass), keep tool descriptions written for models, and never log secrets.

License

MIT — open for everyone: use it, modify it, ship it, sell with it. Just keep the copyright notice.

-
license - not tested
Not graded
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • Connect AI agents to bank accounts, transactions, balances, and investments.

  • Log, query, and edit expenses, budgets, and accounts in Ledgy from any MCP-compatible AI assistant.

  • Live & historical FX rates and currency conversion for AI agents. No API keys.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nnishad/open-splitwise-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server