Rajandran R Creator of OpenAlgo - OpenSource Algo Trading framework for Indian Traders. Building GenAI Applications. Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Building Algo Platforms, Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in

NSE MCP Python Tutorial: Build a Simple Stock Market AI Agent with Agno

9 min read

NSE has launched its own Model Context Protocol (MCP) server. In simple words, NSE now gives AI assistants and AI agents a standard plug to fetch NSE market data: 5 years of daily (end-of-day) history, plus a live snapshot of the current trading day. No login and no API key are needed to connect.

In this tutorial we will connect to NSE MCP from Python, see all the tools it offers, call a tool directly, and finally build a small AI agent that answers stock market questions in plain English. The code is kept short and beginner friendly. We will use Agno as the agent framework and OpenAI’s gpt-5.6-luna as the model.

NSE MCP page: NSE Market Data, Native to Your AI
NSE MCP home page (nseindia.com/nse-mcp)

What is MCP?

MCP (Model Context Protocol) is an open standard that lets an AI model talk to external tools and data sources in a common way. NSE describes it like a USB-C port for AI: instead of writing custom code for every data source, any MCP aware app (Claude, ChatGPT, or your own Python agent) can plug into the NSE server and discover what it can do.

An MCP server publishes a list of tools. Each tool has a name, a description and a JSON schema for its inputs. The AI model reads these descriptions, decides which tool to call, and the MCP client runs the call and hands the result back to the model.

The Two NSE MCP Endpoints

NSE runs two separate MCP servers. Both use the Streamable HTTP transport and need no authentication.

Server nameEndpointWhat it gives you
nse-bhavcopyhttps://mcp.nseindia.in/bhavcopy/cm/mcpEnd-of-day (Bhavcopy) data for the last 5 years, updated daily with the previous trading day’s final numbers
cm-markethttps://mcp.nseindia.in/cmmkt/mcpLive snapshot of the current trading day (NSE says 1 to 3 minutes behind real-time; in our test the data refreshed every 5 minutes)

This is the same configuration NSE shows for Claude Desktop:

{
  "mcpServers": {
    "nse-bhavcopy": {
      "url": "https://mcp.nseindia.in/bhavcopy/cm/mcp",
      "transport": "streamable-http"
    },
    "cm-market": {
      "url": "https://mcp.nseindia.in/cmmkt/mcp",
      "transport": "streamable-http"
    }
  }
}

Note: in the Claude Connectors section of the NSE page, the live server URL is printed as msc.nseindia.in. The correct host is mcp.nseindia.in, as shown above and in the Claude Desktop config.

The Tools: 26 in Total

NSE says 15+ tools. When we actually connect and list them (Step 1 below), we get 13 tools on each server, 26 in total.

NSE MCP tools available: NSE Bhavcopy and CM Market Live
Tool groups listed on the NSE MCP page

nse-bhavcopy (historical data)

ToolWhat it does
get_stock_historyDaily OHLCV price history for a stock
get_ltp_by_dateClosing price of a stock on a specific date
get_52_week_high_low52-week high and low with dates
moving_averageSimple moving average of close prices over N days
get_volume_analysisVolume trend for a stock over N trading days
compare_stocksCompare returns and drawdown of several stocks
get_bulk_quoteLatest end-of-day snapshot for many stocks in one call
get_top_moversTop gainers or losers on a given date
get_top_by_volumeMost actively traded stocks on a given date
get_market_breadthAdvance and decline numbers for a date
get_corporate_actionsDividends, splits, bonus and other corporate actions
search_symbolsFind a symbol by company name or partial symbol
nse_lookup_symbolLook up ticker symbols by keyword (no prices)

cm-market (live data)

ToolWhat it does
nse_get_market_moversMain tool for live top gainers and losers
nse_get_gainersTop N gainers across all indices
nse_get_losersTop N losers across all indices
cm_get_live_gainersRaw gainers data grouped by index (NIFTY, BANKNIFTY and more)
cm_get_live_losersRaw losers data grouped by index
cm_get_stock_quoteLive quote for one stock by exact symbol
cm_get_live_market_dataLive market data for a chosen index or variation
cm_get_equity_stocksLive data for all equity series stocks (EQ, BE and others)
cm_get_sme_stocksLive data for SME segment stocks
cm_get_call_auction_stocksLive data for call auction session stocks
cm_get_bond_stocksLive data for bonds and debt instruments
cm_get_data_statusHow fresh the live market data is
cm_get_allstocks_statusHow fresh the all-stocks data cache is

What Time Series Data Does NSE MCP Give You?

