MCP Finance Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@MCP Finance Serverlist top gainers on Swedish market"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Finance Server
MCP server for market data, fundamentals, screener analytics, options analytics, and Wheel strategy workflows.
This project combines:
Interactive Brokers (real-time market connectivity)
Yahoo Finance (broad coverage for fundamentals/history)
Local ELT pipeline (normalized + cached tables for reliable LLM queries)
Default market for LLM-facing analytics is sweden.
Core Goals
Stable, LLM-friendly tools with explicit defaults and predictable response envelopes.
Reliable cached analytics from local DB first, with controlled fallbacks.
Fast answers for practical trading questions (screener, options, Wheel).
Clear data lineage from raw ingestion to curated analytics tables.
Why This Server vs Others
IBKR real-time + Yahoo + local curated cache (not only direct Yahoo API reads).
Wheel-first toolset (put selection, capacity, assignment flow, covered call continuation).
Options with greeks + option metrics snapshots for IV and screening.
Event risk modeling focused on Wheel impact windows.
Local pipeline with deterministic serial jobs and MCP-friendly discovery tools.
End-to-end Example 1 (Wheel Put Selection)
get_wheel_put_candidates(symbol='Nordea', market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)analyze_wheel_put_risk(symbol='Nordea', pct_below_spot=5.0, target_dte=7)get_wheel_contract_capacity(symbol='Nordea', capital_sek=200000, market='sweden')
End-to-end Example 2 (Event Risk Window)
get_wheel_event_risk_window(ticker='NDA-SE.ST', market='sweden', days_ahead=14)get_corporate_events(ticker='NDA-SE.ST', market='sweden')get_monetary_policy_events(market='sweden')
Architecture
MCP-Finance-Server/
├── mcp_server.py # MCP tool registry and entrypoint
├── services/
│ ├── market_service.py # Price lookup and symbol resolution
│ ├── option_service.py # IB option chain + greeks
│ ├── option_screener_service.py # Cached option metrics queries
│ ├── screener_service.py # Stock screener + rankings
│ ├── classification_service.py # Sector/subsector/core business/earnings
│ ├── wheel_service.py # Wheel analytics (puts, calls, risk, stress)
│ └── job_service.py # ELT job controls
├── dataloader/
│ ├── models.py # SQLAlchemy models
│ ├── seed.py # DB seed + default jobs
│ ├── scheduler.py # Cron-like job runner
│ └── scripts/ # Extract/transform/curation scripts
└── README.mdData Model Highlights
Key normalized/curated tables used by MCP tools:
stocks,realtime_prices,historical_pricesfundamentals,dividendsstock_metrics,market_moversoption_metricsoption_iv_snapshots(IV history snapshots from option metrics)exchanges,market_indicessector_taxonomy,industry_taxonomy,subindustry_taxonomystock_classification_snapshots,company_profilesraw_earnings_events,earnings_eventsraw_market_events,market_eventsstock_intelligence_snapshots(local cache for news/holders/recommendations/statements)
MCP Tool Groups
Market and Fundamentals
get_stock_price(symbol, exchange=None, currency='USD')get_historical_data(symbol, duration='1 D', bar_size='1 hour', exchange=None, currency='USD')get_historical_data_cached(symbol, period='1y', interval='1d')search_symbol(query)get_fundamentals(symbol)get_dividends(symbol)get_dividend_history(symbol, period='2y')get_company_info(symbol)get_financial_statements(symbol)get_comprehensive_stock_info(symbol)get_exchange_info(symbol)yahoo_search(query)
Notes:
get_stock_price,get_historical_data,search_symbol,get_option_chain, andget_option_greeksare DB-first (pipeline-backed snapshots).IB live connection remains required for account/portfolio endpoints and ingestion jobs.
IB Account and Portfolio
get_account_summary(masked=True)Resource:
finance://account/summary(masked by default)Resource:
finance://portfolio/positions
Stock Screener
get_stock_screener(market='sweden', sector=None, sort_by='perf_1d', limit=50)get_top_gainers(market='sweden', period='1D', limit=10)get_top_losers(market='sweden', period='1D', limit=10)get_most_active_stocks(market='sweden', period='1D', limit=10)get_top_dividend_payers(market='sweden', sector=None, limit=10)get_technical_signals(market='sweden', signal_type='oversold', limit=20)get_highest_rsi(market='sweden', limit=10)get_lowest_rsi(market='sweden', limit=10)get_fundamental_rankings(market='sweden', metric='market_cap', limit=10, sector=None)
Classification and Earnings
get_companies_by_sector(market='sweden', sector=None, industry=None, subindustry=None, limit=50)get_company_core_business(symbol)get_earnings_events(symbol=None, market='sweden', upcoming_only=False, limit=20)
Options (Cached + Live)
get_option_chain(symbol)get_option_greeks(symbol, last_trade_date, strike, right)get_option_screener(symbol=None, expiry=None, right=None, min_delta=None, max_delta=None, min_iv=None, max_iv=None, has_liquidity=True, limit=50)get_option_chain_snapshot(symbol, expiry=None)get_options_data(symbol, expiration_date=None)
Market Intelligence (Local Cache)
get_news(symbol, limit=10)get_institutional_holders(symbol, limit=50)get_analyst_recommendations(symbol, limit=50)get_technical_analysis(symbol, period='1y')get_sector_performance(symbols)
Wheel Strategy Tools
get_wheel_put_candidates(symbol, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10, limit=5, require_liquidity=True)get_wheel_put_annualized_return(symbol, market='sweden', target_dte=7)get_wheel_contract_capacity(symbol, capital_sek, market='sweden', strike=None, margin_requirement_pct=1.0, cash_buffer_pct=0.0, target_dte=7)analyze_wheel_put_risk(symbol, market='sweden', pct_below_spot=5.0, target_dte=7)get_wheel_assignment_plan(symbol, assignment_strike, premium_received, market='sweden')get_wheel_covered_call_candidates(symbol, average_cost, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=21, min_upside_pct=1.0, limit=5)compare_wheel_premiums(symbol_a, symbol_b, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)evaluate_wheel_iv(symbol, market='sweden', lookback_days=90, high_iv_threshold_percentile=70.0, target_dte=7)simulate_wheel_drawdown(symbol, strike, premium_received, drop_percent=10.0, market='sweden')compare_wheel_start_timing(symbol, market='sweden', wait_drop_percent=3.0, delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)build_wheel_multi_stock_plan(capital_sek, symbols=None, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10, margin_requirement_pct=1.0, cash_buffer_pct=0.10)stress_test_wheel_portfolio(capital_sek, sector_drop_percent=20.0, symbols=None, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)
Event Calendar Tools
get_event_calendar(market='sweden', category=None, event_type=None, ticker=None, start_date=None, end_date=None, min_volatility_impact='low', limit=50)get_corporate_events(market='sweden', ticker=None, start_date=None, end_date=None, min_volatility_impact='low', limit=50)get_macro_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)get_monetary_policy_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)get_geopolitical_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)get_market_structure_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)get_wheel_event_risk_window(ticker, market='sweden', days_ahead=14, limit=100)
Local Cached DB Tools
get_earnings_history(symbol, limit=10)get_earnings_calendar(symbol)query_local_stocks(country=None, sector=None)query_local_fundamentals(symbol)
Job and Pipeline Management
list_jobs()get_job_logs(job_name, limit=5)trigger_job(job_name)toggle_job(job_name, active)get_job_status()run_pipeline_health_check()
Capability Discovery
get_market_capabilities()Returns grouped capabilities (
methods+examples) so an LLM can answer "what can you do?" with concrete actions.
describe_tool(tool_name)Returns parameter schema (types/defaults), Pydantic JSON schema (when available), docstring summary and examples for one tool.
help_tool(tool_name)Alias for
describe_tool, useful for agents that ask forhelp.
get_server_health()Returns health payload equivalent to
/health.
get_server_metrics(output_format='json'|'prometheus')Returns metrics payload equivalent to
/metrics.
Health and Metrics Resources
Resource:
finance://statusResource:
finance://healthResource:
finance://metrics
LLM Service Design Rules
Use these rules when adding/updating tools so other agents can depend on stable behavior.
Prefer intent-specific tools over mega-tools.
Keep safe defaults (
market='sweden', low-risklimit, bounded windows).Clamp limits and normalize known enum-style fields.
Return explicit
criteriaandempty_reasonfor zero-result queries.Empty result is not a system error (
success=true,data=[]).Include
as_of_dateoras_of_datetimewhen data is snapshot-based.Do not fabricate unavailable backend data; return uncertainty or insufficient-data states.
Keep response keys stable; avoid breaking renames.
Keep table schema stable when possible; evolve at query/service layer.
Protect admin endpoints with API key and strict script-path validation.
Agent Directives (MCP-friendly)
Use these directives when wiring another AI agent to this server:
Start by calling
get_market_capabilities()for intent routing.For unknown tools, call
describe_tool(tool_name)before execution.Prefer intent-specific tools over broad queries.
Always use explicit market defaults (
market='sweden') unless user overrides.Respect uncertainty: if backend has no data, return insufficient-data response.
Never infer timestamps; use
meta.asoffrom tool responses.In Yahoo-only mode (
IB_ENABLED=false), avoid IB tools and fallback to local/Yahoo tools.For sensitive info, keep
get_account_summary(masked=True)unless user explicitly requests otherwise in trusted environment.If a tool returns
validation_error, fix input and retry once with corrected parameters.If a source is open-circuited (
circuit_open), avoid repeated retries until cooldown.
Event Modeling Rules
Use unified events in market_events with this minimum contract:
Identification:
event_id,event_type,category,subtypeTime:
event_datetime_utc,timezone,market,is_market_hours,is_pre_market,is_after_marketScope:
ticker,sector,country,region,affected_marketsImpact:
expected_volatility_impact,systemic_risk_level,is_recurring,confidence_scoreSpecific data:
expected_eps,previous_eps,expected_revenue,previous_value,forecast_value,actual_value
Supported categories:
corporatemacromonetary_policygeopoliticalmarket_structure
Stable Response Envelope
Preferred shape:
{
"success": true,
"data": {},
"error": {
"code": null,
"message": null,
"details": null
},
"meta": {
"source": "ibkr|yahoo|local_db|pipeline|system|...",
"asof": "2026-02-13T12:34:56.000000+00:00",
"cache_ttl": null,
"request_id": "uuid",
"default_market": "sweden",
"market_timezone": "Europe/Stockholm"
}
}Notes:
The envelope is normalized in
mcp_server.py(tool_endpointdecorator).Existing service-specific keys (
count,criteria, etc.) are preserved.
Wheel Analytics Formulas
Used in wheel_service.py and exposed by MCP tools:
Put period return (%) =
(premium / strike) * 100Annualized return (%) =
period_return * (365 / DTE)Cash-secured capital per contract =
strike * 100Capacity =
floor((capital * (1-cash_buffer_pct)) / (strike * 100 * margin_requirement_pct))Break-even (short put) =
strike - premiumAssignment probability proxy =
abs(delta)Drawdown scenario at expiry =
max(0, break_even - final_price)
Notes:
abs(delta)is a proxy, not a true probability model.Timing comparison tools return scenario analysis with explicit uncertainty (no forecasts).
Data Pipeline Jobs (Key)
Major jobs in dataloader/seed.py include:
Raw ingestion: Yahoo prices/fundamentals, IBKR prices, IBKR instruments, option metrics.
Normalization: prices, fundamentals, classification taxonomy, company profiles.
Curation: earnings events.
Analytics: stock metrics, market movers, option IV snapshots, event calendar.
Intelligence cache: news, institutional holders, analyst recommendations, financial statements snapshots.
Loaders: stock list, reference data, dividends, historical prices, index performance.
Validation: pipeline health check.
Seed behavior (python -m dataloader.seed):
Idempotent sync of default jobs: missing jobs are created and existing jobs are updated (description/script/cron/timeout/tables) without duplicating rows.
Full first load runs by default and always in serial (no parallel job execution).
Load order is phase-based to maximize robustness:
MASTER: reference/tickers/raw+transform/history/dividends/earnings/classification.IB: IBKR extractors/options (still serial, can be skipped).COMPUTE: metrics/movers/events/intelligence snapshots.
First-load dataset includes:
historical prices (5y),
dividends (5y),
earnings (10y) + curation,
classification normalization + company profile enrichment,
stock metrics + market movers,
normalized event calendar generation.
market intelligence snapshots.
Built-in fallback: if screener baseline remains empty, it retries historical load + metrics/movers.
Optional flags:
--skip-first-load: only init DB + sync jobs.--skip-ib: skip IB-dependent steps during first load.--warmup: deprecated alias (first load is already default).
Quick Start
5-minute onboarding (plug-and-play)
pip install -e .
python -m dataloader.seed --skip-ib
IB_ENABLED=false mcp-financeThen point your MCP client to this server (examples below).
Docker
docker compose up -d
docker compose --profile init run seedLocal
pip install -e .
python -m dataloader.seed
mcp-finance
python -m dataloader.appRuntime Profiles
Yahoo-only:IB_ENABLED=falseNo IB connection attempt on startup.
IB tools return structured
ib_disablederrors.
IBKR + Yahoo:IB_ENABLED=true(default)Requires IB Gateway/TWS connectivity and market data permissions.
Environment Variables (Reference)
IB_ENABLED:true|false(defaulttrue)
MCP_TRANSPORT:sse|stdio(defaultsse)
MCP_HOST:default
0.0.0.0
MCP_PORT:default
8000
DEFAULT_MARKET:default
sweden
DEFAULT_MARKET_TIMEZONE:default
Europe/Stockholm
MCP_TOOL_ALLOWLIST:comma-separated tool names; if set, only listed tools are callable
CIRCUIT_BREAKER_FAILURE_THRESHOLD:default
4
CIRCUIT_BREAKER_COOLDOWN_SECONDS:default
45
MCP Client Config Examples
Claude Desktop
{
"mcpServers": {
"finance": {
"command": "mcp-finance",
"env": {
"IB_ENABLED": "false",
"DEFAULT_MARKET": "sweden",
"DEFAULT_MARKET_TIMEZONE": "Europe/Stockholm"
}
}
}
}Cursor
{
"mcp": {
"servers": {
"finance": {
"command": "mcp-finance",
"args": [],
"env": {
"IB_ENABLED": "true",
"MCP_TRANSPORT": "stdio"
}
}
}
}
}Windsurf
{
"mcpServers": [
{
"name": "finance",
"command": "mcp-finance",
"env": {
"IB_ENABLED": "false"
}
}
]
}Minimal Python Agent
import os
import subprocess
env = os.environ.copy()
env["IB_ENABLED"] = "false"
proc = subprocess.Popen(["mcp-finance"], env=env)
print("MCP Finance server PID:", proc.pid)Security Notes
Set
DATALOADER_API_KEYfor admin API endpoints.Keep
DATALOADER_ALLOW_INSECURE=trueonly in local development.Configure CORS with
DATALOADER_ALLOWED_ORIGINS.Optional tool allowlist: set
MCP_TOOL_ALLOWLIST=get_market_capabilities,describe_tool,....Account summary is masked by default (
get_account_summary(masked=true)).If running MCP over network transport (
MCP_TRANSPORT=sse), keep host/firewall restricted and use API/auth controls on your MCP client gateway.
Threat Model (What this server does NOT do)
Does not place orders.
Does not modify positions.
Does not submit trades.
Does not transfer funds.
Does not provide guaranteed forecasts.
Read-only by design: analytics, screening, events, account inspection, and pipeline control only.
Observability and Operations
get_server_health()and resourcefinance://healthget_server_metrics(output_format='json'|'prometheus')and resourcefinance://metricsStructured JSON logs per tool call (
request_id, tool, source, latency, success)Circuit breaker by source (IBKR/Yahoo/local groups) with cooldown
Built-in tool-level metrics: calls/failures/avg latency/source breakdown
Rate limiter metrics exposed via IB connection runtime snapshot
Code Quality and Releases
pre-commithooks configured (ruff,black,isort,mypy)GitHub Actions CI (
.github/workflows/ci.yml) running lint, type-check and testsRecommended release flow:
bump
versioninpyproject.tomlcreate git tag (
vX.Y.Z)update changelog/release notes
Operational Notes
If screener returns empty, run:
Historical Prices LoaderCalculate Stock MetricsUpdate Market Movers
If Wheel IV analysis reports insufficient history, run option metrics jobs and
Snapshot Option IVfor multiple days.If option greeks are sparse, ensure IB market data permissions and option subscriptions are active.
For macro/monetary/geopolitical events, maintain
dataloader/data/manual_events.jsonand runLoad Event Calendar.To refresh local news/holders/recommendations/statements cache, run
Load Market Intelligence.To avoid duplicate manual runs, backend and frontend both protect against concurrent triggers for the same job:
backend returns
"Job '<name>' is already queued/running"when an open run exists,frontend disables the run button while request is in flight.
Scheduler execution model is now a single-worker queue:
all cron/manual triggers are enqueued with
status='queued',only one job runs at a time globally,
same job is deduplicated while already
queued/running.on scheduler startup, orphan
queued/runningruns are auto-recovered tofailed.
Jobs UI uses in-app notifications/toasts and confirmation modal (no browser
alert()flow).
Troubleshooting
Error during metrics seed like
operands could not be broadcast together with shapes (29,) (30,):fixed by using robust return series (
pct_change) in volatility calculation instead of brittle array slicing.ensure you are on commit
4d0292for newer.
If seed fails due missing deps locally, install project dependencies first:
pip install -e .
License
MIT
This server cannot be installed
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/douglashiga/MCP-Finance-Server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server