# I built an open-source MCP server that gives any AI assistant live NSE + BSE stock data

> Source: <https://dev.to/govind_sisara/i-built-an-open-source-mcp-server-that-gives-any-ai-assistant-live-nse-bse-stock-data-5f8h>
> Published: 2026-06-20 02:54:53+00:00

Ask ChatGPT or Claude "what was Reliance's operating margin last quarter?" and you get one of two answers: a polite "I don't have live data," or a confident, wrong number. The reasoning is great. The data access is nonexistent — these models are blind to anything past their training cut-off, and they have zero native window into NSE/BSE.

So I built an MCP server to fix it, and open-sourced it. This is the build story + a quick-start if you want to plug it into your own setup.

The **Model Context Protocol** is an open standard that lets AI assistants call external tools through a consistent interface. Instead of guessing, the model issues a structured request — `get_stock_quote`

for `RELIANCE`

— gets real data back, and reasons over it. One protocol, and Claude, ChatGPT, Cursor, Gemini, and Grok can all hit the same data source.

It's basically USB-C for AI tools.

```
search_stocks            screen_stocks (326 fundamental filters)
screen_stocks_technical  get_company_profile   get_financials
get_stock_quote          get_price_history     get_shareholding
get_fii_dii_detail       market_ipo            market_fno_ban
get_user_portfolio       add_to_watchlist      ...and 21 more
```

Coverage: all ~8,200 NSE + BSE stocks, fundamentals, technicals, institutional flows, market data, and portfolio tracking. (It's a research tool, not a broker — it doesn't place trades.)

The big one: **remote-first, on the edge.**

```
┌─────────────────┐   JSON-RPC / HTTPS   ┌──────────────────────┐
│  AI Assistant   │ ───────────────────► │  Cloudflare Worker   │
│ (Claude, etc.)  │ ◄─────────────────── │  (stateless MCP)     │
└─────────────────┘                       └──────────────────────┘
                                              │
                                   D1 (users, tokens, usage)
                                   KV (rate limits, auth codes)
```

Most MCP servers ship as local stdio processes you have to install and run. That's a friction wall for non-developers. I wanted someone to paste one URL into claude.ai and be done — so the server runs as a Cloudflare Worker. Globally distributed, no servers to babysit.

The MCP SDK's `WebStandardStreamableHTTPServerTransport`

in stateless mode maps perfectly onto Workers — any request hits any edge location and is served identically:

``` js
const server = createServer(env, ph, userId);
const transport = new WebStandardStreamableHTTPServerTransport({
  sessionIdGenerator: undefined,  // stateless
  enableJsonResponse: true,
});
await server.connect(transport);
```

MCP clients vary wildly. Chat apps (Claude.ai, ChatGPT) expect a full OAuth flow with **Dynamic Client Registration (RFC 7591)** plus discovery endpoints (RFC 8414, RFC 9728). Code editors often just want a bearer token.

The trick that makes the OAuth handshake "just work": return a `401`

with a `WWW-Authenticate`

header on the first `initialize`

. That's the signal that kicks off the client's built-in OAuth flow.

```
if (!authHeader?.startsWith("Bearer ") && !isPublicMethod) {
  return Response.json(
    { error: "authentication_required" },
    { status: 401, headers: {
        "WWW-Authenticate":
          `Bearer resource_metadata="${metadataUrl}", scope="openid email"`,
    }},
  );
}
```

So the server accepts **both** short-lived HMAC access tokens and long-lived personal tokens, distinguished by prefix (`tpt_rt_…`

). One auth surface, two credential types. `tools/list`

and `ping`

stay public so registries can discover the catalog without auth.

Two independent layers:

`UPSERT`

reserves a unit The part I'm happiest with: **failed calls get refunded.** The MCP SDK throws `InvalidParams`

whenever a tool argument fails schema validation — and LLMs hallucinate bad arguments constantly. Charging a user's quota because their model fumbled an argument would be infuriating.

```
if (quotaConsumed && userId) {
  quotaConsumed = false;            // guard against double-refund
  if (hasError) {
    ctx.waitUntil(refundRateLimitV2(env.DB, userId, date, month));
  } else {
    ctx.waitUntil(trackToolCall(env.DB, userId, src));
  }
}
```

For stdio-only clients there's a tiny npm package — ~300 lines, zero runtime deps. No business logic: it reads JSON-RPC from stdin, forwards to the Worker over HTTPS, writes responses to stdout. It auto-detects message framing (Content-Length vs newline-delimited JSON, which differ across clients) and refreshes the access token before expiry. All tool logic lives on the server, so new tools ship instantly without anyone running `npm update`

.

**No install** (claude.ai, ChatGPT, Gemini, Grok) — paste the URL, sign in with Google:

```
https://mcp.tapetide.com/mcp
```

**Local via npm** (Cursor, Windsurf, Claude Desktop):

```
{
  "mcpServers": {
    "tapetide": {
      "command": "npx",
      "args": ["-y", "tapetide-mcp"],
      "env": { "TAPETIDE_TOKEN": "your_token_here" }
    }
  }
}
```

Then just ask:

"Find mid-caps where FII holding rose last quarter, ROE above 15%, and RSI under 40."

`npx`

command for reach.`.well-known`

discovery endpoints precisely.Free and open source under MIT. Source, all 34 tools, and setup guides:

🔗 [https://github.com/Tapetide-hq/nse-bse-indian-stock-market-data-mcp](https://github.com/Tapetide-hq/nse-bse-indian-stock-market-data-mcp)

If you build something on top of it or have ideas for tools you'd want, I'd love to hear it in the comments.
