indmoney-mcp
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 chromium2. 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 value3. 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 |
|
Linux |
|
Windows |
|
{
"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 |
| 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. |
| No |
| How long a logged-in session stays valid before requiring re-login |
| No |
| Disk cache TTL — how long fetched portfolio data is kept on disk |
| No |
| In-memory cache TTL — subsequent queries within this window return instantly |
| No |
| Per-request timeout in seconds |
| No |
| Total timeout for a full data fetch in seconds |
| No |
| Log verbosity: |
| No |
| Set |
| No |
| Path to store the persistent Playwright browser profile (cookies, localStorage) |
| No |
| 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 INDmoneyClaude 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 |
| Connection status, session age, cache inventory |
| Open browser for OTP login (saves encrypted session) |
| Log out, wipe session + cache |
Portfolio Data
Tool | What it returns |
| Indian stock holdings — symbol, quantity, avg price, current value, P&L |
| MF holdings — scheme name, invested, current value, returns, XIRR |
| US stock holdings — ticker, quantity, value in INR |
| Gold holdings (digital gold, SGBs, ETFs) |
| Cash / savings — bank balances, FDs, EPF |
| Credit card outstanding balances and due dates |
| Loan accounts and outstanding amounts |
| Debt instruments (bonds, NCDs, debt MFs) |
| Experian credit score, rating factors, active loans, and credit card limits |
| Aggregated total invested, current value, P&L, asset allocation |
Utilities
Tool | Description |
| 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 .envVariable | Default | Description |
| (auto-generated) | 32-byte hex key for AES-256-GCM |
|
| How long a session stays valid |
|
| Disk cache TTL |
|
| In-memory cache TTL |
|
| Per-request timeout (seconds) |
|
|
|
|
| Set |
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 logsDevelopment
# 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.pySecurity
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 |
Tools return stale data | Ask Claude to "clear cache and refresh" |
Session deleted unexpectedly | Never run |
Gold returns nothing | Your gold holding may already be in |
Contributing
Fork the repo
Create a feature branch:
git checkout -b feature/my-thingWrite tests for your changes
Make sure
pytest tests/passesOpen a pull request
All contributions welcome — new broker adapters, parser fixes, documentation improvements.
License
MIT — free to use, modify, and distribute.
This server cannot be installed
Maintenance
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
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/VIckys-AI-Stuffs/indmoney-mcp-python'
If you have feedback or need assistance with the MCP directory API, please join our Discord server