indmoney-mcp
Read-only INDmoney portfolio access for Claude — Indian stocks, mutual funds, US stocks, gold, credit cards, loans, and Experian credit score. OTP browser login with AES-256-GCM encrypted sessions.
README
INDmoney MCP Server
A Model Context Protocol (MCP) server that gives Claude read-only access to your INDmoney portfolio — stocks, mutual funds, US stocks, gold, credit cards, liquid savings, loans, and debt.
Built with Python + Playwright. Uses browser automation for OTP login and network interception to capture live API data. Sessions are encrypted and persist across restarts.
What you can ask Claude
Once connected, you can ask things like:
- "Show me my stock holdings and P&L"
- "How are my mutual funds performing?"
- "What's my US stocks portfolio in INR?"
- "What's my outstanding credit card balance?"
- "Give me a full portfolio summary with asset allocation"
- "How much cash do I have in my savings accounts?"
Features
| 14 MCP tools | Status, connect, disconnect, holdings, MF, US stocks, gold, loans, credit cards, liquid, debt, summary, credit score, discover |
| Persistent sessions | AES-256-GCM encrypted session survives server restarts (12-hour TTL) |
| Two-level cache | In-memory (5 min) + disk (60 min) — subsequent queries are instant |
| Reliable fetching | Direct JWT Bearer calls + page-nav interception fallback |
| Read-only | No order placement, no fund transfers — portfolio data only |
| Type-safe | Pydantic models throughout; all responses are structured JSON |
Requirements
- Python 3.11+
- macOS / Linux / Windows (WSL2)
- Claude Desktop (or any MCP-compatible client)
- An INDmoney account
Installation
1. Clone and install
git clone https://github.com/VIckys-AI-Stuffs/indmoney-mcp-python.git
cd indmoney-mcp-python
python3.11 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -e .
python -m playwright install chromium
2. Generate an encryption key
The server encrypts your session on disk with AES-256-GCM. Generate a persistent key once and keep it — losing it means losing your saved session (you'll just need to log in again):
python3 -c "import secrets; print(secrets.token_hex(32))"
# example output: a3f1c8e2b4d7... ← copy this value
3. Configure Claude Desktop
Open your Claude Desktop config file and add the indmoney server block. All configuration is passed directly via the env key — no .env file needed.
| Platform | Config file location |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
{
"mcpServers": {
"indmoney": {
"command": "/absolute/path/to/indmoney-mcp-python/venv/bin/python",
"args": ["/absolute/path/to/indmoney-mcp-python/main.py"],
"env": {
"PYTHONUNBUFFERED": "1",
"SESSION_ENCRYPTION_KEY": "paste-your-32-byte-hex-key-here"
}
}
}
}
Important: Use the full absolute path to
venv/bin/python, not justpython.
All supported env variables
| Variable | Required | Default | Description |
|---|---|---|---|
SESSION_ENCRYPTION_KEY |
Recommended | (auto-generated) | 32-byte hex key for AES-256-GCM session encryption. If omitted, a new key is generated on every restart and your saved session will be lost each time. |
SESSION_TTL_HOURS |
No | 12 |
How long a logged-in session stays valid before requiring re-login |
CACHE_TTL_MINUTES |
No | 60 |
Disk cache TTL — how long fetched portfolio data is kept on disk |
IN_MEMORY_CACHE_TTL_MINUTES |
No | 5 |
In-memory cache TTL — subsequent queries within this window return instantly |
API_REQUEST_TIMEOUT |
No | 10 |
Per-request timeout in seconds |
API_TOTAL_TIMEOUT |
No | 60 |
Total timeout for a full data fetch in seconds |
LOG_LEVEL |
No | INFO |
Log verbosity: DEBUG, INFO, WARNING, ERROR |
BROWSER_HEADLESS |
No | false |
Set true to hide the browser window (not recommended — you need to see it for OTP login) |
BROWSER_DATA_DIR |
No | ./browser-data |
Path to store the persistent Playwright browser profile (cookies, localStorage) |
SESSIONS_DIR |
No | ./sessions |
Path to store encrypted session + cache files |
Advanced: full config example with all options
{
"mcpServers": {
"indmoney": {
"command": "/absolute/path/to/indmoney-mcp-python/venv/bin/python",
"args": ["/absolute/path/to/indmoney-mcp-python/main.py"],
"env": {
"PYTHONUNBUFFERED": "1",
"SESSION_ENCRYPTION_KEY": "paste-your-32-byte-hex-key-here",
"SESSION_TTL_HOURS": "12",
"CACHE_TTL_MINUTES": "60",
"IN_MEMORY_CACHE_TTL_MINUTES": "5",
"LOG_LEVEL": "INFO",
"BROWSER_HEADLESS": "false"
}
}
}
}
Alternative: Instead of the
envblock, you can copy.env.exampleto.envin the project root and set values there. Both approaches work — the Claude configenvblock takes precedence over.envif the same key appears in both.
3. Restart Claude Desktop
Quit completely and reopen. The indmoney server should appear in Settings → MCP Servers.
Connecting for the first time
In Claude, say:
Connect me to INDmoney
Claude will:
- Open a Chromium browser window
- Navigate to INDmoney login
- Wait while you enter your phone number + OTP
- Detect successful login, save the encrypted session, and close the browser
The OTP login window may timeout after ~30 seconds on Claude's side — that's okay. The browser stays open and the session is saved when you complete the OTP. Call
broker_statusafterward to confirm.
MCP Tools Reference
Session Management
| Tool | Description |
|---|---|
broker_status |
Connection status, session age, cache inventory |
broker_connect |
Open browser for OTP login (saves encrypted session) |
broker_disconnect |
Log out, wipe session + cache |
Portfolio Data
| Tool | What it returns |
|---|---|
get_holdings |
Indian stock holdings — symbol, quantity, avg price, current value, P&L |
get_mutual_funds |
MF holdings — scheme name, invested, current value, returns, XIRR |
get_us_stocks |
US stock holdings — ticker, quantity, value in INR |
get_gold |
Gold holdings (digital gold, SGBs, ETFs) |
get_liquid |
Cash / savings — bank balances, FDs, EPF |
get_credit_cards |
Credit card outstanding balances and due dates |
get_loans |
Loan accounts and outstanding amounts |
get_debt |
Debt instruments (bonds, NCDs, debt MFs) |
get_credit_score |
Experian credit score, rating factors, active loans, and credit card limits |
get_portfolio_summary |
Aggregated total invested, current value, P&L, asset allocation |
Utilities
| Tool | Description |
|---|---|
discover_endpoints |
Navigates dashboard pages and logs all live API URLs — useful if endpoints change |
How it works
Claude ──STDIO JSON-RPC──► MCP Server (Python)
│
┌───────────┴───────────┐
│ │
Session Manager INDmoney Scraper
(disk + AES-256-GCM) (Playwright)
│ │
sessions/indmoney/ browser-data/indmoney/
├── session.json (persistent browser profile
└── cache/ with cookies + localStorage)
├── holdings.json
└── ...
Authentication flow:
- Playwright launches a persistent Chromium context (keeps cookies/localStorage between runs)
- User completes OTP login manually in the browser window
- Server extracts the JWT from
document.cookie(tokencookie onwww.indmoney.com) - JWT is stored encrypted on disk; browser context preserves cookies for the lifetime of the session
Data fetching:
- Most endpoints:
page.evaluate(fetch(url, {Authorization: Bearer <jwt>}))— direct API call from the browser context (avoids CORS) - Some endpoints (gold, fallbacks):
page.expect_response(predicate)while navigating to the relevant SPA page — captures the first matching network response
Configuration
Copy .env.example to .env and edit as needed:
cp .env.example .env
| Variable | Default | Description |
|---|---|---|
SESSION_ENCRYPTION_KEY |
(auto-generated) | 32-byte hex key for AES-256-GCM |
SESSION_TTL_HOURS |
12 |
How long a session stays valid |
CACHE_TTL_MINUTES |
60 |
Disk cache TTL |
IN_MEMORY_CACHE_TTL_MINUTES |
5 |
In-memory cache TTL |
API_REQUEST_TIMEOUT |
10 |
Per-request timeout (seconds) |
LOG_LEVEL |
INFO |
DEBUG, INFO, WARNING, ERROR |
BROWSER_HEADLESS |
false |
Set true to hide the browser window |
If
SESSION_ENCRYPTION_KEYis empty, one is auto-generated and printed on first run. Copy it to.envto keep sessions valid across restarts.
Project structure
indmoney-mcp-python/
├── main.py # Entry point — STDIO MCP transport
├── pyproject.toml
├── .env.example
│
├── mcp_server/
│ ├── server.py # All 14 MCP tool handlers
│ ├── config.py # Config (env vars + paths)
│ ├── logger.py # stderr-only logger
│ │
│ ├── types/ # Pydantic models
│ │ └── portfolio.py # Holding, MutualFundHolding, CreditCardAccount, …
│ │
│ ├── adapters/indmoney/
│ │ ├── scraper.py # Playwright fetch + page-nav interception
│ │ ├── endpoints.py # All API URLs (Octopus, apixt-*, etc.)
│ │ ├── auth.py # OTP login flow
│ │ └── parser.py # Raw API → Pydantic models
│ │
│ ├── session/
│ │ ├── manager.py # SessionManager singleton
│ │ ├── store.py # Disk read/write
│ │ ├── crypto.py # AES-256-GCM encrypt/decrypt
│ │ └── cache.py # Multi-level cache
│ │
│ ├── browser/
│ │ ├── manager.py # Playwright context lifecycle
│ │ └── interceptor.py # Network response interception
│ │
│ └── utils/
│ └── retry.py # Exponential backoff retry decorator
│
├── tests/
│ ├── conftest.py # Autouse fixture — isolates session dir per test
│ ├── test_integration_basic.py
│ ├── test_phase2_session_management.py
│ ├── test_phase3_browser_automation.py
│ └── test_phase4_scraper_and_parser.py
│
├── sessions/ # GITIGNORED — encrypted session data
├── browser-data/ # GITIGNORED — Playwright persistent profile
└── logs/ # GITIGNORED — runtime logs
Development
# Activate venv
source venv/bin/activate
# Run tests
pytest tests/ -v
# Run with coverage
pytest --cov=mcp_server tests/
# Code quality
black mcp_server/
isort mcp_server/
flake8 mcp_server/
# Test server directly (no Claude needed)
python -c "
import asyncio
from mcp_server.server import INDmoneyMCPServer
async def main():
s = INDmoneyMCPServer()
r = await s._handle_broker_status({})
print(r[0].text)
asyncio.run(main())
"
# Interactive tool testing
mcp dev main.py
Security
- Encrypted at rest: Session tokens are encrypted with AES-256-GCM before being written to disk. The key lives only in
.env(gitignored). - OTP stays in your browser: The OTP you type never passes through the MCP server — it goes directly from your keyboard to the INDmoney website.
- Read-only: The server has no tools for placing orders, transferring funds, or modifying your account.
- Local only: All data stays on your machine — nothing is sent to any third-party server.
ToS notice: Browser-based scraping may be against INDmoney's Terms of Service. Use responsibly and at your own risk.
Troubleshooting
See TROUBLESHOOTING.md for detailed solutions to common issues.
Quick fixes:
| Symptom | Fix |
|---|---|
| Server not showing in Claude | Check absolute path in config; restart Claude fully |
| "not connected" after OTP | Call broker_status — session may have saved after timeout |
| Tools return stale data | Ask Claude to "clear cache and refresh" |
| Session deleted unexpectedly | Never run pytest without the test isolation fixture |
| Gold returns nothing | Your gold holding may already be in get_holdings (e.g., GOLDBEES ETF) |
Contributing
- Fork the repo
- Create a feature branch:
git checkout -b feature/my-thing - Write tests for your changes
- Make sure
pytest tests/passes - Open a pull request
All contributions welcome — new broker adapters, parser fixes, documentation improvements.
License
MIT — free to use, modify, and distribute.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。