This is the first question most traders ask: can I get intraday candles? The short answer is no. NSE MCP gives you daily time series for the last 5 years and a live snapshot of today. There are no 1 minute, 5 minute or any other intraday candles, either live or historical. We tested both servers to confirm this.

DataAvailable?Server and toolDetails
Daily OHLCV historyYes, about 5 yearsnse-bhavcopy: get_stock_historyOne bar per trading day: open, high, low, close, previous close, volume, traded value. In our test (1 October 2026) data started on 1 October 2021.
Today’s live snapshotYescm-market: cm_get_stock_quoteToday’s open, high, low, last traded price, change, volume and value so far. One snapshot per call, not a series.
Intraday candles (1m, 5m, 15m and so on)NoNoneNone of the 26 tools accepts an interval or a time range for intraday data.
Tick data and order book depthNoNoneMentioned on the NSE page, but not exposed by any tool at the time of writing.

A few details worth knowing when you work with the daily series:

  • History comes in chunks: get_stock_history returns at most 3 months per call. The response includes a next_end_date field. Pass it as endDate in the next call to page backwards. An AI agent handles this paging on its own.
  • Latest bar is the previous trading day: the bhavcopy server is updated once a day after market close. For today’s numbers, use the cm-market tools.
  • Live data refresh: cm_get_data_status reported a crawl interval of 5 minutes in our test. Before the market opens, the live quote still shows the previous session.
  • Prices are not adjusted: RELIANCE trades near 1,187 today but shows around 2,400 in late 2021 because of the 2024 1:1 bonus. If you calculate long range returns or moving averages, adjust for splits and bonus issues first. get_corporate_actions gives you the dates.
  • Going past 5 years: asking for data before the window returns a “Symbol not found” error, not an “out of range” message. The symbol is fine, the date is simply too old.
  • Delivery quantity: the deliveryQty field was 0 in every row we checked, so delivery based analysis is not possible yet.

If you need intraday candles, you can build your own by calling cm_get_stock_quote every 5 minutes and storing the results, or use a broker API for proper intraday history.

Why Agno?

Agno is an open source Python framework for building AI agents. You could talk to MCP servers with the raw mcp SDK and write your own tool calling loop, but Agno removes almost all of that work:

  • Built-in MCP support: MCPTools(url=..., transport="streamable-http") connects to a server, discovers every tool and converts it into a tool the model can call. One line per server.
  • The tool calling loop is handled for you: the agent sends the question to the model, runs the tool calls the model asks for, sends back the results and repeats until there is a final answer.
  • Model agnostic: we use OpenAI here, but switching to Claude, Gemini or a local model is a one line change.
  • Memory with one setting: add a SQLite database and add_history_to_context=True and the agent remembers earlier questions, so follow-ups like “which of them had more volume?” just work.
  • Beginner friendly output: print_response shows the question, every tool call and the final answer in the terminal, which makes it easy to learn what the agent is doing.

The result is a complete NSE market assistant in about 50 lines of Python.

Prerequisites

  • Python 3.10 or above (we used 3.12)
  • An OpenAI API key
  • Basic familiarity with running a Python script

Create a project folder, a virtual environment, and install the packages:

python -m venv .venv
.venv\Scripts\activate        # Windows
# source .venv/bin/activate    # Mac / Linux

pip install "agno[mcp]" openai python-dotenv "sqlalchemy[asyncio]"

Create a .env file in the same folder with your OpenAI key and the model name:

OPENAI_API_KEY=sk-your-openai-key
OPENAI_MODEL=gpt-5.6-luna

Step 1: List All NSE MCP Tools

This script connects to both servers and prints every tool. It does not use any AI model, so no API key is needed for this step. It is a good first check that your machine can reach NSE MCP.

# list_tools.py
# Step 1: connect to both NSE MCP endpoints and print every tool they expose.
# No LLM and no API key needed for this step.

import asyncio
import logging

from agno.tools.mcp import MCPTools

# Hide a harmless warning printed when the NSE server closes the session
logging.getLogger("mcp.client.streamable_http").setLevel(logging.ERROR)

NSE_SERVERS = {
    "nse-bhavcopy": "https://mcp.nseindia.in/bhavcopy/cm/mcp",  # end-of-day data, last 5 years
    "cm-market": "https://mcp.nseindia.in/cmmkt/mcp",           # live market data (1-3 min delay)
}


