mdd-stock-mcp
An MCP server for Maximum Drawdown (MDD) analytics across US stocks, Korean stocks (KOSPI/KOSDAQ), and cryptocurrencies. Plug it into Claude Desktop and ask questions like "What was SPY's worst drawdown during COVID?" or "비트코인 2022년 MDD 알려줘" — Claude will fetch the data and discuss it conversationally.
Disclaimer: This project uses yfinance, an unofficial Yahoo Finance scraper. Not affiliated with Yahoo, not for production trading systems, not for financial advice. Data may be inaccurate, delayed, or unavailable. Use at your own risk.
What it does
- Calculates Maximum Drawdown for any supported asset over a date range
- Returns OHLCV price history for plotting
- Returns a daily drawdown (underwater) series
- Compares MDD across multiple tickers side-by-side
Supported markets (via the market parameter):
market |
Examples | Notes |
|---|---|---|
us (default) |
AAPL, SPY, QQQ |
NYSE / NASDAQ |
kr |
005930 → 005930.KS (Samsung), 035720.KQ (KOSDAQ) |
6-digit codes auto-append .KS (KOSPI). Use explicit .KQ for KOSDAQ. |
crypto |
BTC → BTC-USD, ETH-USD, BTC-KRW |
Bare symbols auto-append -USD. |
Quickstart (Claude Desktop)
1. Clone the repo:
git clone https://github.com/librarywon/mdd-stock-mcp.git
cd mdd-stock-mcp
2. Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"mdd-stock-mcp": {
"command": "uvx",
"args": ["--from", "/absolute/path/to/mdd-stock-mcp", "mdd-stock-mcp"]
}
}
}
Replace /absolute/path/to/mdd-stock-mcp with the actual path where you cloned the repo (e.g. /Users/yourname/Documents/mdd-stock-mcp).
3. Restart Claude Desktop.
Ask: "Using mdd-stock-mcp, what was AAPL's MDD between 2020-01-01 and 2020-12-31?"
Alternative install (after PyPI publishing)
uvx mdd-stock-mcp
(Placeholder — not yet published to PyPI.)
Tools
| Tool | Description | Example |
|---|---|---|
calculate_mdd |
Single-ticker MDD | calculate_mdd("SPY", "2020-01-01", "2020-12-31") |
get_price_history |
OHLCV time series | get_price_history("005930", "2024-01-01", "2024-06-30", market="kr") |
get_drawdown_series |
Daily drawdown % series | get_drawdown_series("BTC", "2022-01-01", "2022-12-31", market="crypto") |
compare_mdd |
Multi-ticker MDD comparison | compare_mdd(["SPY","QQQ","DIA"], "2020-01-01", "2020-12-31") |
Each tool accepts:
price:"adj_close"(default, dividend/split adjusted) or"close"(raw closing price)market:"us"(default),"kr", or"crypto"— see the supported markets table
Output schemas
calculate_mdd — success response
{
"ticker": "SPY",
"mdd_pct": -0.338915,
"peak_date": "2020-02-19",
"trough_date": "2020-03-23",
"drawdown_duration_days": 33,
"recovered": false,
"recovery_date": null,
"market": "us",
"currency": "USD"
}
calculate_mdd — error response
{
"error": true,
"error_type": "InvalidTickerError",
"message": "InvalidTickerError: Ticker 'XYZFAKE' not found or returned no data from Yahoo Finance."
}
get_price_history — success response
{
"ticker": "AAPL",
"price_basis": "adj_close",
"count": 62,
"data": [
{
"date": "2020-01-02",
"open": 296.239990,
"high": 300.600006,
"low": 295.190002,
"close": 298.829956,
"volume": 33870100
}
]
}
get_drawdown_series — success response
{
"ticker": "SPY",
"price_basis": "adj_close",
"count": 125,
"data": [
{"date": "2020-01-02", "drawdown_pct": 0.0},
{"date": "2020-01-03", "drawdown_pct": -0.007054},
{"date": "2020-03-23", "drawdown_pct": -0.338915}
]
}
compare_mdd — success response (partial failure shown)
{
"price_basis": "adj_close",
"start": "2020-01-01",
"end": "2020-06-30",
"results": [
{
"ticker": "SPY",
"mdd_pct": -0.338915,
"peak_date": "2020-02-19",
"trough_date": "2020-03-23",
"drawdown_duration_days": 33,
"recovered": false,
"recovery_date": null,
"error": null
},
{
"ticker": "XYZFAKE",
"mdd_pct": null,
"peak_date": null,
"trough_date": null,
"drawdown_duration_days": null,
"recovered": null,
"recovery_date": null,
"error": "InvalidTickerError: Ticker 'XYZFAKE' not found or returned no data from Yahoo Finance."
}
]
}
How MDD is calculated
- Formula:
drawdown_t = price_t / max(price_{0..t}) - 1 - MDD =
min(drawdown)over the date range (most negative value) - Peak: argmax of price up to and including the trough date
- Recovery: first date after trough where
price >= peak_price - Note:
recovered=falsemeans "did not recover within the queried window", not "never recovered historically"
All price values use dividend/split-adjusted close by default (price="adj_close"). Pass price="close" for raw unadjusted closing prices.
Example Claude conversation
User: mdd-stock-mcp으로 SPY의 2020년 코로나 폭락 분석해줘
Claude: [calls calculate_mdd] SPY는 2020-02-19 최고점에서 2020-03-23 최저점까지 약 -33.9%의 MDD를 기록했습니다. 회복은 2020-08-18에 완료됐어요. 그래프 그려드릴까요?
User: 응
Claude: [calls get_price_history + get_drawdown_series, draws chart in artifact]
Limitations
- US stocks, Korean stocks (KOSPI/KOSDAQ), and major cryptocurrencies — limited to what Yahoo Finance exposes. Other international exchanges (Tokyo, London, etc.) aren't wired up.
- Daily resolution — No intraday (1m, 5m, etc.) data.
- yfinance is unofficial — Yahoo Finance may rate-limit or change their API without notice. For production use, swap
data.pyfor a paid provider like Polygon.io, Alpha Vantage, or Tiingo. - In-memory cache only — Price data is cached for 5 minutes per process. Cache is lost on server restart.
- No real-time data — All data is end-of-day historical prices.
Development
# Install with dev dependencies
uv pip install -e ".[dev]"
# Run tests
pytest tests/
# Open MCP inspector (interactive tool tester)
fastmcp dev src/stock_mcp/server.py
Project structure:
src/stock_mcp/
server.py — FastMCP app + 4 tool definitions
data.py — yfinance wrapper + TTL cache + price-column selector
mdd.py — Pure MDD math functions
models.py — Pydantic input/output models
errors.py — Custom error types
tests/
test_mdd.py — Offline math tests (no network required)
Claude Desktop config reference
{
"mcpServers": {
"mdd-stock-mcp": {
"command": "uvx",
"args": ["--from", "/Users/jaewon/Documents/mdd-stock-mcp", "mdd-stock-mcp"]
}
}
}
After publishing to PyPI, simplify to:
{
"mcpServers": {
"mdd-stock-mcp": {
"command": "uvx",
"args": ["mdd-stock-mcp"]
}
}
}
Deployment
Local (stdio) — default
The default transport is stdio, which is what Claude Desktop expects. Use the uvx config from the Quickstart section above.
Docker
# Build the image
docker build -t mdd-stock-mcp .
# Run with HTTP transport (e.g. for testing or a hosted setup)
docker run -p 8000:8000 mdd-stock-mcp --transport http
Replace 8000 with any port you prefer. The --transport http flag enables the HTTP/SSE transport mode; omit it for the default stdio mode.
Smithery / hosted
Smithery can host MCP servers so you don't need to run them locally. Once the smithery.yaml configuration is present in the repo root, you can register the server through the Smithery dashboard. See the Smithery documentation for registration instructions.
Roadmap
Planned additions (not yet scheduled — PRs welcome):
- Sharpe / Sortino / CAGR tools — additional risk/return metrics as new MCP tools, following the same patterns as the existing four.
- Optional Polygon.io / Alpha Vantage providers — drop-in replacements for the yfinance backend in
data.py, configurable via environment variable. - Shorter date ranges / intraday support — hourly or intraday resolution for ranges under ~7 days, contingent on a stable data provider.
Contributing
This is a small focused project. PRs are welcome — especially for:
- Additional data providers (Polygon, Alpha Vantage, Tiingo) in
data.py - Additional metrics (Sharpe ratio, CAGR, Sortino) as new tools
- Better error messages and edge-case handling
Please open an issue first for significant changes.
License
MIT — see LICENSE
Metadata
Release files for mdd-stock-mcp 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mdd_stock_mcp-0.1.0.tar.gz | 112.5 kB | With provenance | Details for mdd_stock_mcp-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mdd_stock_mcp-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for mdd_stock_mcp-0.1.0-py3-none-any.whl |
Total release size: 126.5 kB
Release files / mdd_stock_mcp-0.1.0.tar.gz
| Download URL | mdd_stock_mcp-0.1.0.tar.gz |
|---|---|
| Size | 112.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e0efcb5d2c67e45f35030a03ae13274050d830807f7d174e856d12519112e2b4
|
|
BLAKE2b-256 checksum How to use checksums |
aea0d674acc4521ec28742ba963b0cc78c7fab50e75a260886d506bc83db0d83
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 30, 2026.
Transparency logRelease files / mdd_stock_mcp-0.1.0-py3-none-any.whl
| Download URL | mdd_stock_mcp-0.1.0-py3-none-any.whl |
|---|---|
| Size | 14.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
621c29ef87d1931ab570aaf6807d580675d93b966c5332d69ca9a79bb59bf478
|
|
BLAKE2b-256 checksum How to use checksums |
f6fc7d5238c29edc16a4d365cd5d51d7c80c577fa841ef8c63dd2024ce539fa0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 30, 2026.
Transparency logSecurity for mdd-stock-mcp 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for mdd_stock_mcp-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 30, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.