← Newsroom

BLOG

[Engineering] What MCP Is, and How We Built Our Server for Financial Data

2026.09.21

Hello, this is the Fintag engineering team.

We recently announced that Fintag now supports MCP. Since then we have been asked the same question more than once: what is MCP? This post explains it from the beginning, then shares the choices we made as a service that handles financial data.

1. MCP is USB-C for AI apps

To ask an AI "summarize our card spending this month," the AI has to be able to read your company's data. The problem is that there are many AI apps and many services holding data.

With 4 AI apps and 10 services, you need 40 integrations. Every service has its own authentication and its own data format. It is the era when every laptop had a different charger.

The Model Context Protocol (MCP) standardizes that connection. A service opens one endpoint that follows the spec, and any AI app that speaks the spec can connect. Forty integrations become fourteen.

Tangled cables versus cables plugged into a single hub

The spec covers three things:

  • How a service advertises what it can do — the AI can ask for a list of available capabilities.
  • How those capabilities are invoked — names and arguments in a fixed shape.
  • How authentication works — who asked, and how far they are allowed to go.

2. The idea of a tool

In MCP, each capability a service exposes is called a tool. For Fintag, that means things like "list accounts," "get card transactions," and "cash flow forecast."

When an AI app connects, it first asks for the tool list. The server answers with entries like this:

{ "name": "get_card_transactions",
  "description": "Finds card transactions by period and conditions",
  "inputSchema": { "from": "date", "to": "date", "cardId": "optional" } }

The AI reads those descriptions and decides on its own which tool the question needs. Ask "how much did we spend on the corporate card last month?" and it calls get_card_transactions with a date range. Instead of branching logic written per question type, you write good tool descriptions and let the model choose.

3. Why we implemented it without the SDK

MCP has an official SDK. We did not use it.

Stateless Streamable HTTP, one of MCP's transports, comes down to this:

Take a JSON-RPC request over POST, handle it, return JSON. That's it.

A Next.js route handler is already "receive a POST, return JSON," so the SDK's session and transport abstractions would add a layer rather than remove one. What we actually needed to attach was authentication, permission filtering, and audit logging — and all three already existed in our server code. So we matched the JSON-RPC spec ourselves and wired the rest to modules we already had.

The tradeoff is that compliance is on us. We built a 25-item checklist and verified each one: discovery documents, the shape of unauthenticated responses, single-use authorization codes, tool list filtering, tenant isolation, and more.

4. Authentication — never handing your password to an AI app

This is the part that matters most. An AI app must not ask for your Fintag ID and password, because then that app holds your password.

So we use OAuth 2.1. The flow looks like this:

1) The AI app asks to connect to Fintag
2) Your browser opens and you log in on Fintag
3) A consent screen shows what the app is asking for
4) On approval, Fintag issues a token scoped to that app
5) From then on, the app only ever sends the token

Your password is entered only on Fintag's own screen. The app holds a token, and if you change your mind you delete that token alone.

On top of that:

  • PKCE with S256 only. It prevents an intercepted authorization code from being used; the older plain method is rejected outright.
  • We never store raw tokens. The database holds hashes only. Reading the entire database gives you nothing you can call the API with.
  • Short lifetimes. Authorization codes last 10 minutes and are single-use, access tokens one hour, refresh tokens 30 days.

A key rotating and splitting into segments

Refresh tokens rotate on every use. If an already-rotated token shows up again, that is a signal someone stole it. At that point we revoke every token in the same family. Both the attacker and the legitimate user get cut off — and for financial data, that is far better than leaving a stolen session quietly open.

5. Permissions — connecting does not mean seeing everything

The most common mistake when adding MCP is treating connection as full access. Fintag filters in three stages.

Cubes passing through a funnel

First, the user's own permissions. Nothing can exceed what that person can already see inside the company. A view-only member who connects an AI app never sees tools that change data.

Second, per-app scope. Even for the same person, each app gets its own range. You can grant one app read-only access.

Third, a re-check at execution. Appearing in the tool list is not enough. Permissions are verified again at call time, so if access was revoked after the list was fetched, the call is refused.

And tools that change data require one more confirmation. If the AI tries to create an event or change a budget, it does not run until the user confirms.

6. Multi-tenancy — why the token carries no company

Embedding the company in the token means you never have to look it up again. It is fast, and it is a common design. We did not do it.

Tokens live for an hour. In that hour an employee can leave, move teams, or have their account suspended. If you trust what is baked into the token, the old permissions stay alive for up to an hour. For financial data, an hour is a long time.

So we resolve the company from the user ID on every request. We pay one extra lookup, and permission changes apply immediately.

For the same reason, abuse controls live on the server: calls per token are capped, and app registrations unused for 30 days are cleaned up automatically.

7. What building it taught us

MCP itself is not hard. You receive a JSON-RPC request and answer it. The hard part was deciding what to expose.

  • Should this tool be visible to an external AI app at all?
  • Does it need a human to confirm before it runs?
  • Does the result contain values that must be masked?

We exclude digital certificates and institution passwords from retrieval entirely, and mask account and card numbers in results. Tools that only make sense inside our own UI are never exposed.

In an era where AI reaches data directly, we think "what must it never be able to do" is the more important design question than "what can it do."

📌 Check your company's finances from the AI app you already use Connect Fintag once and get answers from your real data in apps like Claude and ChatGPT. Start with a 2-week free trial. → app.fintag.kr

The Fintag engineering blog shares the technical decisions we make while building the product, and the reasoning behind them. Contact: support@fintag.kr

Related