# Cash Flow Frog

> Cash flow forecasting: manage scenarios, projections, and bank accounts for your company.

- name: com.cashflowfrog.mcp/server
- version: 1.0.0
- connection class: R2 (oauth_consent_once)
- trust: 69/100 flags: no-repository
- quality: 80/100 (good)
- owner: not claimed
- descriptor: https://api.protogrid.dev/v1/servers/com.cashflowfrog.mcp%2Fserver
- tools: https://api.protogrid.dev/v1/servers/com.cashflowfrog.mcp%2Fserver/tools

**An agent can connect after a one-time OAuth consent by a human.** Remote endpoint behind OAuth 2. Tokens stay with the agent; the registry only exposes the authorization metadata.

## Connection (mcpServers)

```json
{
  "mcpServers": {
    "server": {
      "type": "http",
      "url": "https://mcp.cashflowfrog.com/mcp"
    }
  }
}
```


## Trust

- hygiene: 80
- liveness: 100
- freshness: 45
- provenance: 45
- drivers: +dns-namespace +reachable +uptime-100% -stale-197d -no-repository
- Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed.

## Quality 80/100 (good)

### protocol: n/a (weight 25)

- n/a `protocol.modern`, `protocol.stateless`, `protocol.transport`, `protocol.list_ttl`: no remote answered a protocol handshake (not probed yet, unreachable, or local-only)

### authorization: 83 (weight 15)

- pass `auth.prm`: Protected Resource Metadata (RFC 9728) published
- pass `auth.as_metadata`: authorization server metadata reachable
- warn `auth.cimd`: only Dynamic Client Registration, deprecated in 2026-07-28 in favour of CIMD
- n/a `auth.secret_in_url`: no templated URL

### tool hygiene: 79 (weight 30)

- pass `tools.descriptions`: every tool has a description
- warn `tools.description_length`: 14 tools have descriptions over 1,024 characters, which crowds the context
- pass `tools.schemas`: every tool has an object input schema
- pass `tools.annotations`: 79 of 79 tools declare readOnlyHint or destructiveHint
- pass `tools.directory_hints`: every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint
- fail `tools.token_cost`: about 31,879 tokens to load every tool, a large share of an agent's context
- pass `tools.api_dump`: tools are not a one-to-one API dump

### stability: n/a (weight 15)

- n/a `stability.changes`, `stability.rug_pull`: tool history recorded for 6 of the 7 days needed

### dependencies: n/a (weight 15)

- n/a `deps.known_vulns`, `deps.mcp_sdk_version`, `deps.resolvable`: no npm or PyPI package

