angelone-mcp

Un servidor MCP (Model Context Protocol) que envuelve la SmartAPI de Angel One: trading, cartera, datos de mercado, reglas GTT y margen/bróker.

Documentación

angelone-mcp

Listed on mcpservers.org

Un servidor MCP (Protocolo de Contexto de Modelo) que envuelve la SmartAPI de Angel One — trading, cartera, datos de mercado, reglas GTT y margen/bróker — para que cualquier cliente MCP (Claude, Claude Code, etc.) pueda consultar tu cuenta y realizar órdenes mediante conversación natural.

⚠️

Esto realiza órdenes reales en una cuenta de trading real. Prueba primero con cantidades pequeñas y ten en cuenta que Angel One (como la mayoría de los brókers) no te permite "deshacer" una orden ejecutada.

Qué incluye

  • angelone_mcp/client.py – Cliente REST para cada ruta documentada de SmartAPI: autenticación, órdenes, posiciones/tenencias, reglas GTT, velas históricas/OI, cotizaciones, griegas de opciones, ganadores/perdedores, calculadora de margen, estimador de bróker. Maneja el inicio de sesión TOTP, el re-inicio de sesión automático al expirar el token y se adapta a los límites de tasa documentados de SmartAPI (ver "Límites de tasa" más abajo).
  • angelone_mcp/server.py – Servidor MCP que expone 32 herramientas construidas sobre el cliente (ver la lista completa más abajo).

1. Requisitos previos

  • Python 3.10+
  • Una cuenta de trading de Angel One con acceso a SmartAPI
  • Una aplicación SmartAPI creada en https://smartapi.angelone.in/ (te proporciona una clave API)
  • TOTP configurado en tu cuenta de Angel One, y el secreto base32 utilizado para configurar ese autenticador (no el código de 6 dígitos — el secreto detrás de él). Lo obtienes una vez, cuando escaneas el código QR para habilitar TOTP; si no lo tienes guardado, necesitarás restablecer/reconfigurar TOTP en tu cuenta para obtener un secreto nuevo.

2. Instalación

cd angelone-mcp
python3 -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install -r requirements.txt

3. Configurar credenciales

Establece estas variables de entorno (por ejemplo, en un archivo .env que cargues, o directamente en la configuración de tu cliente MCP):

VariableDescripción
ANGELONE_API_KEYClave API de tu aplicación SmartAPI
ANGELONE_CLIENT_CODETu código de cliente/cuenta de trading de Angel One
ANGELONE_PINTu PIN de inicio de sesión
ANGELONE_TOTP_SECRETSecreto TOTP base32 de tu cuenta

Nunca los envíes al control de versiones. Trata ANGELONE_TOTP_SECRET y ANGELONE_PIN como contraseñas: cualquiera que los tenga junto con tu clave API puede operar en tu cuenta.

Opcional: ejecutar detrás de un proxy HTTP

Si tu máquina/red requiere un proxy HTTP de salida para acceder a internet, establece:

VariableDescripción
ANGELONE_HTTP_PROXYURL del proxy utilizada para solicitudes http://, por ejemplo, http://user:pass@proxyhost:8080
ANGELONE_HTTPS_PROXYURL del proxy utilizada para solicitudes https:// (esta es la que importa — SmartAPI es solo https). Se usa ANGELONE_HTTP_PROXY como respaldo si no está definida.
ANGELONE_NO_PROXYLista opcional separada por comas de hosts para omitir el proxy

Estas solo son necesarias si las variables de entorno estándar HTTP_PROXY / HTTPS_PROXY no son visibles para el proceso del servidor. Esto es común en servidores MCP, ya que los clientes MCP suelen lanzar el servidor con un bloque env explícito (como el JSON a continuación) en lugar de heredar el entorno de tu shell — por lo que un proxy configurado en tu shell no llegará al servidor a menos que lo agregues tú mismo a ese bloque env bajo HTTPS_PROXY, o uses las variables ANGELONE_* anteriores. Si ni ANGELONE_HTTP_PROXY ni ANGELONE_HTTPS_PROXY están definidas, el servidor recurre automáticamente a las variables estándar HTTP_PROXY / HTTPS_PROXY / NO_PROXY.

4. Ejecutarlo

Independiente (para pruebas):

python -m angelone_mcp.server

Habla MCP a través de stdio, por lo que está diseñado para ser lanzado por un cliente MCP, no para ejecutarse de forma interactiva.

Configuración de Claude Desktop / Claude Code

Agrega a la configuración de tu cliente MCP (por ejemplo, claude_desktop_config.json):

{
  "mcpServers": {
    "angelone": {
      "command": "/absolute/path/to/angelone-mcp/.venv/bin/python",
      "args": ["-m", "angelone_mcp.server"],
      "cwd": "/absolute/path/to/angelone-mcp",
      "env": {
        "ANGELONE_API_KEY": "your_api_key",
        "ANGELONE_CLIENT_CODE": "your_client_code",
        "ANGELONE_PIN": "your_pin",
        "ANGELONE_TOTP_SECRET": "your_base32_totp_secret",
        "ANGELONE_HTTPS_PROXY": "http://user:pass@proxyhost:8080"
      }
    }
  }
}

