Skip to main content
Glama
rorygeddes

Luni MCP Server

by rorygeddes

Luni MCP Server

This folder is the MCP (Model Context Protocol) server for Luni Financial. It lets Claude read live data from Luni — transactions, budgets, business P&L, recurring revenue, partner distributions — by connecting Claude directly to the Luni backend API.

When someone adds the Luni connector to Claude, this is what runs underneath it.


What this is, in plain English

Claude can't access your database on its own. This server acts as a secure bridge: Claude asks a question, the MCP server translates it into an API call to your existing Luni backend, and returns the answer in a shape Claude can reason about.

The server holds no secrets. It doesn't touch Plaid, Supabase, or Wise directly — it just forwards the user's authentication token to your backend, which already has all the access control logic. If a user isn't allowed to see something in the Luni app, they can't see it through Claude either.


Related MCP server: monarch-mcp

Folder structure

Luni_MCP/
├── server.js                        Entry point. Registers all tools and starts the server.
├── auth.js                          Figures out which user's token to use on each request.
├── client.js                        Thin wrapper that calls your Express backend with that token.
├── package.json                     Dependencies and scripts.
│
├── tools/
│   ├── list_transactions.js         Personal spending history (Plaid + Wise accounts).
│   ├── get_budget_status.js         Personal budget vs. actual spend for the month.
│   ├── list_splits_outstanding.js   Who owes the user money, and vice versa.
│   ├── list_entities.js             Which businesses and personal spaces the user has access to.
│   ├── get_cash_flow.js             Cash in vs. cash out for a business entity.
│   ├── get_pnl.js                   Profit & Loss statement for a business entity.
│   ├── get_recurring.js             Recurring income and expenses (subscriptions, retainers, etc.).
│   └── get_partner_distribution.js  How net profit is split between partners.
│
└── remote/
    └── vercel-handler.js            Skeleton for the future public/hosted version of this server.

The tools — what each one does

Personal finance tools (3)

list_transactions Returns the user's transactions across all connected accounts. Claude uses this when someone asks "what did I spend on food last week?" or "show me all transactions over $200 in April." Supports filters by date range, category, merchant name, and minimum amount.

get_budget_status Shows how the user is tracking against their personal budgets for a given month. Returns each category with the budget amount, how much has been spent, what's left, and a pace flag (on_track / over / ahead_of_pace / underspending). Claude uses this when someone asks "how am I doing this month?" or "which categories am I over on?"

list_splits_outstanding Lists unresolved split transactions — who owes the user money and who the user owes. Returns totals and per-split detail. Claude uses this when someone asks "who owes me?" or "what do I owe from the Vegas trip?"


Business entity tools (5) — the BI/consultancy layer

These are the new tools added in v0.2.0. They work at the business level, not the personal level, and all require an entity_id (retrieved via list_entities).

list_entities The gateway tool. Returns every business entity and personal space the authenticated user is entitled to see — company name, their role (owner / partner / viewer), currency, and fiscal year start. Claude calls this first whenever the user asks about a company. The backend enforces row-level security so users only see entities they actually belong to.

get_cash_flow Total money in vs. money out for a business entity over a date range. Can be broken down month by month, by expense/income category, or returned as a single totals summary. Claude uses this when someone asks "what was our cash flow in Q1?" or "show me the monthly cash position for last year."

get_pnl A full Profit & Loss statement for a business entity. Shows revenue line items, expense categories, gross profit, and net profit. Supports shorthand periods (this_month, last_quarter, ytd, last_year) and an optional prior-period comparison column for month-over-month or quarter-over-quarter analysis. This is the main tool a Luni Business client would use when they ask Claude "how profitable were we in Q4?"

get_recurring Lists all recurring inflows and outflows for a business entity — retainer income, SaaS subscriptions, recurring vendor payments, etc. Returns the monthly total for each, an annualised value, and a net monthly recurring summary. Claude uses this when someone asks "what are our fixed monthly costs?" or "show me all our recurring revenue."

get_partner_distribution Shows how the entity's net profit is split between partners for a period. This tool is privacy-aware by design: if the caller is a partner, the backend only returns their own slice (their percentage and dollar amount). If the caller is an owner, it returns the full table. Claude uses this when someone asks "how much do I take home this quarter?" or "show me the partner split."


How it works right now (local / v1)

The server runs locally on your machine, started by Claude Desktop as a subprocess. Claude Desktop reads the configuration below, spawns node server.js, and communicates with it over stdin/stdout.

