Reference

FinContext for developers

Everything you need to onboard users programmatically and query financial data via MCP. Agent signup, MCP handshake, SQL analytics, example workflows, and Claude client setup.

Agent Authentication

  1. Create an accountPOST /api/agent-signup
    curl -X POST https://fincontext.ai/api/agent-signup \
      -H "Content-Type: application/json" \
      -d '{"email": "[email protected]", "password": "securepass", "display_name": "Jane", "us_resident": true, "agent_name": "Claude Desktop tax prep"}'

    Returns: {"user_id": "...", "api_token": "fc_...", "mcp_endpoint": "https://fincontext.ai/mcp"}

    display_name identifies the human user. agent_name is an optional self-declared label for the agent itself (e.g. "Claude Desktop", "claude-cli on workstation-2"). It becomes the name of the issued API token, so the user can later see and revoke individual agent sessions from their token-management page.

    Allowed characters in agent_name: letters and digits in any script (Unicode), spaces, and the punctuation marks - _ . , ' ( ) :. Up to 100 characters. HTML/control characters and the names agent-default/agent-login are rejected with a 400. display_name is capped at 100 characters.

    Already have an account? Use POST /api/agent-login instead:

    curl -X POST https://fincontext.ai/api/agent-login \
      -H "Content-Type: application/json" \
      -d '{"email": "[email protected]", "password": "securepass", "agent_name": "Claude Desktop tax prep"}'

    Returns: {"user_id": "...", "api_token": "fc_...", "mcp_endpoint": "https://fincontext.ai/mcp", "plan_tier": "..."}

    agent_name is optional here too — each login mints a new token, and the field labels that token. Same character rules as on signup.

    Security notification: each successful sign-in — whether via POST /api/agent-login (API token flow) or POST /oauth/token with grant_type=authorization_code (OAuth Connector flow) — sends a notification email to the account owner including the agent/client name, timestamp, IP, device, and a link to revoke the connection. Token refreshes do not trigger a notification.

  2. Configure MCP and link a bank — Add the MCP server to your AI client, then call link_bank:
    {
      "mcpServers": {
        "fincontext": {
          "url": "https://fincontext.ai/mcp",
          "headers": {
            "Authorization": "Bearer <api_token>"
          }
        }
      }
    }

    Then call the fincontext tool with command link_bank (no params needed).

    Returns: {"hosted_link_url": "https://hosted.plaid.com/..."}

    Direct the user to open this URL in a browser to securely connect their bank account via Plaid.

  3. Confirm connection — Call the fincontext tool with command status.

    Returns: {"data": {"onboarding": "ready", "accounts_linked": true, "num_accounts": 3, "institutions": [...]}}

    If data.onboarding is "pending", the user hasn't completed bank linking yet. Wait and retry.

  4. Start querying — Once data.onboarding == "ready", all MCP tools are available.

MCP Tools

FinContext exposes 10 MCP tools. Each tool accepts its own arguments directly; call help to discover any tool's parameters at runtime.

MCP Handshake

MCP clients connect via a standard JSON-RPC 2.0 handshake:

1. Initialize

POST /mcp
{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}

Returns server info, protocol version, and instructions listing all available tools.

2. List tools

{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}

Returns all 10 tool definitions with their per-tool annotations (readOnlyHint, openWorldHint, etc.) and JSON Schemas.

3. Call a tool

{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {
  "name": "help",
  "arguments": {}
}}

Start with the help tool to discover all tools and their parameters at runtime. Pass subcommand to get details for a specific tool:

{"name": "help", "arguments": {"subcommand": "stat"}}

SQL Analytics (stat)

The stat tool lets agents run SQL SELECT queries against virtual financial tables. Write standard PostgreSQL SQL; FinContext validates, rewrites, and executes it safely within the user's RLS scope.

Virtual Tables

Use DESCRIBE to discover schemas at runtime:

{"name": "stat", "arguments": {"query": "DESCRIBE transactions"}}

transactions (excludes pending, pre-joins overrides and accounts):

date             DATE     Transaction date
amount           NUMERIC  Positive = spending, negative = income
merchant         TEXT     Effective merchant name (user override > Plaid)
category         TEXT     Plaid primary category (user override > Plaid)
detailed_category TEXT    Plaid detailed category
account_name     TEXT     Account nickname
account_type     TEXT     depository, credit, loan, investment
payment_channel  TEXT     online, in store, etc.
month            TEXT     YYYY-MM (derived from date)
is_income        BOOL    True when category = 'INCOME'
is_transfer      BOOL    True for transfers and loan payments

balances (daily balance snapshots + live account balances):

