GuidesMCP Server Reference

MCP Server Reference

Technical reference for the Forbidden Finance MCP server — the hosted remote endpoint, OAuth setup, the standalone connector, and the full catalog of 40 tools. Premium, limited beta.

Just want to connect your assistant? Start with Connect Your AI Assistant — a plain-language walkthrough. This page is the technical reference: the endpoint, the tool catalog, and how tool visibility is derived.

Overview

The Model Context Protocol (MCP) lets an AI assistant call the Forbidden Finance API on your behalf. Bring the assistant you already use — Forbidden Finance does not supply one, and does not send your data to any model of its own.

There are two ways to reach the server, both backed by the same public API and the same server-enforced privacy model:

  • Hosted remote serverhttps://api.403fin.io/mcp, OAuth 2.1 with dynamic client registration. Best for clients with built-in remote-MCP support.
  • Standalone connector@403fin/mcp, a stdio connector run locally. Best for clients that only launch local MCP servers.
MCP access is a Premium feature and is currently in limited beta. Tools and setup may change while the beta is open.

Requirements

  • Tier: Premium.
  • Auth: either OAuth 2.1 through the hosted server (no key to copy), or an ff_ak_ API key from a connection created under Settings > AI & API Connections. See AI & API Connections.
  • An AI client that supports MCP.

Hosted remote server

POST https://api.403fin.io/mcp

A streamable-HTTP MCP endpoint. Point your client's remote-connector setting at that address and approve in the browser.

The authorization flow is standard remote MCP:

  1. The client fetches /.well-known/oauth-protected-resource/mcp (RFC 9728) to discover the authorization server, which is https://api.403fin.io.
  2. It registers itself dynamically at POST /oauth/register (RFC 7591) — there is no manual app registration to wait on.
  3. The user authorizes in the browser with OAuth 2.1: authorization code plus PKCE, S256 only. Clients are public; there is no client secret.
  4. On the Forbidden Finance consent screen the user picks the connection's scopes, decides whether changes are allowed, and chooses any fields to hide.

Everything about what the connection may do is decided on that screen, by the person authorizing. Your client asks for scopes; it never sets the privacy settings, and it cannot widen what it was granted.

Full metadata is at https://api.403fin.io/.well-known/oauth-authorization-server. See Getting Started for the endpoint table.

Standalone connector

@403fin/mcp is a small stdio connector that speaks MCP to your client and calls the Forbidden Finance API over HTTPS. It is for clients that launch local MCP servers rather than connecting to a remote address.

It is a thin, open-source client — every tool call is one authenticated HTTPS request to /v1. There is no backend of its own and no data store, so your credential and any OAuth tokens stay on your machine. The source is at 403ent/403fin-mcp (MIT).

Run it with npx; there is nothing to install ahead of time:

{
  "mcpServers": {
    "forbidden-finance": {
      "command": "npx",
      "args": ["-y", "@403fin/mcp"],
      "env": {
        "FF_API_KEY": "ff_ak_your_key_here"
      }
    }
  }
}

That same configuration works for Claude Desktop, ChatGPT's stdio MCP servers, Perplexity, and any other client that launches local MCP servers.

The connector requires Node.js 22 or newer. On an older Node, npx will refuse to run it.

It reads these environment variables:

VariableRequiredDefaultPurpose
FF_API_KEYNoYour ff_ API key. Setting it selects API-key auth; leave it unset and the connector signs in with OAuth 2.1 (PKCE, via a local loopback callback) in your browser instead.
FF_BASE_URLNohttps://api.403fin.ioAPI origin; the connector appends the /v1 paths itself. Set it only if you self-host. It must be https:// — the connector refuses plain HTTP and never disables TLS verification.
FF_SCOPESNoomittedOAuth scope string, OAuth mode only. Omitted, the connector asks for every read scope and no writes; set it to narrow the request.

FF_SCOPES is the lever worth knowing about: the connector's default OAuth request is read-only, so a connection made this way cannot write until you both ask for a :write scope here and arm Allow changes on the connection.

Never paste your ff_ key into a chat message — it belongs only in the connector's env block. If a key is exposed, revoke that connection in the app and create a new one.

Tools

The server exposes 40 tools: 29 reads and 11 writes — one per API operation, a faithful 1:1 with the /v1 routes. Every tool call runs the identical authorize → endpoint → redact path a REST request does, so scopes, privacy settings, rate limits, and the audit log all behave the same on both surfaces.

Read tools (29)