Setup:

cd Luni_MCP
npm install

Make sure your backend is running (npm run dev in the backend folder).

Get a JWT for the user you want Claude to act as. The easiest way: sign in to the Luni app and copy currentSession.accessToken from the Supabase auth session. In Supabase → Authentication → Settings, set JWT Expiry to something like 86400 (24 hours) during development so you're not re-pasting every hour.

Add this to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "luni": {
      "command": "node",
      "args": ["/absolute/path/to/Luni_MCP/server.js"],
      "env": {
        "LUNI_BACKEND_URL": "http://localhost:3000",
        "LUNI_JWT": "eyJhbGciOiJIUzI1NiIs..."
      }
    }
  }
}

Restart Claude Desktop. You'll see a plug icon in Claude showing the Luni tools are connected. Try:

  • "What did I spend on restaurants this month?"

  • "How am I doing on my budgets?"

  • "What's Luni Financial's P&L for May?"

  • "Show me our recurring expenses."


Backend routes you need to implement

The three personal-finance tools already have matching routes in the backend. The five new business entity tools expect these routes — they need to be added to backend/server.js:

Tool

Route

Notes

list_entities

GET /api/entities

Filter by ?type=business|personal. RLS must scope to user's memberships.

get_cash_flow

GET /api/entities/:id/cash-flow

Params: start_date, end_date, group_by (month / category / none).

get_pnl

GET /api/entities/:id/pnl

Params: period, start_date, end_date, compare_to_previous.

get_recurring

GET /api/entities/:id/recurring

Params: direction (inflow / outflow / all), status (active / all).

get_partner_distribution

GET /api/entities/:id/distributions

Params: period, start_date, end_date. Must return only caller's slice for partner role.

The privacy rule for get_partner_distribution is the critical one: the RLS policy (or verifyToken middleware) must check the caller's role on the entity and scope the response accordingly — partner sees only their own row, owner sees all rows.


What the tools tell Claude about themselves

Each tool carries annotations that describe its behaviour to Claude and to Anthropic's connector directory reviewers:

annotations: {
  readOnlyHint: true,      // this tool never writes or modifies data
  destructiveHint: false,  // it cannot delete anything
  openWorldHint: false,    // it only accesses Luni data, not the open internet
}

All eight tools are read-only. Future write tools (categorise a transaction, create a split, etc.) will carry readOnlyHint: false plus a required confirm: true parameter that forces the user to explicitly approve the action in chat before anything is written.


How authentication works

Right now (v1): You paste a Supabase JWT into the config file. auth.js reads it from the LUNI_JWT environment variable and attaches it to every API call.

When this goes public (v2): Claude will initiate an OAuth 2.1 / PKCE flow. The user clicks "Connect Luni" in Claude, logs in to their Luni account, and approves the connection. Claude gets back a short-lived bearer token, which auth.js exchanges for a Supabase JWT via a new backend route (POST /oauth/token-exchange). The token cache in auth.js means this exchange only happens once per session, not on every tool call.

The OAuth branch is already stubbed in auth.js — it's waiting for the Vercel transport and OAuth backend routes to be wired in.


The roadmap to a public connector

Getting from "works for me locally" to "anyone can add Luni in Claude" has four steps:

Step 1 — Implement the backend routes listed in the table above. This makes the five business entity tools actually work.

Step 2 — Deploy the remote transport. Replace the stdio transport in server.js with an SSE transport, expose it as a Vercel function. The skeleton is in remote/vercel-handler.js. The tool files don't change at all — only the transport layer changes.

Step 3 — Add OAuth to the backend. Four new routes in backend/server.js:

  • GET /.well-known/oauth-authorization-server — tells Claude where to authenticate

  • GET /oauth/authorize — redirect to Luni login

  • POST /oauth/token — exchange code for access token

  • POST /oauth/token-exchange — exchange MCP bearer for Supabase JWT

Step 4 — Publish. For private clients (like Trillium), give them the MCP server URL and they add it as a custom connector in Claude — no review needed. For a public listing in Anthropic's connector directory, submit through their review form and allowlist these two OAuth redirect URIs:

  • https://claude.ai/api/mcp/auth_callback

  • https://claude.com/api/mcp/auth_callback


