On this page
NavFi MCP server
Connect an AI agent to a NavFi user's route over the Model Context Protocol. The agent asks, and NavFi's optimizer does the math. For setup in plain words, see Connect your AI.
https://api.navfi.money/mcphttps://api.navfi.money/mcp/readonlyServer addresses
| Address | Access | Tools |
|---|---|---|
https://api.navfi.money/mcp | Read and change | 24 |
https://api.navfi.money/mcp/readonly | Read only | 16 |
Transport: Streamable HTTP, JSON-RPC 2.0 over POST. Results are JSON text in the tool result; there is no outputSchema. tools/list is paginated, so follow nextCursor.
The read-only address takes the same sign-in and serves exactly the 16 read tools. Give it to an agent that should ask but never change anything.
Connect
Add the server address in your AI app. The app opens NavFi's sign-in in a browser; the user signs in with an email code and approves what the app may see and change.
Claude
- Open Settings → Connectors on the web, desktop or mobile app.
- Choose Add custom connector, name it NavFi and paste the server address.
- Choose Connect and sign in to NavFi.
ChatGPT
Custom connectors need a paid ChatGPT plan with Developer mode on.
- Turn on Developer mode in Settings.
- Open Settings → Connectors and add a connector with the server address.
- Sign in to NavFi when ChatGPT opens the page.
Claude Code
claude mcp add --transport http navfi https://api.navfi.money/mcpThen type /mcp, pick navfi and choose Authenticate.
Cursor
Or add this to ~/.cursor/mcp.json, then choose Needs login next to navfi in Cursor's MCP settings.
{
"mcpServers": {
"navfi": {
"url": "https://api.navfi.money/mcp"
}
}
}VS Code
code --add-mcp '{"name":"navfi","type":"http","url":"https://api.navfi.money/mcp"}'Or add this to .vscode/mcp.json in a workspace. VS Code asks you to sign in when the server starts.
{
"servers": {
"navfi": {
"type": "http",
"url": "https://api.navfi.money/mcp"
}
}
}Codex CLI
codex mcp add navfi --url https://api.navfi.money/mcp
codex mcp login navfiThe login command opens the NavFi sign-in in your browser.
Other apps
Any client that supports remote MCP servers over Streamable HTTP with OAuth 2.1 works. Add the server address; the client registers itself and runs the sign-in. Its redirect URI must be on a supported AI app's host or on localhost (see Authentication).
Authentication
- OAuth 2.1 with PKCE (S256). Metadata at
https://api.navfi.money/.well-known/oauth-protected-resourceandhttps://api.navfi.money/.well-known/oauth-authorization-server. - Dynamic client registration at
POST https://api.navfi.money/oauth/register: public clients, one scope,mcp:use. Redirect URIs must be on a supported AI app's host or on localhost. To add another, email support@navfi.money. - The user signs in with their email and a 6-digit code sent to it. There is no password. A consent page then lists what the app can see, what it can change and what it never can.
- Access tokens last 1 hour, refresh tokens 30 days. A token works only on the MCP addresses, not on NavFi's app API.
- The read-only address takes the same sign-in and lists only the read tools.
- Users disconnect an app at api.navfi.money/connected-apps, which revokes its access and refresh tokens at once.
- Every call needs an active NavFi subscription. Without one, the call returns a tool error rather than an HTTP error, so the agent can tell the user.
Tools
Read tools carry readOnlyHint. Write tools are marked not destructive, except reroute, which keeps the default because it replaces the route. Claude and ChatGPT ask the user before any write. Ids are NavFi's internal ids: pass them back as given. Money is US dollars, dates are YYYY-MM-DD.
Read tools (16)
Served on both addresses. None of them changes anything.
get_financial_snapshotRead
Compact overview: accounts, credit cards (incl. rewards rates per category), plan summary, upcoming week, goals. Use for quick balance / debt / "how am I doing" / "best card for X" questions.
| Argument | Type | Description |
|---|---|---|
include | array of string | Sections to include. Omit to include all. Any of: accounts, credit_cards, plan_summary, upcoming_week, goals. |
get_upcoming_eventsRead
Plan events between two dates (income, bills, card payments, savings, variable spend), each with the event_id that mark_turn_done takes. Prefer narrow windows for detail.
| Argument | Type | Description |
|---|---|---|
from_daterequired | string | Inclusive start, YYYY-MM-DD. |
to_daterequired | string | Inclusive end, YYYY-MM-DD. |
event_types | array of string | Optional filter by event type. statement_close rows are informational (the statement balance), not money moving. Any of: bill_payment, card_payment, variable_spend, savings, income, internal_transfer, loan_payment, cc_interest_charge, statement_close, interest_earned, savings_withdrawal, savings_repayment, overdraft_fee. |
get_shortfall_diagnosticsRead
Diagnose the current plan shortfall (affected periods, skippable spending, postponable bills, pausable savings). Only call if plan has a shortfall.
No arguments.
get_spending_summaryRead
Aggregated spending in a date window: total, by category (top 8), top merchants (top 5). Does not return individual transactions.
| Argument | Type | Description |
|---|---|---|
from_daterequired | string | Inclusive start, YYYY-MM-DD. |
to_daterequired | string | Inclusive end, YYYY-MM-DD. |
category | string | Optional category name to filter by (partial match). |
merchant | string | Optional merchant name to filter by (partial match). |
get_transactionsRead
Individual transaction rows in a date window. Filter by category, merchant, amount range, direction. Use for "did I spend at X?" / "show recent grocery charges". Use get_spending_summary for totals.
| Argument | Type | Description |
|---|---|---|
from_date | string | Inclusive start, YYYY-MM-DD. Defaults to 30 days ago. |
to_date | string | Inclusive end, YYYY-MM-DD. Defaults to today. |
category | string | Optional partial match on category name (case-insensitive). |
merchant | string | Optional partial match on merchant / transaction name. |
min_amount | number | Optional lower bound on absolute amount. |
max_amount | number | Optional upper bound on absolute amount. |
direction | string | Outflows only ("out"), inflows only ("in"), or both. Defaults to "out". One of: out, in, both. |
limit | integer | Max rows to return (1-50). Defaults to 20. |
get_projected_balanceRead
Plan-projected end-of-day balances on a specific date: per-account cash, per-card debt, totals. Use for "what will I have on Aug 1?" / "how much cash on payday?".
| Argument | Type | Description |
|---|---|---|
daterequired | string | Target date, YYYY-MM-DD. Returns balances at end-of-day on this date (or the nearest earlier plan day if nothing is scheduled for it). |
get_goal_progressRead
Goal progress + plan-based ETA: current vs target, projected arrival date or end-of-horizon shortfall. Use for "how am I doing on emergency fund" / "when will I hit my vacation goal".
| Argument | Type | Description |
|---|---|---|
goal_name | string | Optional partial name match (case-insensitive). Omit to list all active goals. |
list_categoriesRead
Spending categories, such as FOOD_AND_DRINK, with the ids other tools take. kind is expense, income, transfer or cc_payment.
No arguments.
list_accountsRead
The user's accounts and credit cards with their ids and current balances. A card balance is what is owed. manual means added by hand in NavFi rather than linked to a bank.
No arguments.
list_billsRead
The user's recurring bills with their ids: amount, frequency, next due date, category, and the account each is paid from. contributes_to_account_id set means the bill is a transfer into that account (money the user keeps), not spending. processing true means NavFi is still detecting bills from a newly linked bank, so the list may be incomplete.
No arguments.
list_incomeRead
The user's income sources with their ids: amount per paycheck, frequency, the next pay date and the checking account it lands in. processing true means NavFi is still detecting income from a newly linked bank, so the list may be incomplete.
No arguments.
get_weekly_budgetRead
The route's spending budget by category for the week that contains a date (default today): allocated, spent so far, planned purchases and remaining. This answers "how much can I spend on X this week". A category that is not listed has no budget that week.
| Argument | Type | Description |
|---|---|---|
date | string | YYYY-MM-DD. Defaults to today. Weeks run Monday to Sunday. |
get_route_statusRead
The route's state. generation_status is completed, generating, failed, timed_out or no_plan. A route takes minutes to calculate; poll this while it is generating.
No arguments.
get_route_healthRead
Route Health: whether the route still matches what happened. verdict is on_track, ahead, absorbed (drift the route absorbs), soft_rerun or strong_rerun (a reroute is advised) or strong_rerun_stale (the route is old). rerun_recommendation is none, optional, soft or strong. reason is a sentence to pass on. For whether a route exists or is still generating, use get_route_status.
No arguments.
get_readinessRead
Pre-Flight Check: whether NavFi has the data it needs to calculate a route. ready false means the items with severity blocker (for example no checking account, or no income) must be fixed in the NavFi app before a reroute; warnings do not stop one. Each item names the entity and the app screen that fixes it.
No arguments.
can_i_affordRead
Whether a purchase fits that week of the route, and what would have to give. outcome is fits_no_reroute (fits as is, or by moving money within the week), fits_reroute (fits, but only after a reroute) or insufficient_room (does not fit). destination.remaining_after is what is left after the purchase; changes lists money moved between categories before it, and its first row is the category itself. A preview: it changes nothing.
| Argument | Type | Description |
|---|---|---|
primary_category_idrequired | string | A category id from list_categories. |
amountrequired | number | US dollars. |
planned_daterequired | string | YYYY-MM-DD, today or later. |
Write tools (8)
Served on https://api.navfi.money/mcp only. Each goes through the same rules as the NavFi app, and the result says what changed.
add_transactionWrite
Record a transaction on a manual account or card (manual: true in list_accounts; bank-linked ones post their own). amount is positive; the category's kind decides whether it is spending, income or a transfer. date can be up to 30 days back. Give account_id or credit_card_id, not both.
| Argument | Type | Description |
|---|---|---|
account_id | string | A manual account id from list_accounts. |
credit_card_id | string | A manual credit card id from list_accounts. |
primary_category_idrequired | string | A category id from list_categories. |
amountrequired | number | US dollars, positive. |
daterequired | string | YYYY-MM-DD, up to 30 days back, not after tomorrow. |
name | string | What it was, for example the merchant. |
save_billWrite
Add a recurring bill, or edit one by passing its id from list_bills. due_date is the next date it is due. priority says what the route may postpone first in a shortfall: essential, important or optional. A bill paid by credit card has no paid-from account. Saving a bill suspends the route until a reroute; the result says so.
| Argument | Type | Description |
|---|---|---|
id | string | A bill id from list_bills, to edit it. Omit to add a new bill. |
namerequired | string | |
amountrequired | number | US dollars per occurrence. |
due_daterequired | string | YYYY-MM-DD, the next due date. |
end_date | string | YYYY-MM-DD, when it stops. Omit if it goes on. |
frequencyrequired | string | One of: daily, weekly, bi-weekly, semi-monthly, monthly, quarterly, annual, annually, one_time. |
priorityrequired | string | One of: essential, important, optional. |
primary_category_idrequired | string | A category id from list_categories. |
linked_account_id | string | The checking account id it is paid from (list_accounts). Omit when paid by card. |
can_pay_with_credit_card | boolean | True when it goes on a credit card. |
grace_period_days | integer | Days it can run late without penalty. |
save_incomeWrite
Add an income source, or edit one by passing its id from list_income. amount is per paycheck; next_pay_date is the next one. Income lands in a checking account. Saving income suspends the route until a reroute; the result says so.
| Argument | Type | Description |
|---|---|---|
id | string | An income id from list_income, to edit it. Omit to add a new source. |
namerequired | string | |
amountrequired | number | US dollars per paycheck. |
frequencyrequired | string | One of: daily, weekly, bi-weekly, semi-monthly, monthly, quarterly, annual, annually, one_time. |
next_pay_daterequired | string | YYYY-MM-DD, the next pay date. |
end_date | string | YYYY-MM-DD, when it stops. Omit if it goes on. |
linked_account_id | string | The checking account id it lands in (list_accounts). |
save_destinationWrite
Add a destination (a savings goal: an amount in a savings account by a date), or edit one by passing its id from get_goal_progress. A savings account holds one active destination. Saving a destination suspends the route until a reroute; the result says so.
| Argument | Type | Description |
|---|---|---|
id | string | A goal_id from get_goal_progress, to edit it. Omit to add a new destination. |
goal_name | string | |
target_amount | number | US dollars to reach. |
target_date | string | YYYY-MM-DD, after today. |
priority | string | One of: essential, important, optional. |
linked_account_id | string | The savings account id it is saved in (list_accounts). Required when adding; cannot change on an edit. |
count_current_balance | boolean | True when what the account already holds counts toward the target. |
notes | string |
plan_purchaseWrite
Put a one-off purchase on the route: an amount in a category on a date. Call can_i_afford first. If its outcome was fits_no_reroute, pass make_room true and its proposal_hash, and the route is adjusted at once. Otherwise the route is suspended and needs a reroute, which the result says. Nothing is paid; the route only plans for it.
| Argument | Type | Description |
|---|---|---|
primary_category_idrequired | string | A category id from list_categories. |
amountrequired | number | US dollars. |
planned_daterequired | string | YYYY-MM-DD, today or later, within the route. |
name | string | What it is for. |
merchant_name | string | |
make_room | boolean | True to move money within the week as can_i_afford proposed. |
proposal_hash | string | The proposal_hash from can_i_afford, when make_room is true. |
mark_turn_doneWrite
Mark a turn on the route as done: a bill paid, a paycheck received, a planned purchase made. event_id comes from get_upcoming_events or plan_purchase. transaction_id (from get_transactions) links the real transaction; omit it to settle the turn without one. A settled turn is not planned again by the next reroute.
| Argument | Type | Description |
|---|---|---|
event_idrequired | string | The event_id of the turn. |
transaction_id | string | The id of the transaction that paid it, from get_transactions. |
recategorize_transactionWrite
Change a transaction's category. transaction_id comes from get_transactions, primary_category_id from list_categories. Money that left an account cannot become income. If the new category changes what the transaction is (spending to a bill payment, say), its link to a turn is dropped; match_kept says whether it survived. NavFi learns the correction for similar transactions.
| Argument | Type | Description |
|---|---|---|
transaction_idrequired | string | A transaction id from get_transactions. |
primary_category_idrequired | string | A category id from list_categories. |
notes | string | Why, in a few words. |
rerouteWrite
Recalculate the route from today's data. Use it after save_bill, save_income or save_destination, or when get_route_health advises one. It returns at once; the new route takes minutes, so poll get_route_status until generation_status is completed. If the user's data is not ready, the error lists what must be fixed in the NavFi app first (see get_readiness). Each reroute is a full recalculation, so there is a daily limit.
| Argument | Type | Description |
|---|---|---|
reason | string | Why, in a few words. Kept with the route. |
Errors
A refused call comes back as a tool error whose message is written for the agent to act on or pass to the user.
| Error | What it means |
|---|---|
| This needs an active NavFi subscription. | The user has no active subscription. They subscribe in the NavFi app. |
| Validation messages | A missing or malformed argument, an id that is not the user's, or a date out of range. The tools use the same rules as the NavFi app. Ids come from the list and get tools. |
| The week's numbers changed since the preview. | plan_purchase with make_room got a stale proposal_hash. Call can_i_afford again and pass its new hash. |
| The daily limit of 5 reroutes through an AI app is reached. | The user has used today's reroutes through MCP. They can still reroute in the NavFi app. |
| Data not ready | reroute lists what must be fixed in the NavFi app first, the same items get_readiness returns. |
| HTTP 401 | The token is missing or expired. The client refreshes it or runs the sign-in again. |
| HTTP 429 | More than 60 calls in a minute. |
Limits
- 60 calls a minute per user.
- 5 reroutes per user per day through MCP, counted in the user's time zone. The app's own reroute cooldown also applies.
- A reroute returns at once and the new route takes minutes. Poll
get_route_statusuntilgeneration_statusiscompleted. - Nothing through MCP moves money, links a bank or deletes anything.
Changelog
- 2026-11: read tools.
- 2026-11: write tools and the read-only address.
- 2026-11: OAuth 2.1 sign-in with an email code.
Support
Email support@navfi.money. Users can read Connect your AI and the Privacy Policy.
Generated from the server on 2026-11-06.