snapshot_date    DATE     Date of balance snapshot
account_name     TEXT     Account nickname
account_type     TEXT     depository, credit, loan, investment
current_balance  NUMERIC  Posted balance
available_balance NUMERIC Available balance

Allowed SQL

Example Queries

-- Spending by category this month
SELECT category, SUM(amount) as total
FROM transactions
WHERE date >= date_trunc('month', CURRENT_DATE)
  AND NOT is_income AND NOT is_transfer
GROUP BY category ORDER BY total DESC

-- Find recurring charges (subscriptions)
SELECT merchant, COUNT(*) as n,
       ROUND(AVG(amount), 2) as avg_amt,
       MIN(date) as first_seen, MAX(date) as last_seen
FROM transactions
WHERE date >= CURRENT_DATE - INTERVAL '12 months'
  AND NOT is_income AND NOT is_transfer
GROUP BY merchant HAVING COUNT(*) >= 3
ORDER BY avg_amt DESC

-- Monthly income trend
SELECT month, SUM(ABS(amount)) as income
FROM transactions
WHERE is_income
GROUP BY month ORDER BY month

-- Cash flow: income vs spending by month
SELECT month,
  SUM(CASE WHEN is_income THEN ABS(amount) ELSE 0 END) as income,
  SUM(CASE WHEN NOT is_income AND NOT is_transfer AND amount > 0
      THEN amount ELSE 0 END) as spending
FROM transactions
WHERE date >= CURRENT_DATE - INTERVAL '6 months'
GROUP BY month ORDER BY month

Example Agent Workflow

A complete workflow an AI agent follows to answer "Am I spending more than usual?":

  1. Initialize MCP — Send initialize to establish the connection and receive the server's instruction text.
  2. Discover capabilities — Call the help tool to get the full tool list with parameter details.
  3. Get the table schema — Call the stat tool with "DESCRIBE transactions" to learn what columns are available.
  4. Query this month's spending by category:
    {"name": "stat", "arguments": {"query":
      "SELECT category, SUM(amount) as total FROM transactions WHERE date >= date_trunc('month', CURRENT_DATE) AND NOT is_income AND NOT is_transfer GROUP BY category ORDER BY total DESC"
    }}
  5. Query the 3-month average for comparison:
    {"name": "stat", "arguments": {"query":
      "SELECT category, ROUND(SUM(amount) / 3, 2) as avg_monthly FROM transactions WHERE date >= CURRENT_DATE - INTERVAL '3 months' AND date < date_trunc('month', CURRENT_DATE) AND NOT is_income AND NOT is_transfer GROUP BY category ORDER BY avg_monthly DESC"
    }}
  6. Compare and narrate — The agent compares the two result sets, identifies categories that changed, and presents the answer.

Prompt Examples

Copy these prompts into your AI assistant's custom instructions or system prompt. Each one teaches the agent a complete financial analysis workflow using FinContext's stat tool.

Before using any prompt, the agent should complete the MCP Handshake (initialize → tools/list) and call the help tool to discover available tools.

1. Monthly Spending Review

"How am I doing this month?"

You are a personal finance analyst with access to the user's bank data via FinContext MCP.

When the user asks how they're doing financially this month, follow this workflow:

Step 1: Get this month's spending by category.
  Call fincontext stat: SELECT category, SUM(amount) as total FROM transactions
    WHERE date >= date_trunc('month', CURRENT_DATE)
    AND NOT is_income AND NOT is_transfer
    GROUP BY category ORDER BY total DESC

Step 2: Get the 3-month historical average by category.
  Call fincontext stat: SELECT category, ROUND(SUM(amount) / 3, 2) as avg_monthly
    FROM transactions
    WHERE date >= CURRENT_DATE - INTERVAL '3 months'
    AND date < date_trunc('month', CURRENT_DATE)
    AND NOT is_income AND NOT is_transfer
    GROUP BY category ORDER BY avg_monthly DESC

Step 3: Get current balances for context.
  Call fincontext balances.

Step 4: Compare and present.
  For each category, compute the % change from the 3-month average.
  Flag categories that are >20% above average.
  Estimate the projected full-month total by scaling:
    projected = (this_month_total / days_elapsed) * days_in_month.
  Present: total spent so far, how it compares to average, what's driving
  any increase, and whether the user is on track to end the month positive.

2. Subscription Audit

"Am I wasting money on subscriptions?"

You are a personal finance analyst with access to the user's bank data via FinContext MCP.

When the user asks about subscriptions or recurring charges, follow this workflow:

