
Criei um servidor MCP de código aberto que fornece dados de ações NSE + BSE para assistentes de IA
A necessidade
Peça ao ChatGPT ou Claude "qual foi a margem operacional da Reliance no último trimestre?" e você receberá uma de duas respostas: um educado "não tenho dados ao vivo", ou um número confiante, mas errado. O raciocínio é ótimo. O acesso aos dados é inexistente — esses modelos são cegos para qualquer coisa além do seu limite de treinamento, e não têm nenhuma janela nativa para NSE/BSE.
Então eu construí um servidor MCP para corrigir isso e o open-sourci. Esta é a história da construção + um guia rápido se você quiser integrá-lo à sua própria configuração.
Recapitulação do MCP em 30 segundos
O Modelo de Protocolo de Contexto é um padrão aberto que permite que assistentes de IA chamem ferramentas externas através de uma interface consistente. Em vez de adivinhar, o modelo emite um pedido estruturado — get_stock_quote para RELIANCE — recebe dados reais de volta e raciocina sobre isso. Um protocolo, e Claude, ChatGPT, Cursor, Gemini e Grok podem todos acessar a mesma fonte de dados.
É basicamente USB-C para ferramentas de IA.
O que eu expus: 34 ferramentas
search_stocks screen_stocks (326 filtros fundamentais)
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 ...e mais 21
Cobertura: todos os ~8.200 ações da NSE + BSE, fundamentos, técnicos, fluxos institucionais, dados de mercado e rastreamento de portfólio. (É uma ferramenta de pesquisa, não um corretor — não realiza negociações.)
Decisões de arquitetura
A grande questão: remoto-primeiro, na borda.
┌─────────────────┐ JSON-RPC / HTTPS ┌──────────────────────┐
│ Assistente de IA │ ───────────────────► │ Cloudflare Worker │
│ (Claude, etc.) │ ◄─────────────────── │ (MCP sem estado) │
└─────────────────┘ └──────────────────────┘
│
D1 (usuários, tokens, uso)
KV (limites de taxa, códigos de autenticação)
A maioria dos servidores MCP é enviada como processos locais de stdio que você precisa instalar e executar. Isso é uma barreira de atrito para não desenvolvedores. Eu queria que alguém colasse uma URL no claude.ai e estivesse feito — então o servidor roda como um Cloudflare Worker. Globalmente distribuído, sem servidores para cuidar.
Transporte sem estado
O WebStandardStreamableHTTPServerTransport do SDK MCP em modo sem estado se mapeia perfeitamente para Workers — qualquer solicitação atinge qualquer local de borda e é atendida de forma idêntica:
const server = createServer(env, ph, userId);
const transport = new WebStandardStreamableHTTPServerTransport({
sessionIdGenerator: undefined, // sem estado
enableJsonResponse: true,
});
await server.connect(transport);
A autenticação foi a parte difícil
Os clientes MCP variam muito. Aplicativos de chat (Claude.ai, ChatGPT) esperam um fluxo completo de OAuth com Registro Dinâmico de Clientes (RFC 7591) mais endpoints de descoberta (RFC 8414, RFC 9728). Editores de código geralmente só querem um token bearer.
A sacada que faz o handshake OAuth "funcionar": retornar um 401 com um cabeçalho WWW-Authenticate na primeira initialize. Esse é o sinal que inicia o fluxo de OAuth embutido do cliente.
if (!authHeader?.startsWith("Bearer ") && !isPublicMethod) {
return Response.json(
{ error: "authentication_required" },
{ status: 401, headers: {
"WWW-Authenticate":
`Bearer resource_metadata="${metadataUrl}", scope="openid email"`,
}},
);
}
Assim, o servidor aceita ambos tokens de acesso HMAC de curta duração e tokens pessoais de longa duração, diferenciados por prefixo (tpt_rt_…). Uma superfície de autenticação, dois tipos de credenciais. tools/list e ping permanecem públicos para que os registros possam descobrir o catálogo sem autenticação.
Limitação de taxa que não pune usuários honestos
Duas camadas independentes:
- Suavizador de explosão por minuto (KV, falha aberta) — impede que um token despeje toda a sua cota diária em segundos. Se o KV falhar, permita a solicitação; o limite diário é o verdadeiro teto.
-
Cota diária/mensal (D1, falha fechada) — um
UPSERTatômico reserva uma unidade antes que a ferramenta seja executada. Limite inacessível → negar, nunca conceder acesso sem medição.
A parte com a qual estou mais feliz: chamadas falhadas são reembolsadas. O SDK MCP lança InvalidParams sempre que um argumento da ferramenta falha na validação do esquema — e os LLMs constantemente alucinam argumentos ruins. Cobrar a cota de um usuário porque seu modelo falhou em um argumento seria irritante.
if (quotaConsumed && userId) {
quotaConsumed = false; // proteger contra reembolso duplo
if (hasError) {
ctx.waitUntil(refundRateLimitV2(userId);
}
}
A implementação de um servidor MCP pode revolucionar a forma como empresas brasileiras acessam dados financeiros em tempo real. Isso permite que assistentes de IA forneçam informações precisas e atualizadas, melhorando a tomada de decisões. A abertura do código também incentiva a inovação no uso de dados financeiros.