What this server deliberately does NOT do

  • No write operations. Nothing in this server can modify, delete, or create data in Luni. Every tool is read-only.

  • No raw database access. The server never touches Supabase, Plaid, or Wise directly. It only calls the Luni Express backend, which already has all access control logic.

  • No secrets stored here. No Plaid client ID, no Supabase service-role key, nothing sensitive. The JWT lives in the user's local config file and is never logged or stored by this server.

  • No QuickBooks, Stripe, or calendar tools. Those belong in their own connectors. This server is the Luni-data layer only.

Available Tools

8 tools
get_budget_statusA
Read-only

Show the user's personal budget vs actual spend for the current month (or a specified month). Use this when the user asks 'how am I doing', 'am I over budget', 'which categories am I over on', or similar. For business-entity P&L, call get_pnl instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
monthNoMonth to report on, YYYY-MM. Defaults to current month.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the description adds the specific behavioral context of comparing budget to actual spend. This is useful but does not detail output format.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose, followed by usage examples and alternative reference. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the tool's output concept (budget vs actual) and usage, but doesn't explicitly state the return structure (e.g., per-category breakdown). The example queries imply category-level granularity, so it's mostly complete for a simple tool without output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'month' is fully described in the schema with format and default. The description only reiterates the month can be specified, adding no new semantic information beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the tool shows 'personal budget vs actual spend' for a month. Distinguishes from sibling get_pnl by explicitly noting business-entity P&L should use a different tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit user query examples ('how am I doing', 'am I over budget') and directs to alternative get_pnl for business P&L. Clearly defines when to use and when not.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_cash_flowA
Read-only

Return the cash flow summary for a business entity: inflows, outflows, net, and a breakdown by category or by month. Use this when the user asks about revenue vs expenses, monthly cash position, or how much money came in/went out of a company. Call list_entities first to get the entity_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
end_dateNoInclusive end, ISO-8601 date (YYYY-MM-DD). Defaults to today.
group_byNo'month' returns one row per calendar month. 'category' returns one row per category. 'none' (default) returns a single totals object.
entity_idYesThe entity UUID from list_entities.
start_dateNoInclusive start, ISO-8601 date (YYYY-MM-DD).

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint=true and destructiveHint=false, indicating a safe read operation. The description adds value by detailing what the tool returns (inflows, outflows, net, breakdowns) and the grouping behavior, going beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, consisting of two focused sentences with no unnecessary words. Every sentence serves a purpose: explaining output, providing usage context, and giving a prerequisite.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given four parameters and no output schema, the description covers the tool's purpose, usage context, and key output characteristics. While it does not detail the exact response structure, it sufficiently informs the agent about what to expect.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage, the baseline is 3. The description adds context by relating the group_by parameter to the output (e.g., 'by category or by month') and reiterating the need to call list_entities for entity_id, which enhances understanding beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as returning a cash flow summary for a business entity, specifying inflows, outflows, net, and breakdowns by category or month. It distinguishes itself from sibling tools like get_pnl or get_budget_status by focusing on cash flow rather than profit/loss or budget.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool (e.g., questions about revenue vs expenses, monthly cash position) and provides a prerequisite (call list_entities for entity_id). However, it does not mention situations where an alternative sibling tool might be more appropriate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_partner_distributionA
Read-only

Return the profit distribution summary for a business entity — how net profit is split between partners for a given period. Partners see only their own slice; owners see the full split. Use this when the user asks 'how much do I take home', 'what's my distribution', or 'show me the partner split'. Call list_entities first to get the entity_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
periodNoReporting period. Default: this_month.
end_dateNoInclusive end, ISO-8601 (YYYY-MM-DD).
entity_idYesThe entity UUID from list_entities.
start_dateNoInclusive start, ISO-8601 (YYYY-MM-DD).

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description reveals role-based visibility: partners see only their share, owners see the full split. This is important behavioral context that annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is very concise—four short sentences—with the main purpose stated first. Every sentence adds value: purpose, behavior, example queries, and prerequisite call to action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and simple annotations, the description covers purpose, when to use, behavioral nuance, and a prerequisite. It does not describe the output structure, but the term 'distribution summary' implies a breakdown, which is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides descriptions for all parameters with 100% coverage. The description only reiterates that entity_id should come from list_entities, which is already in the schema description. No additional parameter meaning is added.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns a profit distribution summary for a business entity, specifying how net profit is split between partners. This distinguishes it from sibling tools like get_pnl or get_cash_flow which deal with different financial aspects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides example user queries that trigger this tool ('how much do I take home', etc.) and advises to call list_entities first for the entity_id. It does not explicitly exclude when not to use or compare with alternatives, but the examples give clear usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_pnlA
Read-only

