Stocker
by AnkitSurana
README.md
# Stocker
Author: Ankit Surana (ankitsurana002@gmail.com)
A Python MCP server for NSE (Indian stock market) research. Screen stocks
by P/E, momentum, and market cap, get quotes and history, compare a stock
against its sector peers, check watchlist diversification, save alerts,
and pull upcoming corporate events. All data comes from Yahoo Finance (free,
no API key). Everything is a switch in `config.json`: add another data
source later without touching any other file.
## Setup
```
cd stocker-mcp
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
```
That installs `mcp`, `requests`, and `curl_cffi`. The Yahoo provider needs
`curl_cffi` to look like a browser. Without it the server starts but every
data call fails.
Open Claude Desktop, go to Settings, then Developer, then click Edit
Config. Add this entry (use your actual path):
```json
{
"mcpServers": {
"stocker": {
"command": "/absolute/path/to/stocker-mcp/venv/bin/python",
"args": ["/absolute/path/to/stocker-mcp/server.py"]
}
}
}
```
Fully quit and reopen Claude Desktop. Check Settings, then Developer, or
the connectors list, to confirm "stocker" is running.
## A full research session
This is one end-to-end flow: you type plain English on the left, Claude
picks the tool and arguments, and the server returns JSON. The responses
below are real (numbers rounded, some fields trimmed for readability) so
you can see the exact shape of what comes back.
### 1. See what you can screen
> **You:** What NSE indices can you screen?
Calls `list_indices()`:
```json
{ "indices": ["NIFTY 50", "NIFTY NEXT 50", "NIFTY 100", "NIFTY IT",
"NIFTY BANK", "NIFTY AUTO", "NIFTY PHARMA", "NIFTY FMCG",
"NIFTY METAL", "NIFTY ENERGY", "NIFTY REALTY", "NIFTY MEDIA",
"NIFTY FIN SERVICE", "..."] }
```
### 2. Screen an index
> **You:** Screen NIFTY IT for stocks with a P/E under 25.
Calls `screen_stocks(index="NIFTY IT", pe_max=25, max_results=3)`:
```json
{
"index": "NIFTY IT",
"dataSource": "yahoo_finance",
"filters": { "pe_max": 25, "pe_min": null, "min_30d_change_pct": null, "market_cap": "any" },
"matchCount": 3,
"results": [
{ "symbol": "HCLTECH", "lastPrice": 1156.0, "pChange": 0.91, "change30dPct": 0.85, "marketCapBucket": "large", "peRatio": 19.22, "sector": "Technology" },
{ "symbol": "MPHASIS", "lastPrice": 2267.1, "pChange": 1.12, "change30dPct": -3.14, "marketCapBucket": "mid", "peRatio": 24.60, "sector": "Technology" },
{ "symbol": "WIPRO", "lastPrice": 173.6, "pChange": 0.51, "change30dPct": -4.44, "marketCapBucket": "large", "peRatio": 13.84, "sector": "Technology" }
]
}
```
`market_cap` accepts `large` / `mid` / `small` / `any`; add `pe_min` for a
range or `min_30d_change_pct` for a momentum floor.
### 3. Today's movers
> **You:** Who are today's top gainers in NIFTY IT?
Calls `get_top_movers(index="NIFTY IT", direction="gainers", count=3)`
(pass `direction="losers"` for the other end):
```json
{
"index": "NIFTY IT", "direction": "gainers", "dataSource": "yahoo_finance",
"top": [
{ "symbol": "LTTS", "lastPrice": 3210.6, "pChange": 2.21, "perChange30d": -6.06, "marketCapProxy": 34054 },
{ "symbol": "COFORGE", "lastPrice": 1472.7, "pChange": 1.85, "perChange30d": 4.33, "marketCapProxy": 65195 },
{ "symbol": "PERSISTENT", "lastPrice": 4843.9, "pChange": 1.56, "perChange30d": -3.48, "marketCapProxy": 75677 }
]
}
```
(`marketCapProxy` is in ₹ crore; `perChange30d` is the 30-day % move.)
### 4. Quote a stock
> **You:** Get me a quote on TCS.
Calls `get_stock_quote(symbol="TCS")`:
```json
{
"symbol": "TCS", "lastPrice": 2048.5, "change": -9.0, "pChange": -0.44,
"peRatio": 15.34, "sector": "Technology", "eps": 133.53,
"dataSource": "yahoo_finance"
}
```
### 5. Compare against sector peers
> **You:** How does TCS stack up against its IT peers?
Calls `get_peer_comparison(symbol="TCS", max_peers=3)`. It reads TCS's real
sector, pulls the matching sector index, and ranks peers by how close their
P/E is to TCS's:
```json
{
"symbol": "TCS", "sector": "Technology", "peRatio": 15.34,
"peers": [
{ "symbol": "INFY", "lastPrice": 1056.8, "peRatio": 14.04, "pChange": -1.17 },
{ "symbol": "WIPRO", "lastPrice": 173.6, "peRatio": 13.84, "pChange": 0.51 },
{ "symbol": "HCLTECH", "lastPrice": 1155.5, "peRatio": 19.21, "pChange": 0.86 }
]
}
```
### 6. Build and inspect a watchlist
> **You:** Start a watchlist called my_picks with TCS and HDFCBANK.
Two `watchlist_add(list_name="my_picks", symbol=...)` calls give
`{ "my_picks": ["TCS", "HDFCBANK"] }`
> **You:** Is my_picks concentrated in any one sector?
Calls `check_watchlist_diversification(list_name="my_picks")`:
```json
{
"list": "my_picks", "totalSymbols": 2,
"sectorBreakdown": [
{ "sector": "Technology", "count": 1, "pctOfList": 50.0 },
{ "sector": "Financial Services", "count": 1, "pctOfList": 50.0 }
],
"concentrationWarnings": ["No single sector dominates, reasonably diversified"]
}
```
(A sector at ≥40% of the list triggers a concentration warning.)
`watchlist_view(list_name)` shows one list (or all lists if omitted), and
`watchlist_remove(list_name, symbol)` drops a symbol.
### 7. Set and check alerts
> **You:** Alert me if TCS P/E drops below 14.
Calls `add_watchlist_alert(symbol="TCS", condition="pe_below", value=14)`.
Valid conditions: `pe_below`, `pe_above`, `price_below`, `price_above`,
`day_change_above_pct`.
> **You:** Did any of my alerts trigger?
Calls `check_watchlist_alerts()`. It checks every saved alert against live
prices and returns which ones fired:
```json
{ "checked": 1, "triggered": [], "errors": [] }
```
`list_watchlist_alerts()` shows everything you've saved. Pair
`check_watchlist_alerts` with Claude's Scheduled Tasks to get a recurring
check without running your own server.
### 8. Upcoming events
> **You:** Anything coming up for TCS?
Calls `get_upcoming_events(symbol="TCS")`. Each event is tagged `upcoming`
or `past` (Yahoo reports the *most recent* ex-dividend, which is usually
already behind you), and earnings are marked confirmed vs estimated from
Yahoo's own flag, with the consensus EPS/revenue for the quarter:
```json
{
"symbol": "TCS", "dataSource": "yahoo_finance",
"announcements": [
{ "subject": "Earnings date (confirmed)", "date": "2026-07-09", "status": "upcoming",
"consensus": { "epsEstimate": "37.33", "revenueEstimate": "720.42B" }, "attachment": null },
{ "subject": "Ex-dividend date", "date": "2026-05-25", "status": "past", "attachment": null }
]
}
```
### 9. Run a canned strategy
> **You:** What strategies do you have? Run the momentum one.
`list_strategies()` returns `value_picks`, `momentum_picks`,
`large_cap_quality`, `midcap_momentum`. Then
`run_strategy(strategy_name="momentum_picks")` (strong 30-day gainers across
the liquid universe):
```json
{
"strategy": "momentum_picks", "index": "NIFTY 500", "matchCount": 10,
"results": [
{ "symbol": "LODHA", "lastPrice": 1139.85, "change30dPct": 28.37, "marketCapBucket": "large" },
{ "symbol": "PRESTIGE", "lastPrice": 1666.2, "change30dPct": 23.06, "marketCapBucket": "large" },
{ "symbol": "NAUKRI", "lastPrice": 1201.75, "change30dPct": 22.30, "marketCapBucket": "large" }
]
}
```
### 10. Price history
> **You:** Show me TCS daily prices this month.
Calls `get_stock_history(symbol="TCS", start="2026-07-06", end="2026-07-09")`.
Daily OHLCV between two `YYYY-MM-DD` dates:
```json
{
"symbol": "TCS", "dataSource": "yahoo_finance",
"history": [
{ "date": "2026-07-06", "open": 2090.0, "high": 2093.0, "low": 2050.6, "close": 2057.6, "volume": 2567386 },
{ "date": "2026-07-07", "open": 2050.0, "high": 2122.7, "low": 2049.0, "close": 2096.1, "volume": 4769048 },
{ "date": "2026-07-08", "open": 2094.0, "high": 2109.7, "low": 2048.8, "close": 2057.5, "volume": 3666985 },
{ "date": "2026-07-09", "open": 2057.5, "high": 2065.0, "low": 2016.0, "close": 2048.4, "volume": 2574241 }
]
}
```
### Anytime: what's live
> **You:** What data sources are active?
`list_data_sources()` reports every provider, whether it's enabled, and the
priority per capability. Useful for checking what's live without opening
`config.json`.
## More example queries
You don't have to phrase things any particular way. Claude maps natural
language to the right tool and parameters. Variations that all work:
### Screening variations
- "Find me cheap pharma stocks" (screens NIFTY PHARMA with a low P/E cap)
- "Mid-cap stocks in NIFTY 500 that gained at least 10% this month"
- "Large-cap banks with P/E between 10 and 20"
(uses both `pe_min` and `pe_max`)
- "Show me 5 small-cap momentum stocks" (caps `max_results` at 5)
- "Anything in NIFTY METAL under a P/E of 12?"
### Quotes and comparisons
- "TCS price?" (short forms work fine)
- "Is Infosys expensive right now?" (quote, then its P/E vs its sector peers)
- "Compare HDFCBANK to other banks"
- "Which IT stock is closest to TCS in valuation?"
(peer comparison, peers are ranked by P/E proximity)
### Movers and history
- "Biggest losers today" (defaults to NIFTY 500)
- "Top 3 gainers in NIFTY AUTO"
- "How has Reliance moved since June 1st?"
- "TCS price on each day last week"
### Watchlists
- "Start a watchlist called it_bets with TCS, INFY, and WIPRO"
(three `watchlist_add` calls)
- "What's in it_bets?"
- "Drop WIPRO from it_bets"
- "Is my it_bets list too concentrated in one sector?"
### Alerts
- "Tell me if INFY goes above 2000" (`price_above`)
- "Watch for TCS P/E under 22" (`pe_below`)
- "Flag anything in my alerts that moved more than 5% today"
(`day_change_above_pct`)
- "Did any of my alerts trigger?" (evaluates all saved alerts)
### Multi-tool questions
One question can chain several tools. Claude decides the sequence:
- "Screen NIFTY IT for P/E under 25, then add the top 3 to a watchlist
called screen_results"
(`screen_stocks`, then `watchlist_add` three times)
- "Is anything in my_picks reporting results soon?"
(`watchlist_view`, then `get_upcoming_events` per symbol)
- "Compare everything in my_picks against their sector peers"
(`watchlist_view`, then `get_peer_comparison` per symbol)
- "Run the value_picks strategy and alert me if the top result's P/E
drops another 10%"
(`run_strategy`, then `add_watchlist_alert`)
### Analysis on top of the data
The tools return raw data. The reasoning happens in the conversation, so
you can ask follow-ups with no extra tool support needed:
- "Which of these screener results looks most undervalued and why?"
- "Summarize the risk profile of my watchlist in two sentences"
- "Based on the 30 day history, is this stock trending up or
consolidating?"
## Notes
All data comes from `yahoo_finance`, a free source with no API key. It uses
`curl_cffi` to reach Yahoo Finance, which sidesteps the bot blocking you hit
when scraping NSE directly. It serves quotes (price, P/E, sector) and history.
For the screener, movers, and peer-comparison tools it pulls index members
live from the official niftyindices.com CSVs (cached per run), so the lists
stay current across rebalances with nothing hardcoded.
The old providers (`nse_scrape`, `alpha_vantage`, `kite_connect`, `upstox`)
were removed. NSE's site sits behind Akamai and blocks scripts, Alpha Vantage
has no P/E or sector for Indian stocks, and the two broker APIs need a
paid/OAuth setup that was never built. To add a new source, implement the
interface in `providers/base.py`, register it in `providers/manager.py`, and
list it in `config.json`.
## Tests
A regression suite lives in `tests/` (unit tests are hermetic and instant;
integration tests hit the live APIs). Run it after any change:
```
./venv/bin/pip install -r requirements-dev.txt # once
./venv/bin/python -m pytest # all
./venv/bin/python -m pytest -m "not integration" # fast, offline
```
See `tests/README.md` for details.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues