amazing-splitwise-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@amazing-splitwise-mcpwhat does Ana owe me in the Ski trip group?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Splitwise MCP Server (amazing-splitwise-mcp)
A Model Context Protocol server for the Splitwise API v3.0, built on the official MCP Python SDK (FastMCP). It authenticates with a personal API key — no OAuth — so an LLM can read your groups, friends, balances, expenses, comments and notifications, resolve people and categories by name, and — only when you flip the kill-switch — create, update, delete and restore expenses, groups, friends and comments. It runs over stdio by default and ships a second entry point that serves streamable-http behind a bearer token for clients that can only reach a public URL (Grok Bot, for one).
The PyPI distribution and console script are both
amazing-splitwise-mcp(the baresplitwise-mcpandsplitwise-mcp-servernames on PyPI belong to unrelated packages). Always runuvx amazing-splitwise-mcp.
Safety model
Four rails, all enforced in the HTTP client — not in the tools — so no tool can forget them:
Writes are off by default. Every
POSTon this API changes your account (there is no POST that only reads), so anything that creates, updates, deletes or restores an expense, group, friend or comment, or edits your profile, returnsError: … writes are disableduntilSPLITWISE_ALLOW_WRITES=1. Those tools are marked 🔒 below. Reads need nothing.Your login can never be changed.
passwordis never sent anywhere andemailis never sent toupdate_user— the profile tool only edits name, locale and default currency, whatever an LLM asks for."200 OK" is not taken as success. Splitwise answers
200to failed writes and puts the failure in the body (success: falseor a non-emptyerrors). The client raises on that, so a tool can only claim what the body confirms; a partial batch (some friends added, some rejected) lists who did land.Confirmations never claim more than Splitwise said. A create echoes the expense Splitwise returned; an unreadable
200or a5xx/timeout on a write is reported as outcome UNKNOWN with the tool to read back before retrying — the server never retries a write on its own (a retriedcreate_expenseis a duplicate expense).
Everything an LLM sees is scrubbed of the API key and the HTTP bearer. One API key is an access token for your whole account: keep it like a password, and regenerate it on the apps page if it ever leaks. Found a way around one of these rails? Report it privately — see SECURITY.md.
One thing no rail can fix: expense descriptions, notes, comments and notification text are written by the other members of your groups and reach the LLM verbatim (tags stripped, table cells escaped). Treat them as data, not instructions — especially for a client that has writes enabled.
Related MCP server: splitwise-mcp
Features
Balances the way you ask for them. Who owes you and whom you owe, per friend and per currency with totals; per group with the simplified debts rendered as
A → B 12.50 USD.Expenses with three split modes. Equal split inside a group, explicit paid/owed shares, or "split equally between these people" — the shares are computed and checked locally (they must sum to the cost, to the cent) before anything is sent, so a bad split never reaches Splitwise.
Names, not ids.
splitwise_resolve_friend/_group/_categoryturn "Ana", "Ski trip" or "groceries" into the id the write tools need, with a score and an explicit ambiguous verdict when two people match.Groups, friends, comments, notifications, categories and currencies — the whole v3.0 surface (27 endpoints) minus the account's login.
Dual-format responses — markdown for humans and LLMs (default) or JSON for programmatic use, per call via
response_format.Strict inputs, uniform errors. One pydantic model per tool (
extra="forbid"), money as 2-decimal strings, ISO-8601 dates, and Splitwise's{"error"}/{"errors": {...}}bodies normalised into readable strings with a hint for the statuses that have a known fix.Two transports. stdio (every MCP client launches it as a subprocess) and a streamable-http server behind a shared bearer for clients that need a URL.
Available Tools
All 33 tools, grouped by module. 🔒 = refused unless SPLITWISE_ALLOW_WRITES=1.
Tool | Description |
Health | |
| Verify connectivity and the API key against Splitwise, and report the write kill-switch. |
Users | |
| Get the Splitwise user the API key belongs to: name, id, email, currency, locale, notifications. |
| Get another Splitwise user's public profile by id: name, email, registration status. |
| Update your Splitwise profile: first name, last name, locale and/or default currency. |
Groups | |
| Add a person to a group, by user id or by inviting a name + email. 🔒 write. |
| Create a group, optionally with members (you are added automatically). 🔒 write. |
| Delete a group and all its expenses — for every member, not just you. 🔒 destructive write. |
| Read one group: its members with balances, who owes whom, and the invite link. |
| List every group you belong to, with members count and balances per currency. |
| Remove a member from a group. 🔒 destructive write. |
| Restore a deleted group (and its expenses). 🔒 write. |
Friends | |
| Add one person as a Splitwise friend by e-mail. 🔒 Needs SPLITWISE_ALLOW_WRITES=1. |
| Add several people as Splitwise friends in one call. 🔒 Needs SPLITWISE_ALLOW_WRITES=1. |
| Remove a friendship (unfriend a user). 🔒 Needs SPLITWISE_ALLOW_WRITES=1. Destructive. |
| Get one Splitwise friend with their overall and per-group balances. |
| List your Splitwise friends with their balance per currency. |
Expenses | |
| Create an expense with exactly one split mode; the shares are checked locally before sending. |
| Delete an expense (Splitwise keeps it as deleted; restore with |
| Read one expense in full: cost, group, category, every share, repayments and comments. |
| List expenses, newest first, optionally filtered by group, friend and date range. |
| Restore a deleted expense. |
| Change an existing expense — only the fields given are sent. |
Balances | |
| Summarise who owes you and whom you owe, per friend and per currency. |
| Show each member's balance in one group and who should pay whom to settle it. |
Lookup — categories, currencies, name resolution | |
| List Splitwise's expense categories: each parent with its subcategories and their ids. |
| List the currency codes Splitwise accepts, optionally filtered by a substring. |
| Turn a category name into the subcategory id an expense needs, with ranked fuzzy candidates. |
| Turn a friend's name (or email) into their Splitwise user id, with ranked fuzzy candidates. |
| Turn a group's name into its Splitwise group id, with ranked fuzzy candidates. |
Comments | |
| Add a comment to a Splitwise expense. |
| Delete a comment from a Splitwise expense (destructive; comments have no undelete). |
| List the comments on one Splitwise expense. |
Notifications | |
| List your recent Splitwise activity (notifications), newest first. |
Read tools return markdown (default) or JSON; mutating tools return a confirmation that
echoes exactly what Splitwise returned. Tool arguments are nested under a single
params object ({"params": {"group_id": 123}}).
Prerequisites
uv — for the zero-install
uvxpath and for local development (Python 3.13+ is only needed for the clone path;uvxbrings its own).A Splitwise API key — which needs Splitwise Pro. Splitwise only lets a Pro subscriber register an application (the apps page shows "Get Splitwise Pro to register an application" otherwise), and the key comes from the registered app. With Pro active: sign in at https://secure.splitwise.com/apps → Register your application (any name, the URLs do not matter) → on the app's page click API key. It is a personal access token for your whole account — read and write. Regenerate it on the same page to rotate; if Pro lapses, the key stops working (401) until you resubscribe. The self-serve API is for personal use; commercial use needs a licence from Splitwise (see their terms on dev.splitwise.com).
(Optional) Docker if you prefer the container path.
Quickstart
git clone https://github.com/trustxai/splitwise-mcp.git
cd splitwise-mcp
uv sync --group dev
cp .env.example .env # set SPLITWISE_API_KEY
uv run amazing-splitwise-mcp # starts the stdio serverThe server speaks MCP over stdio, so it is normally launched by an MCP client (see
Client Configuration) rather than run by hand. Call
splitwise_health_check first: it reports connectivity, who you are logged in as (with
your user id, which the expense shares need), and whether writes are enabled.
Run with uvx (zero install)
SPLITWISE_API_KEY=your_key uvx amazing-splitwise-mcpUse
amazing-splitwise-mcp, notsplitwise-mcp. The bare name on PyPI is an unrelated package and will not run this server.
Client Configuration
Every client launches the server as a subprocess and passes the key through env.
Add "SPLITWISE_ALLOW_WRITES": "1" only for a client you want to be able to write.
Cursor
Add to ~/.cursor/mcp.json (global) or .cursor/mcp.json (per project):
{
"mcpServers": {
"splitwise": {
"command": "uvx",
"args": ["amazing-splitwise-mcp"],
"env": {
"SPLITWISE_API_KEY": "your_key"
}
}
}
}Claude Desktop
Edit claude_desktop_config.json (Settings → Developer → Edit Config; on macOS it lives
at ~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"splitwise": {
"command": "uvx",
"args": ["amazing-splitwise-mcp"],
"env": {
"SPLITWISE_API_KEY": "your_key"
}
}
}
}Restart Claude Desktop after saving.
Claude Code
claude mcp add splitwise --env SPLITWISE_API_KEY=your_key -- uvx amazing-splitwise-mcpOr add the equivalent block to ~/.claude.json under mcpServers (same shape as the
Cursor example above).
MCP Inspector
SPLITWISE_API_KEY=your_key npx @modelcontextprotocol/inspector uvx amazing-splitwise-mcpIf you cloned the repo, uv run mcp dev src/splitwise_mcp/server.py does the same (the
mcp dev CLI ships in the dev dependency group).
Docker
Build the image from the repo Dockerfile, then point any client at docker run:
docker build -t amazing-splitwise-mcp .{
"mcpServers": {
"splitwise": {
"command": "docker",
"args": ["run", "--rm", "-i", "-e", "SPLITWISE_API_KEY", "amazing-splitwise-mcp"],
"env": {
"SPLITWISE_API_KEY": "your_key"
}
}
}
}The -i flag is required — the server communicates over stdin/stdout.
Remote: streamable-http behind a bearer
Some hosts cannot spawn a local process and only accept an MCP server at a public URL (Grok Bot's connectors, for example). For those the same package ships a second console script:
SPLITWISE_API_KEY=your_key \
SPLITWISE_MCP_BEARER=$(openssl rand -hex 32) \
uvx --from amazing-splitwise-mcp amazing-splitwise-mcp-httpIt serves the MCP endpoint at http://127.0.0.1:8765/mcp and answers 401 to any
request that does not carry Authorization: Bearer <SPLITWISE_MCP_BEARER> — before any
routing, in constant time, without logging the presented token. Rules it enforces:
It refuses to start without a bearer of at least 32 characters, or when bound beyond loopback without
SPLITWISE_MCP_ALLOWED_HOSTS.It is loopback by default: put TLS in front of it — a reverse proxy or Tailscale Funnel. With Funnel, the path prefix is stripped before proxying, so the backend URL must carry the MCP path:
tailscale funnel --bg --https=443 --set-path=/splitwise http://127.0.0.1:8765/mcp # public URL: https://<node>.<tailnet>.ts.net/splitwise/Host pinning (DNS-rebinding protection) is on as soon as
SPLITWISE_MCP_ALLOWED_HOSTSis set — list the public hostname your proxy forwards; the server adds its own loopback addresses. A request with aHostnot on the list gets 421. With pinning on, a request carrying anOriginthat is not one of those hosts gets 403; a cloud client that sends its own Origin goes inSPLITWISE_MCP_ALLOWED_ORIGINS.It runs stateless (no server-side session ids) and keeps no access log, so no URL or header ever lands in your logs.
Connecting Grok Bot (or any URL-only client)
Add a connector with the public URL (keep the trailing slash:
https://<node>.<tailnet>.ts.net/splitwise/) and a custom header
Authorization: Bearer <SPLITWISE_MCP_BEARER>. Set SPLITWISE_ALLOW_WRITES=1 in the
server's environment only if that client should be able to create expenses. One bearer
is the whole account: rotate it (and the connector) if it ever leaks.
Environment Variables
Variable | Default | Meaning |
| — | Personal API key, sent as |
|
| Kill-switch. |
|
| REST base; override only for proxies/tests. |
|
| Per-request timeout. |
| — | HTTP only. Shared secret the client must present (≥ 32 chars). |
|
| HTTP only. Bind address. |
|
| HTTP only. Bind port. |
|
| HTTP only. Endpoint path. |
| — | HTTP only. Comma list of accepted |
| — | HTTP only. Extra |
|
| HTTP only. Stateless streamable-http. |
The stdio server reads only the first four. Values are whitespace-stripped on the way in (a pasted key with a trailing newline would otherwise be an illegal header).
Running Manually
uv run amazing-splitwise-mcp # stdio
uv run python -m splitwise_mcp # same
uv run amazing-splitwise-mcp-http # streamable-http (needs SPLITWISE_MCP_BEARER)The stdio server reads MCP JSON-RPC on stdin and writes it on stdout — nothing else is ever written to stdout.
Troubleshooting
Error (401): Unauthorized – Invalid API request: you are not logged in— the key is missing, mistyped, or was regenerated. Copy it again from your app's page at https://secure.splitwise.com/apps.Error: POST /create_expense would change your Splitwise account, but writes are disabled— by design. SetSPLITWISE_ALLOW_WRITES=1for that client.Error: Splitwise rejected the request to /…: <message>— Splitwise answered200withsuccess: falseor a non-emptyerrors; the message is theirs. For a batch (create_friends) the people that were added are listed under it.… outcome UNKNOWN; read back with …— a write got a5xx, a timeout or an unreadable body. Read the record back before retrying; a blind retry can duplicate it.cost must have at most 2 decimal places/paid shares … must equal the cost— Splitwise takes money as 2-decimal strings and the shares must sum to the cost on both sides; the tool checks locally and nothing was sent.Update accepted by Splitwise — N of M field(s) not confirmed—update_user's response does not echolocale/default_currency; read the profile back withsplitwise_get_current_userto confirm.I ran
uvx splitwise-mcpand got something else — that is an unrelated PyPI package. The script isamazing-splitwise-mcp.HTTP: 401 on every request — the
Authorization: Bearer …header is missing or wrong (exact match, one header). 421 — theHostis not inSPLITWISE_MCP_ALLOWED_HOSTS(matching is exact:example.com≠example.com:443). 403 "Invalid Origin header" — add the client's Origin toSPLITWISE_MCP_ALLOWED_ORIGINS. 404 behind a proxy — the proxy strips the path prefix; point it athttp://127.0.0.1:8765/mcp, not at the bare port.Balances look inverted — the sign convention is stated in every balance tool's output: positive = owed to you (verified against real expenses).
splitwise_resolve_categoryfinds nothing for "groceries" — category names come back in your account's locale (a Spanish account has "Supermercado"). Ask in the language you see in the Splitwise app, or browsesplitwise_get_categories; the ids are the same in every language.
Contributing
uv sync --group dev
uv run pytest -m "not live" && uv run ruff check src/ tests/ && uv run ruff format --check src/ tests/ && uv run mypy src/
uv run python scripts/gen_tool_table.py --check # README tool table is generated, never edited by handLive tests (-m live) run read-only against your own account when SPLITWISE_API_KEY is
in .env; the mutating live_write tests create and delete a throwaway group and only
run with SPLITWISE_TEST_ALLOW_WRITES=1. Commits follow
Conventional Commits; releases are cut by
release-please and published to PyPI through trusted publishing.
License
Apache-2.0 — see LICENSE.
Available Tools
33 toolssplitwise_add_user_to_groupA
Add a person to a group, by user id or by inviting a name + email. 🔒 write.
Calls POST /add_user_to_group with group_id plus EITHER user_id OR all of
first_name, last_name, email (a oneOf, checked locally before any call; an
invited email may receive a Splitwise invitation). Splitwise answers HTTP 200 even on
failure; the client turns success: false / non-empty errors into an error, and the
person is reported as added only when the body says success: true and returns the user.
Refused with Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. Undo:
splitwise_remove_user_from_group with the returned user id.
When to Use:
To add a friend (user id) or a new person (name + email) to an existing group.
When NOT to Use:
To create a group with its members in one call (use
splitwise_create_group).To find a friend's user id by name (use
splitwise_resolve_friendfirst), or a group's id by name (usesplitwise_resolve_group).
Returns:
A confirmation with the user Splitwise returned (First Last (id N)) and its success value.
Examples:
params = {"group_id": 12345, "user_id": 5823}
params = {"group_id": 12345, "first_name": "Ana", "last_name": "Diaz", "email": "ana@example.com"}
Error Handling:
Both or neither identity → rejected before the call; success: false → Error: Splitwise rejected the request ...; 403 → you are not a member of the group.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give generic hints (readOnlyHint=false, openWorldHint=true, idempotentHint=false), but the description goes well beyond: it discloses the SPLITWISE_ALLOW_WRITES=1 auth gate, local oneOf validation before any call, the fact that HTTP 200 can still mean failure and how success is determined, the 403 case, and the undo tool with the returned user id. This is exemplary behavioral disclosure for a mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Sections are clearly headed and front-loaded (what it does, endpoint, then when/when-not, returns, examples, errors). The length is justified by genuinely distinct information — auth gate, error semantics, undo path — with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite already having an output schema, the description still summarizes the return shape ('First Last (id N)' plus success value), and covers auth, validation, failure, and reversal. For a write tool with this complexity, nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the top-level params object carries no schema description (0% coverage signal), the description fully compensates by explaining the oneOf identity semantics (user_id OR first_name+last_name+email), that both-or-neither is rejected, and giving concrete param examples. It adds meaning the schema's per-field descriptions do not capture (the combination constraint).
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('add a person') and resource ('to a group') plus the two identity modes (existing user id vs. name+email invite). It explicitly names siblings it is not (splitwise_create_group, splitwise_resolve_friend, splitwise_resolve_group), so an agent can distinguish it without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has explicit 'When to Use' / 'When NOT to Use' sections naming concrete alternatives and the prerequisite resolve steps for finding ids. The conditions that select this tool versus others are spelled out, not inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_create_commentA
Add a comment to a Splitwise expense.
Write — refused unless SPLITWISE_ALLOW_WRITES=1. Calls POST /create_comment with
expense_id and content. Everyone on the expense can see the comment. Not
idempotent: calling it twice posts the comment twice.
When to Use:
To leave a note on an expense ("paid in cash", "includes the tip").
When NOT to Use:
To change the expense's own description or notes — use
splitwise_update_expense.To read existing comments — use
splitwise_get_comments.
Returns: A confirmation echoing the comment Splitwise returned: its id, the expense id, the author, the type, the creation time and the text.
Examples:
params = {"expense_id": 51023, "content": "Paid in cash, settled at dinner."}
Error Handling:
Refused with Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. A blank
content is rejected before any call. 404 = the expense does not exist or was
deleted; 403 = you are not part of it. On a timeout or 5xx the outcome is UNKNOWN —
read the comments back with splitwise_get_comments before retrying, or the comment
may be posted twice. Undo with splitwise_delete_comment.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: discloses the SPLITWISE_ALLOW_WRITES=1 gate, comment visibility ('everyone on the expense can see the comment'), non-idempotency with an explicit duplicate-post warning, 404/403 meanings, an UNKNOWN-outcome protocol for timeouts/5xx, and the undo path. The annotations (readOnlyHint=false, idempotentHint=false) are confirmed and enriched rather than merely restated.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The write-gate and non-idempotency warnings are front-loaded in the first two paragraphs, then sectioned into When to Use / Returns / Examples / Error Handling. Dense but every block carries actionable information, and the labeled structure makes it skimmable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating, non-idempotent, auth-gated tool this covers the failure modes an agent needs: write gating, visibility scope, duplicate-post hazard, status-code meanings, unknown-outcome recovery, and undo. An output schema exists, so the brief Returns line is a courtesy rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is reported at 0%, so the description must carry the load; it names both `expense_id` and `content`, notes content must be non-blank plain text, and supplies a literal params example showing shape and types. It stops short of explaining id format constraints or the max comment length, so it compensates well but not exhaustively.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add a comment to a Splitwise expense') and immediately distinguishes itself from siblings by naming splitwise_update_expense and splitwise_get_comments as the tools for adjacent jobs. An agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'When to Use' and 'When NOT to Use' sections with concrete triggers ('leave a note on an expense') and named alternatives for the two nearest confusable operations. Nothing about tool selection is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_create_expenseA
Create an expense with exactly one split mode; the shares are checked locally before sending.
Calls POST /create_expense. Refused with Error: … writes are disabled unless
SPLITWISE_ALLOW_WRITES=1 (the server's client enforces it; this tool never bypasses
it). Undo with splitwise_delete_expense. NOT idempotent: every successful call
creates a new expense — never retry blindly after a timeout; list first.
Pick EXACTLY ONE split mode:
A
split_equally: true— a GROUP expense (group_id > 0) that YOU paid, split equally among all group members by Splitwise.B
shares: [...]— explicit shares, one per participant (≥ 2), each withuser_idORemail+first_name+last_name, apaid_shareand anowed_share(2-decimal strings). Σ paid_share and Σ owed_share must each equalcost.C
equal_split_between: [user ids]— equal split between these people (≥ 2, INCLUDING the payer). The payer ispaid_by_user_id, or you when omitted (oneGET /get_current_user). Owed shares are cost / n rounded down to the cent; the leftover cents go on the payer so the sums close (10.00 / 3 → 3.34 payer, 3.33, 3.33).
Shares that do not add up are refused with an error naming the mismatch BEFORE any
request. Shares are sent flattened as users__{i}__user_id|email|first_name|last_name| paid_share|owed_share. Money is a 2-decimal string, never a float.
When to Use:
"Add 90.00 for dinner in the Cusco group, split equally" (mode A).
"I paid 30.00 for a taxi with Ana and Luis, split three ways" (mode C).
"Ana paid 50.00; I owe 20.00 of it and she owes 30.00" (mode B).
When NOT to Use:
To change an existing expense (use
splitwise_update_expense).To find a friend's, group's or category's id by name (use
splitwise_resolve_friend,splitwise_resolve_group,splitwise_resolve_categoryfirst).To comment on an expense (use
splitwise_create_comment).
Returns:
A confirmation echoing Splitwise's response: the literal errors value (empty {}
means accepted), and per returned expense its id, description, cost, group, date and
the shares exactly as Splitwise stored them.
Examples:
params = {"cost": "90.00", "description": "Dinner", "group_id": 12345, "split_equally": true}
params = {"cost": "30.00", "description": "Taxi", "equal_split_between": [491923, 678, 910]}
params = {"cost": "50.00", "description": "Groceries", "currency_code": "PEN", "shares": [ {"user_id": 678, "paid_share": "50.00", "owed_share": "30.00"}, {"user_id": 491923, "paid_share": "0.00", "owed_share": "20.00"}]}
Error Handling:
Local refusals (no request made): more or fewer than one split mode, shares that do not
sum to cost, a share with both or neither identity, duplicate participants, split_equally
without a group, a payer missing from equal_split_between. Splitwise answers 200 even
when it rejects an expense — the client turns a non-empty errors into
Error: Splitwise rejected the request…; if that body still carried an expense object
the error adds "Splitwise still returned N expense object(s) … may have landed" with
the ids, so read back before retrying. On a timeout or 5xx the outcome is UNKNOWN:
check splitwise_get_expenses before retrying.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly=false, idempotent=false, destructive=false, and openWorld=true. The description goes well beyond those by disclosing the SPLITWISE_ALLOW_WRITES=1 gate, local pre-send validation, non-idempotency and the warning never to retry blindly after a timeout, the fact that Splitwise returns HTTP 200 even on rejection, unknown outcome on timeout/5xx, and read-back guidance. These are exactly the behavioral traits annotations cannot express.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is front-loaded with the core purpose and critical constraints, then cleanly organized into split-mode definitions, When to Use / When NOT to Use, Returns, Examples, and Error Handling. It is nevertheless verbose: the Returns section duplicates information likely available in the output schema, and lines about the REST endpoint and flattened payload formatting are not strictly necessary for an agent invoking the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (three split modes, write gating, non-idempotency, timeout ambiguity) and the available annotations and output schema, the description is complete. It covers prerequisites, sibling alternatives, concrete parameter examples, and failure modes, leaving no material gap for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description explains the three mutually exclusive split modes (A, B, C), identity requirements (user_id or email+first_name+last_name), the requirement that sum paid_share and sum owed_share each equal cost, the mode C rounding rule with a worked example, and the 2-decimal money-string format. This adds mode-selection semantics and validation rules that go beyond the nested schema's per-field descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Create an expense') and immediately states the critical constraint of exactly one split mode. It names sibling alternatives for update, deletion, id resolution, and commenting, so an agent can distinguish it from every neighboring tool without opening other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It contains explicit 'When to Use' scenarios and a 'When NOT to Use' section with named alternatives: update_expense, resolve_friend, resolve_group, resolve_category, and create_comment. This leaves no inference required about when this tool is the right selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_create_friendA
Add one person as a Splitwise friend by e-mail. 🔒 Needs SPLITWISE_ALLOW_WRITES=1.
Calls POST /create_friend with user_email (+ user_first_name /
user_last_name when given). If an account already exists for that e-mail the
names are ignored; if not, Splitwise creates an invited user and user_first_name
is required. If you don't know whether they have an account, pass user_first_name;
it is ignored for existing users. Adding someone without an account probably sends
them an invitation e-mail (unverified; the live smoke t10 confirms). Refused with
Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. There is no undo
tool; remove a friend with splitwise_delete_friend.
When to Use:
To befriend one person so you can share non-group expenses with them.
When NOT to Use:
To add several people at once (use
splitwise_create_friends).To add someone to a group (use
splitwise_add_user_to_group).To check whether someone is already a friend (use
splitwise_get_friendsorsplitwise_resolve_friend).
Returns:
A confirmation echoing the friend Splitwise returned: First Last (id N), e-mail and
registration status.
Examples:
Existing user: params = {"user_email": "grace@example.com"}
New user: params = {"user_email": "alan@example.com", "user_first_name": "Alan", "user_last_name": "Turing"}
Error Handling:
Error: … writes are disabled → set SPLITWISE_ALLOW_WRITES=1. A 400 usually means an
invalid e-mail or a missing first name for a new user. On a 5xx/timeout the outcome
is UNKNOWN — check splitwise_get_friends before retrying.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the generic safety profile; the description goes far beyond, disclosing the SPLITWISE_ALLOW_WRITES=1 gate and its exact refusal message, conditional first-name handling for invited users, the likely invitation e-mail side effect, the absence of any undo, and that a 5xx/timeout leaves the outcome UNKNOWN requiring a get_friends check before retry. That is precisely the behavioral context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded: the action and the write gate appear in the first two lines, followed by clean headed sections. A few sentences carry internal-tooling noise ('the live smoke t10 confirms') that dilutes the signal, but nothing is padding in the harmful sense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutating, non-idempotent, open-world tool this covers the full call path: config prerequisite, conditional parameter semantics, side effects, return shape, error taxonomy, and retry safety. An output schema exists, yet the 'Returns' section still adds useful confirmation format detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is reported at 0% (only the nested object carries field descriptions), so the description must compensate — and it does, explaining that names are ignored for existing accounts, that user_first_name becomes required when no account exists, and providing concrete param examples for both cases. Slightly redundant with the schema's own field descriptions, so not a full 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Add one person as a Splitwise friend by e-mail') and immediately names the underlying operation (`POST /create_friend`). It is unambiguously distinguishable from siblings like splitwise_create_friends and splitwise_add_user_to_group.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' and 'When NOT to Use' sections route the agent to four named alternatives (splitwise_create_friends, splitwise_add_user_to_group, splitwise_get_friends, splitwise_resolve_friend), each with the condition that selects it. This is exemplary routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_create_friendsA
Add several people as Splitwise friends in one call. 🔒 Needs SPLITWISE_ALLOW_WRITES=1.
Calls POST /create_friends with the list flattened to
users__{i}__email / users__{i}__first_name / users__{i}__last_name (index from
0). Names matter only for people without a Splitwise account yet. Splitwise answers
HTTP 200 even when it rejects entries, so success is read from the body's errors.
Refused with Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. There is
no undo tool; remove a friend with splitwise_delete_friend.
When to Use:
To befriend a list of people (e.g. trip companions) before sharing expenses.
When NOT to Use:
For a single person (use
splitwise_create_friend).To put people in a group (use
splitwise_create_group/splitwise_add_user_to_group).
Returns:
A confirmation listing every user Splitwise returned (First Last (id N), e-mail,
registration status) and the body's errors (none on success). On a rejected batch
the Error: is followed by the users Splitwise still listed in users[] (probably
the ones it added) and a read-back hint.
Examples:
params = {"friends": [{"email": "grace@example.com"}, {"email": "alan@example.com", "first_name": "Alan", "last_name": "Turing"}]}
Error Handling:
Duplicate e-mails in the list are rejected locally before any call. If Splitwise
reports any error the call is returned as an Error: — the people its response still
listed are named under it (probably added), so read back with splitwise_get_friends
before retrying. On a 5xx/timeout the outcome is UNKNOWN.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well past the annotations (readOnlyHint=false, destructiveHint=false, idempotentHint=false): it discloses the SPLITWISE_ALLOW_WRITES=1 write gate and the exact refusal message, warns that Splitwise returns HTTP 200 even on rejection so success must be read from body `errors`, notes there is no undo tool, states duplicate e-mails are rejected locally before any call, and flags that a 5xx/timeout leaves the outcome UNKNOWN. None of this is derivable from structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the purpose and the write-gate warning, then cleanly partitioned into When to Use / When NOT to Use / Returns / Examples / Error Handling. It is longer than strictly necessary — the Returns section duplicates information the output schema already carries — but each block is scannable and earns most of its space.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a non-idempotent, open-world write tool with an output schema present, the description covers everything an agent needs: auth prerequisite, the deceptive 200-on-error behavior, partial-success read-back procedure via splitwise_get_friends, unknown-outcome semantics on transport failure, and no-undo recovery via splitwise_delete_friend.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Reported schema description coverage is 0%, so the description must carry parameter meaning, and it does: it explains the flattening to users__{i}__email/first_name/last_name with 0-based indexing, clarifies that names matter only for people without an account, and supplies a concrete two-element params example. Minor gap: it does not restate the 1-50 item bound or the e-mail format constraint that live in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: 'Add several people as Splitwise friends in one call,' where 'several' and 'in one call' signal the bulk nature. It explicitly contrasts with the single-person sibling ('For a single person (use splitwise_create_friend)'), so an agent can route between them without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains dedicated 'When to Use' and 'When NOT to Use' sections naming concrete alternatives (splitwise_create_friend, splitwise_create_group, splitwise_add_user_to_group) with the condition that selects each. This is the textbook routing guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_create_groupA
Create a group, optionally with members (you are added automatically). 🔒 write.
Calls POST /create_group with name, group_type, simplify_by_default and the
members flattened to users__{i}__user_id or users__{i}__email /
users__{i}__first_name / users__{i}__last_name. Each member is EITHER an existing
user_id OR an email + first_name (+ last_name) to invite — checked locally
before any call. Refused with Error: … writes are disabled unless
SPLITWISE_ALLOW_WRITES=1. Undo: splitwise_delete_group with the returned id.
When to Use:
To start a new shared-expenses group (a trip, a flat, a couple).
When NOT to Use:
To add someone to an existing group (use
splitwise_add_user_to_group).To bring back a deleted group (use
splitwise_undelete_group).To find a friend's user id by name first (use
splitwise_resolve_friend).
Returns: A confirmation echoing what Splitwise returned: the new group's name, id, type and members, plus how many members were requested vs returned (a silently dropped invite shows up there).
Examples:
params = {"name": "Lima trip", "group_type": "trip", "members": [{"user_id": 5823}]}
params = {"name": "Flat", "group_type": "home", "simplify_by_default": true, "members": [{"email": "ana@example.com", "first_name": "Ana", "last_name": "Diaz"}]}
Error Handling:
A member with both or neither identity is rejected before the call. Splitwise's 400
field errors (e.g. a blank name) are surfaced as Error (400): ....
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnlyHint=false, idempotentHint=false, destructiveHint=false, openWorldHint=true), and the description goes well beyond them: the SPLITWISE_ALLOW_WRITES=1 write gate and its exact refusal message, the local pre-call identity validation, the undo path via splitwise_delete_group, and the requested-vs-returned member count that surfaces silently dropped invites.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and structured under clear headings (When to Use, When NOT to Use, Returns, Examples, Error Handling), with two worked examples. It is longer than strictly necessary, but nearly every line adds operational value rather than restating structured data.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write tool with real prerequisites, the definition covers gating, validation, undo, error surfacing, and examples. An output schema exists, so the brief 'Returns' note is sufficient and the description need not detail the response shape further.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is reported at 0%, so the description carries the burden and does so thoroughly: it documents the body serialization (users__{i}__user_id / email / first_name / last_name), the either/or identity rule per member, and the group_type values. This meaningfully exceeds what the raw schema exposes.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Create a group') and immediately notes the auto-inclusion of the caller. The 'When NOT to Use' block names the exact sibling tools for adjacent operations, so the agent can distinguish this from splitwise_add_user_to_group, splitwise_undelete_group, and splitwise_resolve_friend without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' (new shared-expenses group: trip, flat, couple) and 'When NOT to Use' with a named alternative per exclusion case. This is the full when/when-not/alternatives pattern.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_delete_commentADestructiveIdempotent
Delete a comment from a Splitwise expense (destructive; comments have no undelete).
Write — refused unless SPLITWISE_ALLOW_WRITES=1. Calls POST /delete_comment/{id}.
Splitwise answers with the deleted comment, which this tool renders so you can see
exactly what was removed. There is NO undelete for comments in the Splitwise API — if
needed, re-post the text with splitwise_create_comment (it gets a new id and a new
timestamp).
When to Use:
To remove a comment you posted by mistake (get its id from
splitwise_get_comments).
When NOT to Use:
To delete the expense itself — use
splitwise_delete_expense.When you only know the comment's text — list them with
splitwise_get_commentsfirst.
Returns: A confirmation echoing the deleted comment as Splitwise returned it: id, expense id, author, type, created/deleted times and the text.
Examples:
params = {"comment_id": 79800950}
Error Handling:
Refused with Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. 404 =
the comment id does not exist or is already gone; 403 = you are not allowed to delete
it (you are not part of that expense). Errors come back as an Error ... string, never raised.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the write gate (SPLITWISE_ALLOW_WRITES=1), the underlying endpoint, the absence of any undelete in the Splitwise API, and the recovery path (re-post with splitwise_create_comment, new id/timestamp). It also maps 404 and 403 to concrete causes, which the destructiveHint/idempotentHint annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the operation and its destructive nature, then cleanly sectioned into usage, returns, examples, and errors. It is longer than strictly necessary, and the 'Returns' block largely restates what the output schema already declares, but no section is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers everything an agent needs to invoke this correctly: the required id and where to get it, the environment gate that will refuse the call, what the confirmation contains, and how each error class should be interpreted. The presence of an output schema makes the Returns section a bonus rather than a gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter, and the schema already describes comment_id and its source. The description reinforces the id's provenance ('get its id from splitwise_get_comments') and supplies a literal example payload, adding modest but real value over the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete a comment from a Splitwise expense') and immediately scopes it against siblings by naming splitwise_delete_expense and splitwise_create_comment as different operations. An agent can distinguish this from every other delete tool in the family without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has explicit 'When to Use' and 'When NOT to Use' sections, names the sibling to use instead for each excluded case (splitwise_delete_expense for the expense itself, splitwise_get_comments when only the text is known), and routes the agent to the prerequisite call that supplies the required id.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_delete_expenseADestructiveIdempotent
Delete an expense (Splitwise keeps it as deleted; restore with splitwise_undelete_expense).
Calls POST /delete_expense/{id}. Refused with Error: … writes are disabled unless
SPLITWISE_ALLOW_WRITES=1 (enforced by the server's client). Deleting changes every
participant's balances. Restore with splitwise_undelete_expense and the same id.
When to Use:
Remove a duplicate or mistaken expense.
When NOT to Use:
To fix an amount or split (use
splitwise_update_expense).To remove a whole group with its expenses (use
splitwise_delete_group).
Returns:
The success value Splitwise returned for the deletion, and the undo hint.
Examples:
params = {"expense_id": 3456789012}
Error Handling:
Splitwise answers 200 even when it refuses — the client turns success: false / a
non-empty errors into Error: Splitwise rejected the request…. 404 → wrong id; 403 →
not your expense.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructive/idempotent/openWorld, and the description adds value beyond them: the delete is a recoverable soft delete, it requires SPLITWISE_ALLOW_WRITES=1 or the server refuses, it mutates every participant's balances, and refusal arrives as HTTP 200 with success:false. This is exactly the extra behavioral context the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The header-based layout is front-loaded and scannable, and each section (endpoint, gating, usage, returns, example, errors) earns its place. The undo/restore instruction is stated twice (opening parenthetical and later), which is mild redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an output schema existing, the definition covers everything an agent needs: write gating, blast radius on balances, the undo path, the id source, and the error decoding for 200/403/404 responses. Nothing material is missing for a destructive one-parameter call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one nested parameter and the schema names it with a hint about its origin, but reported coverage is 0%, so the description compensates with a concrete example ({"expense_id": 3456789012}) and ties 404/403 error meanings to the id. It stops short of explaining any format constraint, but with a single required integer that is a minor gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Delete an expense') plus the crucial soft-delete semantics, and explicitly distinguishes itself from splitwise_update_expense, splitwise_delete_group, and splitwise_undelete_expense. An agent can identify this tool among 32 siblings without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'When to Use' (duplicate or mistaken expense) and 'When NOT to Use' sections that name the correct alternative tool for each excluded case (update for amount/split fixes, delete_group for whole-group removal). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_delete_friendADestructiveIdempotent
Remove a friendship (unfriend a user). 🔒 Needs SPLITWISE_ALLOW_WRITES=1. Destructive.
Calls POST /delete_friend/{id} with the friend's user id. Splitwise answers HTTP
200 even when it refuses, so the outcome is read from the body's success /
errors. Refused with Error: … writes are disabled unless
SPLITWISE_ALLOW_WRITES=1. There is no undelete for friendships — re-add with
splitwise_create_friend.
When to Use:
The user explicitly asked to remove someone from their friends list.
When NOT to Use:
To remove someone from a group (use
splitwise_remove_user_from_group).To settle a balance (record the repayment as an expense via
splitwise_create_expense).When the id is uncertain — confirm it first with
splitwise_resolve_friendorsplitwise_get_friend.
Returns:
A confirmation with the user id and the body's success value.
Examples:
params = {"friend_id": 4821}
Error Handling:
Error: … writes are disabled → set SPLITWISE_ALLOW_WRITES=1. If Splitwise refuses,
its errors message is returned as Error: Splitwise rejected the request …. 404
means the id is not a friend.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (destructiveHint=true, idempotentHint=true), the description discloses the write gate (SPLITWISE_ALLOW_WRITES=1), the underlying endpoint, the critical quirk that Splitwise returns HTTP 200 even when it refuses so success must be read from the body, that there is no undelete, and how 404 should be interpreted. This is exactly the extra context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Sections are clearly labeled and front-loaded with the destructive/write-gate warning first, which is the right priority. It is longer than strictly necessary — the Examples block largely restates the schema's own example — but no section is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, gated, non-idempotent-in-practice mutation, the description covers preconditions, failure modes, refusal handling, and recovery (re-add via splitwise_create_friend). Return values are also summarized even though an output schema exists, so nothing an agent needs to call this safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is reported as 0%, though the single friend_id property does carry an inline description. The description reinforces that the parameter is the friend's user id, supplies a concrete example ({"friend_id": 4821}), and adds error semantics tied to the id (404 means the id is not a friend). With only one parameter this is close to fully covered, but it stops short of adding format constraints beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line states a specific verb and resource ('Remove a friendship (unfriend a user)'), and the surrounding text makes clear it operates on the friend relationship rather than group membership. An agent can distinguish it from splitwise_remove_user_from_group and splitwise_create_friend without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' and 'When NOT to Use' sections name the exact alternatives for adjacent intents: splitwise_remove_user_from_group for group removal, splitwise_create_expense for settling balances, and splitwise_resolve_friend / splitwise_get_friend when the id is uncertain. Routing conditions are fully specified.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_delete_groupADestructiveIdempotent
Delete a group and all its expenses — for every member, not just you. 🔒 destructive write.
Calls POST /delete_group/{id}. Splitwise destroys the group's associated records:
every expense in it disappears for all members. Refused with
Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. Undo:
splitwise_undelete_group with the same id restores the group and its expenses.
When to Use:
Only when the user explicitly asked to delete this group. Confirm the id first with
splitwise_get_group, and runsplitwise_get_expenseswith group_id so the user knows how many expenses will go with it.
When NOT to Use:
To leave a group or drop one member (use
splitwise_remove_user_from_group).To delete a single expense (use
splitwise_delete_expense).With a group NAME — resolve it to an id first (use
splitwise_resolve_group).
Returns:
A confirmation with the success value Splitwise returned and how to undo it — or, when
the body does not say success: true, a note to verify before reporting it as deleted.
Examples:
params = {"group_id": 12345}
Error Handling:
A refusal that comes back as HTTP 200 with success: false is reported as
Error: Splitwise rejected the request ...; 403 → not a member; 404 → wrong id or already deleted.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint and readOnlyHint=false, but the description adds substantial context beyond them: exactly what gets destroyed (every member's expenses), a write-permission gate (SPLITWISE_ALLOW_WRITES=1), a specific undo path (splitwise_undelete_group), and error semantics including the tricky HTTP 200 + success:false case, 403, and 404.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the destructive scope, then organized under clear headers (When to Use, When NOT to Use, Returns, Examples, Error Handling). Every section earns its place; nothing is padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive tool, the description covers blast radius, permission gating, undo, error mapping, and parameter prerequisites. An output schema exists, so the Returns section is slightly redundant but harmless, and nothing an agent needs to invoke this safely is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only one parameter, and the schema already describes group_id. The description still adds value by giving a concrete example ({"group_id": 12345}) and warning not to pass a group name, directing the agent to splitwise_resolve_group first.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (delete) and resource (group), plus the blast radius ('all its expenses — for every member, not just you'), which immediately separates it from splitwise_remove_user_from_group and splitwise_delete_expense. The endpoint POST /delete_group/{id} is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has dedicated 'When to Use' and 'When NOT to Use' sections that name the exact alternatives: splitwise_remove_user_from_group for leaving, splitwise_delete_expense for single expenses, splitwise_resolve_group for name resolution. Prerequisites (confirm id with splitwise_get_group, preview with splitwise_get_expenses) are called out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_balancesARead-onlyIdempotent
Summarise who owes you and whom you owe, per friend and per currency.
Calls GET /get_friends once and, from each friend's balance list, renders every
non-zero balance per currency, plus per-currency totals: how much you are owed, how
much you owe, and the net. Friend balances already combine group and non-group
expenses. Sign convention: positive = the friend owes you (owed to you); negative =
you owe the friend. Zero balances are hidden unless include_zero is true; the
optional currency filter keeps a single currency (applied locally — the endpoint
takes no filter). An amount Splitwise sends that is not a plain decimal, or an entry
with no currency, is shown raw and flagged, and left out of the totals.
When to Use:
"How much am I owed / do I owe overall?", "who owes me money?", "my USD balance".
Before settling up, to see every open balance in one call.
When NOT to Use:
For balances inside ONE group and who pays whom there (use
splitwise_get_group_balances).For friend profiles, e-mails or per-group breakdowns (use
splitwise_get_friends/splitwise_get_friend).To find a friend's id from a name (use
splitwise_resolve_friend).
Returns:
Markdown: the sign convention, a totals table (Currency | You are owed | You owe | Net)
and a table of friends (First Last (id N) with e.g. +12.50 USD, -3.00 PEN; with
include_zero, settled up or no USD balance), capped at 50 rows (totals cover every
friend except the flagged entries). JSON: {sign_convention, currency_filter, totals: {CUR: {owed_to_you, you_owe, net}}, unparsed: [{friend_id, currency_code, amount, reason}], friend_count, friends: [raw friend objects]} with you_owe as a positive magnitude and
money as 2-decimal strings.
Examples:
params = {}
params = {"currency": "USD"}
params = {"include_zero": true, "response_format": "json"}
Error Handling:
A bad currency (not 3 letters) is rejected before any call. 401 means the API key is
missing or was regenerated; 429 means back off (Retry-After). Errors come back as an
Error ... string.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld, and the description adds substantial behavior beyond them: the underlying call (GET /get_friends), the sign convention that positive means owed-to-you, that the currency filter is applied locally because the endpoint takes no filter, that malformed amounts are shown raw, flagged, and excluded from totals, and the 401/429/Retry-After error semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a one-line summary and cleanly sectioned (When to Use / When NOT / Returns / Examples / Error Handling), so navigation is fast. However, the Returns section is long and partly restates what an existing output schema already conveys, so a little trimming is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read tool with annotations, an output schema, and only one nested params object, the description covers everything an agent needs: scope, alternatives, filtering semantics, output shape for both formats, the 50-row cap, and failure modes. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although the top-level 'params' object has no schema description (0% coverage per the signal), the description carries the parameters: it explains include_zero's effect (zero balances hidden unless true), the currency filter being a 3-letter local filter that is rejected before any call, and what response_format switches between, plus three concrete parameter examples.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource ('Summarise who owes you and whom you owe, per friend and per currency') and the When NOT to Use block explicitly routes to splitwise_get_group_balances for single-group balances. An agent can distinguish it from every sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' triggers ('who owes me money', before settling up) and an explicit 'When NOT to Use' list naming the three alternative siblings (splitwise_get_group_balances, splitwise_get_friends/get_friend, splitwise_resolve_friend) with the condition that selects each. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_categoriesARead-onlyIdempotent
List Splitwise's expense categories: each parent with its subcategories and their ids.
Calls GET /get_categories once and caches the answer in-process for 24 h (the list is
static); refresh: true refetches. Expenses must use a subcategory id as
category_id — a parent id is not accepted. When nothing fits, use the "Other"
subcategory under the closest parent (or "General" under "Uncategorized").
Names come back in the account's locale (a Spanish account sees "Supermercado",
"Taxi", "Avión" — not the English names from Splitwise's docs); the ids are the same
everywhere.
When to Use:
To browse the categories before creating or recategorising an expense.
To list one parent's subcategories (
parent: "food").
When NOT to Use:
To turn a category name into an id — use
splitwise_resolve_category, which ranks subcategories by similarity and says when one is a clear match.For currencies — use
splitwise_get_currencies.
Returns:
A markdown table with one row per parent (flagged as not usable for expenses) and its
subcategories as Name (id N), capped at 50 parents; or the raw {"categories": [...]}
objects (with icons and nested subcategories) when response_format is json.
Examples: params = {} params = {"parent": "transport"} params = {"refresh": true, "response_format": "json"}
Error Handling:
A 401 means the API key is missing or was regenerated. A failed fetch is never cached
(a failed refresh keeps the previous cached list); a parent filter that matches
nothing lists the parent names to pick from.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, open-world and non-destructive, but the description adds substantial behavior beyond them: a 24 h in-process cache with refresh override, the rule that failed fetches are never cached and a failed refresh retains the prior list, locale-dependent names with globally stable ids, and a 401 meaning an invalid/regenerated key. This is exactly the extra context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but front-loaded and sectioned (behavior, When to Use, When NOT to Use, Returns, Examples, Error Handling). Every block carries distinct, non-redundant information – caching rules, subcategory-id constraint, locale caveat, call examples – so no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool's output shape is spelled out (markdown table vs raw JSON with icons and nested subcategories) even though an output schema exists, the caching/auth failure modes are covered, and the subcategory-id requirement closes the main misuse risk. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema already documents parent (substring/numeric id match), refresh (bypass cache) and response_format (markdown vs json), so the description's marginal value is mostly on refresh cache semantics, the empty-parent-match fallback, and the 50-parent cap. It reinforces but rarely surpasses the schema text for the individual parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('List Splitwise's expense categories: each parent with its subcategories and their ids') and immediately distinguishes itself from splitwise_resolve_category and splitwise_get_currencies by name. An agent knows exactly what this tool returns and what it is not for without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' / 'When NOT to Use' sections with named alternatives: name-to-id lookup goes to splitwise_resolve_category, currencies go to splitwise_get_currencies. It even states the prerequisite workflow (browse categories before creating/recategorising an expense).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_commentsARead-onlyIdempotent
List the comments on one Splitwise expense.
Calls GET /get_comments?expense_id=… and renders one row per comment: its id, the
author as First Last (id N), the type (System = written by Splitwise, e.g. an
edit log; User = written by a person), when it was created, and the text.
When to Use:
To read the discussion or the edit history on an expense.
To find a comment's id before deleting it with
splitwise_delete_comment.
When NOT to Use:
To read the expense itself (cost, shares) — use
splitwise_get_expense.To see recent activity across all expenses and groups — use
splitwise_get_notifications.To find an expense id from a description — use
splitwise_get_expenses.
Returns:
Markdown: a table | Id | Author | Type | Created | Content | (at most 50 rows, the
rest counted; each text capped at 2,000 characters, the cut counted). JSON: {"expense_id", "count", "comments": [raw comment objects]}.
Examples:
params = {"expense_id": 51023}params = {"expense_id": 51023, "response_format": "json"}
Error Handling:
404 means the expense id does not exist or was deleted; 403 means you are not part of
that expense. Errors come back as an Error ... string, never raised.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial context beyond them: the System vs User comment-type semantics, truncation behavior (50 rows, 2,000 chars, with counts of what was cut), and error semantics (404 = nonexistent/deleted expense, 403 = not a member, errors returned as strings never raised).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a one-line purpose, then clearly sectioned into When to Use / When NOT / Returns / Examples / Error Handling. Every section earns its place, though the Returns paragraph restates part of what the output schema already carries, making it slightly longer than strictly necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with an output schema, the description closes the remaining gaps an agent would hit: authorization failure modes, the meaning of each comment type, and the truncation limits on the rendered output. Nothing needed to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema descriptions exist for both fields, but the description adds meaning: it explains that response_format chooses between a rendered table and raw comment objects, and provides two concrete worked payloads for expense_id. It stops short of describing any constraint on expense_id beyond what the schema already says.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('List the comments on one Splitwise expense') and immediately disambiguates from siblings like splitwise_get_expense and splitwise_get_notifications. The agent can distinguish this from every other get_* tool without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' (read discussion/edit history, find a comment id before splitwise_delete_comment) and 'When NOT to Use' sections that name three concrete alternative tools and the condition that selects each. This is exactly the routing guidance an agent needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_currenciesARead-onlyIdempotent
List the currency codes Splitwise accepts, optionally filtered by a substring.
Calls GET /get_currencies once and caches the answer in-process for 24 h (the list is
static); refresh: true refetches. Codes are mostly ISO 4217 plus a few colloquial ones
(e.g. BTC); each comes with its display unit ($, S/, €).
When to Use:
To check that a currency code is accepted before using it as
currency_codeon an expense or as a user'sdefault_currency.To find a code from its symbol (
query: "€").
When NOT to Use:
For balances per currency — use
splitwise_get_balances.For categories — use
splitwise_get_categories.
Returns:
A markdown table of Code | Unit (capped at 50 rows; narrow with query), or the raw
{"currencies": [{currency_code, unit}]} objects when response_format is json.
Examples: params = {} params = {"query": "pen"} params = {"query": "eur", "response_format": "json"}
Error Handling: A 401 means the API key is missing or was regenerated. A failed fetch is never cached; a query that matches nothing says so instead of returning an empty table.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite readOnlyHint/idempotentHint already covering safety, the description adds substantial behavior: a 24 h in-process cache, refresh semantics, the 50-row cap, 401 meaning a missing/regenerated key, and the fact that failed fetches are never cached and empty results are messaged rather than silently empty.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core action and organized under clear headers; the examples are concrete and useful. It is on the long side, and the Returns block partially restates what the output schema already carries, but no section is padding.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers caching, refresh, filtering, output shape (including the row cap), auth failure mode, and no-match behavior — everything an agent needs to call this correctly and interpret the result, even with a nested params object and no per-parameter coverage in the context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is reported as 0%, so the description must compensate, and it does: it explains that query is a case-insensitive substring match over code or unit (with a symbol example), that refresh bypasses the 24 h cache, and that response_format selects table vs raw objects.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource: listing currency codes accepted by Splitwise. It also distinguishes itself from siblings by explicitly naming splitwise_get_balances and splitwise_get_categories as the tools for other per-currency/category needs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' and 'When NOT to Use' sections give concrete scenarios (validating a currency_code before an expense, resolving a symbol like "€") and name the alternative tools for out-of-scope needs. Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_current_userARead-onlyIdempotent
Get the Splitwise user the API key belongs to: name, id, email, currency, locale, notifications.
Calls GET /get_current_user and renders your name and id (as First Last (id N), so
the id can be chained into other tools), email, registration status, default
currency, locale, the unread notifications count, when notifications were last read,
and your email-notification settings (expense_added=on, …).
When to Use:
To learn your own user id before building expense shares or updating your profile.
To check your default currency or locale before creating expenses.
To see how many unread notifications you have (read them with
splitwise_get_notifications).
When NOT to Use:
To check the API key / kill-switch state (use
splitwise_health_check).To look up someone else (use
splitwise_get_user, orsplitwise_resolve_friendfor a name → id).To read balances (use
splitwise_get_balances/splitwise_get_friends).To change your name, locale or default currency (use
splitwise_update_user).
Returns:
Markdown (default): a bullet list with the fields above. JSON: the raw Splitwise
current_user object (incl. picture, notifications_read, notifications).
Examples:
params = {}params = {"response_format": "json"}
Error Handling:
401 means SPLITWISE_API_KEY is missing, mistyped or was regenerated at
https://secure.splitwise.com/apps. Every failure comes back as an Error ... string.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/openWorld, so only additive context is needed, and the description delivers: 401 means the API key is missing/mistyped/regenerated (with the URL to fix it), every failure returns an `Error ...` string, and the markdown rendering is shaped as `First Last (id N)` specifically so the id can be chained into other tools. This is genuinely useful behavior an agent cannot get from the annotations or schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded and clearly sectioned (When to Use, When NOT to Use, Returns, Examples, Error Handling), so an agent can scan it. However, the field enumeration in the opening paragraph largely repeats the fuller enumeration in Returns, which is mild redundancy in an otherwise efficient layout.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description already exceeds the bar by documenting return shapes and error semantics. Combined with explicit routing to siblings, examples, and auth failure behavior, an agent has everything needed to select and call this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single `response_format` parameter is given concrete invocation examples (`params = {}` and `params = {"response_format": "json"}`), and the Returns section explains what each mode produces, which goes beyond the bare schema description. It does not add much more than the schema already states about the enum, so not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get the Splitwise user the API key belongs to') and enumerates the returned fields (name, id, email, currency, locale, notifications). It also implicitly distinguishes itself from `splitwise_get_user` by scoping to the API key's owner, which the When NOT to Use section makes explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit When to Use and When NOT to Use lists, each naming the concrete alternative for the excluded case (`splitwise_health_check` for key state, `splitwise_get_user` / `splitwise_resolve_friend` for other people, `splitwise_get_balances` / `splitwise_get_friends` for balances, `splitwise_update_user` for edits). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_expenseARead-onlyIdempotent
Read one expense in full: cost, group, category, every share, repayments and comments.
Calls GET /get_expense/{id}. The shares table shows what each person paid, owed and
their net on this expense; repayments say who owes whom for it; comments are listed
with author and time. A deleted expense is still readable and is flagged as deleted.
Sign convention: Net = paid − owed; positive = that person is owed money on this expense, negative = they owe.
When to Use:
Before
splitwise_update_expense, to see the current shares (an update with shares replaces ALL of them)."Who paid for dinner and how was it split?"
Checking that a create/update landed the way it was intended.
When NOT to Use:
To list or search expenses (use
splitwise_get_expenses).To read only the comments thread (use
splitwise_get_comments).For overall balances (use
splitwise_get_balances).
Returns:
Markdown: header fields, a | Person | Paid | Owed | Net | table, repayments
From → To amount, and a comments table. JSON: the raw expense object.
Examples:
params = {"expense_id": 3456789012}
params = {"expense_id": 3456789012, "response_format": "json"}
Error Handling: 404 → wrong id; 403 → you are not part of that expense; 401 → API key problem.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so the safety profile is covered. The description goes well beyond that by disclosing the sign convention (Net = paid − owed), the fact that a deleted expense remains readable and is flagged, the concrete return shape (shares table, From → To repayments, comments), and status-code semantics (404 wrong id, 403 not a participant, 401 key problem).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Headers (When to Use / When NOT to Use / Returns / Examples / Error Handling) make it scannable and the purpose is front-loaded in the first sentence. It is on the long side and the 'Returns' block partially duplicates the existing output schema, but nothing is truly wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool this is complete: purpose, routing, output shape, examples and error mapping are all present. An agent has everything needed to call it correctly and interpret common failure modes without further inference.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Top-level schema description coverage is reported at 0%, so the description must compensate, and it does: it clarifies expense_id provenance ('from splitwise_get_expenses'), contrasts markdown vs raw JSON, and supplies two concrete param examples. It stops short of documenting edge cases like id format or the exclusiveMinimum constraint, so not a full 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line states a specific verb and resource ('Read one expense in full') and enumerates the scope: cost, group, category, shares, repayments, comments. It is immediately distinguishable from splitwise_get_expenses (list/search) and splitwise_get_comments (thread only), which are named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'When to Use' triggers (pre-update inspection, 'who paid for dinner', post-create verification) and a 'When NOT to Use' block that routes to splitwise_get_expenses, splitwise_get_comments and splitwise_get_balances. This is the strongest possible form of routing guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_expensesARead-onlyIdempotent
List expenses, newest first, optionally filtered by group, friend and date range.
Calls GET /get_expenses. Splitwise includes DELETED expenses in this list; they are
hidden by default and the response says how many were hidden (include_deleted=true
shows them, tagged [deleted]). Settle-up payments are tagged [settle-up]. Each row
shows the date, description, full cost, group, who paid (shares with paid_share > 0)
and — when current_user_id is given — your net on that expense.
Sign convention: "Your net" is your net_balance on the expense; positive = owed to
you (you paid more than your share), negative = you owe.
When to Use:
"What did we spend in the Lima trip group?" (group_id) or "expenses with Ana" (friend_id).
Finding an expense id before reading, updating or deleting it.
Reviewing recent activity in a date window (dated_after / dated_before).
When NOT to Use:
To see one expense's full split, repayments and comments (use
splitwise_get_expense).To get balances per friend or per group (use
splitwise_get_balances/splitwise_get_group_balances).To turn a group or friend NAME into an id (use
splitwise_resolve_group/splitwise_resolve_friend).
Returns:
Markdown: a table | id | Date | Description | Cost | Group | Paid by | (Your net) |
plus the hidden-deleted count and the next offset. JSON: {count, returned_by_api, hidden_deleted, limit, offset, has_more, next_offset, expenses: [raw expense objects]}.
Pagination:
limit (1-100, default 20) is sent to Splitwise; has_more is true when Splitwise
returned a full page, and the next offset is offset + rows returned by Splitwise
(deleted rows count toward it even when hidden). Markdown shows at most 50 rows; the
note under the table gives the offset to continue from.
Examples:
params = {"group_id": 12345, "dated_after": "2026-09-01"}
params = {"friend_id": 678, "limit": 50, "current_user_id": 491923}
params = {"limit": 20, "offset": 20, "response_format": "json"}
Error Handling: Passing both group_id and friend_id is refused (Splitwise would ignore friend_id). 401 → API key missing/regenerated; 403 → you are not a member of that group; 429 → back off for Retry-After seconds.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only, idempotent, non-destructive and open-world, and the description adds genuinely non-obvious behavior: deleted expenses are returned but hidden and counted, tagged '[deleted]' / '[settle-up]', the net-balance sign convention, refusal when group_id and friend_id are both passed, and 401/403/429 handling with Retry-After.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded core purpose and well-organized with headings, but the Returns section substantially duplicates the output schema and the Pagination paragraph restates the schema's limit default, making it longer than strictly necessary.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers filtering, pagination, response formats, mutual exclusion, tags and error codes; since an output schema exists, the return-format detail is a bonus rather than a gap. An agent has everything needed to call this correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Adds meaning well beyond the schema: the sign convention for current_user_id's 'Your net' column, that deleted rows still consume the offset, that markdown caps at 50 rows, and that group_id/friend_id are mutually exclusive and refused. This is interpretive information the schema alone cannot convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb, resource, ordering and filter scope: 'List expenses, newest first, optionally filtered by group, friend and date range.' Combined with the When NOT to Use section that names splitwise_get_expense, splitwise_get_balances and splitwise_get_group_balances, an agent can distinguish this from every sibling without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit positive cases (cost per group, expenses with a friend, finding an id before update/delete, date-window review) and negative cases with named alternatives for each. Nothing about when to choose this tool is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_friendARead-onlyIdempotent
Get one Splitwise friend with their overall and per-group balances.
Calls GET /get_friend/{id}. Renders the friend as First Last (id N), e-mail,
registration status, the overall balance per currency, the balance in each shared
group (group 0 = non-group expenses) and when the friendship last changed.
Sign convention: positive = they owe you; negative = you owe them.
When to Use:
To see how a balance with one friend splits across shared groups.
To confirm a user id belongs to a friend before using it in an expense.
When NOT to Use:
To list every friend (use
splitwise_get_friends).To turn a name into an id (use
splitwise_resolve_friend).For a user who is not a friend (use
splitwise_get_user).
Returns: Markdown: a summary block plus a "Shared groups" list. JSON: the raw friend object.
Examples:
params = {"friend_id": 4821}
params = {"friend_id": 4821, "response_format": "json"}
Error Handling: 404 means the id is not one of your friends (or does not exist); 401 means the API key is missing or revoked.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, openWorldHint, and destructiveHint=false, so safety is covered. The description adds real behavioral context beyond them: the sign convention (positive = they owe you), the markdown-vs-json output shape, and the 404/401 error meanings. It stops short of describing pagination or rate-limit behavior, but for a single-entity read that is a minor omission.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core purpose and sign convention before the routing guidance, and each section (usage, returns, examples, errors) earns its place. It is somewhat long for a one-parameter read tool, with mild redundancy between the 'Returns' section and the response_format explanation.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers routing, endpoint, rendering format, sign convention, examples, and error codes for a tool whose annotations already establish the safety profile and whose output schema exists. An agent has everything needed to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Reported schema coverage is 0%, so the description must carry the load, and it does: it shows the id flows into GET /get_friend/{id}, gives a concrete example value (4821), and explains that response_format='json' returns the raw friend object versus markdown for a readable summary. It lacks detail on valid id ranges or failure modes per format, hence a 4 rather than 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Get one Splitwise friend') and immediately scopes the payload to overall and per-group balances. It is unmistakably distinct from splitwise_get_friends, splitwise_resolve_friend, and splitwise_get_user, all of which it names.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'When to Use' and 'When NOT to Use' sections with three named alternatives (splitwise_get_friends, splitwise_resolve_friend, splitwise_get_user) each paired with the condition that selects them. No inference is required from the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_friendsARead-onlyIdempotent
List your Splitwise friends with their balance per currency.
Calls GET /get_friends. One row per friend: First Last (id N), e-mail,
registration status (confirmed | invited | dummy) and the overall balance per
currency. Sign convention: positive = they owe you; negative = you owe them.
JSON mode returns the raw friend objects, including groups[] with the balance
per shared group (group 0 = non-group expenses).
When to Use:
To see who owes you / whom you owe, per friend and currency.
To find a friend's user id before building expense shares or adding them to a group.
With
only_with_balance=trueto list only the friendships that are not settled up.
When NOT to Use:
To find a friend by a fuzzy name (use
splitwise_resolve_friend).For totals per currency across all friends (use
splitwise_get_balances).For one friend's detail incl. per-group balances (use
splitwise_get_friend).For balances inside one group (use
splitwise_get_group_balances).
Returns:
Markdown: a header with the sign convention and counts, then a table
(Friend | Email | Status | Balance), capped at 50 rows with a note when more exist.
JSON: {"count", "only_with_balance", "friends": [raw friend objects]}.
Examples:
All friends: params = {}
Only open balances: params = {"only_with_balance": true}
Raw objects with per-group balances: params = {"response_format": "json"}
Error Handling: 401 means the API key is missing or revoked (https://secure.splitwise.com/apps); 429 means back off and retry later.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so the safety profile is covered. The description adds real value beyond that: the sign convention (positive = they owe you), the 50-row cap with overflow note, and error semantics (401 = missing/revoked key, 429 = back off and retry). The only mild gap is that it doesn't note anything about pagination beyond the row cap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose followed by cleanly labeled When to Use / When NOT to Use / Returns / Examples / Error Handling sections; every sentence carries information. It is longer than strictly necessary, since the Returns block partly duplicates an existing output schema, which keeps it from a 5.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter read tool with an output schema, annotations covering safety, and a large sibling set, this description supplies everything an agent needs: purpose, routing alternatives, parameter semantics, return shapes, examples, and error handling. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Reported schema coverage is 0%, so the description must carry parameter meaning — and it does, describing only_with_balance ('list only the friendships that are not settled up') and response_format ('Raw objects with per-group balances') with concrete param examples. It doesn't add syntax or type detail beyond the schema, so it falls just short of a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (list) and resource (Splitwise friends) and immediately narrows scope with 'with their balance per currency'. Combined with the explicit 'When NOT to Use' routing to splitwise_resolve_friend, splitwise_get_balances, splitwise_get_friend and splitwise_get_group_balances, an agent can distinguish this tool from every similar sibling without reading a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains an explicit 'When to Use' block with three concrete scenarios and a 'When NOT to Use' block naming four alternatives plus the condition that selects each. This is the strongest form of usage guidance: both positive triggers and exclusions are spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_groupARead-onlyIdempotent
Read one group: its members with balances, who owes whom, and the invite link.
Calls GET /get_group/{id}. Members are rendered First Last (id N) with every
non-zero balance per currency. Debts are rendered A → B 12.50 USD (A owes B), names
resolved from the group's own members; the simplified debts are shown, or the
original debts (labelled as such) when Splitwise returned no simplified ones.
Sign convention for member balances: positive = that member is owed money; negative =
they owe. Group id 0 is the pseudo-group for non-group expenses.
When to Use:
To see who owes whom inside a group before settling up.
To get a member's user id before removing them or building expense shares.
To fetch the group's invite link.
When NOT to Use:
To list all your groups (use
splitwise_get_groups), or find one by name (splitwise_resolve_group).For the group's expenses (use
splitwise_get_expenseswith group_id).
Returns: A markdown block (name, type, settings, members, debts, invite link; members and debts capped at 50 each, with a note) or, with response_format=json, the raw group object.
Examples:
params = {"group_id": 12345}
params = {"group_id": 12345, "response_format": "json"}
Error Handling:
403 → you are not a member of that group; 404 → wrong id or the group was deleted
(see splitwise_undelete_group).
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive), yet the description adds substantial non-obvious behavior: member/debt rendering formats, the balance sign convention, fallback from simplified to original debts, 50-item caps with a note, and 403/404 error semantics. This is well beyond what the annotations convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but highly structured and front-loaded: one-line purpose first, then endpoint/format details, then When to Use / When NOT to Use, Returns, Examples, Error Handling. Every section carries call-relevant information; no filler sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite an output schema existing, the description still specifies return shape (markdown block contents, caps, JSON alternative), gives concrete call examples, and documents the two likely error codes with remediation. Nothing an agent needs to invoke this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema gives minimal per-parameter prose (coverage reported at 0%), but the description clarifies group id 0 as the non-group-expenses pseudo-group and explains that response_format=json returns the raw group object versus default markdown. It adds real meaning, though response_format is partly a restatement of the enum.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource+scope: 'Read one group: its members with balances, who owes whom, and the invite link.' It also names the underlying endpoint (GET /get_group/{id}) and explicitly distinguishes itself from splitwise_get_groups, splitwise_resolve_group, and splitwise_get_expenses, so an agent can route correctly without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Contains dedicated 'When to Use' and 'When NOT to Use' sections with named alternatives for each exclusion (splitwise_get_groups for listing, splitwise_resolve_group for name lookup, splitwise_get_expenses with group_id for expenses). The selection logic is fully explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_group_balancesARead-onlyIdempotent
Show each member's balance in one group and who should pay whom to settle it.
Calls GET /get_group/{group_id} and renders the members' non-zero balances per
currency, then the group's debts as From → To amount CUR (From owes To), with names
resolved from the group's own members (an id not among them is shown as user N).
Uses simplified_debts; when Splitwise returns none, falls back to original_debts
and says so. Sign convention: positive = the member is owed by the group; negative =
the member owes the group. Settled-up members are listed by name only. An amount
that is not a plain decimal is shown raw and flagged (unparsed).
When to Use:
"Who owes whom in the Trip group?", "how do we settle up the apartment?".
Before recording a settle-up payment, to get the exact amounts and user ids.
When NOT to Use:
For your balances across all friends (use
splitwise_get_balances).For non-group expenses: group_id 0 is the non-group pseudo-group;
/get_group/0answers but lists only you as a member, so per-friend balances come fromsplitwise_get_balances, not from here.For the group's details, invite link or membership changes (use
splitwise_get_group,splitwise_add_user_to_group,splitwise_remove_user_from_group).To find a group id from its name (use
splitwise_resolve_group/splitwise_get_groups).
Returns:
Markdown: a member table (First Last (id N) | +20.00 USD), the settled-up members,
and the debts list with its source (simplified_debts or original_debts), capped at
50 rows each. JSON: {group: {id, name}, sign_convention, members: [raw members], debts_source: "simplified_debts" | "original_debts" | null, debts: [raw debts]}.
Examples:
params = {"group_id": 12345}
params = {"group_id": 12345, "response_format": "json"}
Error Handling:
403 means you are not a member of that group; 404 means the id is wrong or the group
was deleted (splitwise_undelete_group restores it) — or, for group_id 0, that the
pseudo-group is not served here (use splitwise_get_balances). Errors come back as an
Error ... string.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial context beyond them: the sign convention (positive = owed by group), the simplified_debts → original_debts fallback and that it says so, the 50-row cap, raw-and-flagged behavior for unparseable amounts, and 403/404 error semantics. This is unusually rich behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded and sectioned with headers, so the length is scannable rather than rambling. However, the detailed 'Returns' section partially restates content already available in the output schema, which is minor redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the group/currency/settlement complexity, the description covers the sign convention, debt-source fallback, member-name resolution, error codes, and the pseudo-group trap. Combined with the existing output schema, an agent has everything needed to call and interpret this tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is reported at 0%, so the description must carry the burden, and it does: it explains group_id 0 as the non-group pseudo-group whose only member is you, and what response_format 'markdown' vs 'json' returns. It also supplies concrete example param objects.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource with scope ('each member's balance in one group and who should pay whom to settle it'), and explicitly distinguishes itself from splitwise_get_balances, splitwise_get_group, and the group-mutation siblings. An agent can pick this tool without opening another schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has dedicated 'When to Use' and 'When NOT to Use' sections naming concrete alternatives (splitwise_get_balances for all-friend balances, splitwise_get_group for details, splitwise_resolve_group for id lookup) and an explicit edge case (group_id 0 pseudo-group returning only you). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_groupsARead-onlyIdempotent
List every group you belong to, with members count and balances per currency.
Calls GET /get_groups and renders one row per group: name, id, type, number of
members and the balance column. With current_user_id the column is YOUR balance in
that group; without it, members' non-zero balances are listed compactly (at most 6 per
group — splitwise_get_group has the rest). Group id 0 is Splitwise's pseudo-group for
non-group expenses.
Sign convention: positive = owed to that member (with current_user_id: owed to you);
negative = they (you) owe.
When to Use:
To find a group's id before reading, adding an expense to it, or changing its members.
For an overview of where you owe or are owed money, group by group.
When NOT to Use:
To match a group by a fuzzy name (use
splitwise_resolve_group).For one group's members, debts and invite link (use
splitwise_get_group).For balances per friend across all groups (use
splitwise_get_balances/splitwise_get_friends).
Returns:
A markdown table or, with response_format=json,
{"count", "offset", "shown", "has_more", "next_offset", "groups": [raw group objects]}.
Pagination:
Splitwise returns every group at once; the tool shows 50 per call. When more remain it
reports the next offset — call again with offset set to it.
Examples:
params = {}
params = {"current_user_id": 491923}
params = {"offset": 50, "response_format": "json"}
Error Handling:
401 → the API key is missing or was regenerated; network errors are reported as Error: ....
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive, and the description adds substantial behavior beyond them: 50-per-call pagination with next-offset, the sign convention for balances, the group id 0 pseudo-group, response-format behavior, and 401/network error handling. This is rich operational context rare in tool descriptions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Purpose and key caveats are front-loaded, then cleanly sectioned into When to Use / When NOT to Use / Returns / Pagination / Examples / Error Handling. Every section carries unique information; no sentence is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read tool with both annotations and an output schema, this description covers everything an agent needs: selection guidance, pagination continuation, sign interpretation, and failure modes. Nothing material is left for the agent to guess.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite the low reported schema coverage signal, the description fully explains each parameter's effect: offset ties to the 50-per-call window, current_user_id changes whose balance is shown and flips the sign convention, and response_format governs the return shape. Worked examples show concrete parameter combinations.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence states a specific verb and resource ('List every group you belong to') plus the returned columns (members count, balances per currency). It also disambiguates from close siblings like splitwise_get_group and splitwise_get_balances via the When NOT to Use list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit When to Use and When NOT to Use sections name concrete alternatives (splitwise_resolve_group, splitwise_get_group, splitwise_get_balances) and the conditions that select them. An agent can route correctly without inferring anything.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_notificationsARead-onlyIdempotent
List your recent Splitwise activity (notifications), newest first.
Calls GET /get_notifications and renders one row per notification: when it
happened, what kind it is (expense added/updated/deleted, comment added, group and
friend changes, …), its text with the HTML flattened (a struck-through old value
shows as ~~old~~), what it is about (source type, id and URL) and who triggered it
(user N). Codes Splitwise has not documented show as unknown (N).
When to Use:
"What changed in my Splitwise lately?" / "Did anyone add an expense this week?"
To find the id of a recently added or edited expense or group (the source column).
When NOT to Use:
To list expenses with filters (group, friend, dates) — use
splitwise_get_expenses.To read the comments on one expense — use
splitwise_get_comments.To see who owes whom — use
splitwise_get_balances.
Returns:
Markdown: | When | Type | Content | Source | By | Id |, at most 50 rows (the rest
counted; each text capped at 2,000 characters, the cut counted). JSON: {"count", "limit", "updated_after", "type_names", "notifications": [raw objects]} — content stays raw HTML there, and type_names maps the codes
present to their names.
Pagination:
There is no offset. limit returns the newest N (0 = the server's maximum, which
can be large); updated_after returns only what changed since a point in time (e.g.
your last check). Combine them to keep the response small.
Examples:
params = {}(the 20 most recent)params = {"updated_after": "2026-10-01", "limit": 50}params = {"limit": 5, "response_format": "json"}
Error Handling:
A malformed updated_after or a limit outside 0–100 is rejected before any call.
401 means the API key is missing or was regenerated. Errors come back as an
Error ... string, never raised.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), and the description goes well beyond them: 50-row cap with overflow counted, 2,000-character text cap, HTML flattening with `~~old~~` convention, undocumented codes rendered as `unknown (N)`, pre-call validation of inputs, and 401/error-as-string semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The purpose is front-loaded and the sectioned layout (When to Use / When NOT / Returns / Pagination / Examples / Error Handling) is easy to scan. It is somewhat long for a three-parameter read tool and re-states a few details that also live in the schema, but almost every line is actionable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only list tool with an output schema present, the definition supplies everything an agent needs: trigger conditions, exclusions with alternatives, pagination model, output shapes for both formats, and failure modes. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With schema description coverage reported at 0%, the description carries the load and does so fully: `limit` (0 = server maximum, can be large, prefer a number), `updated_after` (ISO-8601, bare date = midnight UTC), and `response_format` behavior, plus concrete parameter examples and guidance to combine the two.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The first sentence states a specific verb (list) plus resource (recent Splitwise activity/notifications) and ordering (newest first), then details exactly what each row contains. It is immediately distinguishable from siblings like splitwise_get_expenses and splitwise_get_comments.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There are explicit 'When to Use' and 'When NOT to Use' sections, and the negative cases name the correct alternative for each scenario (splitwise_get_expenses, splitwise_get_comments, splitwise_get_balances). No inference is left to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_get_userARead-onlyIdempotent
Get another Splitwise user's public profile by id: name, email, registration status.
Calls GET /get_user/{id}. Splitwise only answers for users you are connected to —
a friend, or someone who shares a group with you — and for yourself.
When to Use:
To turn a user id seen in an expense, debt or notification into a name and email.
To check whether someone is a
confirmeduser or adummy/invitedplaceholder.
When NOT to Use:
For yourself with notification settings, currency and locale (use
splitwise_get_current_user).To find a user id from a name (use
splitwise_resolve_friend).For balances with that person (use
splitwise_get_friend/splitwise_get_balances).
Returns:
Markdown (default): First Last (id N) <email> and the registration status
(confirmed | dummy | invited). JSON: the raw Splitwise user object (incl. picture).
Examples:
params = {"user_id": 491923}params = {"user_id": 491923, "response_format": "json"}
Error Handling:
403 when the user is neither your friend nor in a group with you; 404 when the id
does not exist; 401 when the API key is missing or revoked. Every failure comes back
as an Error ... string.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly/idempotent/non-destructive/openWorld, and the description still adds a non-obvious access constraint (only friends, group co-members, or self), the underlying endpoint, the full error contract (403/404/401) and the fact that failures return as `Error ...` strings. It also distinguishes `confirmed` vs. `dummy`/`invited` user states, which the annotations cannot convey.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose, then cleanly sectioned by usage, returns, examples and errors; the examples section is somewhat redundant given the schema. Well-sized overall but slightly longer than strictly necessary for a one-parameter read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the access model, both output formats, the endpoint, and every failure mode. Even though an output schema exists (so return values are technically redundant here), the extra detail about the registration-status field meaning makes a one-parameter read tool fully self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema documents both properties inline, and the description reinforces them with concrete example payloads (`{"user_id": 491923}`) plus the access precondition on user_id and the meaning of response_format. It adds example values and the friend/group requirement, though it doesn't explain edge cases beyond the schema's own notes.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Starts with a specific verb+resource+scope: "Get another Splitwise user's public profile by id" and enumerates the returned fields (name, email, registration status). It explicitly names the sibling tools it is not (splitwise_get_current_user, splitwise_resolve_friend, splitwise_get_friend), so an agent can route without opening a schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has dedicated "When to Use" and "When NOT to Use" sections, the latter naming four concrete alternatives with the condition that selects each (self vs. other, name-to-id vs. id-to-name, balances vs. profile). This is as explicit as routing guidance gets.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_health_checkARead-onlyIdempotent
Verify connectivity and the API key against Splitwise, and report the write kill-switch.
Calls GET /get_current_user with the configured personal API key and renders who
you are logged in as (name, id, email, default currency, locale, unread
notifications). Also states whether writes are enabled (SPLITWISE_ALLOW_WRITES).
When to Use:
As the first call after configuring the server, to confirm the key works.
To learn your own user id before building expense shares.
To debug a 401 (key missing / regenerated) before trying other tools.
When NOT to Use:
To read balances (use
splitwise_get_balances/splitwise_get_friends).To change profile settings (use
splitwise_update_user).
Returns:
A markdown block with the base URL, the kill-switch state, connectivity, and the
current user — or an Error ... string describing the failure.
Error Handling: 401 means the key is missing, mistyped, or was regenerated at https://secure.splitwise.com/apps; a connection error means the API URL or the network is wrong. Without a configured key the tool returns the config state and says what to set, without calling the API.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), and the description adds substantial context beyond them: the SPLITWISE_ALLOW_WRITES kill-switch, the exact endpoint called, the 401 remediation path, and the fallback behavior when no key is configured (returns config state without hitting the API).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and cleanly sectioned with headers, which suits an agent scanning for a diagnostic tool. It is slightly long — the Returns section partially overlaps the existing output schema — but every block still carries operational value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-param diagnostic tool with an output schema, this is fully complete: it discloses the endpoint, the kill-switch, error semantics (401 vs connection error), and no-key behavior. An agent has everything needed to call it and interpret both success and failure.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so per the rubric the baseline is 4. Nothing about argument semantics needs explaining, and the description correctly stays silent on params rather than inventing meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Verify connectivity and the API key against Splitwise, and report the write kill-switch') and even names the endpoint it calls (GET /get_current_user). It explicitly distinguishes itself from siblings like splitwise_get_balances and splitwise_get_current_user by defining its diagnostic role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'When to Use' (first call after config, learn own user id, debug 401) and 'When NOT to Use' sections with named alternatives for each exclusion. Nothing is left to inference about when this tool is the right pick.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_remove_user_from_groupADestructiveIdempotent
Remove a member from a group. 🔒 destructive write.
Calls POST /remove_user_from_group with group_id and user_id. Splitwise refuses
when the member has a non-zero balance in the group (settle up first) — and it does so
with HTTP 200 + success: false, which the client turns into an error. The member is
reported as removed only when the body says success: true. Refused with
Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. Undo:
splitwise_add_user_to_group with the same ids.
When to Use:
To drop someone (or yourself) from a group whose balances are settled.
When NOT to Use:
To delete the whole group (use
splitwise_delete_group).To check balances first (use
splitwise_get_group).With a group NAME — resolve it to an id first (use
splitwise_resolve_group).
Returns:
A confirmation with the success / errors values Splitwise returned — or, when the
body does not say success: true, a note to verify before reporting it as removed.
Examples:
params = {"group_id": 12345, "user_id": 5823}
Error Handling:
A non-zero balance (or any refusal) → Error: Splitwise rejected the request ... with
Splitwise's message; 403 → you are not a member of the group.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and readOnlyHint=false, but the description goes far beyond them: the HTTP 200 + success:false quirk, the SPLITWISE_ALLOW_WRITES=1 gate, the refusal on non-zero balance, the 403 meaning, and the exact undo call. This is unusually rich behavioral disclosure for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with a one-line purpose and emoji-flagged destructiveness, then sectioned into scannable blocks. It is long for a two-parameter tool, but every section (guard railing, returns, error handling) carries information an agent needs, so little is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the destructive/auth prerequisites, the ambiguous-success failure mode, the undo path, and error mapping, so nothing needed to invoke or interpret the call is missing. An output schema exists, yet the extra success/errors interpretation guidance still adds value.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema's nested properties do carry short descriptions, but the description reinforces them with a concrete example ({"group_id": 12345, "user_id": 5823}) and adds the rule that a group NAME must first be resolved via splitwise_resolve_group. That name-to-id guidance is meaningfully beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Remove a member from a group') and immediately distinguishes it from siblings like splitwise_delete_group and splitwise_add_user_to_group. An agent can identify the tool's scope without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' and 'When NOT to Use' sections name three alternatives (delete_group, get_group, resolve_group) plus the balance-settled precondition. Routing decisions are fully enumerated rather than left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_resolve_categoryARead-onlyIdempotent
Turn a category name into the subcategory id an expense needs, with ranked fuzzy candidates.
Reads the categories from GET /get_categories through the same 24 h in-process cache
as splitwise_get_categories (refresh: true refetches). Every subcategory is
scored with difflib.SequenceMatcher on case- and accent-folded text — the best of its
name, each piece of the name split on / and spaces ("phone" → TV/Phone/Internet), and
"Parent Subcategory" (so "transportation other" picks the right "Other").
Subcategories are listed first and are the only ones that can be resolved: exactly
one exact (1.000) match, or — with no exact match — exactly one scoring ≥ 0.85
(unique_strong; a wrong category is cheap to fix with splitwise_update_expense).
Either way no other subcategory may start with the query ("tax" next to Taxi and Taxes
is ambiguous), a fuzzy match needs a query of 4+ characters, and digits in the query
must match. The closest parent categories follow, flagged "parent — not usable for
expenses", with their subcategories so you can pick one; a parent scores the better of
its own name and its best subcategory (so "groceries" surfaces "Food and drink").
The names scored are the ones Splitwise returns for this account's locale: on a
Spanish account "groceries" finds nothing but "supermercado" resolves. Query in the
language the user sees in their Splitwise app, or browse splitwise_get_categories.
When to Use:
Before
splitwise_create_expense/splitwise_update_expense, when the user named a category ("groceries", "taxi").
When NOT to Use:
To browse the whole tree — use
splitwise_get_categories.For people or groups — use
splitwise_resolve_friend/splitwise_resolve_group.
Returns:
The resolution line, a markdown table of the top limit subcategories (rank,
Name (id N), parent, score, matched on), then up to 3 parents with their
subcategories; or, with response_format json, {query, resolution, ambiguous_count, reason, resolved, subcategories: [...], parents: [...]} where
resolution is exact | unique_strong | ambiguous | none, ambiguous_count
(always present, 0 unless ambiguous) says how many candidates are in contention, and
parents carry usable_for_expenses: false.
Examples: params = {"query": "groceries"} params = {"query": "transportation other", "response_format": "json"}
Error Handling: A 401 means the API key is missing or was regenerated. A failed fetch is never cached. Several subcategories share the name "Other" — "other" alone is reported as ambiguous; qualify it with the parent.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly, idempotent, non-destructive, openWorld), and the description adds substantial context beyond them: the shared 24 h cache and what refresh does, the exact resolution thresholds (1.000 exact, unique_strong ≥ 0.85), the ambiguity rules (prefix collision, 4+ char fuzzy minimum, digit matching), locale-dependent naming, and error handling (401 = missing/regenerated key, failed fetches never cached). This is far richer than the annotations alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded one-line summary, then clearly headed sections (When to Use / When NOT to Use / Returns / Examples / Error Handling). Highly dense and mostly earns its length, but the deep dive into scoring internals (difflib on accent-folded text, the 'phone' → TV/Phone/Internet example) is more than an agent strictly needs to invoke the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a fuzzy-resolution tool with an output schema, everything an agent needs is present: prerequisite sequencing before expense creation, cache/refresh behavior, locale caveats, ambiguity outcomes, and error handling. The Returns section is redundant with the output schema but harmless.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Although coverage is reported low, the description adds real meaning beyond the schema: refresh is explained in terms of the 24 h cache, response_format is tied to the concrete json/markdown shapes, and query is given crucial semantics the schema lacks — query in the user's Splitwise locale language, 4+ characters required for fuzzy matching, digits must align, and 'other' alone is ambiguous and must be qualified with a parent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening line states a precise verb and resource ('turn a category name into the subcategory id an expense needs') plus the scope of output ('ranked fuzzy candidates'). It is immediately distinguishable from splitwise_get_categories, which the description explicitly routes the browser to. An agent can tell which tool to pick without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Dedicated 'When to Use' and 'When NOT to Use' sections name the exact upstream callers (splitwise_create_expense / splitwise_update_expense) and the alternative tools for browsing and for people/groups. The condition that selects each alternative is stated, not implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_resolve_friendARead-onlyIdempotent
Turn a friend's name (or email) into their Splitwise user id, with ranked fuzzy candidates.
Calls GET /get_friends (not cached — friends change) and scores every friend with
difflib.SequenceMatcher on case- and accent-folded text: the best of "first last",
the first name, the last name, the email local-part and the full email. Returns the top
limit candidates with their scores.
A friend is resolved ONLY on an exact match (1.000 on one of those fields, for exactly one friend, and no other friend's name or email starting with the query). A wrong id here is a wrong person — the expense, the group membership or the deletion lands on someone else — so a close-but-not-exact candidate ("Daniela" vs "Daniel", 0.923) is reported as probable and must be confirmed with the user. No fuzzy candidate is offered for a query under 4 characters or whose numbers differ.
When to Use:
Before
splitwise_create_expense,splitwise_add_user_to_group,splitwise_get_friendorsplitwise_delete_friend, when the user named a person ("split it with Jon").
When NOT to Use:
For balances with each friend — use
splitwise_get_balances/splitwise_get_friends.For groups or categories — use
splitwise_resolve_group/splitwise_resolve_category.Someone who is not your friend yet: they will not be listed — add them with
splitwise_create_friend.
Returns:
The resolution line plus a markdown table (rank, First Last (id N), email, score,
matched on); or, with response_format json, {query, resolution, ambiguous_count, reason, resolved, probable, candidates: [{id, first_name, last_name, email, score, matched_on}]} where resolution is exact | probable | ambiguous | none,
ambiguous_count (always present, 0 unless ambiguous) says how many candidates are in
contention, resolved is set only for exact, and probable only for probable.
Examples: params = {"query": "Jon"} params = {"query": "maria garcia", "limit": 3, "response_format": "json"}
Error Handling:
A 401 means the API key is missing or was regenerated. With no friends at all the tool
says so. Anything but exact means: ask the user, do not pick.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover the safety profile (readOnly, idempotent, non-destructive), and the description adds substantial behavior beyond them: the endpoint is uncached, the scoring algorithm, the exact-match-only resolution rule, the danger of a wrong id, and that sub-4-character or digit-differing queries get no fuzzy candidate. This is exactly the extra context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Long but well-sectioned (purpose, when-to-use, when-not-to-use, returns, examples, error handling) with the core purpose front-loaded. Every section adds distinct value; only minor tightening is possible.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the ambiguity/resolution model, the exact/probable/ambiguous/none states, error handling (401, empty friend list), and usage examples. An agent has everything needed to call it correctly and to know not to auto-pick a fuzzy match.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Reported schema coverage is 0%, but the description compensates: it explains that `limit` bounds the top-N candidates, that `query` is 'the name as the user said it,' and fully specifies the `response_format`='json' payload shape. Semantics for each param are grounded in behavior rather than just restated.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource+scope: 'Turn a friend's name (or email) into their Splitwise user id, with ranked fuzzy candidates.' It is immediately distinguishable from siblings like splitwise_get_friends or splitwise_resolve_group, which are named explicitly later.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Dedicated 'When to Use' and 'When NOT to Use' sections name the prerequisite tools (splitwise_create_expense, splitwise_add_user_to_group, etc.) and route non-friend lookups to splitwise_get_balances, splitwise_resolve_group, and splitwise_create_friend. Explicit alternatives with conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_resolve_groupARead-onlyIdempotent
Turn a group's name into its Splitwise group id, with ranked fuzzy candidates.
Calls GET /get_groups (not cached — groups change) and scores every group name with
difflib.SequenceMatcher on case- and accent-folded text. Returns the top limit
candidates with their scores. Group id 0 is Splitwise's pseudo-group for non-group
expenses (group_id: 0 = no group).
A group is resolved ONLY on an exact name match (1.000, for exactly one group, and no other group name starting with the query — "Peru trip" next to "Peru trip 2026" is ambiguous). A close-but-not-exact name is reported as probable and must be confirmed with the user; a query whose numbers differ ("peru trip 2025" vs "Peru trip 2026") or that is under 4 characters gets no fuzzy candidate at all.
When to Use:
Before
splitwise_create_expense,splitwise_get_group,splitwise_get_expenses,splitwise_add_user_to_grouporsplitwise_delete_group, when the user named a group ("the Peru trip").
When NOT to Use:
To list every group with balances — use
splitwise_get_groups.For people or categories — use
splitwise_resolve_friend/splitwise_resolve_category.
Returns:
The resolution line plus a markdown table (rank, Name (id N), type, members, score);
or, with response_format json, {query, resolution, ambiguous_count, reason, resolved, probable, candidates: [{id, name, group_type, members_count, pseudo_group, score}]} where resolution is exact | probable | ambiguous | none,
ambiguous_count (always present, 0 unless ambiguous) says how many candidates are in
contention, resolved is set only for exact, and probable only for probable.
Examples: params = {"query": "peru trip"} params = {"query": "home", "limit": 3, "response_format": "json"}
Error Handling:
A 401 means the API key is missing or was regenerated. With no groups the tool says
so. Anything but exact means: ask the user, do not pick.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only/idempotent safety profile, but the description goes well beyond them: the endpoint is uncached because groups change, scoring uses difflib.SequenceMatcher on case/accent-folded text, resolution succeeds only on an exact unique match (with the 'Peru trip' vs 'Peru trip 2026' ambiguity rule), short/numeral-differing queries yield no fuzzy candidate, group id 0 is the pseudo-group, and a 401 means the API key is missing or regenerated. This is unusually rich behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well front-loaded with the core purpose first, then structured sections. It is long, and the 'Returns' block partially duplicates the output schema, but each section earns its place given the resolution semantics an agent must get right.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists, the description still supplies the resolution-state machine (exact/probable/ambiguous/none), the always-present ambiguous_count, the conditional resolved/probable keys, error handling, and the fallback instruction ('ask the user, do not pick'). Nothing an agent needs to call or interpret this tool is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema itself documents limit (1-25 range) and response_format, and the description reinforces both with the example call and the JSON return shape. It adds real semantic value for `query` by explaining the folding/scoring and <4-character and numeral-mismatch behavior — meaning the schema cannot convey — though it does not spell out the maxLength=100 or required-only constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a precise verb+resource+outcome ('turn a group's name into its Splitwise group id, with ranked fuzzy candidates') and explicitly distinguishes itself from sibling resolvers and from splitwise_get_groups. An agent can identify this as the name-to-id resolver without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Has dedicated 'When to Use' and 'When NOT to Use' sections naming the concrete downstream tools that require a resolved id (create_expense, get_group, get_expenses, add_user_to_group, delete_group) and routing list queries to splitwise_get_groups and person/category lookups to splitwise_resolve_friend / splitwise_resolve_category.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_undelete_expenseAIdempotent
Restore a deleted expense.
Calls POST /undelete_expense/{id}. Refused with Error: … writes are disabled unless
SPLITWISE_ALLOW_WRITES=1 (enforced by the server's client). The expense comes back
with its original shares, so balances change again.
When to Use:
Undo a
splitwise_delete_expense.Bring back an expense seen as
[deleted]insplitwise_get_expenseswith include_deleted=true.
When NOT to Use:
On an expense that is not deleted (nothing to restore).
To restore a deleted group (use
splitwise_undelete_group).
Returns:
The success value Splitwise returned.
Examples:
params = {"expense_id": 3456789012}
Error Handling:
Splitwise answers 200 even when it refuses — the client turns success: false into
Error: Splitwise rejected the request…. 404 → wrong id; 403 → not your expense.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the SPLITWISE_ALLOW_WRITES=1 gate and its refusal message, the side effect that balances change again via restored shares, and detailed error semantics (200-on-refusal, 404 vs 403). This is exactly the behavioral context annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the action, then routes via labeled sections; nearly every line earns its place. The 'Returns: The success value Splitwise returned.' line is largely redundant given an output schema exists, costing the top score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write tool with an unavoidable auth/environment prerequisite, the definition covers the gate, side effects, alternatives, a call example, and error mapping. An agent has everything needed to invoke it correctly, and return values are covered by the output schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It provides a concrete example call with a nested params wrapper and an integer id, which usefully disambiguates the envelope shape, but adds no further semantics for the single expense_id field.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Restore) and resource (a deleted expense) in the first line, and explicitly distinguishes itself from the sibling splitwise_undelete_group. An agent can route to it without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Dedicated 'When to Use' and 'When NOT to Use' sections name the exact triggering operations (undo splitwise_delete_expense, recover `[deleted]` rows from splitwise_get_expenses) and point to the correct alternative for groups.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_undelete_groupAIdempotent
Restore a deleted group (and its expenses). 🔒 write.
Calls POST /undelete_group/{id}. Splitwise answers HTTP 200 even when this fails and
puts the outcome in success / errors; the client turns a failure into an error,
and this tool reports the group as restored only when the body says success: true.
Refused with Error: … writes are disabled unless SPLITWISE_ALLOW_WRITES=1. Undo:
splitwise_delete_group.
When to Use:
To bring back a group deleted by mistake (
splitwise_delete_group).
When NOT to Use:
To restore one expense (use
splitwise_undelete_expense).To re-add a removed member (use
splitwise_add_user_to_group).With a group NAME — resolve it to an id first (use
splitwise_resolve_group).
Returns:
A confirmation with the success / errors values Splitwise returned — or, when the
body does not say success: true, a note to verify before reporting it as restored.
Examples:
params = {"group_id": 12345}
Error Handling:
success: false / non-empty errors come back as Error: Splitwise rejected the request ....
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations by disclosing the HTTP-200-with-success/errors quirk, the write gate requiring SPLITWISE_ALLOW_WRITES=1, the failure transformation into an Error, the undo path, and the refusal message text. These are exactly the behaviors an agent cannot derive from readOnlyHint/destructiveHint/idempotentHint alone.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded purpose line followed by tight labeled sections (When to Use, When NOT to Use, Returns, Examples, Error Handling). Dense but every sentence contributes actionable information with no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the mutation's failure modes, environment gating, return-value interpretation, and error surface, which is more than enough for a one-parameter write tool even though an output schema exists. An agent has everything needed to call and interpret it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
One required param with reported 0% schema coverage, so the description carries the burden: it supplies an example params block and, crucially, warns that a group NAME must first be resolved to an id via splitwise_resolve_group. That adds real semantic value, though it does not restate the schema's own '0 is not a real group' constraint.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Restore a deleted group (and its expenses)') and mirrors the exact endpoint POST /undelete_group/{id}. An agent can distinguish it from splitwise_delete_group and splitwise_undelete_expense without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit When to Use / When NOT to Use sections and names each alternative with the condition that selects it (splitwise_undelete_expense for one expense, splitwise_add_user_to_group for re-adding members, splitwise_resolve_group for name-to-id resolution). Nothing is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_update_expenseAIdempotent
Change an existing expense — only the fields given are sent.
Calls POST /update_expense/{id}. Refused with Error: … writes are disabled unless
SPLITWISE_ALLOW_WRITES=1 (enforced by the server's client).
WARNING: shares REPLACES ALL existing shares. Splitwise treats any users__* key as
the complete new split, so list EVERY participant with their paid_share and
owed_share — sending only the person who changed drops everyone else from the
expense. Read the current split first with splitwise_get_expense.
No undo tool — to revert, re-send the previous values read with
splitwise_get_expense first.
When shares is given, Σ paid_share and Σ owed_share must each equal the cost: the new
cost if you pass one, otherwise the expense's current cost (read once with
GET /get_expense/{id}). A mismatch is refused before the update is sent. Changing
cost WITHOUT shares leaves the split to Splitwise, which may reject it if the
current shares no longer add up — pass both to be explicit.
When to Use:
Fix a description, date, category or currency.
Change the amount together with the full new split.
Move an expense to another group (group_id; 0 = no group).
When NOT to Use:
To create a new expense (use
splitwise_create_expense).To delete or restore one (use
splitwise_delete_expense/splitwise_undelete_expense).To look up ids by name (use
splitwise_resolve_friend/splitwise_resolve_group/splitwise_resolve_category).
Returns:
A confirmation echoing Splitwise's response: the literal errors value and the expense
as returned (id, description, cost, group, date, shares).
Examples:
params = {"expense_id": 3456789012, "description": "Dinner (incl. tip)"}
params = {"expense_id": 3456789012, "cost": "60.00", "shares": [ {"user_id": 491923, "paid_share": "60.00", "owed_share": "30.00"}, {"user_id": 678, "paid_share": "0.00", "owed_share": "30.00"}]}
Error Handling:
Refused locally (nothing sent) when no field is given, when shares do not add up, or a
share has both/neither identity. Splitwise answers 200 even on failure — the client turns
a non-empty errors into Error: Splitwise rejected the request…; if that body still
carried an expense object the error adds "Splitwise still returned N expense object(s) …
may have landed", so read the expense back before retrying. 404 → wrong id; 403 →
not your expense.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond the annotations: it discloses the SPLITWISE_ALLOW_WRITES=1 write gate, that shares REPLACES the whole split and silently drops omitted participants, the no-undo requirement to re-read and re-send, and the trap that Splitwise returns HTTP 200 even on failure so a non-empty 'errors' body must be inspected. Annotations only say readOnly=false, idempotent=true, destructive=false; the description supplies the operational consequences those hints do not.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loads the core behaviour and the shares warning, then organises the rest under headers (When to Use / When NOT to Use / Returns / Examples / Error Handling). It is long, and the shares-replacement warning is repeated in both the body and the shares paragraph, but the redundancy is on the highest-risk failure mode and every section carries distinct information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a stateful mutation tool with a nested share sub-object, it covers the write gate, replacement semantics, arithmetic constraints, confirmation payload, worked examples, and a full error taxonomy (refused-local, 200-with-errors, 404 wrong id, 403 not your expense, possibly-landed writes). Nothing an agent needs before or after calling it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Adds cross-field meaning the schema cannot express: Σ paid_share and Σ owed_share must each equal the new cost (or the current cost if cost is omitted), that a mismatch is refused before sending, and that changing cost without shares defers the split to Splitwise. group_id 0 = no group is also clarified. Some of the shares warning duplicates the schema's own field description, which is why this is not a 5.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the specific verb and resource ('Change an existing expense'), the endpoint it calls, and the partial-update semantics ('only the fields given are sent'). It also names sibling tools for adjacent operations (create/delete/undelete/resolve), so an agent can distinguish it from every neighbouring write tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit 'When to Use' and 'When NOT to Use' lists that map each alternative (create_expense, delete_expense, undelete_expense, resolve_*) to the case that should select it. The prerequisite for safe share edits (read the current split with splitwise_get_expense first) is stated up front, not left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
splitwise_update_userAIdempotent
Update your Splitwise profile: first name, last name, locale and/or default currency.
Calls POST /update_user/{id} with only the fields you pass (at least one). This is
a write: it is refused with Error: … writes are disabled unless
SPLITWISE_ALLOW_WRITES=1. Email and password are NOT updatable on purpose — the
input has no such fields and the server's client refuses to send them under any
configuration, so an LLM can never change the account's login. There is no undo tool:
to revert, read the current values first with splitwise_get_current_user and call
this tool again with them.
When to Use:
To fix a typo in your name, or switch the default currency / interface locale.
When NOT to Use:
To change email or password (impossible here by design — do it at https://secure.splitwise.com).
To read your profile (use
splitwise_get_current_user).To rename a friend or group member (Splitwise does not allow editing other users).
Returns:
A confirmation naming the user Splitwise returned and, for each field you sent, the
value as it appears in the response. It is headed "Profile updated" only when every
sent field comes back with exactly the value sent. Otherwise it is headed "Update
accepted by Splitwise — N of M field(s) not confirmed" with those fields flagged, and
tells you to read the profile back with splitwise_get_current_user. This is common
for locale/default_currency, which the flat user object in the response may omit.
Examples:
params = {"user_id": 491923, "default_currency": "PEN"}params = {"user_id": 491923, "first_name": "Ada", "last_name": "Lovelace", "locale": "es"}
Error Handling:
Validation rejects a call with no field to change, an unknown field (including
email/password) or a currency that is not a 3-letter code, before any request.
locale is checked for format only and passed through; Splitwise decides whether it
is supported (a value it ignores shows as 'differs' in the confirmation).
403 when user_id is not your own id; 400 with Splitwise's field messages for a value
it rejects. A timeout or 5xx leaves the outcome UNKNOWN — read the profile back with
splitwise_get_current_user before retrying.
| Name | Required | Description | Default |
|---|---|---|---|
| params | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety/idempotency profile; the description adds far more: the SPLITWISE_ALLOW_WRITES=1 gate, that email/password are structurally impossible, that there is no undo (with the read-back-and-recall recovery pattern), the partial-confirmation semantics for locale/currency, and that a timeout/5xx leaves the outcome UNKNOWN. This is exactly the behavioral context an agent needs beyond structured fields.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-organized with clear headers and front-loaded purpose and write-gate warning. It is long, and the 'Returns' section partly restates what the output schema already conveys, so not every line is strictly additive, but nothing is filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write tool with annotations and an output schema, the definition still covers auth gating, reversibility, partial-success behavior, and error mapping (403/400/timeout). An agent has everything required to invoke and recover correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description reinforces the 'at least one field' constraint, gives worked examples with concrete currency/locale values, and explains the locale pass-through-vs-validated distinction. The schema itself already documents each field, so the description mainly adds the cross-field constraint and example syntax rather than new per-parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence names a specific verb (Update) and resource (your Splitwise profile) and enumerates the exact mutable fields. It is trivially distinguishable from siblings like splitwise_get_current_user or splitwise_update_expense.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit 'When to Use' and 'When NOT to Use' sections name the concrete alternative for reads (splitwise_get_current_user) and rule out email/password edits and editing other users. The routing is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
33 tool updates
v0.1.0- First observed
splitwise_add_user_to_group - First observed
splitwise_create_comment - First observed
splitwise_create_expense - First observed
splitwise_create_friend - First observed
splitwise_create_friends - First observed
splitwise_create_group - First observed
splitwise_delete_comment - First observed
splitwise_delete_expense - First observed
splitwise_delete_friend - First observed
splitwise_delete_group - First observed
splitwise_get_balances - First observed
splitwise_get_categories - First observed
splitwise_get_comments - First observed
splitwise_get_currencies - First observed
splitwise_get_current_user - First observed
splitwise_get_expense - First observed
splitwise_get_expenses - First observed
splitwise_get_friend - First observed
splitwise_get_friends - First observed
splitwise_get_group - First observed
splitwise_get_group_balances - First observed
splitwise_get_groups - First observed
splitwise_get_notifications - First observed
splitwise_get_user - First observed
splitwise_health_check - First observed
splitwise_remove_user_from_group - First observed
splitwise_resolve_category - First observed
splitwise_resolve_friend - First observed
splitwise_resolve_group - First observed
splitwise_undelete_expense - First observed
splitwise_undelete_group - First observed
splitwise_update_expense - First observed
splitwise_update_user
TDQS
Scored across 33 tools
The descriptions are unusually explicit, with When to Use / When NOT to Use sections, so most tools are clearly distinguishable. However, a few retrieval pairs overlap in output—splitwise_get_group_balances and splitwise_get_group both expose group debts/member balances, and splitwise_get_expense already includes comments while splitwise_get_comments is separate—so occasional misselection is possible.
All 33 tools use the same splitwise_ prefix and snake_case, with a consistent verb_noun pattern (get_, create_, update_, delete_, undelete_, add_, remove_, resolve_). Even the few non-verb forms are predictable within the set.
33 tools is well above the 3-15 typical range and exceeds the 25+ threshold for 'too many' in this dimension. While the Splitwise domain is broad and many tools map to distinct API endpoints, there are singular/batch duplicates and overlapping balance readers that could be consolidated.
The surface covers the domain broadly: CRUD plus delete/undelete for expenses and groups, comments create/read/delete, friend lifecycle, group membership, balances, categories, currencies, notifications, user profile, and resolve helpers. No obvious lifecycle gap is apparent; missing update operations such as group rename or comment edit appear unsupported by the Splitwise API.
Maintenance
Related MCP Connectors
Remote streamable-HTTP MCP server running on a single Cloudflare Worker. Your assistant gets live Airbnb, Amazon, Booking.com, Google Flights, Maps and Reddit data, social search on X, Instagram and TikTok, the Meta Ad Library, and image/video generation without any keys. Connect your own accounts to let it send WhatsApp or Telegram messages, work an IMAP inbox, manage Meta Ads campaigns and publish to X and LinkedIn. OAuth 2.1 with PKCE; stored credentials are AES-256-GCM encrypted.
Verified, pay-per-use API tools for AI agents through one authenticated connection.
Pay-per-use tool API for AI agents. Free tier, x402 USDC micropayments, or API key.
17 pay-per-call web, finance, legal and onchain tools for AI agents. USDC on Base via x402/MPP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables natural language management of Splitwise expenses, groups, and friends via the Model Context Protocol, with dual authentication and fuzzy name resolution.15MIT
- AlicenseNot gradedqualityCmaintenanceMCP server that exposes every endpoint from Splitwise's public self-serve API docs as MCP tools, covering 27 operations for managing expenses, users, and groups.445 npmMIT
- AlicenseNot gradedqualityCmaintenanceA local MCP server that exposes the Splitwise API as tools, enabling conversational management of expenses, groups, and friends. It runs entirely locally over stdio with no hosting required.445 npmMIT
- AlicenseAqualityBmaintenanceEnables AI agents to manage Splitwise expenses through natural language, including reading balances, splitting costs, and handling authentication and rate limits automatically.7MIT