Return the Profit & Loss statement for a business entity for a given period. Shows revenue line items, expense categories, gross profit, and net profit. Use this when the user asks about profitability, revenue, operating expenses, or wants a P&L or income statement for a company. Call list_entities first to get the entity_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
periodNoShorthand period. If omitted, use start_date/end_date.
end_dateNoInclusive end, ISO-8601 (YYYY-MM-DD).
entity_idYesThe entity UUID from list_entities.
start_dateNoInclusive start, ISO-8601 (YYYY-MM-DD).
compare_to_previousNoInclude a prior-period comparison column.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true. Description adds that it shows revenue, expenses, etc., but no additional behavioral details beyond what annotations provide. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no fluff, front-loaded with purpose and usage. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema, description provides enough context on what is returned (revenue, expenses, etc.). Could be more detailed on format but adequate given complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema covers all 5 parameters with descriptions. Description does not add value beyond schema; schema coverage is 100% so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool returns a P&L statement for a business entity with specific line items, and it distinguishes from siblings like get_cash_flow and get_budget_status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use (user asks about profitability, revenue, etc.) and prerequisite call to list_entities. Missing explicit when-not-to-use but clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_recurringA
Read-only

List recurring inflows and outflows for a business entity: subscriptions, retainers, recurring revenue, and regular vendor payments. Use this when the user asks about fixed costs, recurring revenue, SaaS spend, or wants to know what the business can count on month to month. Call list_entities first to get the entity_id.

ParametersJSON Schema
NameRequiredDescriptionDefault
statusNoFilter by status. Default: active (detection only returns active).
directionNo'inflow' = recurring revenue, 'outflow' = recurring expenses, 'all' (default).
entity_idYesThe entity UUID from list_entities.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, making safety clear. The description adds minimal behavioral context beyond listing examples; it does not mention response format, pagination, or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences plus a practical usage hint. No redundancy; every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with well-documented parameters and no output schema, the description covers purpose, usage context, and prerequisite. Missing return format details, but overall adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters are fully documented in the schema. The description adds no new semantic meaning beyond what the schema provides, meeting the baseline of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'list' and the resource 'recurring inflows and outflows' with examples (subscriptions, retainers, etc.), distinguishing it from siblings like list_transactions or get_cash_flow.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use (fixed costs, recurring revenue, SaaS spend) and provides a prerequisite (call list_entities). Lacks explicit when-not-to-use or alternatives, but the guidance is clear and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_entitiesA
Read-only

List the business entities and personal spaces the authenticated user has access to in Luni. Call this first when the user asks about a company, partnership, or business account. The returned entity_id values are required by get_cash_flow, get_pnl, get_recurring, and get_partner_distribution.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNo'business' returns company/partnership spaces only. 'personal' returns the user's personal Luni space only. 'all' (default) returns both.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. Description adds context about the scope of entities listed (user's accessible) and the need for entity_id in sibling tools. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences: first defines the action, second provides usage guidance and dependencies. Efficiently packed with no unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a simple list tool: describes purpose, usage trigger, and output importance. Annotations cover behavioral aspects. No missing info.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a well-documented enum. Description does not repeat parameter details, which is appropriate. No additional semantics needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool lists business entities and personal spaces. It specifies usage context ('Call this first when the user asks about a company, partnership, or business account') and distinguishes from siblings by noting the returned entity_id is required by multiple other tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to call this first when the user asks about a company/partnership/business account. Implicitly provides when-not but no explicit exclusions. The mention of downstream tool dependency gives strong guidance on workflow.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_splits_outstandingA
Read-only

List unsettled split transactions for the authenticated user. Returns who owes the user money and who the user owes. Use this for questions like 'who owes me', 'do I owe anyone', or 'how much is outstanding from the Airbnb trip'.

ParametersJSON Schema
NameRequiredDescriptionDefault
friend_name_containsNoOptional case-insensitive substring filter on the other party's name.

TDQS

A4.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive. Description adds output context (who owes whom) but no additional behavioral traits beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with a list of examples. Front-loaded with core functionality, no unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Simple tool with one optional parameter and no output schema; description sufficiently explains purpose and output (who owes whom). Complete for the tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a well-described optional parameter (friend_name_contains). Description does not add extra meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists unsettled split transactions, with examples of use cases. This differentiates it from sibling tools like get_cash_flow or get_pnl.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit use cases like 'who owes me' and 'do I owe anyone', guiding when to use. Lacks exclusion criteria for when not to use, but use cases are specific enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_transactionsA
Read-only