- tools: 79, about 31,879 tokens to load them all
- tool set hash: c8bd52d1df325ea66afe5a50ae5d2b8c
- badge: [![protogrid quality](https://protogrid.dev/badge/com.cashflowfrog.mcp/server.svg)](https://protogrid.dev/servers/com.cashflowfrog.mcp/server)
- Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed.

### Tool changes

_No tool definition changes recorded._

## Remotes

- https://mcp.cashflowfrog.com/mcp (streamable-http, auth oauth2, reachable true, uptime30d 1)

## Packages

_none_

## Tools (79)

- `addRecurringExpense`: Simplified way to add a recurring cash-out projection (expense).
Handles direction, the required VENDOR dimension, and recurrence mapping automatically.

Before calling:
  1. Call listDimensionOptions(dimensionType=ACCOUNT) to find a valid accountApiId.
  2. Optionally call listDimensionOptions(dimensionType=VENDOR) to find a vendorId.
     If vendorId is omitted, the projection is posted under a generic vendor.

Frequency values: ONCE, DAILY, WEEKLY, BIWEEKLY, MONTHLY, QUARTERLY, YEARLY.

Use this instead of createProjection for straightforward recurring expenses such as
rent, salaries, subscriptions, and loan repayments.

- `addRecurringIncome`: Simplified way to add a recurring cash-in projection (income).
Handles direction, the required CUSTOMER dimension, and recurrence mapping automatically.

Before calling:
  1. Call listDimensionOptions(dimensionType=ACCOUNT) to find a valid accountApiId.
  2. Optionally call listDimensionOptions(dimensionType=CUSTOMER) to find a customerId.
     If customerId is omitted, the projection is posted under a generic customer.

Frequency values: ONCE, DAILY, WEEKLY, BIWEEKLY, MONTHLY, QUARTERLY, YEARLY.

Use this instead of createProjection for straightforward recurring income such as
retainer payments, subscription revenue, and rental income.

- `bulkCreateProjections`: Create up to 500 cash flow projections in a single call. Use this whenever the user
provides a list of expected future cash flows to import — from a CSV, a spreadsheet,
a pasted table, or even a verbal description ("add these 8 payments").

COLUMN MAPPING WORKFLOW — always follow these steps before calling this tool:

1. PARSE. Extract individual items from the user's data. Each item needs at minimum:
   amount (positive for inflow, negative for outflow), date (YYYY-MM-DD), and
   a counterparty name (customer or vendor).

2. RESOLVE ACCOUNT. Call listDimensionOptions(dimensionType=ACCOUNT) with a keyword
   that matches the nature of the cash flows (e.g. "receivable" for customer invoices,
   "payable" for vendor bills, "payroll" for salary runs). Use the same account for
   all items unless the data has materially different types. The value field from the
   returned option is what goes in the projection's account field.

3. RESOLVE COUNTERPARTIES. For each unique customer or vendor name, call
   listDimensionOptions(dimensionType=CUSTOMER, search="<name>") or VENDOR. Use the
   returned value in the CUSTOMER or VENDOR dimension. If no match found, use
   value='OTHER'. Call once per unique name — do NOT load all customers upfront.

4. MAP RECURRENCE. One-time items: recurrenceType=NONE. Recurring items: use the
   appropriate recurrenceType (MONTHLY, WEEKLY, etc.) with an endDate. For "monthly
   for 12 months starting February", set date=first occurrence and endDate=last.

5. CONFIRM. Show the user a summary before creating — e.g. "I'll import 12 projections
   totalling $84,000 against Accounts Receivable for Acme Corp. Proceed?" — and wait
   for confirmation.

6. CALL. Send all projections in one call. Invalid items are returned in errors[] with
   their zero-based index and the rejection reason — do not fail the whole batch.
   Present any errors to the user after the call.

companyId and scenarioId from individual projections in the list are ignored — always
use the top-level companyId and scenarioId parameters.

See createProjection for the full list of fields and validation rules.
See addRecurringExpense / addRecurringIncome for simple single-item creation.

- `bulkSetBillExpectedPaymentDate`: Update the expected payment date for multiple bills in a single call — useful when
planning a cash conservation strategy (defer non-critical bills) or scheduling a
batch of vendor payments for a specific date.

Provide a list of {billId, expectedPaymentDate} pairs. Partial success is normal:
the result reports how many succeeded and lists any per-bill failures with their
reasons. The scenario-scoped cash flow forecast is updated for each successfully
changed bill.

- `bulkSetInvoiceExpectedCollectionDate`: Update the expected collection date for multiple invoices in a single call — useful when
a customer confirms a batch of payments at once or when you want to reschedule an entire
AR book to align with a cash flow plan.

Provide a list of {invoiceId, expectedCollectionDate} pairs. Partial success is
normal: the result reports how many succeeded and lists any per-invoice failures with
their reasons. The scenario-scoped cash flow forecast is updated for each successfully
changed invoice.

- `clearAccountCategory`: Remove an account's category mapping. The account becomes unmapped — its transactions
and projections fall into the default "OTHER" bucket until you map it to a category again.

Idempotent: succeeds even when the account is already unmapped. Returns the updated account.

- `clearBillPaymentSchedule`: Remove a bill's split payment schedule, reverting it to a single expected payment date.
Idempotent: succeeds even when the bill has no split. Returns the updated bill.

- `clearEstimateCollectionSchedule`: Clear an estimate's split collection schedule, reverting to a single expected collection
date. Idempotent: succeeds even when the estimate has no split. Returns the updated estimate.

- `clearInvoiceCollectionSchedule`: Remove an invoice's split collection schedule, reverting it to a single expected
collection date. Idempotent: succeeds even when the invoice has no split.
Returns the updated invoice.

- `clearPurchaseOrderPaymentSchedule`: Clear a purchase order's split payment schedule, reverting to a single expected payment
date. Idempotent: succeeds even when the purchase order has no split. Returns the updated
purchase order.

- `clearSalesOrderCollectionSchedule`: Clear a sales order's split collection schedule, reverting to a single expected collection
date. Idempotent: succeeds even when the sales order has no split. Returns the updated
sales order.

- `compareScenariosForPeriod`: Returns side-by-side cash flow forecasts for two or more scenarios over the same period.
Use this whenever the user wants to compare scenarios — "best vs worst case",
"base case vs new hire scenario", or "which scenario leaves us with more cash?".

Provide 2–5 scenario IDs. Returns one forecast per scenario in the same order,
each with opening/closing balance, total inflows/outflows, and per-period breakdown.
Use listScenarios first to find the scenario IDs to compare.

- `createCashFlowCategory`: Create a new cash flow category (shown in the app UI as a new "Account Type").
The name must be unique within the company.

Pick the type carefully — it determines which cash-in / cash-out bucket the category
shows up under in the cash flow statement:
  - CASH_IN  for income categories (e.g. "Sales", "Refunds Received")
  - CASH_OUT for expense categories (e.g. "Payroll", "Rent")
  - ANY      only when the category genuinely applies to both directions

- `createProjection`: Create a new cash flow projection.

REQUIRED fields:
  - account: the account dimension (use listDimensionOptions with type=ACCOUNT to find options)
  - date: start date in YYYY-MM-DD format
  - recurrenceType: NONE (one-time), DAILY, WEEKLY, BIWEEKLY, SEMIMONTHLY, MONTHLY, QUARTERLY, SEMIANNUAL, or ANNUAL
  - amount: positive for income, negative for expense (required unless 'rule' is provided)
  - secondDayOfMonth: required when recurrenceType=SEMIMONTHLY
  - dimensions: MUST include a CUSTOMER dimension for income (positive amount) or a VENDOR dimension
    for expense (negative amount). Use listDimensionOptions with type=CUSTOMER or VENDOR to find options,
    or pass value='OTHER' if no specific vendor/customer applies.
    Example expense: [{"dimensionType": "VENDOR", "value": "vendor-api-id", "name": "Vendor Name"}]
    Example income: [{"dimensionType": "CUSTOMER", "value": "customer-api-id", "name": "Customer Name"}]
    For common projection creation, prefer addRecurringExpense or addRecurringIncome — they handle
    dimensions automatically.

OPTIONAL fields:
  - recurrenceValue: positive integer multiplier on the recurrence interval (default 1).
    Combined with recurrenceType to express custom intervals — e.g. recurrenceType=WEEKLY +
    recurrenceValue=3 means every three weeks; recurrenceType=MONTHLY + recurrenceValue=2
    means every two months. Ignored when recurrenceType=NONE.
  - active: whether the projection is included in cash flow forecasts (default true).
    Set to false to create the projection in an excluded/disabled state.
  - details: description/label (strongly recommended)
  - endDate: last recurrence date (required for recurring projections)
  - additional entries in dimensions: DEPARTMENT, LOCATION, PROJECT, CLASS
  - trend: growth/decline per recurrence (mutually exclusive with rule)
  - rule: dynamic amount rule (mutually exclusive with amount and trend)
  - notes: list of notes

The category is automatically derived from the account — do not set it manually.

- `createScenario`: Create a new cash flow scenario for a company.
Use this to model different financial situations with different projections.
For example, create a "New Office Lease" scenario to see how signing a lease
would affect the company's cash position, without changing the base scenario.

- `deleteCashFlowCategory`: Delete a cash flow category. Fails if the category is still referenced by any account
mapping or projection — clear those references first (use setAccountCategory / clearAccountCategory
on the affected accounts, and update or delete the affected projections).

Categories synced from an accounting system are soft-disabled instead of hard-deleted, so
a re-sync will not resurrect them as fresh entries.

- `deleteProjection`: Delete a cash flow projection and all its occurrences.
This is irreversible. To stop a recurring projection from a specific date without
deleting past occurrences, use updateProjection to set endDate to today instead.

Do NOT call this for projections where recurringTemplate=true. Those are mirrors of
accounting software recurring transaction templates and cannot be deleted from CFF.
Inform the user and suggest they manage the template in their accounting software, or
use company settings to exclude all recurring template projections from the forecast.

- `deleteScenario`: Delete a cash flow scenario and all of its projections.
This is irreversible. The company's base/default scenario cannot be deleted.

- `detectNegativeBalancePeriods`: Scans the cash flow forecast and identifies all contiguous periods where the projected
balance drops below a threshold (default: zero). Returns each at-risk date range with
its minimum balance, along with overall minimum and cash runway in days.

Use this to answer questions like:
  - "Will we ever run out of cash?"
  - "Are there months where our balance goes negative?"
  - "How many days of runway do we have?"
  - "When is the riskiest point in our cash flow?"

If riskPeriods is empty, the balance stays above the threshold for the entire scanned
period — no cash flow risk was detected.

- `exportCustomReport`: Export a saved custom AI report with live company data and return a presigned download link.
The link is valid for 15 minutes and points to the generated XLSX or CSV file.

Call listCustomReports first to discover available report IDs and their baked-in date ranges.
If the report has a dateRange preset (e.g. NEXT_N 4 weeks), compute the actual calendar dates
from today before calling this tool — do not leave startDate/endDate empty.

If the export fails with a message about the data set being too large, tell the user. For reports
without aggregationDimensions, suggest a shorter date range. For reports with aggregationDimensions,
use the two-stage flow instead: prepareCustomReportExport → finalizeCustomReportExport.

- `finalizeCustomReportExport`: Stage 2 of the two-stage MCP export flow.

Receives the structured rows you produced from cashFlowData[], builds the final XLSX or CSV
file, uploads it to S3, and returns a presigned download link valid for 15 minutes.

You must call prepareCustomReportExport first to obtain the exportToken.
The exportToken expires 15 minutes after it was issued — finalize within that window.

Row format:
  - headers: column names in order, matching the columns in your processingPrompt output.
  - rows: one inner list per data row; values must be in the same column order as headers.
  - Use JSON numbers (not strings) for numeric cells so Excel formats them correctly.

Example:
  headers: ["Project", "Week 1 In", "Week 1 Out", "Net"]
  rows:    [["Alpha", 15000.0, 3200.0, 11800.0], ["Beta", 9000.0, 1100.0, 7900.0]]

- `generateCashFlowReportPdf`: Generate a standard PDF cash flow report and return a one-time download link.
The link is valid for 15 minutes. The PDF is visual — it contains embedded bar and
line charts (OVERVIEW, CASH_BALANCE pages) alongside tables. It is the only output
format that produces charts or graphs; CSV/XLSX exports from saveCustomReport/
exportCustomReport are tabular only.

WHEN TO CALL: Immediately when the user asks for a PDF, a chart, a graph, or any
visual summary of cash flow — e.g. "give me a PDF of my cash flow", "show me a
graph of my next 6 months", "I want a chart", "generate a report I can share",
"show me outflows for October as a PDF". Do not analyse intent first — just call
this tool. When the user asks for a graph or chart and does not specify Excel, this
is the correct tool; explain the output is PDF after the link is ready.

THIS TOOL FETCHES ALL ITS OWN DATA INTERNALLY. Do NOT call getCashFlowBreakdown,
listBills, getCashFlowForecast, or any other data tool before calling this one.
The only pre-flight calls that may be needed are listCompanies and listScenarios
if you do not already have companyId and scenarioId.

Use cashFlowType to scope the report:
  - ANY     — full report with both inflows and outflows (default)
  - CASH_IN — only the inflow-related pages and data
  - CASH_OUT — only the outflow-related pages and data

The report has 8 standard pages that can each be individually included or excluded:
  COVER, OVERVIEW, CATEGORY_BREAKDOWN, CASH_BALANCE,
  CASH_IN_BREAKDOWN, CASH_OUT_BREAKDOWN, CUSTOMER_INSIGHTS, NOTES
All pages are included by default — only set pages when the user wants to
hide specific sections.

grouping controls the time granularity:
  DAY — day-by-day (up to ~3 months), WEEK — week-by-week (1–6 months),
  MONTH — month-by-month (6–18 months), QUARTER — quarter-by-quarter (multi-year)

topLevelGroupBy controls how cash flows are grouped in the breakdown:
  ACCOUNT_TYPE (default), QB_CLASS, XERO_TRACKING_CATEGORY,
  DEPARTMENT, LOCATION, PROJECT

DO NOT use this tool for custom column layouts, Excel/CSV exports, AR/AP aging reports,
or any report requiring a user-defined data structure — use saveCustomReport +
exportCustomReport for those.

- `getAccount`: Get a single account by its id, including its current category mapping.
Use this to confirm an account's classification before or after a setAccountCategory / clearAccountCategory call.

IMPORTANT: accountId must come from listAccounts (the `id` field). Never use a groupId from
getCashFlowBreakdown — those are category/dimension identifiers, not account ids.

- `getAPSummary`: Return a high-level accounts-payable summary for the scenario: total open balance,
total overdue balance, open and overdue bill counts, the age of the oldest overdue
bill (in days), and the single largest open bill.

Use this as a quick health-check for the AP book — "how much do we owe and how much
is past due?" — before drilling into individual bills.

- `getARSummary`: Return a high-level accounts-receivable summary for the scenario: total open balance,
total overdue balance, open and overdue invoice counts, the age of the oldest overdue
invoice (in days), and the single largest open invoice.

Use this as a quick health-check for the AR book — "how much do customers owe us and
how much is overdue?" — before drilling into individual invoices.

- `getBankBalance`: Get the projected (forecast) total bank balance for a company on a specific future date,
based on a scenario's projections added to the current actual bank balance. This is not
the live bank balance — it is the forecasted balance after applying all projected cash
flows up to that date.

Use this to answer questions like:
  - "What will our bank balance be on [date]?"
  - "Will we have enough cash to cover the lease payment on [date]?"
  - "What's the projected balance at end of quarter?"

Returns the projected total balance across all tracked bank accounts.

- `getBill`: Get a single bill by its id, including its expected payment date and any split payment schedule.
- `getCashFlowBreakdown`: Get a categorized cash flow breakdown for a company and scenario over a date range.
Returns inflows and outflows split by a chosen axis (category by default), with optional
drill-down detail.

Use this when getCashFlowForecast (which only returns flat per-period totals) isn't
enough. Typical questions this answers:
  - "Which categories made up most of last quarter's expenses?"
  - "Which customers drove Q3 inflows?" (groupBy=CATEGORY, drillDownBy=CUSTOMER_OR_VENDOR)
  - "Show me payroll spend by department." (groupBy=DEPARTMENT)
  - "Break down rent by location." (groupBy=LOCATION)

For a forecast scoped to a specific dimension (e.g. one project only), use
getCashFlowForecast with dimensionFilters instead.

Defaults: groupBy=CATEGORY, drillDownBy=NONE.

groupBy controls the top-level grouping axis (what each row in the output represents).
drillDownBy controls the secondary axis inside each group (sub-rows). These are
independent: groupBy=CATEGORY + drillDownBy=CUSTOMER_OR_VENDOR shows each category
broken down by who paid/was paid.

Output shape:
  - `periods[]`: per-period objects (periodStart, totalInflows, totalOutflows, closingBalance,
    isHistorical=true if entirely past).
  - `cashIn` / `cashOut`: each has `total`, `totalsByPeriod`, and `groups[]`.
    Each group has `label`, `groupId` (null when unclassified), `total`, `totalsByPeriod`,
    and `drillDown[]` (omitted when drillDownBy=NONE). Outflow values are negative.
  - `drillDown[].id` is populated only when drillDownBy=ACCOUNT.

Cross-reference: groupId on a CATEGORY group is the same id used in listCashFlowCategories /
setAccountCategory. Drill-down account ids match the id in listAccounts.
For individual transaction rows within a category or drill-down group, use listTransactions.

IMPORTANT: groupId values in this response are category/dimension identifiers — NOT account ids.
Never pass a groupId to getAccount or setAccountCategory as an accountId. Account ids come
exclusively from listAccounts.

- `getCashFlowCategory`: Get a single CashFlowCategory by id.
- `getCashFlowForecast`: Primary tool for cash flow analysis. Get a cash flow forecast for a scenario over a
date range, grouped by the chosen time granularity. Combines real bank account balances
with the scenario's projected cash flows — including AR invoices, AP bills, estimates,
sales orders, purchase orders, and manual projections — to show how the cash position
is expected to change over time.

Use this to answer questions like:
  - "What will our cash balance look like next month?" (MONTHLY grouping)
  - "When will we hit our lowest cash point this quarter?" (WEEKLY or DAILY grouping)
  - "Are we going to run out of cash before our next big payment comes in?" (DAILY grouping)
  - "Give me a quarterly cash flow overview for the rest of the year" (QUARTERLY grouping)

Choose grouping based on the question:
  - DAILY   — precise day-by-day view, best for short ranges (up to ~3 months)
  - WEEKLY  — week-by-week view, good for 1–6 month ranges
  - MONTHLY — month-by-month view, good for 6–18 month ranges
  - QUARTERLY — quarter-by-quarter view, best for multi-year ranges

Use dimensionFilters to scope the forecast to a specific customer, vendor, project,
or other dimension. For a breakdown by category or dimension group, use
getCashFlowBreakdown instead. For individual transaction rows within any period,
use listTransactions.

Returns: opening/closing balances for the full period, total inflows/outflows,
and a per-period breakdown with each period's balance and cash movements.

- `getCashPosition`: Returns a cash health snapshot: current bank balance, projected balances at 30/60/90 days,
the lowest projected balance within the horizon, and the first date the balance goes
negative (if any). Use this as the starting point for any question about current or
near-term cash position. Combines real bank account balances with scenario projections.

Use this to answer questions like:
  - "What is our current cash situation?"
  - "How much cash will we have in 30/60/90 days?"
  - "Are we heading toward a cash crunch?"
  - "What's the lowest our balance will get this quarter?"

For detailed risk analysis — exact periods when balance goes negative, cash runway in days —
use detectNegativeBalancePeriods instead.

- `getCategoryVariance`: Returns an Actual-vs-Plan variance comparison for every cash flow category over a date range.
For each category, surfaces the actual total, the planned total (what was forecast when
the period was still in the future), the variance (actual − planned), and the variance
as a percentage of the plan.

Use this when the user wants to know:
  - "Which categories came in over or under budget last quarter?"
  - "How did our payroll compare to plan in Q1?"
  - "Where did actual inflows beat or miss our forecast?"
  - "Give me a budget vs actual breakdown for last month."
  - "What was the biggest variance category this year?"

Variance sign convention (consistent for both cashIn and cashOut):
  - Positive variance → favorable: actuals exceeded plan for cashIn, or spending was
    below plan for cashOut (cashOut values are negative, so actual less negative = positive).
  - Negative variance → unfavorable: cashIn below plan, or cashOut above plan (overspent).

For meaningful results, use a historical (or mostly historical) date range — plan comparison
is only available where isHistorical=true periods exist. Future periods contribute actuals
but will have null planned values.

grouping controls the time granularity of per-period arrays. For month-over-month analysis
use MONTHLY; for week-by-week use WEEKLY. Match the granularity to the range length.

Output shape:
  - periods[]: period headers with periodStart, periodEnd, isHistorical (true = past)
  - cashIn / cashOut: each has aggregate actual, planned, variance, variancePct and
    categories[] sorted by absolute variance (largest deviations first).
    Each category has categoryName, categoryId, actual, planned, variance, variancePct,
    plus per-period arrays: actualByPeriod, plannedByPeriod, varianceByPeriod.
    varianceByPeriod entries are null for future periods (no plan comparison available).
  - categoryId can be passed as groupId to getCashFlowBreakdown for drill-down detail
    (e.g. to see which customers or vendors drove the variance in a specific category).

- `getCompanySettings`: Returns all company forecast settings grouped by area:
projections, invoices, bills, estimates, salesOrders, purchaseOrders, cashBalance, and advanced.
Call this before updateCompanySettings to inspect the current state.

- `getEstimate`: Get a single estimate by its id, including its expected collection date and any split collection schedule.
- `getEstimateSummary`: Get a high-level summary of all open estimates: total open amount, count, expiring-soon
count (estimates expiring within 30 days), and the largest estimate.

Use this as a quick health-check for the estimates pipeline — "how much is in open
quotes?" — before drilling into individual estimates.

- `getIntegrationStatus`: Return the accounting software integration status for a company: which platform is
connected (e.g. XERO, QUICKBOOKS), current connection status (CONNECTED, DISCONNECTED,
ERROR, PENDING), timestamps of the last sync attempt and last successful sync, and any
error message when the connection is in an error state.

Call this first when a user asks whether their data is up to date, why their forecast
looks stale, or whether there are any sync problems — before querying invoices, bills,
or forecasts that may reflect outdated data.

- `getInvoice`: Get a single invoice by its id, including its expected collection date and any split collection schedule.
- `getOnboardingUrl`: Returns a URL for the user to open in their browser to set up or reconnect their
accounting software integration with Cash Flow Frog.

Call this when listCompanies returns an empty list, or when getIntegrationStatus
returns DISCONNECTED or ERROR for any company. No parameters are needed — the server
determines the appropriate URL from the authenticated user's context and integration state.

Present the returned url as a clickable link with the message as context. After the
user confirms they have completed the flow, call listCompanies again to verify.

Returns: url (the link to present), action ("setup" | "reconnect" | "connected"),
message (human-readable explanation to show alongside the URL).

- `getProjection`: Get a single cash flow projection by its id.
Use this to retrieve full details of a specific projection after finding its id from listProjections.

- `getPurchaseOrder`: Get a single purchase order by its id, including its expected payment date and any split payment schedule.
- `getPurchaseOrderSummary`: Get a high-level summary of all open purchase orders: total open amount, count, and the
largest purchase order.

Use this as a quick health-check for outstanding purchase commitments — "how much in
open purchase orders has not been billed yet?" — before drilling into individual purchase
orders.

- `getReportBuilderStep`: Returns the instructions for the current step of the custom report intake flow.
Call with step=1 to begin, then step=2 when you are ready to draft and save.

- `getSalesOrder`: Get a single sales order by its id, including its expected collection date and any split collection schedule.
- `getSalesOrderSummary`: Get a high-level summary of all open sales orders: total open amount, count, and the
largest sales order.

Use this as a quick health-check for the sales order pipeline — "how much in open orders
has not been invoiced yet?" — before drilling into individual sales orders.

- `listAccounts`: List the company's chart of accounts together with their current cash flow category mapping.
Use this to see how accounts are classified, find unmapped accounts, or locate a specific
account by name.

The `categoryId` / `categoryName` fields are the account's user-facing "Account Type"
(its CashFlowCategory mapping). A null value means the account is unmapped — its
transactions fall into the default "OTHER" bucket. Reassign with setAccountCategory.
The raw `type` / `subType` / `classification` fields are internal source-accounting-system
values; do not report them to the user as the account's "type".

Filters are optional and combine (AND).

- `listBankAccounts`: List all bank and financial accounts for a company, including their current balances.
These are the accounts that Cash Flow Frog tracks and forecasts.
Use this to understand the company's current liquidity position and to answer
questions like "what is our current total cash balance?".
Returns: id, name, type (e.g. Bank, CreditCard), subType (e.g. Checking, Savings),
balance, currencyCode, and whether the account is active.

- `listBills`: List the company's open bills (accounts payable) for a scenario — money the company
owes its vendors. Returns only open (unpaid) bills. Each bill includes its open
balance, due date, the expected payment date that drives the cash flow forecast, an
overdue flag, and any split payment schedule.

Each bill's expectedPaymentDate determines when it appears in the cash flow forecast —
if null, the dueDate is used as a fallback. Use setBillExpectedPaymentDate to update
when payment is actually planned. For aggregate totals without individual rows, use
getAPSummary.

Results are sorted by expected payment date. Filters are optional and combine (AND).
Use overdueOnly=true to focus on bills already past their due date.
Use date range filters to answer questions like "what bills are due this month?"
Use minAmount / maxAmount to filter by open balance — e.g. minAmount=200 returns only
bills where the outstanding balance is at least 200 (in the company's home currency).

- `listCashFlowCategories`: List the cash flow categories defined for a company. Categories are the buckets that
accounts (and therefore transactions and projections) are classified under in cash-in
and cash-out reports.

NOTE: the app UI calls a cash flow category an "Account Type". If a user asks to
"list account types", this is the tool to use. (The `type` field on an Account is a
separate internal accounting-system value — not what users mean by "account type".)

Each category has a `type` of its own (its cash flow direction):
  - CASH_IN  — categories used for income (positive cash flow)
  - CASH_OUT — categories used for expenses (negative cash flow)
  - ANY      — categories that can apply to either direction

Disabled categories are hidden by default; pass includeDisabled=true to see them.

- `listCompanies`: REQUIRED FIRST STEP — call this before any other tool. Lists all companies the
authenticated user has access to. The `id` field from the response is the companyId
required by nearly every other tool. Users typically have one company, but may have
multiple. After calling this, call listScenarios to get the available scenarios.
Returns: id, name, currencyCode, timezone, accountingSoftware.

- `listCustomReports`: List all custom AI report definitions for the company.
Returns saved report definitions that can be exported with live company data.
Use this to discover available reports before exporting one.

- `listDimensionOptions`: List selectable values (options) for a specific dimension type, with optional name search.
Returns up to 200 results. When truncated=true there are more options than were returned
— use a more specific search term to find what you need.

Examples:
  - dimensionType=CUSTOMER, search="acme" → customers whose name contains "acme"
  - dimensionType=ACCOUNT, search="payroll" → accounts matching "payroll"
  - dimensionType=CLASS → all QuickBooks classes (omit search to list all)

The returned 'value' field is what you pass as the account field (for ACCOUNT options)
or as value inside a dimensions entry (for all other types) when creating a projection.
Valid dimensionType values: ACCOUNT, CLASS, CUSTOMER, DEPARTMENT, LOCATION, PROJECT, VENDOR, CUSTOM.
Omit or pass null for 'search' to return all options for the type (capped at 200).

Required before calling createProjection or bulkCreateProjections: call with
dimensionType=VENDOR for expense projections or dimensionType=CUSTOMER for income
projections. For bulk imports, call once per unique counterparty name rather than
loading all options upfront. If the specific vendor/customer is not found, you may
use the string 'OTHER' as the value.

- `listDimensions`: List the available dimensions (category types) for a company.
Dimensions are the axes along which projections can be categorized and filtered,
such as CUSTOMER, VENDOR, CLASS (QuickBooks), DEPARTMENT, LOCATION, or PROJECT.
Call this before createProjection to know which category types are available.
Returns: id, name, type (dimension type key), and whether it's a custom dimension.

- `listEstimates`: List the company's open sales estimates for a scenario — quotes issued to customers that
have not yet been fully invoiced. Only estimates with an open balance (not yet fully
invoiced) are returned. An estimate disappears from this list once it has been fully
converted to invoices. Each estimate includes its uninvoiced balance, total amount,
expiry date, the expected collection date that drives the cash flow forecast, and any
split collection schedule.

Each estimate's expectedCollectionDate determines when it appears in the cash flow
forecast. Use setEstimateExpectedCollectionDate to update when collection is actually
expected. For aggregate totals without individual rows, use getEstimateSummary.

Results are sorted by expected collection date. Filters are optional and combine (AND).
Use date range filters to answer questions like "what estimates were issued this quarter?"
Use minAmount / maxAmount to filter by open balance — e.g. minAmount=500 returns only
estimates where the uninvoiced balance is at least 500 (in the company's home currency).

- `listInvoices`: List the company's open invoices (accounts receivable) for a scenario — money customers
owe the company. Returns only open (unpaid) invoices. Each invoice includes its open
balance, total amount, due date, the expected collection date that drives the cash flow
forecast, an overdue flag, and any split collection schedule.

Each invoice's expectedCollectionDate determines when it appears in the cash flow
forecast — if null, the dueDate is used as a fallback. Use
setInvoiceExpectedCollectionDate to update when collection is actually expected.
For aggregate totals without individual rows, use getARSummary.

Results are sorted by expected collection date. Filters are optional and combine (AND).
Use overdueOnly=true to focus on invoices already past their due date.
Use date range filters to answer questions like "what invoices are due this week?"
Use minAmount / maxAmount to filter by open balance — e.g. minAmount=200 returns only
invoices where the outstanding balance is at least 200 (in the company's home currency).

- `listProjections`: List cash flow projections for a company and scenario, with optional filters.
Returns up to 500 projections. Use filters to narrow results.
Projections represent expected future cash flows — income (positive) or expenses (negative).
They can be one-time or recurring, and may have a dynamic rule-based amount.
By default both included (active=true) and excluded (active=false) projections are returned;
use the `active` filter to restrict to one or the other.

Two read-only boolean fields classify each projection:
- recurringTemplate: true when the projection is a CFF representation of an accounting
  software recurring transaction template (QuickBooks, Xero, Zoho, Sage, etc.). The record
  lives in the accounting software and cannot be deleted from CFF; exclude it from the
  forecast via company settings instead.
- patternDetected: true when CFF auto-generated the projection by detecting a recurring
  cash flow pattern in historical bank transactions. The user did not create it explicitly.
  These projections may duplicate a manually entered one (e.g. causing rent to appear
  twice). Set active=false via updateProjection to exclude from the forecast without
  deleting.

Use the `recurringTemplate` or `patternDetected` filters to query projections of a
specific type, e.g. patternDetected=true to list all auto-detected projections and
identify duplicates or unwanted entries.

- `listPurchaseOrders`: List the company's open purchase orders for a scenario — vendor orders that have not yet
been fully received or billed. Only purchase orders with a remaining unbilled amount are
returned. A purchase order disappears from this list once it has been fully billed.
Each purchase order includes its remaining unbilled balance, total amount, the expected
payment date that drives the cash flow forecast, and any split payment schedule. Amounts
represent expected cash outflow.

Each purchase order's expectedPaymentDate determines when it appears in the cash flow
forecast. Use setPurchaseOrderExpectedPaymentDate to update when payment is actually
planned. For aggregate totals without individual rows, use getPurchaseOrderSummary.

Results are sorted by expected payment date. Filters are optional and combine (AND).
Use date range filters to answer questions like "what purchase orders were placed this quarter?"
Use minAmount / maxAmount to filter by open balance — e.g. minAmount=1000 returns only
purchase orders where the remaining unbilled balance is at least 1000 (in the company's
home currency).

- `listSalesOrders`: List the company's open sales orders for a scenario — customer orders that have not yet
been fully invoiced. Only sales orders with an open balance (not yet fully invoiced) are
returned. A sales order disappears from this list once it has been fully converted to
invoices. Each sales order includes its uninvoiced balance, total amount, the expected
collection date that drives the cash flow forecast, and any split collection schedule.

Each sales order's expectedCollectionDate determines when it appears in the cash flow
forecast. Use setSalesOrderExpectedCollectionDate to update when collection is actually
expected. For aggregate totals without individual rows, use getSalesOrderSummary.

Results are sorted by expected collection date. Filters are optional and combine (AND).
Use date range filters to answer questions like "what sales orders were placed this quarter?"
Use minAmount / maxAmount to filter by open balance — e.g. minAmount=1000 returns only
sales orders where the uninvoiced balance is at least 1000 (in the company's home currency).

- `listScenarios`: List all cash flow scenarios for a given company.
Each scenario can have different projections, enabling side-by-side comparison
of different business situations (e.g. "Base Case", "New Client", "Worst Case").
The active field identifies the scenario currently shown on the company's main cash
flow view. When the user refers to "the active scenario", "the current scenario",
or "the default scenario", use the scenario where active=true.

- `listTransactions`: List individual cash flow transactions — historical bank transactions and forecast items — for a specific, targeted query. Always apply at least one filter beyond the date range.

⚠ THIS TOOL IS FOR TARGETED LOOKUPS — NOT BULK ANALYTICS.
The data set can be very large (thousands of records per month). Calling this tool without specific filters over a wide date range will return an unmanageably large result set that cannot be meaningfully processed. For any aggregation, totalling, or summarisation task, use getCashFlowBreakdown instead — it returns pre-aggregated results in a fraction of the tokens.

WHEN TO USE THIS TOOL — zoom-in scenarios with narrow scope:
  • Show all transactions for a specific customer or vendor → filter by counterpartyId or counterpartyName
  • Investigate a particular account → filter by accountId
  • Find transactions matching a keyword or document number → use search
  • Look at a specific type of forecast item → filter by type (e.g. INVOICE, BILL)
  • Check cash-in or cash-out only → filter by direction
  • Find large transactions above a threshold → use minAmount

WHEN NOT TO USE THIS TOOL — use a better alternative instead:
  • "Show me cash flow by category / customer / project" → getCashFlowBreakdown
  • "What are my total inflows / outflows?" → getCashFlowForecast or getCashFlowBreakdown
  • "List open invoices / bills with balances" → listInvoices / listBills
  • "Export a custom report" → exportCustomReport

Use kind=HISTORY for bank transactions only, kind=FORECAST for forecast items only, or omit for both.
Results are paginated. Keep pageSize small (default 50, max 500) and date ranges narrow.
The total match count is returned in totalElements — check it before paginating.

- `prepareCustomReportExport`: Stage 1 of the two-stage MCP export flow for large or aggregated reports.

Fetches the company's cash flow data for the report and returns it along with the layout
instructions (processingPrompt) and a signed exportToken. YOU then transform the data
according to the processingPrompt and pass the result to finalizeCustomReportExport.

When to use this instead of exportCustomReport:
  - The report has aggregationDimensions (hundreds of summary rows)
  - The date range is large and likely to time out the synchronous export

Steps:
  1. Call this tool to get cashFlowData[] + processingPrompt + exportToken.
  2. Apply the processingPrompt to cashFlowData[] to produce headers[] and rows[][].
  3. Call finalizeCustomReportExport with the exportToken, headers, and rows.

The exportToken expires in 15 minutes — complete the two-stage flow without delay.

- `reportMissingCapability`: Report an AI capability gap to the Cash Flow Frog team.
Call this when the user requests something you genuinely cannot fulfill with the available
tools and data — for example, a report type that requires data not currently exposed,
a calculation that goes beyond what the MCP tools support, or an integration that does
not yet exist.

Do NOT call this for temporary errors, authentication issues, or cases where the user
just needs to rephrase their request. Only call it for genuine product capability gaps
that would require the team to add new features or data sources.

Always explain the limitation to the user first, then call this tool to log the gap.

- `saveCustomReport`: Save a new custom AI report definition for the company.
Call this tool after the user has reviewed and confirmed the report definition.

The processingPrompt is sent verbatim to an export AI that receives company cash flow
data and produces the final spreadsheet. Write it as explicit spreadsheet layout
instructions: name every column, state how rows are grouped, specify sort order, and
call out any totals, subtotals, or computed columns needed.

DATA SOURCE — the export AI receives data in one of two schemas depending on aggregationDimensions:

SCHEMA A — Raw transactions (aggregationDimensions is null/empty):
  cashFlowHistory[]  : period, date, kind (HISTORY), type (BANK_TRANSACTION), amount, direction
                       (CASH_IN/CASH_OUT), category, description, docNumber, accountName, accountId,
                       counterpartyName, counterpartyId, counterpartyType,
                       locationName, locationId, projectName, projectId,
                       departmentName, departmentId, className, classId
  cashFlowForecast[] : period, date, kind (FORECAST),
                       type (INVOICE|BILL|ESTIMATE|SALES_ORDER|PURCHASE_ORDER|MANUAL|RECURRING_TXN|DEPOSIT|VAT),
                       amount, direction, category, description, docNumber, accountName, accountId,
                       counterpartyName, counterpartyId, counterpartyType,
                       locationName, locationId, projectName, projectId,
                       departmentName, departmentId, className, classId
  Use this schema for reports that need individual transaction detail (open AR lists, transaction logs).
  WARNING: large date ranges or high transaction volumes will exceed the payload limit.

SCHEMA B — Pre-aggregated (aggregationDimensions is non-empty):
  cashFlowData[] : dimension label fields (from aggregationDimensions) + historyCashIn,
                   historyCashOut, forecastCashIn, forecastCashOut
  Use this schema for summary/totals reports (one row per project, per department, etc.).
  This is the correct choice whenever rows represent aggregated entities, not individual transactions.

aggregationDimensions values: PERIOD, PROJECT, DEPARTMENT, LOCATION, CLASS, CATEGORY, COUNTERPARTY, TYPE
  - PERIOD: group by the groupBy period (include when the report has a time dimension per entity)
  - PROJECT/DEPARTMENT/LOCATION/CLASS/CATEGORY/COUNTERPARTY/TYPE: group by that entity dimension

groupBy values: MONTH | QUARTER | WEEK
scenarioMode values:
  FIXED         — always use the default active scenario
  USER_SELECTED — the user picks the scenario at export time
  COMPARISON    — side-by-side comparison of multiple scenarios (wider output)
outputFormat values: CSV | XLSX

- `setAccountCategory`: Map an account to a CashFlowCategory — i.e. set the account's user-facing "Account Type".
This is what a user means when they ask to "change an account's type". Creates or updates
the underlying mapping; it is idempotent — calling with the same categoryId again is a no-op.

The categoryId must come from listCashFlowCategories. If no suitable category exists,
create one first with createCashFlowCategory.

Returns the updated account (with the new categoryId / categoryName populated).

- `setBillExpectedPaymentDate`: Plan when a bill will be paid by setting its expected payment date. This date drives
the cash flow forecast for the given scenario — moving it changes when the outflow
appears in the forecast.

Use this to plan a payment (e.g. push a bill to next month to preserve cash). To plan
a payment in several installments instead, use splitBillPayment.

Returns the updated bill.

- `setEstimateExpectedCollectionDate`: Set the date CashFlowFrog expects to collect payment for this estimate, overriding the
auto-derived date. This drives the estimate's position in the cash flow forecast —
moving it changes when the inflow appears.

Use this to plan collection for a quote that a customer has verbally committed to. To
plan collection in several installments instead, use splitEstimateCollection.

Returns the updated estimate.

- `setInvoiceExpectedCollectionDate`: Plan when an invoice will be collected by setting its expected collection date. This date
drives the cash flow forecast for the given scenario — moving it changes when the inflow
appears in the forecast.

Use this to plan a collection (e.g. a customer who has promised to pay late). To plan a
collection in several installments instead, use splitInvoiceCollection.

Returns the updated invoice.

- `setPurchaseOrderExpectedPaymentDate`: Set the date CashFlowFrog expects to pay this purchase order, overriding the auto-derived
date. This drives the purchase order's position in the cash flow forecast — moving it
changes when the outflow appears.

Use this to plan payment for a vendor order (e.g. push to next month to preserve cash).
To plan payment in several installments instead, use splitPurchaseOrderPayment.

Returns the updated purchase order.

- `setSalesOrderExpectedCollectionDate`: Set the date CashFlowFrog expects to collect payment for this sales order, overriding the
auto-derived date. This drives the sales order's position in the cash flow forecast —
moving it changes when the inflow appears.

Use this to plan collection for a confirmed order. To plan collection in several
installments instead, use splitSalesOrderCollection.

Returns the updated sales order.

- `splitBillPayment`: Split a bill's payment across multiple dates instead of paying it all at once. Provide
the schedule lines — each with a date (YYYY-MM-DD) and a positive amount. The supplied
lines fully replace any existing split for this bill in the given scenario.

The split drives the cash flow forecast: each line becomes a separate planned outflow.
To revert to a single payment date, use clearBillPaymentSchedule.

Returns the updated bill.

- `splitEstimateCollection`: Split the expected collection for an estimate across multiple dates. Replaces any existing
split. Provide the schedule lines — each with a date (YYYY-MM-DD) and a positive amount.

The split drives the cash flow forecast: each line becomes a separate planned inflow.
To revert to a single collection date, use clearEstimateCollectionSchedule.

Returns the updated estimate.

- `splitInvoiceCollection`: Split an invoice's collection across multiple dates instead of expecting it all at once.
Provide the schedule lines — each with a date (YYYY-MM-DD) and a positive amount. The
supplied lines fully replace any existing split for this invoice in the given scenario.

The split drives the cash flow forecast: each line becomes a separate planned inflow.
To revert to a single collection date, use clearInvoiceCollectionSchedule.

Returns the updated invoice.

- `splitPurchaseOrderPayment`: Split the expected payment for a purchase order across multiple dates. Replaces any
existing split. Provide the schedule lines — each with a date (YYYY-MM-DD) and a
positive amount.

The split drives the cash flow forecast: each line becomes a separate planned outflow.
To revert to a single payment date, use clearPurchaseOrderPaymentSchedule.

Returns the updated purchase order.

- `splitSalesOrderCollection`: Split the expected collection for a sales order across multiple dates. Replaces any
existing split. Provide the schedule lines — each with a date (YYYY-MM-DD) and a
positive amount.

The split drives the cash flow forecast: each line becomes a separate planned inflow.
To revert to a single collection date, use clearSalesOrderCollectionSchedule.

Returns the updated sales order.

- `updateCashFlowCategory`: Update fields on an existing cash flow category. Pass only the fields you want to change;
null fields are left untouched.
Renames must keep the name unique within the company.

- `updateCompanySettings`: Updates company settings using patch semantics: only fields you explicitly provide are changed.
Omit a field (leave it null) to leave it unchanged. Omit an entire group to leave all its fields unchanged.

Nest fields inside the relevant group. Example — to disable accounting-software projections only:
  { "projections": { "includeAccountingSoftwareProjections": false } }

Example — to change invoice payment prediction and expiry together:
  { "invoices": { "predictPaymentDates": true, "expireAfterOverdueDays": 90 } }

Call getCompanySettings first to read the current state before making changes.
Returns the full updated settings after the change is applied.

- `updateCustomReport`: Update an existing custom AI report definition.
Use when the user wants to refine or correct a previously saved report definition.
All fields are replaced — include the full definition, not just changed fields.

- `updateProjection`: Update an existing cash flow projection. Replaces all fields with the provided values.
Retrieve the current projection with getProjection first, modify the fields you want to change,
then call this tool with the full updated projection.
Changes apply to all occurrences of a recurring projection.

REQUIRED: dimensions must include a CUSTOMER entry (for income) or a VENDOR entry (for
expense). Always preserve the dimensions list from the current projection when updating —
omitting it or sending an empty list will fail validation. Use value='OTHER' if no specific
counterparty applies.

Common update patterns:
  - Toggle `active` to include or exclude the projection from forecasts without deleting it.
  - Adjust `recurrenceValue` together with `recurrenceType` to change the recurrence interval
    (e.g. switch a monthly projection to every two months by setting recurrenceValue=2).

- `updateScenario`: Update the name or description of an existing scenario.
Does not affect any projections within the scenario.

- `uploadReportTemplate`: Links an Excel template file (uploaded by the user during the chat) to a saved report.
Call this IMMEDIATELY after saveCustomReport when pageContext contains pendingTemplateAttachmentId.
The template will be used to preserve the exact column layout and styling when exporting.

Pass pageContext.pendingTemplateAttachmentId as the attachmentId.
This step is MANDATORY whenever pendingTemplateAttachmentId is present — do not skip it.