Herramientas expuestas

Sesión login, logout, get_profile

Órdenes place_order, modify_order, cancel_order, get_order_book, get_trade_book, get_individual_order_details

Cartera / fondos get_positions, get_holdings, get_all_holdings, get_rms_limit, convert_position

Reglas GTT (Good Till Triggered) gtt_create_rule, gtt_modify_rule, gtt_cancel_rule, gtt_details, gtt_list

Datos de mercado get_ltp, get_market_quote, search_scrip, get_candle_data, get_oi_data, get_option_greeks, get_gainers_losers, get_put_call_ratio, get_oi_buildup, get_nse_intraday_data, get_bse_intraday_data

Margen y bróker get_margin, estimate_charges

Cómo funciona la autenticación

AngelOneClient inicia sesión de forma diferida en la primera llamada a una herramienta usando clientcode + pin + un TOTP generado sobre la marcha a partir de ANGELONE_TOTP_SECRET (mediante pyotp). Almacena en caché el jwtToken, refreshToken y feedToken resultantes en memoria durante la vida del proceso. Si alguna llamada devuelve un 401/403 o un TokenException, se vuelve a iniciar sesión de forma transparente una vez y reintenta — no necesitas llamar a login tú mismo a menos que quieras forzar una sesión nueva.

Las sesiones emitidas por SmartAPI son válidas hasta la medianoche IST independientemente de la actividad, por lo que un servidor de larga duración puede necesitar un inicio de sesión nuevo al día siguiente — la lógica de reintento automático lo maneja en la siguiente llamada.

Persistencia de sesión entre reinicios

Un inicio de sesión exitoso también se guarda en un archivo en disco, de modo que un proceso de servidor nuevo no necesita un inicio de sesión TOTP nuevo cada vez que arranca (útil porque TOTP requiere que el código se genere recientemente — reiniciar el servidor varias veces seguidas significaría varios inicios de sesión reales seguidos).

Al arrancar, antes de atender cualquier llamada a herramientas, el servidor llama a AngelOneClient.restore_session(), que:

  1. Busca un archivo de sesión guardado previamente. Si no hay uno, no hace nada más — el cliente permanece en su modo diferido normal e inicia sesión en la primera llamada a una herramienta, igual que antes de que existiera esta función.
  2. Si se encuentra una sesión guardada, carga los tokens en caché y los verifica con una llamada real a getProfile.
  3. Si esa verificación tiene éxito, la sesión restaurada se usa tal cual — sin necesidad de un inicio de sesión nuevo.
  4. Si falla por cualquier motivo (token expirado, sesión revocada, archivo corrupto, etc.), los tokens en caché se descartan y se ejecuta un inicio de sesión nuevo normal.

Cada inicio de sesión exitoso (nuevo o mediante el reintento automático 401/403 descrito anteriormente) vuelve a guardar el archivo de sesión, por lo que se mantiene actualizado durante todo el tiempo que el servidor esté en ejecución, no solo al arrancar. logout elimina el archivo.

VariableDescripción
ANGELONE_SESSION_PERSISTEstablécelo en false / 0 / no / off para deshabilitar la persistencia de sesión por completo (predeterminado: habilitado)
ANGELONE_SESSION_FILESobrescribe la ruta del archivo utilizada para persistir la sesión. Predeterminado: un archivo en el directorio temporal del sistema operativo, nombrado a partir de un hash de tu código de cliente (para que varias cuentas en la misma máquina no colisionen)

El archivo de sesión contiene un token de acceso activo — no tu PIN ni el secreto TOTP, pero suficiente para llamar a la API como tú hasta que expire. Se escribe con permisos de archivo solo para el propietario donde el sistema operativo lo permite; trátalo como sensible de la misma manera que tratarías cualquier sesión de inicio de sesión en caché.

Límites de tasa

AngelOneClient adapta cada llamada saliente a los límites de tasa por endpoint documentados de SmartAPI — inicio de sesión y la mayoría de lecturas de cartera a 1 solicitud/seg, getProfile a 3/seg, consultas de cotizaciones/GTT/detalles de órdenes a 10/seg, colocación de órdenes a 20/seg, y así sucesivamente. Los límites son por endpoint de SmartAPI, no globales, por lo que llamar a diferentes herramientas consecutivamente nunca se ralentiza por esto — solo una llamada repetida al mismo endpoint más rápida de lo que permite el propio límite de SmartAPI se retiene, lo cual querrías de todos modos.

