← All docs MCP server

Talk to your wallet.

A Model Context Protocol server at POST /mcp. Point Claude Desktop (or any MCP client) at it with your Finstracker bearer token and ask things like "what card should I use at Costco?"

Overview

Finstracker speaks Model Context Protocol at POST /mcp. Any MCP-compatible client (Claude Desktop, Claude Web custom connectors, agent SDKs, the mcp CLI) can connect with your Finstracker bearer token and call nine tools that read or write your wallet data.

The transport is stateless Streamable HTTP (MCP spec 2025-03-26): one JSON-RPC request per POST, no session IDs, no long-lived SSE streams. This is the simplest profile and is friendly to serverless hosts.

Quickstart (Claude Desktop)

  1. Create or log into your Finstracker account at finstracker.com/signup.
  2. Get a bearer token. From a terminal:
    curl -X POST https://finstracker.com/api/auth/login \
      -H 'Content-Type: application/json' \
      -d '{"username":"YOUR_USERNAME","password":"YOUR_PASSWORD"}'
    Copy the data.token field from the response.
  3. Open your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS) and add:
    {
      "mcpServers": {
        "finstracker": {
          "transport": "http",
          "url": "https://finstracker.com/mcp",
          "headers": {
            "Authorization": "Bearer <paste-jwt-here>"
          }
        }
      }
    }
  4. Restart Claude Desktop. Ask: "What cards do I have on Finstracker?" Claude should call list_cards and respond with your wallet.

Authentication

The MCP server reuses the same JWT bearer auth as the REST API. Same token, same login endpoint, no OAuth flow to wire up.

StepWhereNotes
Mint a tokenPOST /api/auth/loginReturns data.token (JWT). Valid 7 days.
Attach to MCPAuthorization: Bearer <jwt> on every POST /mcpSent automatically by your MCP client.
RefreshRe-run login when the token expiresThe server returns isError on the next call so your client knows.

One tool, get_catalog_card, is public and works without a token, since the cards catalog is non-PII reference data.

Endpoint & transport

PropertyValue
URLhttps://finstracker.com/mcp
MethodsPOST (and OPTIONS for CORS). GET and DELETE return 405.
Content-Typeapplication/json (JSON-RPC 2.0)
Acceptapplication/json, text/event-stream (MCP spec requirement)
Session IDNone. Server runs in stateless mode
SDK versionImplements MCP 2025-03-26

Tools

Every tool returns a content array with a single text block containing pretty-printed JSON. Errors set isError: true and put a human message in the same text block.

list_cards auth

Returns every credit card the authenticated user is tracking, with balances, point value, annual fee, and sign-up bonus progress.

Input: none.

Output:

{
  "count": 9,
  "cards": [
    {
      "id": "...",
      "cardKey": "chase-sapphire-preferred",
      "displayName": "Sapphire Preferred",
      "issuer": "Chase",
      "rewardType": "points",
      "currentPoints": 84210,
      "currentCashBack": 0,
      "pointValueCents": 1.25,
      "annualFee": 95,
      "signupBonus": { "spendRequired": 4000, "currentSpend": 4200, "bonusAmount": 75000, "bonusUnit": "points", "completed": true, "applied": true }
    }
  ]
}

list_perks auth

Returns recurring statement credits (monthly Uber Cash, annual hotel credits, etc.) with deadlines and used status.

ParameterTypeDefaultNotes
scope"open" | "used" | "all""open"Filters by claim status.
cardIdstringRestrict to one card.
yearint 2000–2100Restrict to a calendar year.
limitint 1–500100Max rows returned.

list_offers auth

Returns merchant offers (Amex Offers, Chase Offers, BoA Deals) attached to your cards.

ParameterTypeDefaultNotes
categoryenumOne of dining, travel, streaming, retail, grocery, gas, entertainment, other.
merchantstring ≤80Case-insensitive substring match.
includeUsedboolfalseInclude offers you've already claimed.
includeExpiredboolfalseInclude offers past their expiration.
limitint 1–500100

list_transactions auth

Returns recent earn/redeem transactions, newest first.

ParameterTypeDefaultNotes
cardIdstringRestrict to one card.
type"earn" | "redeem"
unit"points" | "cashback"
limitint 1–50050
beforeISO datetimeCursor pagination: return only items older than this.

get_billing_status auth

Returns the user's subscription state: trialing, active, past_due, or expired, plus the plan, trial end, and any scheduled cancel-at-period-end.

Input: none.

get_catalog_card public

Looks up catalog metadata for a credit card by cardKey. Public, no auth required.

ParameterTypeDefaultNotes
cardKeystring ≤80e.g. chase-sapphire-preferred. Omit to get the full catalog.

recommend_card_for_merchant auth

Returns the top three cards from the user's wallet to use at a given merchant. Active merchant offers win first; otherwise the highest point-value card wins.

ParameterTypeDefaultNotes
merchantstring 1–120requiredMerchant name. Case-insensitive substring match against your offers.
categoryenum (same as list_offers)Helps tie-break when no offer matches.
amountCentsint 0–10,000,000Pass the purchase amount for accurate %-back math.

log_transaction auth write

Records an earn or redeem transaction on a card you own. The card's balance is updated atomically; the unit must match the card's reward type. Gated by the trial paywall: calls fail with a clear error after the trial expires unless you have an active subscription.

ParameterTypeNotes
cardIdstringRequired.
type"earn" | "redeem"Required.
unit"points" | "cashback"Required; must match card.
amountnumber > 0Must be an integer for points cards.
notestring ≤200Optional free-text label.

mark_perk_used auth write

Toggles whether a perk has been claimed. used: false undoes a claim and clears usedAt.

ParameterTypeDefaultNotes
perkIdstringrequired
usedbooltrue

Errors

Two error layers, matching the MCP spec:

  1. JSON-RPC protocol errors (bad method, malformed request) come back as an error envelope with a numeric code.
  2. Tool errors (unauthorized, validation failed, paywall) come back as a normal result with isError: true and a human message in content[0].text. This is what an LLM client will surface to the user.

Common tool errors:

MessageCause
Unauthorized. Attach Authorization: Bearer <jwt>…No bearer token, expired token, or invalid token.
Session expired. Please sign in again.Token valid but user no longer exists (e.g. account deleted).
Trial ended. Please choose a plan to continue.Trial expired and no active subscription. Read tools still work; write tools and recommendations gated.
Card not found.The cardId doesn't belong to you (or doesn't exist).
Insufficient points/cashback to redeem…log_transaction would push the balance below zero.

Rate limits

No hard rate limits today. The endpoint runs on Netlify Functions and is bounded by their per-request timeout (~26 s). LLM clients that call tools in tight loops may want to add their own client-side throttling. A built-in token bucket is on the roadmap.

Troubleshooting

  • "Server didn't respond" in Claude Desktop. Make sure the JSON config lives under mcpServers, the URL has no trailing slash, and the transport is "http". Restart Claude after editing.
  • Every tool returns "Unauthorized". Your token is missing, malformed, or expired. Re-mint via POST /api/auth/login.
  • 406 Not Acceptable. Your client isn't sending Accept: application/json, text/event-stream. MCP-spec clients do this automatically; raw curl needs the header set explicitly.
  • Recommendations are empty. You have no cards. Add one at finstracker.com/app first.

Versioning

The server reports its version as finstracker@0.1.0 during MCP initialize. Tool input schemas may evolve while the API is in beta. Breaking changes will be called out in the changelog and bumped in the version string.

Try it

Sign up, mint a token, paste it into your Claude Desktop config. That's the whole setup.

Create your account