AreaTools
Accounts & connectionslist_accounts, get_account, get_account_balances, list_connections, get_sync_status
Transactionslist_transactions, get_transaction, search_transactions, list_categories
Budgetslist_budgets, get_budget, get_budget_progress
Recurring & billslist_recurring, list_upcoming_bills
Goalslist_goals, get_goal, get_goal_progress, get_goal_history, list_goal_contributions
Net worth & assetsget_net_worth, get_net_worth_history, list_holdings, list_liabilities, get_debt_summary, compute_debt_payoff_plan
Insightsget_spending_by_category, get_income_vs_expenses, get_month_summary, get_cash_flow_forecast

compute_debt_payoff_plan is a read despite computing something: it returns a plan and changes nothing.

Write tools (11)

AreaToolsScope
Transactions — annotateannotate_transaction, categorize_transactionstransactions.annotate:write
Transactions — full editcreate_transaction, update_transaction, delete_transactiontransactions:write
Categoriescreate_category, update_category, delete_categorycategories:write
Goalsupdate_goal, record_goal_contributiongoals:write
Budgetsswitch_budget_methodbudgets:write

Every write tool takes a required idempotency_key argument, which routes into the same store the REST Idempotency-Key header uses. A retried call with the same key replays rather than re-applies; a corrected retry needs a fresh key. The full semantics — versioning, partial bulk results, editing bank-synced rows — are on Writing Data, and they are identical here.

Tool visibility is derived, not configured

A write tool appears in tools/list only when the connection holds its scope and has the Allow changes switch on. Neither alone is enough.

The practical effect is that an assistant never sees a tool it would be refused. Grant a categorizing assistant transactions.annotate:write and it is offered annotate_transaction and categorize_transactions — the three tools that could change an amount or remove a row are simply not in its list. Turn Allow changes off later and all eleven write tools disappear at once, without touching the scope list.

Read tools filter the same way: a scope the connection lacks means its tools are absent, not merely refused.

Destructive tools

Three tools carry MCP's destructiveHint, because a call removes or replaces something that already existed. A client that gates destructive tools behind a confirmation should gate these:

ToolWhy
delete_transactionRemoves a transaction. Bank-synced rows are refused, but manual and imported ones go.
delete_categoryRemoves a custom category; its transactions become uncategorized or are merged elsewhere.
switch_budget_methodDoes not edit the current budget — it archives it and creates a new one.

Every other write is additive or an in-place field edit, and says so: the tools declare destructiveHint: false explicitly rather than leaving it unset, since an absent hint means "assume destructive".

All eleven declare idempotentHint: true — the required idempotency_key is exactly what makes that true.

switch_budget_method archives the active budget and creates a new one for the chosen method. If the budget is shared with a partner, the switch needs that partner's approval in the app and cannot be completed here. Confirm with the user before calling it.

Writes through MCP never teach the categorizer

Every transaction edit made through this surface — as through the REST API — suppresses rule learning. No per-merchant rule is created or updated, no vote reaches the global category model, and no categorization event is published. An assistant's opinion about one merchant does not quietly become the default for everything else.

Split transactions are refused rather than flattened: a category change on a split parent comes back as a refusal, or as status split in a bulk result, leaving the slices the person set by hand intact.

Privacy

Whatever the client, redaction and exclusion are enforced on Forbidden Finance's servers — not by the AI client, and not by any connector on your machine. A redacted field is omitted from the tool result; an excluded account or category is absent entirely; and a write that would touch a hidden field is refused without naming it.

Tool descriptions are static strings. Your data is never interpolated into a tool description, so nothing in the tool catalog can carry content from your account.

See Data Privacy & Redaction for the full model.

Frequently Asked Questions

Why can't my assistant see the write tools?

Either the connection lacks that :write scope, or its Allow changes switch is off. Both are required, and a tool the connection could not use is hidden rather than shown-and-refused. Check the connection under Settings > AI & API Connections.

Does the hosted server need an API key?

No. The hosted server uses OAuth — you approve in the browser and there is no key to copy or store. API keys are for the standalone connector and for your own scripts.

Is the tool list the same as the REST API?

Yes, one tool per operation, all 40. Anything you can do over REST you can do as a tool, under the same scopes and the same privacy settings.

Can an assistant move money, or reach my bank login?

No. Those operations do not exist on this API, so there is no tool for them. The write surface is transactions, categories, budgets, and goals.

Does Forbidden Finance send my data to an AI model?

Not through this surface. MCP answers the questions your assistant asks, within the scopes and privacy settings you set. What that assistant and its provider then do with the answer is governed by their terms, not ours.

Connect Your AI Assistant

The plain-language setup walkthrough.

Writing Data

Idempotency, versioning, and every write in detail.

Scopes & Permissions

What each scope grants, and the two-switch rule.

Data Privacy & Redaction

Control exactly what an assistant can see.

Need more help? Contact us at [email protected].