List the user's personal Luni transactions. Use this whenever the user asks about their own spending, recent purchases, a specific merchant, or a category total. Returns transactions across all connected accounts (Plaid + Wise) for the authenticated Luni user. For business-entity spending, call get_pnl or get_cash_flow instead.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax transactions to return (1–200). Default 50.
categoryNoFilter to a single top-level category, e.g. 'Food & Drinks', 'Transportation', 'Bills & Utilities'. Case-sensitive.
end_dateNoInclusive upper bound, ISO-8601 date (YYYY-MM-DD).
min_amountNoFilter to transactions with absolute value >= this amount (in dollars).
money_typeNoFilter by money type. Use 'spending' to show only real expenses (hides transfers, income, debt payments). Other values: 'income', 'transfer', 'debt_payment'.
start_dateNoInclusive lower bound, ISO-8601 date (YYYY-MM-DD).
merchant_containsNoCase-insensitive substring match against merchant name.

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is clear. The description adds valuable context: 'Returns transactions across all connected accounts (Plaid + Wise) for the authenticated Luni user.' It also specifies personal vs. business scope. However, it does not mention return format or pagination, which would be helpful since no output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise at three sentences, each adding distinct value: purpose, usage context, and exclusion/alternatives. No wasted words, front-loaded with the key action.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (7 optional parameters, no output schema), the description covers purpose, scope, and alternatives. It lacks mention of return format or pagination, but the schema documents parameters well. For a tool with read-only annotations and clear sibling differentiation, it is largely complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with each parameter having a clear description. The tool description does not add further meaning to the parameters beyond the schema. Baseline score of 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'List the user's personal Luni transactions' with a clear verb and resource. It also distinguishes from sibling tools by saying 'For business-entity spending, call get_pnl or get_cash_flow instead.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit when-to-use guidance: 'Use this whenever the user asks about their own spending, recent purchases, a specific merchant, or a category total.' It also gives clear when-not-to-use and alternatives for business spending.

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.

  1. 8 tool updatesv0.4.0
    • First observedget_budget_status
    • First observedget_cash_flow
    • First observedget_partner_distribution
    • First observedget_pnl
    • First observedget_recurring
    • First observedlist_entities
    • First observedlist_splits_outstanding
    • First observedlist_transactions

TDQS

A4.4/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a distinct purpose clearly separated by personal vs. business context. Overlapping concepts like cash flow vs. P&L are explicitly differentiated in descriptions, and personal tools are marked as separate from business entity tools.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern using snake_case, with either 'get_' or 'list_' prefixes. No mixing of conventions or irregular patterns.

Tool Count5/5

With 8 tools, the server covers personal and business financial querying needs without being excessive. Each tool serves a specific, necessary function in the domain.

Completeness5/5

The tool set covers essential read operations for both personal (budget, transactions, split debts) and business (cash flow, P&L, partner distribution, recurring items) finance. No obvious gaps for querying, especially with prerequisite tool list_entities.

Maintenance

ActivityInactive
ResponsivenessNo issues

Related MCP Connectors

  • An MCP server that provides read access to your cloud storage providers, bank accounts and more.

  • MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.

  • The Ramp MCP server enables users to securely connect Ramp with AI assistants like ChatGPT and Claude to query financial data and take actions using natural language. It transforms Ramp's developer API into a SQL interface that LLMs can query, allowing admins to analyze spend trends, identify cost savings, and run complex SQL analyses on comprehensive datasets (transactions, purchase orders, vendors, users), while all users can manage cards, view transactions, request reimbursements, and get expense policy answers.

  • Query your real net worth, spending, transactions, budgets and portfolio from any MCP client.

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    An MCP server that enables AI assistants to interact directly with Lunch Money's financial API, allowing users to query transactions, access budget information, and perform financial analysis through natural language.
    -
  • F
    license
    B
    quality
    D
    maintenance
    MCP server that bridges Claude to Monarch Money for personal-finance analysis and lightweight edits.
    18
    -
  • F
    license
    B
    quality
    D
    maintenance
    A personal MCP server that gives Claude native access to YNAB budget data.
    46
    -
  • A
    license
    B
    quality
    C
    maintenance
    A read-only MCP server for YNAB budgeting data, enabling daily/weekly/monthly expense reviews and planning support via Claude Desktop or Claude Code.
    4
    Apache 2.0