async def main():
    for name, url in NSE_SERVERS.items():
        async with MCPTools(url=url, transport="streamable-http") as mcp:
            print(f"\n=== {name} ({len(mcp.functions)} tools) ===")
            for tool_name, tool in mcp.functions.items():
                desc = (tool.description or "").strip().split("\n")[0]
                print(f"- {tool_name}: {desc}")


if __name__ == "__main__":
    asyncio.run(main())

Output (trimmed):

=== nse-bhavcopy (13 tools) ===
- get_top_by_volume: Get the top N most actively traded NSE stocks on a specific date, sorted descending.
- get_top_movers: Get the top N gaining or losing NSE stocks on a specific date.
- get_volume_analysis: Analyse trading volume trends for an NSE stock over N trading days.
...
=== cm-market (13 tools) ===
- cm_get_sme_stocks: Get latest live data for NSE SME (Small & Medium Enterprises) stocks (series: SM, ST).
- cm_get_live_market_data: Get live NSE market data for a specific variation type.
- nse_get_market_movers: PRIMARY TOOL for: "What are the top gainers today?", "top losers today?" ...
...

Step 2: Call a Tool Directly

Before handing the tools to an AI model, it helps to see the raw data. Here we print the input schema of get_52_week_high_low and then call it for RELIANCE.

# call_tool.py
# Step 2: call one NSE MCP tool directly, without any AI model.
# Useful to see the raw data the agent will receive.

import asyncio
import logging

from agno.tools.mcp import MCPTools

logging.getLogger("mcp.client.streamable_http").setLevel(logging.ERROR)

BHAVCOPY_URL = "https://mcp.nseindia.in/bhavcopy/cm/mcp"


async def main():
    async with MCPTools(url=BHAVCOPY_URL, transport="streamable-http") as mcp:
        # See the inputs a tool expects
        print(mcp.functions["get_52_week_high_low"].parameters)

        # Call the tool and print the raw result
        result = await mcp.session.call_tool("get_52_week_high_low", {"symbol": "RELIANCE"})
        print(result.content[0].text)


if __name__ == "__main__":
    asyncio.run(main())

Output:

{'type': 'object', 'properties': {'symbol': {'type': 'string', 'description': 'NSE stock symbol in uppercase. Example: RELIANCE, TCS, INFY'}}, 'required': ['symbol'], 'additionalProperties': False}
{"symbol":"RELIANCE","last_close":1187.0,"52w_high":1611.8,"52w_high_date":"2026-01-05","52w_low":1181.7,"52w_low_date":"2026-09-30","position_in_range_pct":1.23,"from_52w_high_pct":-26.36,"from_52w_low_pct":0.45,"trading_days":245}

The tool returns clean JSON. This is exactly what the AI model receives when it calls the tool.

Step 3: Build the NSE Market Agent

Now the fun part. We give both MCP servers to an Agno agent and let the model decide which tools to use.

# nse_agent.py
# Step 3: a simple AI agent that answers stock market questions using NSE MCP.

import asyncio
import logging
import os

from dotenv import load_dotenv
from agno.agent import Agent
from agno.db.sqlite import SqliteDb
from agno.models.openai import OpenAIResponses
from agno.tools.mcp import MCPTools

# Use the key and model from .env, even if another key is set in your system
load_dotenv(override=True)
logging.getLogger("mcp.client.streamable_http").setLevel(logging.ERROR)

# The two official NSE MCP endpoints (no authentication required)
BHAVCOPY_URL = "https://mcp.nseindia.in/bhavcopy/cm/mcp"  # historical end-of-day data
LIVE_URL = "https://mcp.nseindia.in/cmmkt/mcp"            # live market data


async def main():
    # Connect to both NSE MCP servers
    async with MCPTools(url=BHAVCOPY_URL, transport="streamable-http") as bhavcopy, \
               MCPTools(url=LIVE_URL, transport="streamable-http") as live:

        agent = Agent(
            name="NSE Market Assistant",
            model=OpenAIResponses(id=os.getenv("OPENAI_MODEL", "gpt-5.6-luna")),
            tools=[bhavcopy, live],
            instructions=[
                "You are a helpful assistant for Indian stock market data from NSE.",
                "Always use the NSE tools to fetch data. Never guess numbers.",
                "Use the live tools for today's prices and the bhavcopy tools for history.",
                "Show numbers in a small markdown table when it helps.",
                "End with: Data from NSE MCP, for educational use only.",
            ],
            add_datetime_to_context=True,  # so the agent knows today's date
            db=SqliteDb(db_file="nse_chat.db"),  # stores the chat so the agent can remember it
            add_history_to_context=True,         # remember earlier questions in this chat
            markdown=True,
        )

        print("NSE Market Assistant. Type 'exit' to quit.")
        while True:
            question = input("\nYou: ").strip()
            if question.lower() in ("exit", "quit"):
                break
            if question:
                await agent.aprint_response(question, stream=True)