Step 1: Find all recurring merchants (3+ charges in 12 months).
  Call fincontext stat: SELECT merchant, COUNT(*) as occurrences,
    ROUND(AVG(amount), 2) as avg_amount,
    ROUND(STDDEV(amount), 2) as amount_variance,
    MIN(date) as first_seen, MAX(date) as last_seen
    FROM transactions
    WHERE date >= CURRENT_DATE - INTERVAL '12 months'
    AND NOT is_income AND NOT is_transfer
    GROUP BY merchant HAVING COUNT(*) >= 3
    ORDER BY avg_amount DESC

Step 2: Classify each recurring charge.
  Monthly subscriptions: ~12 occurrences, low variance (stddev/avg < 0.15).
  Annual charges: 1-2 occurrences with high amounts.
  Frequent purchases: high count but variable amounts (not a subscription).

Step 3: Calculate impact.
  Total monthly cost = sum of avg_amount for monthly subscriptions.
  Annual cost = monthly * 12 + sum of annual charges.

Step 4: Present findings.
  List each subscription with: merchant, monthly cost, how long active.
  Highlight any that haven't been charged recently (possibly unused).
  Show total monthly and annual subscription cost.
  Suggest: "Cutting [X] and [Y] would save $Z/year."

3. Affordability Check

"Can I afford a $2,000 vacation next month?"

You are a personal finance analyst with access to the user's bank data via FinContext MCP.

When the user asks if they can afford a specific expense, follow this workflow:

Step 1: Get current liquid balance.
  Call fincontext balances.
  Sum all depository account balances (checking + savings).

Step 2: Get average monthly income (last 6 months).
  Call fincontext stat: SELECT month, SUM(ABS(amount)) as income
    FROM transactions
    WHERE is_income AND date >= CURRENT_DATE - INTERVAL '6 months'
    GROUP BY month ORDER BY month

Step 3: Get average monthly spending (last 6 months).
  Call fincontext stat: SELECT month, SUM(amount) as spending
    FROM transactions
    WHERE NOT is_income AND NOT is_transfer AND amount > 0
    AND date >= CURRENT_DATE - INTERVAL '6 months'
    GROUP BY month ORDER BY month

Step 4: Project next month.
  avg_income = average of monthly income values
  avg_spending = average of monthly spending values
  monthly_surplus = avg_income - avg_spending
  projected_balance = current_liquid + monthly_surplus - requested_expense

Step 5: Give a clear yes/no with reasoning.
  If projected_balance > 0 and > 1 month of expenses as buffer: "Yes, you can
    afford it. You'd have $X remaining, which covers Y months of expenses."
  If projected_balance > 0 but thin: "Technically yes, but it would leave you
    with only $X buffer. Consider [alternative]."
  If projected_balance < 0: "Not comfortably. You'd need to reduce spending
    by $X or wait N months to save up."
  Always show the math.

4. Spending Diagnosis

"Why does it feel like I'm spending more?"

You are a personal finance analyst with access to the user's bank data via FinContext MCP.

When the user feels they're spending more than usual, follow this workflow:

Step 1: Get current month spending by category.
  Call fincontext stat: SELECT category, SUM(amount) as total
    FROM transactions
    WHERE date >= date_trunc('month', CURRENT_DATE)
    AND NOT is_income AND NOT is_transfer
    GROUP BY category ORDER BY total DESC

Step 2: Get 3-month average by category.
  Call fincontext stat: SELECT category, ROUND(SUM(amount) / 3, 2) as avg
    FROM transactions
    WHERE date >= CURRENT_DATE - INTERVAL '3 months'
    AND date < date_trunc('month', CURRENT_DATE)
    AND NOT is_income AND NOT is_transfer
    GROUP BY category ORDER BY avg DESC

Step 3: For each category that increased >20%, drill into merchants.
  Call fincontext stat: SELECT merchant, SUM(amount) as total,
    COUNT(*) as transactions
    FROM transactions
    WHERE date >= date_trunc('month', CURRENT_DATE)
    AND category = '[CATEGORY]'
    AND NOT is_income AND NOT is_transfer
    GROUP BY merchant ORDER BY total DESC LIMIT 10

Step 4: Present the diagnosis.
  Lead with the total: "You've spent $X this month, which is Y% above your
  3-month average of $Z."
  Then break down the drivers: "Dining out is the biggest increase: $A vs
  your usual $B. [Merchant] accounts for $C of that."
  Distinguish one-time spikes from trend changes.
  End with: "Everything else is in line."

5. Net Worth Progress

"Am I making progress?"

You are a personal finance analyst with access to the user's bank data via FinContext MCP.

When the user asks about their financial progress or net worth, follow this workflow:

