Content
# Indian NSE Stock Insights 🇮🇳📈
Public MCP server for Indian stock market analysis — **Nifty 500 universe**, **12 tools**, **3 timeframes**.
Built with [FastMCP](https://github.com/jlowin/fastmcp) · Data from [yfinance](https://github.com/ranaroussi/yfinance) · Hosted at `stockmcp.alokbarnwal.com`
> **Educational only. Not investment advice.** See [DISCLAIMER.md](DISCLAIMER.md).
---
## Quick Connect — 30 Seconds
**Claude.ai** → Settings → Connectors → Add custom MCP connector:
```
Name: Indian NSE Stock Insights
URL: https://stockmcp.alokbarnwal.com/mcp
```
That's it. Start asking questions about Indian stocks.
---
## 12 Tools
| # | Tool | Parameters | What it returns |
|---|------|-----------|-----------------|
| 1 | `get_stock_quote` | `symbol` | Last close, prev close, change %, day H/L, volume |
| 2 | `get_ohlc_data` | `symbol`, `timeframe?`, `limit?` | OHLCV candles (up to 500, newest first) |
| 3 | `get_technical_indicators` | `symbol`, `timeframe?` | EMAs, SMAs, RSI, MACD, Bollinger, ADX, Stoch, ATR, OBV, VWAP |
| 4 | `get_support_resistance` | `symbol`, `timeframe?` | Pivot points + historical S/R levels |
| 5 | `get_demand_supply_zones` | `symbol`, `timeframe?`, `status?` | Demand/supply zones (DBR/RBR/RBD/DBD) |
| 6 | `get_candlestick_patterns` | `symbol`, `timeframe?`, `limit?` | HAMMER, DOJI, ENGULFING, etc. |
| 7 | `get_chart_patterns` | `symbol`, `timeframe?`, `status?` | DOUBLE_TOP, HEAD_AND_SHOULDERS, etc. |
| 8 | `get_fibonacci_levels` | `symbol`, `timeframe?` | Retracement swings (UP/DOWN) with fib levels |
| 9 | `get_volume_analysis` | `symbol` | 5min hotspots, OBV trend, volume ratio |
| 10 | `get_market_overview` | *(none)* | Indices, top gainers/losers, most active, breadth |
| 11 | `compare_stocks` | `symbols` (2-5) , `timeframe?` | Side-by-side: quote, RSI/MACD/ADX, trend, 30d return |
| 12 | `screen_stocks` | `filters` | Filter by RSI, ADX, trend, pattern, sector, etc. |
`timeframe` defaults to `daily`. Options: `daily`, `15min`, `5min`.
---
## Example Prompts
Try these in Claude.ai after connecting:
- *"RELIANCE ka technical analysis do — RSI, MACD, aur support/resistance levels batao"*
- *"Show me Nifty 500 stocks with RSI below 30 and ADX above 25"*
- *"Compare TCS, INFY, and WIPRO — which one has the best setup right now?"*
- *"What does the overall market look like today? Show me top gainers and losers"*
- *"HDFC Bank ke demand and supply zones dikhao on the 15-minute chart"*
---
## Architecture
```mermaid
graph TB
subgraph Internet
C[Claude.ai / MCP Client]
end
subgraph Server["Production Server"]
subgraph Protection
F2B[fail2ban<br/>auto-ban repeat abusers]
NG[nginx<br/>rate limit 20r/s · conn limit · TLS]
end
subgraph Application
MCP["FastMCP Server<br/>port 8089 · 12 tools"]
TOOLS["Tool Modules<br/>quote · ohlc · indicators<br/>levels · zones · patterns<br/>fibonacci · volume · market<br/>compare · screener"]
end
subgraph Data
DB[(MySQL: nse_public<br/>500 stocks × 3 timeframes)]
CRON[Cron Jobs<br/>5min · 15min · daily]
end
end
subgraph External
YF[Yahoo Finance<br/>yfinance API]
end
C -->|HTTPS POST /mcp| NG
NG -->|proxy_pass| MCP
MCP --> TOOLS
TOOLS -->|read-only queries| DB
YF -->|OHLCV data| CRON
CRON -->|upsert| DB
F2B -.->|monitors| NG
```
---
## Data Coverage
| Timeframe | Retention | Update Frequency | Stocks |
|-----------|-----------|-----------------|--------|
| Daily | 5 years | EOD (18:00 IST) | 500 |
| 15-minute | 2 years | Every 15 min (market hours) | 500 |
| 5-minute | 6 months | Every 5 min (market hours) | 500 |
Market hours: 09:15–15:30 IST, Monday–Friday (excluding NSE holidays).
---
## Rate Limits
| Layer | Limit | Action |
|-------|-------|--------|
| nginx | 20 requests/sec per IP (burst 40) | HTTP 429 |
| nginx | 10 simultaneous connections per IP | HTTP 429 |
| fail2ban | 5× rate-limit violations in 2 min | IP banned for 1 hour |
---
## Self-Hosting
<details>
<summary><strong>Click to expand — full deployment runbook</strong></summary>
> Runs on `/home/ubuntu/nse-public-mcp/` — completely isolated from `/home/ubuntu/swingtrader/`.
### 1. Clone
```bash
cd /home/ubuntu
git clone https://github.com/alokbarnwal/nse-public-mcp.git
cd nse-public-mcp
```
### 2. Create database and user
```bash
sudo mysql <<'SQL'
CREATE DATABASE IF NOT EXISTS nse_public CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER IF NOT EXISTS 'nse_writer'@'localhost' IDENTIFIED BY 'CHANGE_ME_STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON nse_public.* TO 'nse_writer'@'localhost';
FLUSH PRIVILEGES;
SQL
```
### 3. Apply schema
```bash
mysql -u nse_writer -p nse_public < db/schema.sql
mysql -u nse_writer -p nse_public < db/schema_indicators.sql
mysql -u nse_writer -p nse_public < db/schema_price_action.sql
```
### 4. Install dependencies
```bash
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```
### 5. Configure environment
```bash
cp .env.example .env
chmod 600 .env
nano .env # set DB_PASSWORD to match step 2
```
### 6. (Optional) Refresh full Nifty 500 list
The repo ships with the top ~100 stocks hardcoded. To expand to all 500:
```bash
python -m config.stocks --refresh # fetches NSE archives, rewrites config/stocks.py
```
### 7. Load stock universe into DB
```bash
python -m config.stocks --load-to-db
```
### 8. Backfill historical data (long-running, use screen/tmux)
```bash
screen -S backfill
source .venv/bin/activate
python -m data.backfill --all
# Ctrl-A D to detach. Reattach: screen -r backfill
```
Expected runtime:
- `daily 5y × 500`: ~30 min
- `15min 2y × 500`: ~2 h
- `5min 6mo × 500`: ~1 h
If anything fails, the failure list is written to `backfill_failures_<timeframe>.json`. Re-run:
```bash
python -m data.backfill --timeframe 15min --resume
```
### 8b. Bulk-compute indicators (long-running, use screen/tmux)
After the candle backfill completes, populate the `indicators` table for all 500 stocks across all 3 timeframes:
```bash
screen -S indicators
cd /home/ubuntu/nse-public-mcp
python3 -m indicators.runner --all
# Ctrl-A D to detach
```
Expected runtime: ~30–45 min. Idempotent — safe to re-run if interrupted.
### 8c. Bulk-compute price action (long-running, use screen/tmux)
After indicators are populated, compute price-action features (zones, S/R,
patterns, breakouts, fibs, gaps, volume profile) for all 500 stocks across
all 3 timeframes:
```bash
screen -S price_action
cd /home/ubuntu/nse-public-mcp
python3 -m price_action.runner --timeframe daily --all-features
python3 -m price_action.runner --timeframe 15min --all-features
python3 -m price_action.runner --timeframe 5min --all-features
# Ctrl-A D to detach
```
Expected runtime: ~60–90 min total. Idempotent — safe to re-run if interrupted.
### 9. Install crontab
```bash
crontab -e
```
Add:
```cron
# nse-public-mcp candle updaters
*/5 9-15 * * 1-5 cd /home/ubuntu/nse-public-mcp && /home/ubuntu/nse-public-mcp/.venv/bin/python -m jobs.cron_5min >> logs/cron_5min.log 2>&1
*/15 9-15 * * 1-5 cd /home/ubuntu/nse-public-mcp && /home/ubuntu/nse-public-mcp/.venv/bin/python -m jobs.cron_15min >> logs/cron_15min.log 2>&1
0 18 * * 1-5 cd /home/ubuntu/nse-public-mcp && /home/ubuntu/nse-public-mcp/.venv/bin/python -m jobs.cron_daily >> logs/cron_daily.log 2>&1
# nse-public-mcp indicator updaters (each runs after the matching candle fetch)
30 18 * * 1-5 cd /home/ubuntu/nse-public-mcp && /usr/bin/python3 -m jobs.cron_indicators_daily >> logs/indicators_daily.log 2>&1
20,35,50 9-15 * * 1-5 cd /home/ubuntu/nse-public-mcp && /usr/bin/python3 -m jobs.cron_indicators_15min >> logs/indicators_15min.log 2>&1
5 16 * * 1-5 cd /home/ubuntu/nse-public-mcp && /usr/bin/python3 -m jobs.cron_indicators_15min >> logs/indicators_15min.log 2>&1
2-57/5 9-15 * * 1-5 cd /home/ubuntu/nse-public-mcp && /usr/bin/python3 -m jobs.cron_indicators_5min >> logs/indicators_5min.log 2>&1
# nse-public-mcp price-action updaters (each runs after the matching indicator cron)
35 18 * * 1-5 cd /home/ubuntu/nse-public-mcp && /usr/bin/python3 -m jobs.cron_price_action_daily >> logs/price_action_daily.log 2>&1
25,55 9-15 * * 1-5 cd /home/ubuntu/nse-public-mcp && /usr/bin/python3 -m jobs.cron_price_action_15min >> logs/price_action_15min.log 2>&1
9-54/15 9-15 * * 1-5 cd /home/ubuntu/nse-public-mcp && /usr/bin/python3 -m jobs.cron_price_action_5min >> logs/price_action_5min.log 2>&1
```
> Cron times are server-local. Verify the server is on IST (`timedatectl`) — if not, shift the hour ranges.
> The 5-min indicator cron is offset to `2-57/5` so it runs ~2 minutes after `cron_5min` and never reads stale candles.
> The price-action 5-min cron is offset to `9-54/15` (minutes 9, 24, 39, 54) so it runs ~2 minutes after each `cron_indicators_5min` slot.
### 10. Verification
```bash
mysql -u nse_writer -p nse_public <<'SQL'
SELECT 'daily' AS tf, COUNT(*) AS n FROM candles_daily
UNION ALL SELECT '15min', COUNT(*) FROM candles_15min
UNION ALL SELECT '5min', COUNT(*) FROM candles_5min;
-- Per-stock coverage on daily — flag any with < 1000 rows (~4 trading years)
SELECT symbol, COUNT(*) AS n
FROM candles_daily
GROUP BY symbol
HAVING n < 1000
ORDER BY n;
-- Latest data freshness
SELECT MIN(candle_date) AS earliest, MAX(candle_date) AS latest
FROM candles_daily;
-- Recent cron health
SELECT job_type, timeframe, symbols_success, symbols_failed, started_at, duration_seconds
FROM fetch_log
ORDER BY started_at DESC
LIMIT 20;
SQL
```
DB size on disk:
```bash
sudo du -sh /var/lib/mysql/nse_public/
```
</details>
---
## Service Management
```bash
# Server status
sudo systemctl status nse-public-mcp
# Restart
sudo systemctl restart nse-public-mcp
# Logs
sudo journalctl -u nse-public-mcp -n 100 -f
# nginx
sudo nginx -t && sudo systemctl reload nginx
# fail2ban
sudo fail2ban-client status nginx-mcp-ratelimit
```
---
## Layout
See [PROJECT.md](PROJECT.md) for architecture and data-flow diagram.
```
config/ # settings, stock universe, holiday calendar
data/ # yfinance fetcher, backfill CLI, shared upsert helpers
db/ # schema and pooled connection
indicators/ # technical indicator compute, persist, runner
price_action/ # zones, patterns, levels, trends
mcp_server/ # FastMCP server + 12 tool modules
jobs/ # cron entrypoints (candles + indicators + price action)
deploy/ # systemd service, nginx config, fail2ban rules
tests/ # mocked unit tests (82 tests)
```
---
## Operational Notes
- **Be respectful to Yahoo Finance.** The fetcher sleeps 1–3 s between requests and retries with backoff. Don't reduce these.
- **Idempotent.** All inserts are `INSERT … ON DUPLICATE KEY UPDATE`. Replaying a cron tick or rerunning backfill is safe.
- **Holiday calendar** lives in `config/holidays.py`. Update it once a year when NSE publishes the next year's list.
- **Retention cleanup** runs at the end of `jobs/cron_daily.py`. Daily candles older than 5 y, 15min older than 2 y, 5min older than 6 mo are purged.
---
## License
[MIT](LICENSE) — free to use, modify, and distribute.
## Disclaimer
This project is for **educational and informational purposes only**. Not investment advice. See [DISCLAIMER.md](DISCLAIMER.md).
Connection Info
You Might Also Like
ai-native-pm-os
The exhaustive guide to mastering Claude for Product Managers. Build your...
Train-in-Silence
The first Task-Aware MCP server and automated VRAM calculator for LLM...
stacklit
108,000 lines of code. 4,000 tokens of index. One command makes any repo...
AppClaw
AI-powered mobile automation agent — describe what you want in plain...
pdf-mcp
Production-ready MCP server for PDF processing with intelligent caching....
kotadb
Local-only code intelligence API for AI developer workflows (Bun +...