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
-
Create an account —
POST /api/agent-signupcurl -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_nameidentifies the human user.agent_nameis 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 namesagent-default/agent-loginare rejected with a 400.display_nameis capped at 100 characters.Already have an account? Use
POST /api/agent-logininstead: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_nameis 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) orPOST /oauth/tokenwithgrant_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. -
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
fincontexttool with commandlink_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.
-
Confirm connection — Call the
fincontexttool with commandstatus.Returns:
{"data": {"onboarding": "ready", "accounts_linked": true, "num_accounts": 3, "institutions": [...]}}If
data.onboardingis"pending", the user hasn't completed bank linking yet. Wait and retry. -
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.
balances— Get current account balancestransactions— Search and filter transactions by date, category, account, amountcategories— List all available spending categoriesupdate— Override merchant name or category for a transactionstat— Run SQL analytics queries against virtual tableshelp— Show available tools and detailed usagelink_bank— Generate a Plaid Hosted Link URL to connect a bank accountstatus— Check if bank accounts are linkedsync— Pull latest transactions and balances from Plaid (async, returns immediately)feedback— Send bug reports, feature requests, or praise to the FinContext team
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
- Statements: SELECT only (no INSERT, UPDATE, DELETE, DDL)
- Clauses: GROUP BY, HAVING, ORDER BY, LIMIT, WHERE, subqueries, UNION
- Aggregates: SUM, AVG, COUNT, MIN, MAX, STDDEV
- Functions: ROUND, ABS, date_trunc, to_char, EXTRACT, COALESCE, LOWER, UPPER, TRIM, LENGTH
- Restrictions: No CTEs (WITH), no self-joins, no system tables, no pg_* functions
- Limits: 1000 rows max, 5-second timeout, 500 KB response cap
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?":
- Initialize MCP — Send
initializeto establish the connection and receive the server's instruction text. - Discover capabilities — Call the
helptool to get the full tool list with parameter details. - Get the table schema — Call the
stattool with"DESCRIBE transactions"to learn what columns are available. -
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" }} -
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" }} - 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
POST /mcp— JSON-RPC 2.0 requests. Returnsapplication/jsonby default, ortext/event-stream(SSE) when the client sendsAccept: text/event-stream.GET /mcp— Returns 405 (no server-initiated notifications).DELETE /mcp— Returns 200 (sessionless).
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.
- Open Claude Desktop or claude.ai → Settings → Connectors → Add custom connector.
- Enter
https://fincontext.ai/mcpas the remote MCP server URL. - 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. - Click Approve. Claude receives an
fco_access token and completes setup. - Verify: open a new chat and ask the agent to list its tools — the 10 FinContext tools (
balances,transactions,status, etc.) should appear. Call thestatustool and confirmdata.onboardingis 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