if __name__ == "__main__":
    asyncio.run(main())

How it works:

  • load_dotenv(override=True) loads the key and model from .env. override=True makes sure the .env values win, even if an old OPENAI_API_KEY is set in your system environment.
  • MCPTools(url=..., transport="streamable-http") opens a connection to each NSE server. Using async with closes the connections automatically when you exit.
  • OpenAIResponses uses OpenAI’s Responses API, which is the API that newer reasoning models such as luna use for tool calling.
  • instructions tell the agent to always fetch data from the tools instead of guessing numbers.
  • add_datetime_to_context=True tells the model today’s date, so “last 1 month” means the right dates.
  • db=SqliteDb(...) plus add_history_to_context=True gives the agent memory of the conversation.

Run it with python nse_agent.py and start asking questions. Here is a real session (output simplified):

You: Compare TCS, INFY and WIPRO over the last 1 month

Tool Calls
  compare_stocks(symbols=['TCS', 'INFY', 'WIPRO'], months=1)

  Stock  Start price  End price   Return  Max drawdown
  WIPRO      181.70     158.50   -12.77%        13.71%
  TCS      2,369.00   2,050.60   -13.44%        14.21%
  INFY     1,156.00     994.10   -14.01%        14.01%

You: Which of them had the highest average volume in the last 10 days?

Tool Calls
  get_volume_analysis(symbol=TCS, days=10)
  get_volume_analysis(symbol=INFY, days=10)
  get_volume_analysis(symbol=WIPRO, days=10)

  Stock     Average volume
  WIPRO  27,506,465 shares
  INFY   10,032,097 shares
  TCS     3,402,629 shares

Notice the second question never mentions TCS, INFY or WIPRO. The agent remembered them from the first question, picked the get_volume_analysis tool on its own and called it once for each stock.

Questions to Try

  • What are the top 5 gainers in NIFTY right now?
  • Give me the live quote of HDFCBANK.
  • What was the market breadth yesterday? How many stocks advanced and declined?
  • Show the 20 day moving average of INFY and tell me if the last close is above it.
  • Which stocks had the highest traded volume on 30 September 2026?
  • Has ITC announced any dividend in the last 1 year?

A Few Practical Notes

  • Model choice: luna models need the Responses API for tool calling. At the time of writing, Agno 3.0.11 recognises gpt-5* models as reasoning models, so gpt-5.6-luna works out of the box. gpt-6-luna failed with a missing reasoning item error during tool calls on this Agno version, so stick to gpt-5.6-luna until Agno adds support.
  • Harmless warning: without the logging line in the scripts you will see Session termination failed: 501 on exit. The NSE server simply does not support the optional session close request. It does not affect results.
  • Live vs historical: as covered in the time series section, the agent should use the cm-market tools for today’s prices and the bhavcopy tools for history, which is why we mention this in the instructions.
  • Data freshness: the live server has a cm_get_data_status tool. Ask the agent “how fresh is the live data?” if numbers look stale.
  • Educational use only: NSE states that MCP data is for informational and educational purposes, not for real-time trading, commercial deployment, or training AI models.

Where to Go Next

  • Add a web UI using Agno’s AgentOS, or wrap the agent in a Streamlit app.
  • Add more MCP servers (for example a news MCP) to the same agent with another MCPTools line.
  • Ask the agent to produce a daily end-of-day market summary and email it to yourself.

Disclaimer

This post is for educational purposes only and is not investment advice. Data is accessed through NSE’s public MCP service and is subject to NSE’s terms of use. Output generated by AI models may contain errors, so always verify important numbers from the source.

Rajandran R Creator of OpenAlgo - OpenSource Algo Trading framework for Indian Traders. Building GenAI Applications. Telecom Engineer turned Full-time Derivative Trader. Mostly Trading Nifty, Banknifty, High Liquid Stock Derivatives. Trading the Markets Since 2006 onwards. Using Market Profile and Orderflow for more than a decade. Designed and published 100+ open source trading systems on various trading tools. Strongly believe that market understanding and robust trading frameworks are the key to the trading success. Building Algo Platforms, Writing about Markets, Trading System Design, Market Sentiment, Trading Softwares & Trading Nuances since 2007 onwards. Author of Marketcalls.in

Leave a Reply

Get Notifications, Alerts on Market Updates, Trading Tools, Automation & More