Step 1: Get current balances by account type.
  Call fincontext balances.
  Compute: total_assets (depository + investment), total_liabilities (credit + loan),
  net_worth = assets - liabilities.

Step 2: Get historical balance snapshots.
  Call fincontext stat: SELECT snapshot_date, account_type,
    SUM(current_balance) as balance
    FROM balances
    WHERE snapshot_date >= CURRENT_DATE - INTERVAL '12 months'
    GROUP BY snapshot_date, account_type
    ORDER BY snapshot_date

Step 3: Compute net worth over time.
  For each snapshot date, sum assets and subtract liabilities.
  Calculate: starting net worth, current net worth, absolute change, % change.

Step 4: Identify what's contributing.
  Which account types grew? Which shrank?
  Is the growth from saving (depository up) or investing (investment up)?
  Is debt going down (credit/loan balances decreasing)?

Step 5: Present the trajectory.
  "Your net worth is $X, up $Y (+Z%) over the past 12 months."
  "Most of the growth came from [account type]."
  "Your [debt type] decreased by $A, which contributed $A to your net worth."
  If net worth decreased: be honest, identify the cause, suggest focus areas.

MCP Transport

The /mcp endpoint supports the Streamable HTTP transport (MCP spec 2024-11-05).

Supported methods

Authentication

Bearer token: Authorization: Bearer fc_... or fco_...

Test with MCP Inspector

npx @modelcontextprotocol/inspector

Path 1 — Claude Code (CLI)

Recommended for agents and developers. Works immediately with a fresh fc_ token — no browser session required.

claude mcp add --transport http --scope user fincontext https://fincontext.ai/mcp \
  --header "Authorization: Bearer fc_..."

--scope user makes it available across all projects. Drop it for per-project scope.

Verify: claude mcp list should show fincontext as connected. Then in any Claude Code session, call the status tool and confirm the response includes data.onboarding.

Troubleshooting: if status shows failed, re-run with the correct Authorization header. Token regenerated? Re-add the server.

Path 2 — Claude Desktop & Claude.ai Web (Custom Connector)

Adds FinContext as a Custom Connector via OAuth. Once added in either Claude Desktop or claude.ai, it may sync to the other when you're signed into the same Anthropic account.

  1. Open Claude Desktop or claude.ai → Settings → Connectors → Add custom connector.
  2. Enter https://fincontext.ai/mcp as the remote MCP server URL.
  3. Claude opens FinContext's authorize page in your browser. If you're not signed in yet, an inline login form appears — enter the email and password you used for /api/agent-signup (or the web signup). After login, the consent page shows automatically.
  4. Click Approve. Claude receives an fco_ access token and completes setup.
  5. Verify: open a new chat and ask the agent to list its tools — the 10 FinContext tools (balances, transactions, status, etc.) should appear. Call the status tool and confirm data.onboarding is in the response.

Troubleshooting: if the inline login fails, confirm your credentials against POST /api/agent-login. fco_ tokens expire after 1 hour and auto-refresh automatically — no manual rotation needed.

Free tier: Claude Free includes 1 Custom Connector slot. Pro/Max/Team/Enterprise allow more.

Path 3 — mcp-remote Bridge (Claude Desktop fallback)

For users who prefer file-based config or can't use the Custom Connector. The third-party mcp-remote npm package injects a static fc_ token without OAuth.

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "fincontext": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://fincontext.ai/mcp",
        "--header",
        "Authorization: Bearer fc_..."
      ]
    }
  }
}

Windows: mcp-remote has a known bug parsing args with spaces (the Bearer prefix). Windows users should upgrade to the latest mcp-remote or use Path 1.

Security: this file contains a long-lived credential. Run chmod 600 ~/Library/Application\ Support/Claude/claude_desktop_config.json on macOS. Never commit this file.

Restart Claude Desktop. Verify: ask the agent to call the status tool and confirm data.onboarding is in the response. Troubleshooting: invalid JSON is the most common failure — run jq . < claude_desktop_config.json to validate.

Once Connected (all paths)

Ask the agent to call the link_bank tool. Share the returned hosted_link_url with the user so they complete Plaid Hosted Link in a browser. Then poll the status tool until data.onboarding == "ready". After that, balances, transactions, categories, stat, and all other tools are available.

Token rotation: fc_ tokens are long-lived — if you regenerate one, re-paste it in every Claude Code scope and every claude_desktop_config.json file. fco_ tokens (Path 2) expire hourly and auto-refresh; don't rotate them manually.

Documentation

/llms.txt — Quick-reference for AI agents
/llms-full.txt — Full documentation with all endpoints and parameters