Skip to main content
Glama
VIckys-AI-Stuffs

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 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 just python.

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 env block, you can copy .env.example to .env in the project root and set values there. Both approaches work — the Claude config env block takes precedence over .env if 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:

  1. Open a Chromium browser window

  2. Navigate to INDmoney login

  3. Wait while you enter your phone number + OTP

  4. 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_status afterward 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:

  1. Playwright launches a persistent Chromium context (keeps cookies/localStorage between runs)

  2. User completes OTP login manually in the browser window

  3. Server extracts the JWT from document.cookie (token cookie on www.indmoney.com)

  4. 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_KEY is empty, one is auto-generated and printed on first run. Copy it to .env to 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

  1. Fork the repo

  2. Create a feature branch: git checkout -b feature/my-thing

  3. Write tests for your changes

  4. Make sure pytest tests/ passes

  5. Open a pull request

All contributions welcome — new broker adapters, parser fixes, documentation improvements.


License

MIT — free to use, modify, and distribute.

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
1Releases (12mo)

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