Si SmartAPI informa que se alcanzó su propio límite de todos modos (HTTP 403/429, "Acceso denegado por exceder la tasa de acceso"), la llamada retrocede y reintenta algunas veces con un retraso creciente antes de rendirse — y esa respuesta ya no se malinterpreta como una sesión expirada ni provoca un inicio de sesión adicional espurio como solía hacerlo.

Esto se aplica automáticamente a todas las herramientas; no hay nada que configurar para obtenerlo. Para desactivar por completo la adaptación del lado del cliente (SmartAPI aún aplica sus propios límites en el servidor de todos modos — esto solo controla si el cliente intenta mantenerse por debajo de ellos de forma proactiva):

VariableDescripción
ANGELONE_RATE_LIMIT_DISABLEDEstablécelo en true / 1 / yes / on para deshabilitar la adaptación proactiva (predeterminado: habilitado)

Pruebas

pip install -e ".[test]"

# Offline: verifies the server registers the expected tools. No credentials
# or network access needed.
python -m pytest tests/test_tool_registration.py -v

# Offline: unit tests for session persistence (login state cached to disk,
# restored + verified via get_profile on restart, falls back to a fresh
# login when the cache is missing/invalid). Uses a fake HTTP layer - no
# credentials or network access needed.
python -m pytest tests/test_session_persistence.py -v

# Offline: unit tests for AngelOneClient's own rate limiting (pacing per
# ROUTE_MIN_INTERVAL, backoff/retry on a 403/429 rate-limit response, and
# that such a response is never misread as an expired session). Uses a fake
# HTTP layer - no credentials or network access needed.
python -m pytest tests/test_client_rate_limiting.py -v

# Live, read-only smoke test against your real account. Calls get_profile,
# get_order_book, get_holdings, search_scrip, get_ltp, etc. through the
# actual MCP server subprocess, plus a check that a session survives a
# restart of the server without calling the "login" tool again. Never calls
# place_order/modify_order/cancel_order/gtt_create_rule/gtt_modify_rule/
# gtt_cancel_rule/convert_position/logout - a SafeSession wrapper
# hard-asserts those are never invoked. On top of the server's own rate
# limiting (see "Rate limiting" above), the test itself also paces its tool
# calls and backs off/retries if the API reports one was hit anyway (see
# "Rate limiting in the live test" below) - belt and suspenders. Requires
# ANGELONE_API_KEY/ANGELONE_CLIENT_CODE/ANGELONE_PIN/ANGELONE_TOTP_SECRET
# to be set; skips automatically if they aren't.
python -m pytest tests/test_readonly_live.py -v -s
# or, for a plain-text report without pytest:
python tests/test_readonly_live.py

Límites de tasa en la prueba en vivo

La prueba en vivo (tests/test_readonly_live.py) llama a una cuenta real contra la SmartAPI real. El servidor que impulsa ya se adapta a sí mismo (ver "Límites de tasa" más arriba), pero la prueba agrega su propia adaptación independiente encima — útil porque también ejercita cosas que el limitador del lado del servidor no ve por sí mismo, como dos subprocesos de servidor separados (la verificación de persistencia de sesión) golpeando la misma cuenta consecutivamente:

  • Un RateLimiter rastrea la última vez que se llamó a cada herramienta MCP y, antes de llamarla de nuevo, espera el resto del intervalo mínimo de ese endpoint (1/límite de solicitudes por segundo, más un margen de seguridad de ~20%). Herramientas distintas golpean endpoints distintos de SmartAPI con límites independientes, por lo que esto solo retrasa una llamada repetida a la misma herramienta (por ejemplo, get_profile siendo llamada de nuevo por el segundo arranque del servidor en la verificación de persistencia de sesión) — una pasada normal única a través del conjunto, donde cada herramienta se llama una o dos veces, no se ralentiza en la práctica.
  • Si SmartAPI informa que se alcanzó un límite de tasa de todos modos (HTTP 403, "Acceso denegado por exceder la tasa de acceso"), la prueba retrocede y reintenta un par de veces con un retraso creciente en lugar de fallar directamente.
  • Esto gobierna solo el ritmo de solicitudes propio del conjunto de pruebas — no tiene efecto en cómo se comporta el servidor MCP para un cliente MCP real (Claude, etc.); SmartAPI aún aplica sus límites en el servidor de todos modos.

Notas / limitaciones

  • Los parámetros de órdenes (price, quantity, etc.) se pasan como cadenas, coincidiendo con lo que espera placeOrder de SmartAPI.
  • get_margin y estimate_charges toman una lista de diccionarios de posición/orden — consulta la documentación de SmartAPI para los nombres de campo exactos por tipo de instrumento (https://smartapi.angelone.in/docs/Margin,.../Brokerage).
  • Los límites de tasa son aplicados por Angel One por endpoint; consulta https://smartapi.angelone.in/docs/RateLimit. Este servidor no realiza su propia limitación de tasa del lado del cliente.
  • No está afiliado ni respaldado por Angel One / Angel Broking.